Phát hiện Decibel mức độ tiếng ồn trong MXChip Azure IoT DevKit


Bùi Phước Nghĩa
10 tháng trước
Hữu ích 2 Chia sẻ Viết bình luận 0
Đã xem 1593

Giới thiệu

Chơi với Azure IoT DevKit MXChip luôn thú vị; Thiết bị có nhiều khả năng. Trong vài ngày qua, tôi đã làm việc với một số khả năng của thiết bị này như áp suất khí quyển, nhiệt độ và độ ẩm thông qua các cảm biến của nó. Trong bài viết này, tôi sẽ chỉ cho bạn cách bạn có thể tính toán mức độ tiếng ồn bằng cách sử dụng micrô của Thiết bị IoT AZ3166. Bây giờ, hãy bắt đâù!

Lý lịch

Trong bài viết cuối cùng của chúng tôi, chúng tôi đã xem cách đọc nhiệt độ, độ ẩm, áp suất khí quyển từ các cảm biến MXChip AZ3166 và gửi chúng đến Trung tâm Azure IoT của chúng tôi. Trong bài viết này, chúng tôi sẽ thực hiện các nhiệm vụ sau.

  1. Tìm mức độ tiếng ồn bằng cách sử dụng lớp AudioClassV2
  2. Gửi các giá trị đến Trung tâm IoT của chúng tôi

Mã nguồn

Xin vui lòng chơi xung quanh với kho lưu trữ này .

Sử dụng mã

Khi bạn có không gian làm việc của riêng mình, chúng tôi có thể mở giải pháp trong VSCode và bắt đầu mã hóa.

chính

Đây là điểm khởi đầu giải pháp của chúng tôi - mỗi dự án phải có tệp phác thảo riêng. Thông thường, tập tin này sẽ chứa các chức năng  loop() và  setup().

Trước khi chúng tôi bắt đầu, hãy bao gồm các tệp tiêu đề chúng tôi sẽ sử dụng.

//Header files - Start//
#include "AZ3166WiFi.h"
#include "AzureIotHub.h"
#include "DevKitMQTTClient.h"
#include "config.h"
#include "utility.h"
#include "SystemTickCounter.h"
#include "RingBuffer.h"
#include "parson.h"
#include "EEPROMInterface.h"
#include "http_client.h"
#include <Arduino.h>
#include <stdio.h>
#include <math.h>
#include "OledDisplay.h"
#include "AudioClassV2.h"
#include "stm32412g_discovery_audio.h"
#include "RGB_LED.h"
#include <stdint.h>

#define MFCC_WRAPPER_DEFINED
#include "featurizer.h"
//Header files - End//
//**********************//


Bây giờ, chúng ta có thể khai báo hằng và biến của chúng ta.

//Constants and variables- Start//
enum AppState
{
APPSTATE_Init,
APPSTATE_Error,
APPSTATE_Recording
};

static AppState appstate;
// These numbers need to match the compiled ELL models.
const int SAMPLE_RATE = 16000;
const int SAMPLE_BIT_DEPTH = 16;
const int FEATURIZER_INPUT_SIZE = 512;
const int FRAME_RATE = 33; // assumes a "shift" of 512 and 512/16000 = 0.032ms per frame.
const int FEATURIZER_OUTPUT_SIZE = 80;
const int CLASSIFIER_OUTPUT_SIZE = 31;
const float THRESHOLD = 0.9;
static int scaled_input_buffer_pos = 0;
static float scaled_input_buffer[FEATURIZER_INPUT_SIZE]; // raw audio converted to float
const int MAX_FEATURE_BUFFERS = 10; // set to buffer up to 1 second of audio in circular buffer
static float featurizer_input_buffers[MAX_FEATURE_BUFFERS][FEATURIZER_INPUT_SIZE]; // input to featurizer
static int featurizer_input_buffer_read = -1; // next read pos
static int featurizer_input_buffer_write = 0; // next write pos
static int dropped_frames = 0;
static float featurizer_output_buffer[FEATURIZER_OUTPUT_SIZE]; // 40 channels
static float classifier_output_buffer[CLASSIFIER_OUTPUT_SIZE]; // 31 classes
static int raw_audio_count = 0;
static char raw_audio_buffer[AUDIO_CHUNK_SIZE];
static int prediction_count = 0;
static int last_prediction = 0;
static int last_confidence = 0; // as a percentage between 0 and 100.
static uint8_t maxGain = 0;
static uint8_t minGain = 0;
int decibels = 0;
float min_level = 100;
float max_level = 0;
RGB_LED rgbLed;
static bool hasWifi = false;
static bool messageSending = true;
static uint64_t send_interval_ms;
int messageCount = 0; // holds ID
bool messageReceived = false;
char device_id[6];
AudioClass &Audio = AudioClass::getInstance();
//Constants and variables- End//
//************************************//


