After having used it for a while I have to say that Arduino IDE is nice to start a project, you don’t need to know much because it makes it easy to get the board and libraries into the project.
But apart from that it’s a major pain in the ass as it’s a very basic IDE.
I think they should have written a plugin for a major IDE like IntelliJ IDEA or VS Code to leverage the power of real IDEs.
So Arduino IDE has “sketches” with a .ino file extension.
They basically are written in an Arduino’s flavored C++ and contain 2 functions:
setup that is run when the microcontroller starts;
loop which is run after setup then again and again in a loop.
#include<Adafruit_HTU31D.h>#include<Adafruit_NeoPixel.h>#include<MQTTPubSubClient_Generic.h>#include<WiFiClientSecure.h>#include<Wire.h>#define NUMPIXELS 1 // Number of pixels present on the board.
#define SLEEP_TIME 60 // Number of seconds to sleep between 2 measures.
#define NB_RETRIES 10 // Number of retries to do something before giving up.
Adafruit_NeoPixelpixels(NUMPIXELS,PIN_NEOPIXEL,NEO_GRB+NEO_KHZ800);Adafruit_HTU31Dhtu=Adafruit_HTU31D();constcharHOSTNAME[]PROGMEM="drybox";// Host name of this microcontroller.
constcharWIFI_SSID[]PROGMEM="wifi-ssid";// Put here the SSID of your WiFi access point.
constcharWIFI_PASSWORD[]PROGMEM="wifi password";// Put here the password of your WiFi access point.
constcharMQTT_SERVER[]PROGMEM="mqtt.example.com";// Put here the address of your MQTT server.
constuint16_tMQTT_PORT=8883;// Put here the port on which the mqtt server is listening.
constcharMQTT_USERNAME[]PROGMEM="mqttloginfordrybox";// Put here the username to log into the MQTT server.
constcharMQTT_PASSWORD[]PROGMEM="mqtt password";// Put here the password to log into the MQTT server.
// Let's encrypt root certificate
constcharROOT_CA[]PROGMEM= \
"-----BEGIN CERTIFICATE-----\n" \
"MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow\n" \
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB\n" \
"AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC\n" \
"ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL\n" \
"wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D\n" \
"LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK\n" \
"4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5\n" \
"bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y\n" \
"sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ\n" \
"Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4\n" \
"FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc\n" \
"SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql\n" \
"PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND\n" \
"TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw\n" \
"SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1\n" \
"c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx\n" \
"+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB\n" \
"ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu\n" \
"b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E\n" \
"U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu\n" \
"MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC\n" \
"5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW\n" \
"9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG\n" \
"WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O\n" \
"he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC\n" \
"Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5\n" \
"-----END CERTIFICATE-----\n";constuint8_tTCA_ADDRESS=0x70;// Address of the multiplexer.
constuint8_tHTU_ADDRESS=0x40;// Address of the sensors.
// Colors
constuint32_tRED=0xFF0000;constuint32_tBLUE=0x0000FF;constuint32_tGREEN=0x00FF00;constuint32_tOFF=0x000000;WiFiClientSecuresecureClient;MQTTPubSubClientmqttClient;voidsetup(){// Nothing to do here.
}voidloop(){if(!startup(RED)){stop(BLUE);deep_sleep(OFF);}measure_and_publish(GREEN);stop(BLUE);deep_sleep(OFF);}//// STARTUP PROCESS ////
boolstartup(uint32_tcolor){startPixel();setLed(color);startSerial();boolsuccess=startWifi();if(success){success=startMqtt();}if(success){success=Wire.begin();}returnsuccess;}voidstartPixel(){pixels.begin();pixels.setBrightness(1);// Reduce brightness.
}voidsetLed(uint32_tcolor){pixels.fill(color);pixels.show();}voidstartSerial(){Serial.begin(115200);for(uint8_ti=0;i<NB_RETRIES;i++){if(Serial)break;delay(100);// Wait until serial port opens
}}boolstartWifi(){print("Attempting to connect to SSID: ");print(WIFI_SSID);print("…");WiFi.setHostname(HOSTNAME);WiFi.begin(WIFI_SSID,WIFI_PASSWORD);for(uint8_ti=0;i<NB_RETRIES;i++){if(WiFi.status()==WL_CONNECTED){println(" connected!");printWifiStatus();returntrue;}delay(1000);print(".");}println(" failed!");returnfalse;}voidprintWifiStatus(){print("SSID: ");println(WiFi.SSID());IPAddressip=WiFi.localIP();print("IP Address: ");println(ip);longrssi=WiFi.RSSI();print("Signal strength (RSSI):");print(rssi);println(" dBm");}boolstartMqtt(){secureClient.setCACert(ROOT_CA);secureClient.connect(MQTT_SERVER,MQTT_PORT);if(!secureClient.connected())returnfalse;mqttClient.begin(secureClient);print("Connecting to MQTT broker…");boolconnected=false;for(uint8_ti=0;i<NB_RETRIES;i++){if(mqttClient.connect(MQTT_USERNAME,MQTT_USERNAME,MQTT_PASSWORD)){println(" connected!");returntrue;}else{delay(1000);print(".");}}println(" failed!");returnfalse;}//// STOP PROCESS ////
voidstop(uint32_tcolor){setLed(color);if(Wire.available())Wire.end();if(mqttClient.isConnected())mqttClient.disconnect();if(secureClient.connected())secureClient.stop();if(WiFi.status()==WL_CONNECTED)WiFi.disconnect(true,true);}//// SLEEP PROCESS ////
voiddeep_sleep(uint32_tcolor){setLed(color);esp_sleep_enable_timer_wakeup(SLEEP_TIME*1000UL*1000UL);esp_deep_sleep_start();}//// MAIN PROCESS ////
voidmeasure_and_publish(uint32_tcolor){setLed(color);for(uint8_tport=0;port<8;port++){print("Port ");print(String(port,HEX));tcaSelectPort(TCA_ADDRESS,port);delay(100);// Check if there's an HTU sensor
if(!htu.begin(HTU_ADDRESS)){println("");continue;}print(" - Address "+String(HTU_ADDRESS,HEX));sensors_event_thumidity_event,temperature_event;htu.getEvent(&humidity_event,&temperature_event);print(" - "+String(humidity_event.relative_humidity,2)+" \% RH");print(" - "+String(temperature_event.temperature,2)+" °C");println("");StringhumidityUrl="gladys/master/device/mqtt:drybox"+String(port)+"/feature/mqtt:drybox"+String(port)+"humidity/state";StringtempratureUrl="gladys/master/device/mqtt:drybox"+String(port)+"/feature/mqtt:drybox"+String(port)+"temperature/state";mqttClient.publish(humidityUrl,String(humidity_event.relative_humidity,2));mqttClient.publish(tempratureUrl,String(temperature_event.temperature,2));}}voidtcaSelectPort(uint8_ttcaAddress,uint8_tport){if(port>7)return;Wire.beginTransmission(tcaAddress);Wire.write(1<<port);Wire.endTransmission();}//// UTILS ////
voidprint(constcharstr[]){if(Serial)Serial.print(str);}voidprintln(constcharstr[]){if(Serial)Serial.println(str);}voidprint(constfloatn){if(Serial)Serial.print(n);}voidprint(constString&s){if(Serial)Serial.print(s);}voidprintln(constString&s){if(Serial)Serial.println(s);}voidprintln(constPrintable&x){if(Serial)Serial.println(x);}//// END ////
The code is not great, it would require some refactoring and fixing some stuff, but as a first try it’s good enough.
Beginning is about declaring constants.
Note that I had to put Let’s Encrypt root certificate (line 25) so that the TLS connection to the MQTT server is accepted.
The idea here is that the microcontroller will connect to Wi-Fi and MQTT server, send the sensor values, disconnect, sleep for 1 minute, then do it all over again.
So in the loop function (line 74):
call the startup function that:
starts the NeoPixel LED on the board (line 102);
lights it up in red (line 107);
starts the serial port for debugging (line 112);
starts Wi-Fi (line 120);
starts MQTT (line 154);
starts I²C connection (line 97).
then call measure_and_publish function that:
lights the NeoPixel in green;
then for each of the 8 ports of the multiplexer (line 198) will:
select the port (line 225);
check if there’s an HTU sensor (line 205);
read humidity and temperature from the sensor (line 213);
send those values to the MQTT server (lines 220 and 221).
then call stop function that:
lights the NeoPixel in blue;
stops I²C connection (line 179);
disconnect from MQTT server (line 180);
disconnect the TLS connection (line 181);
disconnect the Wi-Fi (line 182).
then call deep_sleep function that:
turns off the NeoPixel;
tells the microcontroller to wake up in 1 minute (line 189);
puts the microcontroller in deep sleep (line 190).
So with the breadboard connected to the computer and one sensor, I can see the following logs:
Attempting to connect to SSID: wifi-ssid….. connected!
SSID: wifi-ssid
IP Address: 192.168.XXX.XXX
Signal strength (RSSI):-68.00 dBm
Connecting to MQTT broker… connected!
Port 0 - Address 40 - 47.99 % RH - 23.77 °C
Port 1
Port 2
Port 3
Port 4
Port 5
Port 6
Port 7
Comments Add one by sending me an email.