Let’s look at connecting an Arduino Yun to the cloud using Node-RED — the Bluemix Internet of Things (IoT) service.

Bluemix is IBM’s new cloud app dev environment. It includes point and click software-as-a-service installs such internet of things services, database storage and analytics. The good news is many Bluemix services are free to try out with generous quotas to allow real world examples to run — so a great way to get stuff up and running fast.

Node-RED allows creation of IoT services. Bluemix provides two main approaches to using Node-RED: quickstart which is a pre-defined service that will receive and graph sensor data; and custom full-featured app development. We’re going to use quickstart. For quickstart, there is standard sample code to connect an Ardunio Uno to the Internet and use the Uno to send temperature sensor readings to the cloud which are then available via a browser graphed on a timeline. The docs for that are here https://developer.ibm.com/iot/recipes/arduino-uno/.

Personally, I prefer the Ardunio Yun to the Uno when connecting projects to the Internet as the Yun doesn’t require any additional shields to connect; The Yun has wireless and ethernet pre-built on the board. Nice and simple. So I wanted to connect the Yun instead of an Uno to Node-RED.

However, there is no free lunch for the software developer here. The Yun’s internal structure is not the same as a typical Arduino such as the Uno. Simply running the sample Bluemix Node-RED Uno sketch on the Yun won’t work. A bit of hacking is required.

The Yun is really two devices in one — an Arduino microprocessor and a Linux computer — as opposed to the Uno which is just an Arduino. When a network shield is connected to an Uno, the microprocessor in the Uno — the Atmel 328P — has direct access to the network device that connects the Arduino to the Internet; In the Yun, the network hardware is NOT connected directly to the microprocessor. Instead, it is connected to the Linux half — an Atheros AR 9331 chip running a linux variant called Linino. So in the Yun, the Arduino half needs to communicate with the Linux half to access the networking device. This makes life a little more complicated for the software developer, but makes for a simpler setup with the form factor. Swings and roundabouts as we say in the country I was born in.

So the game plan is to construct a new Arduino sketch configured for the Yun.

Below is the new code you will need to get the Yun running. You will need to supply the mac address for your Yun in XXXXXXXXXXXX.

#include <YunClient.h>
#include <PubSubClient.h>
#include <Console.h>

YunClient yunClient;
PubSubClient mqtt("messaging.quickstart.internetofthings.ibmcloud.com", 1883, callback, yunClient);
unsigned long time;
float temp;
String pubString;
char pubChars[50];

void setup()
{
  Bridge.begin();
  Console.begin();
  mqtt.connect("d:quickstart:sensors:XXXXXXXXXXXX");
  setupADC();
}

void loop()
{
  if (millis() > (time + 5000))
  {
    time = millis();

    temp = getTemp();

    pubString = "{\"d\":{\"temp\":" + String(temp) + "}}";

    Console.println(pubString);

    pubString.toCharArray(pubChars, pubString.length() + 1);
    mqtt.publish("iot-2/evt/status/fmt/json", pubChars);
  }
  mqtt.loop();
}

void setupADC(){

  //ADC Multiplexer Selection Register
  ADMUX = 0;
  ADMUX |= (1 << REFS1);  //Internal 2.56V Voltage Reference with external capacitor on AREF pin
  ADMUX |= (1 << REFS0);  //Internal 2.56V Voltage Reference with external capacitor on AREF pin
  ADMUX |= (0 << MUX4);  //Temperature Sensor - 100111
  ADMUX |= (0 << MUX3);  //Temperature Sensor - 100111
  ADMUX |= (1 << MUX2);  //Temperature Sensor - 100111
  ADMUX |= (1 << MUX1);  //Temperature Sensor - 100111
  ADMUX |= (1 << MUX0);  //Temperature Sensor - 100111

  //ADC Control and Status Register A
  ADCSRA = 0;
  ADCSRA |= (1 << ADEN);  //Enable the ADC
  ADCSRA |= (1 << ADPS2);  //ADC Prescaler - 16 (16MHz -> 1MHz)

  //ADC Control and Status Register B
  ADCSRB = 0;
  ADCSRB |= (1 << MUX5);  //Temperature Sensor - 100111
}