Bây giờ, chúng ta có thể thêm mã cho cấu hình. Thông thường, bạn sẽ không phải chỉnh sửa bất kỳ mã nào trong phần này.

//Configuration functions - Start//
static void initWifi()
{
Screen.print(2, "Connecting...");

if (WiFi.begin() == WL_CONNECTED)
{
IPAddress ip = WiFi.localIP();
Screen.print(1, ip.get_address());
hasWifi = true;
Screen.print(2, "Running... \r\n");
}
else
{
hasWifi = false;
Screen.print(1, "No Wi-Fi\r\n ");
}
}

static void sendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result)
{
if (result == IOTHUB_CLIENT_CONFIRMATION_OK)
{
blinkSendConfirmation();
}
}

static void messageCallback(const char *payLoad, int size)
{
blinkLED();
Screen.print(1, payLoad, true);
}

static void deviceTwinCallback(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char *payLoad, int size)
{
char *temp = (char *)malloc(size + 1);
if (temp == NULL)
{
return;
}

memcpy(temp, payLoad, size);
temp[size] = '\0';
parseTwinMessage(updateState, temp);
free(temp);
}

static int deviceMethodCallback(const char *methodName, const unsigned char *payload, int size, unsigned char **response, int *response_size)
{
LogInfo("Try to invoke method %s", methodName);
const char *responseMessage = "\"Successfully invoke device method\"";
int result = 200;

if (strcmp(methodName, DIRECT_METHOD_NAME) == 0)
{
messageReceived = true;

char *temp = (char *)malloc(size + 1);
memcpy(temp, payload, size);
temp[size] = '\0';

if (temp != NULL)
{
Screen.init();
Screen.print(0, "NEW MESSAGE!");
Screen.print(2, temp);
}

free(temp);
}
else
{
LogInfo("No method %s found", methodName);
responseMessage = "\"No method found\"";
result = 404;
}

*response_size = strlen(responseMessage);
*response = (unsigned char *)malloc(*response_size);
strncpy((char *)(*response), responseMessage, *response_size);

return result;
}
//Configuration functions - End//
//***********************************//


Như tôi đã đề cập trước đó, mỗi tệp INO sẽ có  chức năng setup() và  loop()chức năng riêng  . Chúng ta có thể sửa đổi setup() chức năng của chúng tôi  như dưới đây.

void setup()
{
Screen.init();
Screen.print(0, "IoT Device Demo");
Screen.print(2, "Initializing...");

Screen.print(3, " > Serial");
Serial.begin(115200);

// Initialize the WiFi module
Screen.print(3, " > WiFi");
hasWifi = false;
initWifi();
if (!hasWifi)
{
return;
}

Screen.print(3, " > Sensors");
sensorInit();

Screen.print(3, " > IoT Hub");
DevKitMQTTClient_Init(true);
DevKitMQTTClient_SetOption(OPTION_MINI_SOLUTION_NAME, "mlIoTPlatformDevice");
DevKitMQTTClient_SetSendConfirmationCallback(sendConfirmationCallback);
DevKitMQTTClient_SetMessageCallback(messageCallback);
DevKitMQTTClient_SetDeviceTwinCallback(deviceTwinCallback);
DevKitMQTTClient_SetDeviceMethodCallback(deviceMethodCallback);

appstate = APPSTATE_Init;
Serial.begin(115200);

int filter_size = mfcc_GetInputSize(0);
if (filter_size != FEATURIZER_INPUT_SIZE)
{
Serial.printf("Featurizer input size %d is not equal to %d\n", filter_size, FEATURIZER_INPUT_SIZE);
show_error("Featurizer Error");
}

if (appstate != APPSTATE_Error)
{
::memset(featurizer_input_buffers[0], 0, FEATURIZER_INPUT_SIZE);

// give it a whirl !!
mfcc_Filter(nullptr, featurizer_input_buffers[0], featurizer_output_buffer);

// check audio gain and print the result.
uint32_t id = Audio.readRegister(nau88c10_CHIPID_ADDR);
if (id == NAU88C10_ID)
{
Serial.printf("Found audio device: NAU88C10\r\n");
}
else
{
Serial.printf("Found audio device: 0x%x\r\n", id);
}

// a default gain level of 4 seems to work pretty well.
start_recording();

Screen.clean();

Screen.print(0, "Listening...");
Screen.print(1, "A = min gain");
Screen.print(2, "B = max gain");

minGain = 0;
maxGain = 7;

set_gain();
display_gain();
}

send_interval_ms = SystemTickCounterRead();
}


Hàm  loop() sẽ được gọi mỗi năm giây, vì tôi đã đặt INTERVAL là 5000 mili giây.

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

