This tutorial presents how Beebotte can be used to monitor Carbon-monoxide
levels in the air. We will use Arduino Uno
board to report data to Beebotte and an MQ-7
sensor to detect CO gas levels.
This tutorial assumes that you have successfully registered
to Beebotte and obtained your API and Secret keys
.
Tutorial contents:
We need the following hardware to complete this tutorial:
We will use the Arduino IDE to write our code, compile it and upload it to the board. We will use community provided Arduino libraries for MQTT connectivity and JSON parsing/decoding:
Open your Arduino IDE, click on Sketch
tab and go to Include Library
to install PubSubClient and ArduinoJson libraries.
In this tutorial, we will use a ready made MQ-7
sensor module. If you wish to build your own module, you can buy the required parts and solder them to a PCB (this is beyond the scope of this tutorial).
The MQ-7
module has 4 pins:
In this example, we will send AOUT and DOUT values to Beebotte to be able to monitor CO levels from anywhere using a Dashboard.
Follow the wiring diagram below to setup your hardware:
In your account home page, click on Create New
and follow the instructions to create your channel.
For the purpose of this tutorial, we will create a channel named Arduino
and add a resource co
with type number
and another resource overLimit
with type boolean
.
MQTT
endpoint to send sensor data to the created channel. We need to specify the channel token, and to indicate the names of the channel and resources.Include dependencies:
#include <SPI.h> #include <Ethernet.h> #include <PubSubClient.h> #include <ArduinoJson.h>
In the code snippet below, we will initialize constants, definitions, MQTT client and all the pin connections of the sensor and the LED. Two variables, overLimit and rawValue, are also declared. These will be used to store the values of the analog pin AOUT and digital pin DOUT.
#define bbt "mqtt.beebotte.com" // Domain name of Beebotte MQTT service #define Token "token:xxxxxxxxxxxxx" // Set your channel token here #define Channel "Arduino" // Replace with your channel name #define CoResource "co" //Replace with your resource name #define OverLimitResource "overLimit" //Replace with your resource name #define Write true EthernetClient ethClient; PubSubClient client(ethClient); byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; long lastReconnectAttempt = 0; // interval for sending CO readings to Beebotte const long interval = 10000; // 10 seconds // last time CO sensor data were sent to Beebotte unsigned long lastReadingMillis = 0; const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; char id[17]; // Set the static IP address to use if the DHCP fails to assign // Feel free to change this according to your network settings IPAddress ip(192, 168, 1, 50); IPAddress gateway(192,168,1,1); IPAddress subnet(255,255,255,0); const int aOutPin=0; //the AOUT pin connected to analog pin A0 of Arduino const int dOutPin=8; //the DOUT pin connected to digital pin D8 of Arduino const int ledPin=13; //the anode of the LED connected to digital pin D13 int rawValue; int overLimit;
In the Sketch setup
function we will open serial communications for debugging and initialize the Ethernet connection.
void setup() { Serial.begin(9600); //Sets the data rate for for serial data transmission pinMode(dOutPin, INPUT); //sets the pin as an input to the arduino pinMode(ledPin, OUTPUT); //sets the pin as an output of the Arduino client.setServer(BBT, 1883); // Open serial communications and wait for port to open: while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // try to configure using IP address instead of DHCP: Ethernet.begin(mac, ip, gateway, subnet); } // give the Ethernet shield a second to initialize: delay(1000); Serial.println("connecting..."); lastReconnectAttempt = 0; }
Reading sensor data and publishing data to Beebotte
void readSensorData() { rawValue= analogRead(aOutPin); //reads CO sensor's AOUT pin overLimit = digitalRead(dOutPin); //reads CO sensor's DOUT pin if (!isnan(rawValue )) { publish(CoResource, rawValue, Write); } if (overLimit== HIGH){ digitalWrite(ledPin, HIGH);//if limit has been reached, LED turns on publish(OverLimitResource, true, Write); } else { digitalWrite(ledPin, LOW);//if threshold not reached, LED remains off publish(OverLimitResource, false, Write); } } // publishes data to the specified resource void publish(const char* resource, float data, bool persist) { StaticJsonBuffer<128> jsonOutBuffer; JsonObject& root = jsonOutBuffer.createObject(); root["channel"] = Channel; root["resource"] = resource; if (persist) { root["write"] = true; } root["data"] = data; // Now print the JSON into a char buffer char buffer[128]; root.printTo(buffer, sizeof(buffer)); // Create the topic to publish to char topic[64]; sprintf(topic, "%s/%s", Channel, resource); // Now publish the char buffer to Beebotte client.publish(topic, buffer); }
A utility function to generate random ID for the MQTT connection
const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; char id[17]; const char * generateID() { randomSeed(analogRead(0)); int i = 0; for(i = 0; i < sizeof(id) - 1; i++) { id[i] = chars[random(sizeof(chars))]; } id[sizeof(id) -1] = '\0'; return id; }
The Sketch's loop
and MQTT reconnect function in case connection to Beebotte is lost:
// reconnects to Beebotte MQTT server boolean reconnect() { if (client.connect(generateID(), TOKEN, "")) { Serial.println("Connected to Beebotte MQTT"); } return client.connected(); } void loop() { if (!client.connected()) { long now = millis(); if (now - lastReconnectAttempt > 5000) { lastReconnectAttempt = now; // Attempt to reconnect if (reconnect()) { lastReconnectAttempt = 0; } } } else { // Client connected // read sensor data every interval // and publish values to Beebotte unsigned long currentMillis = millis(); if (currentMillis - lastReadingMillis >= interval) { // save the last time we read the sensor data lastReadingMillis = currentMillis; readSensorData(); } client.loop(); } }
The complete code along with other Arduino examples can be accessed on Github.
In your account page, go to My Dashboards
and click Create Dashboard
; enter a friendly name and a short description for your dashboard then add 2 Attribute
Widgets and 2 Timeline
widgets. For every widget, indicate the channel and resource where data will be read from. Voilà.
In this tutorial we learned how to connect a CO sensor to Arduino to read gas levels and send them to Beebotte using MQTT. We have also learned how to create a channel to store the data received from Arduino and a dashboard to display that data.