double getTemp(){

  ADCSRA |= (1 << ADSC);  //Start temperature conversion
  while (bit_is_set(ADCSRA, ADSC));  //Wait for conversion to finish

  // We could report an precise number but accuracy is only +/-2% at best.
  // ADCW combines ADCL and ADCH into single 16 bit number
  //  double temperature = ADCW;
  //  return temperature - 273.4;

  // take an honest approach to reporting the temp as we know it */
  byte low  = ADCL;
  byte high = ADCH;
  int temperature = (high << 8) | low;  //Result is in kelvin
  return temperature - 273;
}

void callback(char* topic, byte* payload, unsigned int length) { }

To get this code to work, you’ll need an additional library for MQTT — the protocol Node-RED uses to communicate with IOT devices such as sensors and microprocessors. MQTT is a very lightweight protocol — compared to HTTP — and is a common choice for IoT comms. The Yun sketch uses the library written by Nick O’Leary to send the MQTT messages from an Arduino. First, clone Nick’s code from here using git

git clone https://github.com/knolleary/pubsubclient.git

then import the library into the Arduino IDE sketch environment (In the Arduino IDE Sketch/Import Library/Add Library… and chose the PubSubClient directory). Build the sketch, upload this to your Yun, and connect your Yun to the Internet either via the wireless or Ethernet using the standard Yun instructions.

Now logon to Bluemix (or sign up for the trial account if you haven’t already done so). From the dashboard view, follow these steps:

From the Dashboard, “ADD A SERVICE”
Select Internet of Things
  Launch the Service

Wait for the service to start.

If you now look at the console, the messages should be succeeding. This means that Node-RED is gathering sensor readings from your Yun. You may need to reboot the Yun.

Viewing the output

To view the real-time output we need a web browser pointed at a URL that links to data for our device. The mac address is used as the device identifier. So use the following URL with your 12 digit hex mac address for your device.

https://quickstart.internetofthings.ibmcloud.com/#/device/insert-your-12-hex-digit-mac-address-here/sensor/

How it Works

This code uses the quickstart approach to interface the Yun. This is the quickest way to get the device connected and does not require intricacies such as device registration. Quickstart runs a service that uses some pre-defined locations and naming conventions to do its magic.

The first thing is to connect to the default quickstart domain:

messaging.quickstart.internetofthings.ibmcloud.com

using the code:

PubSubClient mqtt("messaging.quickstart.internetofthings.ibmcloud.com", 1883, callback, yunClient);

You should be able to ping this domain from your network. Quickstart uses MQTT which sits on top of TCP-IP. The standard port is 1883. Next, we need to connect to the service using a clientId of the form:

d:<org-id>:<type-id>:<device-id>

Where the <org-id> is the special value quickstart and the <type-id> is sensors and the <device-id> is the mac address of the Yun. Note there is nothing particularly sacred about the <type-id> and the <device-id> except that the <device-id> needs to be unique across the entire quickstart service which is a multi-tenant service. The mac address is a globally unique way to ensure this – the network chip manufacturers have taken care of this detail for us.

mqtt.connect("d:quickstart:sensors:XXXXXXXXXXXX");

The code then loops every 5 seconds reading the internal temperature sensor and sending a fragment of JSON which contains the temp in Celsius. This is published to the topic

iot-2/evt/<event-type>/fmt/<format>

with QoS=0. This is accomplished using the following library call:

mqtt.publish("iot-2/evt/status/fmt/json", pubChars);

The pubChars use the following JSON format.

{"d":
     {"temp": 35.00}
}

The Node-RED quickstart service receives the sensor temp and auto-magically graphs status events on a timeline graph.

BTW the code to read the internal temperature sensor is another difference the Uno and the Yun. The Bluemix Uno code uses some bit twiddling to read the sensor. This involves setting some registers to configure the Atmel chip to use the inbuilt temperature sensor as the input to the analogue-to-digital convertor (ADC) and then triggering the ADC to convert the temperature sensor data. Unfortunately, the 328P in the Uno and the 32U4 in the Yun have a different setup. So we will need to change the temperature reading code. You can read about the details in a separate blog post.

Wrap

This covers the basics of the connecting a Yun to the cloud using Bluemix and Node-RED. There are still plenty more things to do here. For example, the system doesn’t yet record any data — it just sends it and graphs the most recent set of data. Also Node-RED allows for custom workflows and for callbacks to the Yun — for example if a particular state such as “core too hot” is reached, we could remotely shut down the Yun if we wished to. We are not limited to sending just temperature, we can send multiple sensor readings at the same time if we want; A really interesting use case is to include the temp reading in general projects and use the temp to check if the Arduino is running well. Hopefully, I’ll get to these ideas in another post.