// Interval time(ms) for sending message to IoT Hub
#define INTERVAL 5000

#define MESSAGE_MAX_LEN 256

#define TEMPERATURE_ALERT 30

#define DIRECT_METHOD_NAME "message"

// How many messages get sent to the hub before user has to press A to continue
#define MESSAGE_SEND_COUNT_LIMIT 350


Bây giờ, chúng ta có thể chỉnh sửa mã của  loop() hàm, như hiển thị bên dưới.

void loop()
{
if (hasWifi)
{
if (messageSending && (int)(SystemTickCounterRead() - send_interval_ms) >= getInterval())
{
if (appstate != APPSTATE_Error)
{
if (dropped_frames > 0)
{
Serial.printf("%d dropped frames\n", dropped_frames);
dropped_frames = 0;
}
// process all the buffered input frames
featurizer_input_buffer_read = next(featurizer_input_buffer_read);
decibels = get_prediction(featurizer_input_buffers[featurizer_input_buffer_read]);
}

// Send data
char messagePayload[MESSAGE_MAX_LEN];
float *newValues;

newValues = setMessage(messageCount++, messagePayload, decibels);

if (!messageReceived)
{
// Update display
char buff[128];
sprintf(buff, "ID: %s \r\n Temp:%s°C \r\n Humidity:%s%% \r\n Pres:%smb \r\n", device_id, f2s(*(newValues), 1), f2s(*(newValues + 1), 1), f2s(*(newValues + 2), 1));
Screen.print(buff);
}

EVENT_INSTANCE *message = DevKitMQTTClient_Event_Generate(messagePayload, MESSAGE);
DevKitMQTTClient_SendEventInstance(message);
send_interval_ms = SystemTickCounterRead();
}
else
{
DevKitMQTTClient_Check();
}
}

delay(10);
}


tiện ích

Như bạn có thể thấy, một khi chúng ta nhận được các giá trị từ hàm  get_prediction (), chúng ta sẽ chuyển các giá trị decibel cho setMessage() hàm của chúng ta  , mà chúng ta đã xác định trong tệp Utility.cpp. Bên trong  setMessage() hàm, chúng ta sẽ thêm giá trị decibel vào đối tượng JSON bằng cách sử dụng hàm   json_object_set_number ().

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.

#include "HTS221Sensor.h"
#include "AzureIotHub.h"
#include "Arduino.h"
#include "parson.h"
#include <assert.h>
#include "config.h"
#include "RGB_LED.h"
#include "Sensor.h"
#include "LIS2MDLSensor.h"

#define RGB_LED_BRIGHTNESS 32

DevI2C *i2c;
HTS221Sensor *ht_sensor;
LPS22HBSensor *pressureSensor;
LSM6DSLSensor *acc_gyro;
LIS2MDLSensor *lis2mdl;

int gAxes[3];
int mAxes[3];

static RGB_LED rgbLed;
static int interval = INTERVAL;

int getInterval()
{
return interval;
}

void blinkLED()
{
rgbLed.turnOff();
rgbLed.setColor(RGB_LED_BRIGHTNESS, 0, 0);
delay(500);
rgbLed.turnOff();
}

void blinkSendConfirmation()
{
rgbLed.turnOff();
rgbLed.setColor(0, 0, RGB_LED_BRIGHTNESS);
delay(500);
rgbLed.turnOff();
}

void parseTwinMessage(DEVICE_TWIN_UPDATE_STATE updateState, const char *message)
{
JSON_Value *root_value;
root_value = json_parse_string(message);
if (json_value_get_type(root_value) != JSONObject)
{
if (root_value != NULL)
{
json_value_free(root_value);
}
LogError("parse %s failed", message);
return;
}

JSON_Object *root_object = json_value_get_object(root_value);

double val = 0;
if (updateState == DEVICE_TWIN_UPDATE_COMPLETE)
{
JSON_Object *desired_object = json_object_get_object(root_object, "desired");
if (desired_object != NULL)
{
val = json_object_get_number(desired_object, "interval");
}
}
else
{
val = json_object_get_number(root_object, "interval");
}

if (val > 500)
{
interval = (int)val;
LogInfo(">>> Device twin updated: set interval to %d", interval);
}

json_value_free(root_value);
}

void sensorInit()
{
i2c = new DevI2C(D14, D15);

ht_sensor = new HTS221Sensor(*i2c);
ht_sensor->init(NULL);

pressureSensor = new LPS22HBSensor(*i2c);
pressureSensor -> init(NULL);

acc_gyro = new LSM6DSLSensor(*i2c, D4, D5);
acc_gyro->init(NULL);
acc_gyro->enableAccelerator();

lis2mdl = new LIS2MDLSensor(*i2c);
lis2mdl->init(NULL);
}

