Created
December 19, 2024 12:54
-
-
Save ksasao/81939ccb22cc38508fa38bda9e575c62 to your computer and use it in GitHub Desktop.
Azure IoT Hub に対して M5Atom で直接MQTT。SAS Token やルート証明書もハードコーディングしていますが一応通信はできます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "M5Atom.h" | |
#include <WiFi.h> | |
#include <PubSubClient.h> | |
#include <WiFiClientSecure.h> | |
#include "bme68xLibrary.h" | |
#include <math.h> | |
// home | |
const char* ssid = "your-ssid"; | |
const char* password = "your-password"; | |
const char* device_id = "your-device-id"; | |
// Azure IoT Hubの情報を設定します。 | |
// sas_token は VSCode の Azure IoT Hub プラグインでデバイスを右クリック>デバイスのSASトークンを生成 | |
// Expire には適切な値を設定します | |
const char* sas_token = "your-token"; // "SharedAccessSignature sr=で始まる文字列 | |
const char* mqtt_server = "your-server-***.azure-devices.net"; | |
PROGMEM const char root_ca[] = R"(-----BEGIN CERTIFICATE----- | |
ここにルート証明書の文字列を貼る | |
-----END CERTIFICATE----- | |
)"; | |
WiFiClientSecure espClient; | |
PubSubClient client(espClient); | |
// センサ接続先(M5Atom/Grove) | |
#define SDA_PIN 26 | |
#define SCL_PIN 32 | |
// センサパラメータ | |
#define NEW_GAS_MEAS (BME68X_GASM_VALID_MSK | BME68X_HEAT_STAB_MSK | BME68X_NEW_DATA_MSK) | |
#define MEAS_DUR 140 | |
// M5Stack ENV Pro SENSOR の I2Cアドレスは 0x77 (通常は0x76) | |
#define BME688_I2C_ADDR 0x77 | |
Bme68x bme; | |
float _gas[10]; | |
int skipCount = 2; // データが安定するまで待つ | |
String profileName; | |
void setup_wifi() { | |
delay(10); | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) { | |
Serial.print("*"); | |
delay(500); | |
} | |
Serial.println("WiFi Connected."); | |
} | |
void reconnect() { | |
Serial.print("MQTT Connecting: user="); | |
while (!client.connected()) { | |
String uname = "your-server-***.azure-devices.net/" + String(device_id) + "/?api-version=2021-04-12"; | |
Serial.println(uname); | |
if (client.connect(device_id, uname.c_str(), sas_token)) { | |
// 接続成功時の処理 | |
Serial.println("MQTT Connected."); | |
} else { | |
Serial.print("MQTT Connection failed, rc="); | |
Serial.println(client.state()); | |
delay(5000); | |
} | |
} | |
} | |
String setHeatPattern(int pattern){ | |
uint16_t temp[4][10] = { | |
{320,100,100,100,200, 200,200,320,320,320}, | |
{100,100,200,200,200, 200,320,320,320,320}, | |
{100,320,170,320,240, 240,240,320,320,320}, | |
{210,265,265,320,320, 265,210,190,300,230} | |
}; | |
uint16_t mul[4][10] = { | |
{5,2,10,30,5, 5,5,5,5,5}, | |
{2,41,2,14,14, 14,2,14,14,14}, | |
{42,2,42,2,2, 20,21,2,20,21}, | |
{5,2,10,2,10, 6,6,6,6,6}}; | |
String patternName[4] = {"HP-354","HP-301","HP-411","HP-501A"}; | |
/* ヒーターの温度(℃)の1サイクル分の温度変化。 200-400℃程度を指定。配列の長さは最大10。*/ | |
/* ヒーターの温度を保持する時間の割合。数値×MEAS_DUR(ms)保持される。保持時間は1~4032ms。指定温度に達するまで20-30ms程度が必要。 */ | |
/* 各測定(温度,湿度,気圧,抵抗値)の繰り返し間隔(MEAS_DUR)から測定にかかる正味時間を引いたものをsharedHeatrDurに設定 */ | |
uint16_t sharedHeatrDur = MEAS_DUR - (bme.getMeasDur(BME68X_PARALLEL_MODE) / 1000); | |
int p = pattern % 4; | |
skipCount = 2; | |
bme.setTPH(); | |
bme.setHeaterProf(temp[p], mul[p], sharedHeatrDur, 10); | |
bme.setOpMode(BME68X_PARALLEL_MODE); | |
return patternName[p]; | |
} | |
void setup() { | |
M5.begin(true, false, true); | |
delay(50); | |
M5.dis.drawpix(0, 0xff3030); // 赤 | |
delay(5000); | |
M5.dis.drawpix(0, 0xff3030); // 赤 | |
// WiFi/MQTT接続 | |
setup_wifi(); | |
client.setServer(mqtt_server, 8883); | |
espClient.setCACert(root_ca); | |
M5.dis.drawpix(0, 0xffff30); // 橙 | |
// 匂いセンサ接続 | |
Wire.begin(SDA_PIN, SCL_PIN); | |
bme.begin(BME688_I2C_ADDR, Wire); | |
if(bme.checkStatus()) | |
{ | |
if (bme.checkStatus() == BME68X_ERROR) | |
{ | |
Serial.println("Sensor error:" + bme.statusString()); | |
return; | |
} | |
else if (bme.checkStatus() == BME68X_WARNING) | |
{ | |
Serial.println("Sensor Warning:" + bme.statusString()); | |
} | |
} | |
// Set the default configuration for temperature, pressure and humidity | |
Serial.println("BME688 initialized."); | |
M5.dis.drawpix(0, 0x30ff30); // 緑 | |
profileName = setHeatPattern(3); | |
for(int i=0;i<10;i++){ | |
_gas[i] = 10; | |
} | |
delay(1000); | |
} | |
int count = 0; | |
int patternIndex = 0; | |
int patternCount = 0; | |
char _text[256]; // ペイロード構築用 | |
void loop() { | |
if (!client.connected()) { | |
reconnect(); | |
} | |
client.loop(); | |
bme68xData data; | |
uint8_t nFieldsLeft = 0; | |
/* data being fetched for every 140ms */ | |
delay(MEAS_DUR); | |
if (bme.fetchData()) | |
{ | |
do | |
{ | |
nFieldsLeft = bme.getData(data); | |
if (data.status == NEW_GAS_MEAS) | |
{ | |
float current = log(data.gas_resistance); | |
int index = data.gas_index; | |
_gas[index] = current; | |
if(skipCount == 0 && index == 9){ | |
sprintf(_text,"\"Pattern\":\"%s\",\"Temperature\":%.2f,\"Humidity\":%.2f,\"Pressure\":%.2f,\"Value\":[%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f]", | |
profileName.c_str(),data.temperature,data.humidity,data.pressure,_gas[0],_gas[1],_gas[2],_gas[3],_gas[4],_gas[5],_gas[6],_gas[7],_gas[8],_gas[9]); | |
// MQTTTで出力 | |
String path = "devices/" + String(device_id) + "/messages/events/"; | |
String payload = "{\"device_id\":\""+ String(device_id) + "\"," + String(_text)+ "}"; | |
client.publish(path.c_str(), payload.c_str()); | |
Serial.println(payload.c_str()); | |
} | |
if(index == 9 && skipCount > 0){ | |
skipCount--; | |
Serial.println("Waiting.."); | |
M5.dis.drawpix(0, 0x000000); // 消灯 | |
} | |
} | |
} while (nFieldsLeft); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment