I wanted to test connecting the Nano RP2040 Connect to my RPi4 MQTT server by publishing temperature and humidity data from a BME280 sensor. I figured that this should be fairly easy since I've already used the BME280 with another RP2040 board - the SparkFun Pro Micro RP2040 and I've used my MQTT server with multiple ESP32 devices.
Of course, the devil is in the details...
I stayed within the confines of the Arduino IDE hoping that it would makes things simpler, and it did, but new board variants are coming out an incredible pace so things are still a mess.
The Nano RP2040 Connect is supported as arduino mbed_nano hardware and the Pro Micro RP2040 is supported as rp2040 hardware using the board library contributed by Earle Philhower.
The first problem I ran into was with the Wire library. I was using functions to set the I2C pins that are not included in the mbed Wire library (Wire.setSDA(I2C_SDA), Wire.setSCL(I2C_SCL)). I had used these functions to designate the QWIIC connector pins on the Pro Micro RP2040. In mbed you need to instead do that as part of the interface declaration MbedI2C I2C(I2C_SDA, I2C_SCL). Since I'm not using a connector this time, I just used the default I2C pins (i.e. removed the function calls).
The second problem that I ran into is that the Pro Micro uses the WiFi library and the Nano RP2040 Connect uses the WiFiNINA library. I was setting up a static IP addr using the WiFi.config function and the WiFiNINA version of that function uses a different parameter order. And the WiFiNINA function is also a Void rather than Bool (i.e. doesn't return a value).
For the WiFi library the function is WiFi.config(ip, gateway, subnet, dns).
For WiFiNINA library the function is WiFi.config(ip, dns, gateway, subnet).
The final problem was that I am using the dtostrf function to convert integers to strings for MQTT and I couldn't figure out what to include for mbed (it is supposed to be "mbed/dtostrf.h"). After struggling for a while, I took the easy way out and just added the function code to the sketch.
After fixing all that, it is working...
Nano_RP2040_Connct_BME280_MQTT.ino
/* * Created on: 06.11.2021 * * the arduino_secrets.h file: * #define SECRET_SSID "" // network name * #define SECRET_PASS "" // network password * #define SECRET_MQTT_USER "public" // broker username * #define SECRET_MQTT_PASS "public" // broker password * * */ #include <Arduino.h> #include <stdio.h> //#include "mbed/dtostrf.h" #include <WiFiNINA.h> #include <PubSubClient.h> #include "arduino_secrets.h" #include <Wire.h> #include "Adafruit_Sensor.h" #include <Adafruit_BME280.h> #define USE_SERIAL Serial // LED Pin const int ledPin = LED_BUILTIN; // Add your MQTT Broker IP address, example: //const char* mqtt_server = "192.168.1.144"; const char* mqtt_server = "10.0.0.234"; // Set your Static IP address IPAddress local_IP(10, 0, 0, 207); // Set your Gateway IP address IPAddress gateway(10, 0, 0, 1); IPAddress subnet(255, 255, 255, 0); IPAddress primaryDNS(8, 8, 8, 8); //optional IPAddress secondaryDNS(8, 8, 4, 4); //optional WiFiClient rp2040Client; PubSubClient client(rp2040Client); long lastMsg = 0; char msg[50]; int value = 0; Adafruit_BME280 bme; float tempBME = 0.0; float humBME = 0.0; char *dtostrf (double val, signed char width, unsigned char prec, char *sout) { char fmt[20]; sprintf(fmt, "%%%d.%df", width, prec); sprintf(sout, fmt, val); return sout; } void setup() { USE_SERIAL.begin(115200); // while(!USE_SERIAL); delay(500); USE_SERIAL.println(); USE_SERIAL.println(); USE_SERIAL.println(); if (!bme.begin(0x76)){ USE_SERIAL.println("Could not find a valid BME280 sensor, check wiring!"); while (1); } setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); } void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(SECRET_SSID); WiFi.config(local_IP); WiFi.begin(SECRET_SSID, SECRET_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* message, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)message[i]); messageTemp += (char)message[i]; } Serial.println(); // Feel free to add more if statements to control more GPIOs with MQTT // If a message is received on the topic floor2/output, you check if the message is either "on" or "off". // Changes the output state according to the message if (String(topic) == "rp2040connect/output") { Serial.print("Changing output to "); if(messageTemp == "on"){ Serial.println("on"); digitalWrite(ledPin, HIGH); } else if(messageTemp == "off"){ Serial.println("off"); digitalWrite(ledPin, LOW); } } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("RP2040Client")) { Serial.println("connected"); // Subscribe client.subscribe("rp2040connect/output"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); long now = millis(); if (now - lastMsg > 30000) { lastMsg = now; tempBME = bme.readTemperature()*1.8 + 32 - 5; humBME = bme.readHumidity() + 7; // Convert the value to a char array char tempString[8]; dtostrf(tempBME, 1, 2, tempString); Serial.print("Temperature: "); Serial.println(tempString); client.publish("rp2040connect/temperature", tempString); // Convert the value to a char array char humString[8]; dtostrf(humBME, 1, 2, humString); Serial.print("Humidity: "); Serial.println(humString); client.publish("rp2040connect/humidity", humString); } delay(1000); }
Top Comments