float readTemperature()
{
ht_sensor->reset();

float temperature = 0;
ht_sensor->getTemperature(&temperature);

return temperature;
}

float readHumidity()
{
ht_sensor->reset();

float humidity = 0;
ht_sensor->getHumidity(&humidity);

return humidity;
}

float readPressure()
{
float pressure = 0;
pressureSensor->getPressure(&pressure);

return pressure;
}

void setAccelAxes()
{
acc_gyro->getXAxes(gAxes);
}

void setMagAxes()
{
lis2mdl->getMAxes(mAxes);
}

float * setMessage(int messageId, char *payload, int decibels)
{
static float newValues[3];

JSON_Value *root_value = json_value_init_object();
JSON_Object *root_object = json_value_get_object(root_value);
char *serialized_string = NULL;

json_object_set_number(root_object, "messageId", messageId);
json_object_set_number(root_object, "decibels", decibels);

// Obtain values
float temperature = readTemperature();
float humidity = readHumidity();
float pressure = readPressure();
setAccelAxes();
setMagAxes();

// Set new values
newValues[0] = temperature;
newValues[1] = humidity;
newValues[2] = pressure;

bool temperatureAlert = false;

// Set temp json
json_object_set_number(root_object, "temperature", temperature);

// Set humidity json
json_object_set_number(root_object, "humidity", humidity);

// Set pressure json
json_object_set_number(root_object, "pressure", pressure);

// Set gyro axes
json_object_set_number(root_object, "accelX", gAxes[0]);
json_object_set_number(root_object, "accelY", gAxes[1]);
json_object_set_number(root_object, "accelZ", gAxes[2]);

// Set mag axes
json_object_set_number(root_object, "magX", mAxes[0]);
json_object_set_number(root_object, "magY", mAxes[1]);
json_object_set_number(root_object, "magZ", mAxes[2]);

serialized_string = json_serialize_to_string_pretty(root_value);

snprintf(payload, MESSAGE_MAX_LEN, "%s", serialized_string);
json_free_serialized_string(serialized_string);
json_value_free(root_value);

return newValues;
}


Bạn cũng nên thêm các tập tin featurizer.h và featurizer.s để làm cho nó hoạt động. Bạn có thể lấy các tệp đó từ kho lưu trữ mã nguồn được đề cập ở trên.

Biên dịch và tải lên thiết bị

Vì chúng tôi đã thực hiện các thay đổi cần thiết, đã đến lúc biên dịch giải pháp thiết bị và tải lên cùng thiết bị của chúng tôi. Nhấn F1 và chọn Bàn làm việc thiết bị Azure IoT: Biên dịch mã thiết bị. Nếu bạn từng gặp lỗi như lỗi lỗi: Utility.h: Không có tệp hoặc thư mục như vậy, thì xin vui lòng biên dịch lại mã thiết bị. Nếu bạn gặp phải bất kỳ lỗi không mong muốn nào, vui lòng xóa thư mục của .build và biên dịch lại.

Khi bạn nhận được thông báo dưới dạng [Hoàn thành] Đã hoàn tất xác minh phác thảo - Main.ino, trong cửa sổ đầu ra của bạn, bạn có thể tải giải pháp lên thiết bị của mình. Để làm như vậy, nhấn F1 một lần nữa và chọn Bàn làm việc của thiết bị Azure Azure IoT: Tải lên mã thiết bị. Hãy vui lòng đảm bảo rằng thiết bị đã được kết nối với máy của bạn. Nếu mọi thứ suôn sẻ, bạn sẽ nhận được một tin nhắn dưới dạng [[Xong] Đã tải lên bản phác thảo: Main.ino.

Hãy nhớ để xem kho GitHub cho mã đầy đủ.

Thiết bị gửi tin nhắn trên đám mây

Bây giờ, thiết bị của bạn sẽ gửi dữ liệu Decibels đến Azure IoT Hub. Chúng ta hãy xem điều đó trong cửa sổ Giám sát D2C.

Gửi dữ liệu MXChip lên đám mây


{
"messageId": 119,
"decibels": 94,
"temperature": 26.4,
"humidity": 34.400002,
"pressure": 994.585693,
"accelX": -9,
"accelY": -12,
"accelZ": 993,
"magX": -156,
"magY": -5,
"magZ": -253
}


Phần kết luận

Ồ Bây giờ, chúng tôi đã học được:

  • Cách phát hiện độ ồn trong MXChip
  • Cách sử dụng AudioClassV2
  • Cách gửi dữ liệu thiết bị đến Trung tâm Azure IoT

Vui lòng xem xét việc đọc các bài viết IoT của tôi ở đây để tiếp tục.

Hữu ích 2 Chia sẻ Viết bình luận 0
Đã xem 1593