Close

Bridging Arduino to MQTT using NodeJS

A project log for analog.io - A full stack IoT platform

A full stack project dedicated to easily collecting, analyzing and sharing IoT sensor data.

Luke Beno 09/06/2015 at 12:470 Comments

Here's a quick update and a neat little trick for quickly prototyping internet connected devices. If you are anything like me, your typical development process is to write your code using something like the Arduino IDE and then use the serial console to debug your code.

Let's say that your code is reading a ds18b20 temperature sensor and you are simply dumping this value out the serial port of your dev kit. With about 25 lines of NodeJS, this data could be whisked off to the wonderful land of MQTT.

Here's how it is done, first I have some hardware reading a ds18b20 and sending the temperature to the serial console:

#include <OneWire.h>
OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
byte ow_addr[8] = {0x28,0x01,0xB6,0x88,0x06,0x00,0x00,0xEE};

byte data[12];  
byte present = 0;
int i;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop()
{
  radio.print("{\"temp\":");
  radio.print(getTemp(ow_addr));
  radio.print("}");
  sleepSeconds(5);
}

float getTemp(byte* addr) {
  // put your main code here, to run repeatedly:
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(50);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
  
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }
  
  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  byte cfg = (data[4] & 0x60);
  // at lower res, the low bits are undefined, so let's zero them
  if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
  else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
  else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
  //// default is 12 bit resolution, 750 ms conversion time
  return ((float)raw / 16.0) * 1.8 + 32.0;
}

Compile and program this into the device and we can see messages start coming in. All that is left is to close the terminal from the IDE and run this NodeJS from the terminal:

var serialport = require("serialport"); 
var mqtt = require('mqtt')

var SerialPort = serialport.SerialPort; 

var keychain = {};

topic='input/<public_key>/<private_key>';

var serialPort = new SerialPort("/dev/tty.uart-AEFF467AF9C4494B", {
  baudrate: 9600,
  parser: serialport.parsers.readline("\n")
});
 
client = mqtt.createClient(1883, 'test.mosquitto.org'); 

serialPort.on("open", function () {
  serialPort.on('data', function(data) {
    console.log(data);
    client.publish(topic, data);
  });
});
By the way, this code requires 'serialport' and 'mutt' libs loaded from npm, you can do this by typing the following commands into the terminal:
$ npm install serialport
$ npm install mqtt
Enjoy, add comments if you have any questions. Skulls are always very appreciated :)

Discussions