Arduino can be equipped with various sensors like temperature and humidity and you will have a need to send these sensor values over MQTT.
In this tutorial we will look at sending and receiving integer and float data over MQTT using string data and buffer data.
Sending string Data
Sending the data using strings is probably the most common and the easiest.
To send integer data as a string we use the sprintf() function to do the conversion.
As an example to send a temp reading er would use the following code:
int temp=20; boolean rc; char msg_out[20]; sprintf(msg_out, "%d",temp); rc = mqttClient.publish("test/temp", msg_out );
sprintf converts the integer and places it in the array msg_out which we pass to the publish method.
To send a float we would logically use the sprinf function but if we try we get a ? as it doesn’t support floats in Arduino. If you want to understand more about this then see this article.
The solution is to use the dtostrf() function The code below shows how to send a float humidity reading
float humidity =60.11; dtostrf(humidity,2,2,msg_out); Serial.println(humidity); rc = mqttClient.publish("test/humidity", msg_out );
I’ve included the line:
Serial.println(humidity);
which works OK as pointed out in the referenced article.
Also in the dtostrf() function the first 2 is the digits before the decimal point and the second the digits after the decimal point.
Sending Data in Buffers
Program Logic controllers typically send data in binary buffers. So, for example the number 23567 is sent as a 16nit binary number (2 bytes) rather than 5 characters (5 bytes).
Although it saves on network data it is a little trickier to do.
On Arduino an integer is 16 bits (2 bytes) and a float is 32 bits (4 bytes) and the encoding in memory is little Endiness.
Using our temperature example to send as a 2 byte integer we use the following code.
int temp=20; boolean rc; byte buf[2]; buf[0] = (temp >> 8) & 0xFF; buf[1] = temp & 0xFF; rc = mqttClient.publish("test/buffer_int",buf,2 );
Notice the 2 at the end of the publish. As we are sending a byte buffer we need to tell the publish how many bytes there are.
To send a float e.g our humidity reading we use the following code.
//taken from stackoverflow void float2Bytes(float val,byte* bytes_array){ // Create union of shared memory space union { float float_variable; byte temp_array[4]; } u; // Overite bytes of union with float variable u.float_variable = val; // Assign bytes to input array memcpy(bytes_array, u.temp_array, 4); } float humidity =60.11; boolean rc; byte bytes[4]; float2Bytes(f,&bytes[0]); rc = mqttClient.publish("test/buffer_float",bytes,4 );
In this case it is more complex and requires a separate function. Again notice the 4 at the end of the publish as we are sending 4 bytes.
Note: I do not take credit for the code as it was gleaned from answers to questions on stackoverflow.
With the float The Endiness is the Endiness of the stored data which appears to be little. I discovered this as I create a node-red flow to decode the buffer and had to use Little. The code for the function node is shown below:
let buf=msg.payload; msg.payload=buf.readFloatLE(); return msg;
Demo code. The download is an Arduino sketch that illustrate the above.
Demo Sketch
Sends integer,long integer,float and double as strings and
sends integer and float as buffer subscribe to test/# to view.
The results are shown in the screen shot below which is obtained by using the mosquitto_sub tool to subscribe to the topic.
You should notice that when using buffers the displayed message looks like gibberish as it is not text data and so cannot be displayed correctly.
Receiving integers and Floats
In addition to receiving text data in Arduino we need to be able to receive both integers and floats and use them.
Again as in the sending tutorial the integers/floats may be represented as strings or as buffer data.
So we will need to decode the received data and store it in a variable
Receiving integers and Floats as Strings
In this case our integer arrives as a series of numbers e.g 200 and then needs to be converted into an Integer.
To convert a string number into Integer we use the built in function atoi(). The code is simply
int num =atoi(number_as_string)
Example:
int num =atoi(200);
To convert a string float into a float that we can use in Arduino we use the atof() function.
float num =atof(float_as_string)
Example:
float num =atof(260.21);
The demo sketch below accepts humidity(float) and temperature(integer) readings and multiplies them together and displays the result.
You send data using the mosquitto_pub tool on topics test/demo/temp and test/demo/humidity.
Below is a screen shot of the result.
Receiving Integers and Floats as Buffers
To convert a 2 byte integer buffer into a 16 bit integer we use:
temp=(payload[0] << 8) + payload[1];
where payload is a byte buffer.
To convert a4 byte float buffer into a 32 bit float we use a function :
float bytesToFloat( unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) { float output; //may need to reverse these *((unsigned char*)(&output) + 3) = b3; *((unsigned char*)(&output) + 2) = b2; *((unsigned char*)(&output) + 1) = b1; *((unsigned char*)(&output) + 0) = b0; return output; } and we call it passing in the bytes from the payload
hum = bytesToFloat(payload[0],payload[1],payload[2],payload[3]);
Where the payload contains the input bytes.
Depending on the Endiness we may need to change the order and use:
hum = bytesToFloat(payload[3],payload[2],payload[1],payload[0]);
Demo Sketch
The download contains two sketches
1-Accepts float and int as text string on topics test/demo/humidity and test/demo/temp and multiples the values and displays the result to prove they are numbers.
2- Accepts float and int as buffer on topics test/demo/humidity and test/demo/temp and multiples the values and displays the result to prove they are numbers.
Related Tutorials and resources.
- Beginners Guide to Data and Character Encoding
- Arduino -Sending and Receiving JSON Data over MQTT
- Using the Arduino PubSub MQTT Client
- Python Paho MQTT Client Send and Receive Integers and Floats
Dear Steve,
Thank you for the Dmo Sketch!
It’s help me a lot!
Best regards,
Alex
Alex
Glad it helped.
Rgds
Steve