Skip to content

Instantly share code, notes, and snippets.

@ksasao
Created December 19, 2024 12:54
Show Gist options
  • Save ksasao/81939ccb22cc38508fa38bda9e575c62 to your computer and use it in GitHub Desktop.
Save ksasao/81939ccb22cc38508fa38bda9e575c62 to your computer and use it in GitHub Desktop.
Azure IoT Hub に対して M5Atom で直接MQTT。SAS Token やルート証明書もハードコーディングしていますが一応通信はできます。
#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