Reid Carlberg

Connected Devices, salesforce.com & Other Adventures

Tag Archives: raspberry pi

Connect I2C Devices Using Cat5 and RJ45 Ports

1

The other day I shared my approach to reading data off a couple Arduinos with a Raspberry Pi using I2C and Node.js. Works great, but the wiring was ugly and brittle.2arduinos1pi

Mess or not, the wiring did teach me two things: I2C works as long as there is conductivity and yes you can power a couple of Arduinos from the RPi. I2C doesn’t require a particular wiring sequence or whole bunch of cables extending from a central point to a single device, so when I decided to beef it up a bit, I started to imagine a way of connecting devices over a small distance. I was hopeful it would be easy and not require 100% custom wiring. The requirements boiled down to something like this:

raspberry pi arduino i2c

I decided to look for a solution built around Cat5 cable — it’s cheap, has great connectors and I’ve worked with it a fair amount. I found it at Microcenter.  I’m using a couple of el cheapo cable splitters and an RJ45 F-F joiner, for most of the connection, and it works great. I still need to solder 1/2 a Cat5 cable for the Raspberry Pi and another 1/2 for each device, but I can now put the Arduinos (somewhat) arbitrarily far away from the RPi node and add more until my power runs out.

raspberry-pi-arduino-i2c-cables

Still not ideal, but like I said it works great.  Although relatively inexpensive, each splitter is about $10, and I could do without stripping the Cat5 wires and soldering them to pins.  Next up I think I’ll add a couple of RJ45 ports to a proto shield, and connect that directly to each Arduino.  I’ll net a little more soldering, but it will be easier soldering so should be faster.

Here’s what the current system actually looks like in my attic.  Note that the Arduino and RPi are far enough away that it’s impractical to photograph them together.

raspberry-pi-i2c-cat5-example

Questions I’ve pondered:

Why am I doing this instead of just getting an Arduino with an Ethernet shield?  I’m trying to solve two problems, communication and power.  if I go with the Ethernet shield, I’m in it for $60 each if I include a power over ethernet (POE) module, which is a lot.  It solves the power problem and the connectivity problem, but I still have to wire ethernet.

Why don’t I just go wireless? Well, I could.  In fact, I have a bunch of XBees sitting around from Dreamforce 13 that I could harness.  However, I’d still have to get power to each one of these devices, so I’ve only solved one problem.

How will I scale this beyond my attic? I’ll probably need to scale this to the other floors of my house to get the data I want.  I suspect the easiest way to scale it will be to add a nearly identical system on each floor.  Otherwise I’ll have to deal with stringing wires, and I hate stringing wires.

Read Data from Multiple Arduinos with a Raspberry Pi B+ using I2C and Node.js

3

Last year I wrote about controlling an Arduino using a Raspberry Pi and I2C.  I2C being, of course, a 30+ year old protocol that everybody and their brother still supports.  I tried this again, for reasons I’ll state in the very last sentence of this blog, and it failed. Significantly.

Why? Well, turns out I had forgotten the cardinal rule of I2C.

Link your devices, master and slave, sender and receiver, using a shared ground wire.  Otherwise, you’re going to have a bad time.  Really.

Mmm’k, with that out of the way:

1) The Adafruit tutorial is still the best one I’ve found for enabling I2C on your Raspberry Pi. However, raspi-config now helps you do this under advanced options.  I used the advanced options and then doubled checked everything Adafruit told me to do. (Rule #1: do what Adafruit says.)

2) Add your user to the i2c group.  The command is “sudo adduser pi i2c“. This will make your life easier.  Thank you ABC Electronics.

3) Configure your Arduinos as slave senders.  The example code that comes with the Wire library in the Arduino IDE is perfect for this. Wire ground to ground, SDA to SDA and SCL to SCL. Once you add power to the Arduino, install the slave sender example code and boot your pi, you should be able to see your I2C device using the i2cdetect -y 1 command.  Mine with two Arduinos looks like this:

i2cdetect

My code looks a little different than the slave sender sample, since I have a photocell and a temperature probe on each one.  There’s a fair amount of boiler plate code to read those values, but the fundamental structure is the same as the sample code: configure an I2C address, wait for a request, send a fixed length string in response.

#include <Wire.h> 
#include <OneWire>

// Define analog pin
int sensorPin = 0;
int lightLevel = 0;

int DS18S20_Pin = 2; 
OneWire ds(DS18S20_Pin);  // on digital pin 2

String deviceId = "D001";
int wireId = 4;

String lightLevelString = "";
String output;
int m;
char c[5];
char d[10];

// Setup
void setup() {
 Wire.begin(wireId);
 Wire.onRequest(requestEvent);
 // Init serial
 Serial.begin(9600);
}
 
// Main loop
void loop() {
 
 // Get temperature
 int sensorValue = analogRead(sensorPin);
 
 lightLevel = map(sensorValue, 10, 1000, 1, 100);
 m = sprintf(c, "%03d", lightLevel);
 
  float temperature = getTemp();
  
  dtostrf(temperature, 6, 2, d);

  output = deviceId;
  output.concat("|");
  output.concat(String(c));
  output.concat("|");
  output.concat(String(d));
  
  Serial.println(output);
  
 
 delay(1000);
}

void requestEvent() {
  
  char newOut[16];
  output.toCharArray(newOut, 16);
  
  Wire.write(newOut);
}

float getTemp(){
  //returns the temperature from one DS18S20 in DEG Celsius

  byte data[12];
  byte addr[8];

  if ( !ds.search(addr)) {
      //no more sensors on chain, reset search
      ds.reset_search();
      return -1000;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return -1000;
  }

  if ( addr[0] != 0x10 && addr[0] != 0x28) {
      Serial.print("Device is not recognized");
      return -1000;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end

  byte present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE); // Read Scratchpad

  
  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }
  
  ds.reset_search();
  
  byte MSB = data[1];
  byte LSB = data[0];

  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;
  
  return TemperatureSum;
  
}

4) Install node.js on your rpi, and then use npm to install the i2c library.  You should now be able to read your Arduino via Node.js.  My code declares two devices, both with addresses matching the settings in my Arduino code, and it looks like this:

var i2c = require('i2c');
var address = 0x18;

var device1 = new i2c(address, {device: '/dev/i2c-1'});
device1.setAddress(0x4);

var device2 = new i2c(address, {device: '/dev/i2c-1'});
device2.setAddress(0x6);

var devices = [ device1, device2 ];

function handleTimeout() {
	  setTimeout(function() { handleRead(); }, 1000 );
}

function handleRead() {
  	for (i = 0; i < devices.length; i++) {
		    devices[i].readBytes(null,15, function(err,res) {
			      console.log(res.toString('ascii'));
  		  });
  	}
	  handleTimeout();
}

handleTimeout();

The output is pretty simple — it just prints the data it receives, like so:

i2c-dataexample

My final setup consists of two Arduinos (D001 and D002 in the data) connected to one Raspberry Pi B+.  You’ll notice that the RPi is powering both Arduinos.  (Red is power. Back is ground. Blue is SCL. Yellow is SDA.)  Everything is integrated via the breadboard.

2arduinos1pi

Lessons learned (and remembered):

1) Always connect the grounds.  If you’re not seeing your minimally configured, powered and connected slave-sender device, check the ground first.

2) You can easily power a couple of Arduino’s from the RPi.  Nice.  I wonder how many you can power. I’m sure it depends on what you’re doing.

3) The SDA and SCL wires seem to be pretty flexible. You don’t have to chain them in a particular order as far as I can tell. Just make sure there’s some kind of connection and you’re good to go.

4) Arduinos, with built in analog to digital converters, are a lot less painful (and more reliable) to work with when it comes to reading basic sensors and sharing that data with an app running on the RPi.  My original reason for revisiting this use case was dissatisfaction with reading a photocell directly on the RPi using Python (tutorial) and Arduinos are cheap — $10 at MicroCenter.

3D Printer Management Goes Mobile with Salesforce1

1

Full confession: when you look up “3D Printer Newbie” in the OED, you’ll see a picture of me.  I am early on this particular learning curve but as enamored of it as most people who start down this path. This of course means I must somehow connect it to my primary area of interest, Salesforce. That is what I’m going to talk about today.

This post has six parts. 3D Printer Fundamentals, Introducing OctoPrint, The Salesforce Side of the House, Code Review, Practical Applications and Things That Went Wrong Along the Way.  But let’s start with a demo!

(Yes, that bonus soundtrack you hear in the far background is in fact my child.)

3D Printer Fundamentals

My work here was done with a couple of PrintrBot Simple Metal printers I picked up online. They’re not the most advanced printer on the market — if anything, they’re a minimalist interpretation of the form — but they are pretty sweet and at $599 the price is certainly right.

PrintrBot-Simple-Metal-Anatomy-453D printers are what’s referred to as “additive manufacturing.”  This means they start with nothing and add something to create their output. Most 3D printers on the market extrude thin layers of plastic over and over again, and these devices share a few common attributes.  First, since they work in three dimensions, they must be able to move a printhead in three dimensions.  I’ve labeled these as the X, Y and Z axises above so you can see which parts of the PrintrBot move. Second, they have a micro-controller that moves the printhead and regulates temperature and a bed that holds the results.  Finally, they all have a feed that moves plastic filament into a hot end where it melts and is extruded on to the bed.  For filament, I used 1.75mm wide PLA (plant based and compostable).  Layers are about 0.3mm thick, and come out of a 0.4mm hot end nozzle at 190° C.

Controlling a 3D printer is a cooperative effort between the onboard micro-controller and host software. The host software feeds printing instructions to the micro-controller which in turn provides operating details back to the host software.  The most important of these operating details is the temperature of the hot-end.  Probably the most common host software you will hear about is Repetier, and it’s definitely a great way to go. However, it’s not the only way to go and I ended up using another one for this project, which I’ll get to in a second.

Now, this is most of the picture, but you still need to tell the host software what you want to print. A 3D print generally starts off as a 3D design in some kind of CAD program.  There are a bunch of these you can choose from.  SketchUp is popular and free for non-commercial use, TinkerCAD is an online web-app that does it, and there are a bunch of others.  Once you have a 3D design, you need to convert it to something your 3D printer can understand.  Slic3r is the tool of choice for that. It converts 3D designs into a “gcode” file that contains actual instructions your printer can use.  If you want to use someone else’s design to start, checkout the good people at Thingiverse.  They have a lot of designs you can download and use for free.

octoprint

Introducing OctoPrint

Probably the best part of my job is poking my head into a new-to-me corner of the technology world and discovering an unexpected gem. OctoPrint is that gem. OctoPrint is 3D printer host software delivered as a web-app. It’s open source, written in Python, optionally runs on a Raspberry Pi and the devel branch has a pretty sweet API.

If you’ve read any of my earlier posts about controlling quadcopters, Philips Hues or DIY wireless sensor networks, you probably know what happens next.

If you guessed:

3D-Printer-OctoPrint-Salesforce1-NodeJS-Raspberry-Pi_2You are correct.  The basic setup is pretty simple.  I install the OctoPrint friendly Rasbian distro OctoPi (yes, it’s as easy as they make it look — completely awesome, too) on a Raspberry Pi I have sitting around.  I then added Node JS to it and created some familiar looking JS to talk to Salesforce via the Streaming API. OctoPrint talks to the PrintrBot Simple by way of a USB cable, so nothing special there. Also, in case you’re curious, I opted to have a single Pi control a single PrintrBot, so the setup in the video requires two units.

(Incidentally, I wanted to mix this architecture up this time, but was stymied.  See “Things That Went Wrong Along the Way” below for details on that.)3D-Printer-Salesforce

The Salesforce Side of the House

Let’s start with the data model.  It’s pretty easy, but a little different than the ones I’ve used before.

Historically, I’ve used a single message object.  The OctoPrint API is pretty rich, though, and has a variety of requirements (some commands are GETS and others are POSTS with bodies requiring a JSON object, for example), so I added an additional object to store API Command Templates.  The UI simply lists the available commands, and then creates a printer message based on the template.

Schema_Builder___salesforce_com_-_Developer_Edition

I really like this approach because it let’s me add new API commands as data, not metadata, so it’s super easy to add functionality and update the system as OctoPrint changes without having to deploy code.  (I can’t remember who, but I think I’m stealing this idea from someone.  Sam maybe?  I hate it when I can’t remember, so ping me if it’s you.)

Notice I don’t have a Printer object here. I do have one in the code, but it only holds names. It should be a relationship on the Printer Message object, but I didn’t get around to it.

The rest of the app is plain old Visualforce and Apex.  I’m not using any of the modern JS frameworks (Angular JS, etc), and I haven’t gone out of my way to optimize queries etc.  As you can see in the YouTube above, it performs pretty well.  The longest delay is doing the asynchronous round trip all the way back from the PrintrBot.

(Full confession: Christophe talked me into adding a little padding around the page so the Bootstrap based CSS didn’t extend completely end to end.  He was right.)

Code Review

As I said, the code on the Salesforce side of the house is pretty basic.  You can see it on the Github repo and yes there’s a link to an unmanaged package there too.  Literally all I’m doing is inserting an object based on a template contained in another object. The code that’s doing the interface is pretty similar the the quadcopter code, but it has a couple of twists.  The full gist is here.

In the likely event you don’t want to parse through the code pasted below, the simple flow is:

  1. On Salesforce1, create a Printer Message using a little step-by-step process governed by a controller in Apex (here).
  2. Wait for messages on the Streaming API, send them to handleOctoPrintCall and store the message’s original SFDC ID (below).
  3. Determine if we need a GET or a POST, create the outbound request and send it to OctoPrint. OctoPrint then sends it to the printer.  Note that OctoPrint and this script are running on the same Raspberry Pi.
  4. When the results come back, get the original message ID, and update the original request using a custom Apex REST service (here).

That’s is.

function handleOctoPrintCall(command, body) {
	var options;
  if (body == null) {
    console.log("body is null");
    options = {
	    url: OctoPrintURL + command,
	    headers: {
           	'X-Api-Key': OctoPrintApiKey
    	    }
	   };
   } else {
      console.log("body isn't null");
     options = {
      url: OctoPrintURL + command,
      method: "POST",
      body: body,
      headers: {
            'X-Api-Key': OctoPrintApiKey,
            'Content-Type': 'application/json'
          }
      };
 
   }
 
	request(options, callback);
}
 
function callback(error, response, body) {
  console.log("callback from printer");
  console.log(body);
  console.log("end callback from printer");
  
  if (!error && response.statusCode == 200) {
    console.log(body);
    sendPrinterResponse(body);
  } else if (!error && response.statusCode == 204) {
    console.log("Empty Body (204)");
    sendPrinterResponse( JSON.stringify({ "result" : "OK" }) );
  }
 
}
 
function sendPrinterResponse(body) {
 
  var newBody = {
    originalId : lastMessageId,
    responseJson : body
  };
 
  var options = {
      url: orgOauth.instance_url + '/services/apexrest/PrinterResponse',
      method: "POST",
      body: JSON.stringify(newBody),
      headers: {
            'Authorization': 'OAuth ' + orgOauth.access_token,
            "Content-Type": 'application/json'
          }
    };  
 
  request(options, printerResponseCallback);  
 
}
 
function printerResponseCallback(error, response, body) {
  console.log('printerResponseCallback');
  lastMessageId = '';
  if (!error) {
    console.log("success");
    console.log(body); 
  } else { 
    console.log("error");
    console.log(error);
  }
}

The other bits of code in the gist are relatively mundane — a heartbeat so I know the system is alive, OAuth magic with salesforce (thanks Kevin et al!)

Practical Applications

The most frequent question people ask me when I tie together a few interesting bits of technology is simple: why? That’s a great question, and sometimes I’m doing it just to demonstrate that it’s possible. 3D printing and Salesforce is different.

One practical (but abstract) application  of an integration like this is to check asset utilization.  The more expensive, specialized equipment you have, the more likely you are to care about it’s utilization.  In general, the more you utilize these assets, the better.  The classic example here is Southwest Airlines and their drive to turn their planes around very quickly. The more often their planes are flying, the more money they’re making.  All of these assets and this data should be surfaced through whatever interface your team is likely to use in service of this goal.

More concretely, let’s say you have a 3D printer farm at your company, and you use those printers to create parts.  Maybe these are R&D parts, maybe they’re spare parts, maybe they’re promotional chochkies.  Having something to spawn jobs and monitor progress is a good thing.  More than that, having a source of engineered, iterated on and blessed 3D designs means that users are more likely to get the results they want.  A central resource like the one I’ve shown here is a step in the right direction.

If you take this idea one level further, let’s saying you have a very interesting service scenario where a piece of equipment reports a system fault automatically.  That fault is then diagnosed as needing a unique spare part, which is 3D printed and then automatically delivered by, for example, a quadcopter.  That’s some next generation stuff right there.

There are more ideas, but you get my general train of thought here.

Three-Quarter-T-Rex-Skull

Things That Went Wrong Along the Way

Lots of things went wrong and didn’t work.

  1. Most irritatingly, I accidentally aborted printing this super-cool T-Rex skull.  Totally blaming Seligman but it’s my fault for wanting to show him another project.  ProTip: think before you unplug that USB. Hours of printing and meters of filament down the drain.
  2. I wanted to get out of the Streaming API pattern and connected OctoPrint directly to the Internet.  No reason that shouldn’t work, except my attempts at using VyperVPN and No-Ip to get that going failed, failed and failed again.  Killed a whole day.  Someone better at networking could do it. The Streaming API is dead easy because I don’t have to worry about open a port on my network, etc.
  3. Turns out 3D printers are relatively hard to get.  I somehow caught a window where I could buy these on Amazon.  The first two that arrived were all busted up like someone had dropped them off a pretty tall conveyor, but replacements were only a couple days away.  Lots of places advertise filament and printers and neglect to mention a 6 week lead time and even on Amazon these are now a 2-4 week delivery item.
  4. At one point, I jammed the feed on the printer so bad I had to call in backup.  Gory details over on their forum. Turned into a great excuse to take apart the printer though and I always like that.
  5. The PrintrBot Simple intro video made some mention of the various kinds of surface treatments you could use to enhance your printing.  The standard is blue painters tape–it works like a charm!  I also tried some beige masking tape I had lying around the house, since The blue stuff was a Home Depot away, and it was an unmitigated disaster.

Wrap Up

Over all, I end where I started: this stuff is super cool.  But it’s also still pretty new and not very polished yet.  If you jump in now, you’ll need to be patient and interested in tinkering.  And if you are those things — WOW.  You’re going to love it!

Philips Hue, Raspberry Pi, Node.js, Salesforce and You

5

One of the devices I brought to the Dreamforce Connected Device Lab was a Philips Hue Starter Kit. A friend of mine whipped up a little Ruby script to flash the lights and change colors at random for the Lab, and I got to wondering what it would look like to control the whole thing through Salesforce.  Here’s what I did.

TL;DR: Connected a Raspberry Pi to the Hue bridge using Node.js.  The same app is connected to a Salesforce app using the Streaming API and is controllable using the Salesforce1 mobile app.  Salesforce Package (and raw code).  Node.js Code.

The Hue system has a pretty straightforward architecture.  The bulbs connect to a bridge and that bridge connects to your network.  Once it’s on the network, you can start to control them via the Hue app or the Hue API.

Step 1. The first thing you need to do is choose the device you want to use to control the bridge. This device will have to live on the same physical network as the Hue bridge.  I chose a Raspberry Pi.  Configuring the Raspberry Pi is pretty easy, these are my standard steps.  This includes installing Node.js which isn’t part of the Raspbian distro.

Step 2. Use NPM to install the Hue interface library.  “Node-Hue-API” seems to be the winner in this department.  Follow the instructions on the Github repo.  They’re really good.  The basics are:

  • Find the bridge and get the IP address (code).
  • Create a user on the bridge (code) — note that you’ll need to update the code with your bridge’s IP address.
  • Remember everything it just spat out for later.

Step 3. You are now ready to configure Salesforce.  There are a few steps to this process.  If you don’t have a developer org, it’s time to go get one.

Configure a new connected app in your developer org (detailed instructions from Help).

Start by clicking on Setup at the top of your screen, click on Create on the side, click on Apps, and then click on the New button under Connected Apps.

Apps___salesforce_com_-_Developer_Edition-10

You will now see the New Connected App screen.  Enter the required fields indicated in red.  The API Name is an internal name that will fill itself in once you complete the name field.  Check the box labeled “Enable OAuth Settings” and add http://localhost:3000/oauth/_callback as your callback URL.  Select all of the available OAuth scopes, and click the add button.  Click on Save.

Connected_App___salesforce_com_-_Developer_Edition-17

Once you click on “Save”, you’ll have a fully configured connected app.  You’ll be using the Oauth2 web server flow, which requires your consumer key and your consumer secret.

Connected_App__Hue_Sample___salesforce_com_-_Developer_Edition-2

Note: it may take a few minutes for your new connected app to be fully active.  This is normal.

Finally, configure your personal security token.  (Lots of information about Salesforce Security Concepts including the security token is available in the API docs.)   Start by clicking on your name at the top of the screen, click on My Settings in the drop down menu, then click on Reset My Security Token on the left.

Hello__Reid_Carlberg____salesforce_com_-_Developer_Edition-10

Click on the big green “Reset My Security Token” button.  This will result in an email which we’ll use again in a minute.

Reset_My_Security_Token___salesforce_com_-_Developer_Edition-2

Now that your Connected App is created, you need to install the unmanaged package which contains the objects, code and UI that helps you control the Hue.  You’ll be able to see the code once you’ve installed it, or you can see it on Github.  For now, use this link to start the install process.

https://login.salesforce.com/packaging/installPackage.apexp?p0=04tU0000000E0eU

This will guide you through a series of steps.  Since this is a demo and you’re in a demo environment, just accept all the defaults.  You’ll click “Continue”, “Next”, “Next” and finally “Install”.

Install_Package___salesforce_com_-_Developer_Edition-4

When you have done this successfully, you will land on a screen which declares “Install Complete!”.  You must now click on the app selector in the upper right which probably says “Sales”.  Then click on the app labeled “LAB Hue Interface”.

Package_Details__LAB_Hue_Demo___salesforce_com_-_Developer_Edition-4

Once you do that, you immediately see a screen telling you that setup is not yet complete.  Please go ahead and click on the big “Complete Setup” button.

Mozilla_Firefox-2This will bring you to a screen that helps you insert something called a Push Topic.  Push Topics are part of the super cool and extensively documented Streaming API.  Don’t worry, just click the button.

salesforce_com_-_Developer_Edition-2

And then click the link.

salesforce_com_-_Developer_Edition

Which brings you back to the Hue interface, which now looks like this:

Mozilla_FirefoxAs an aside, you might be thinking, wow, that’s a lot of steps.  And you’re right!  There is a way to automate this configuration, however, you wouldn’t be able to see the code as easily.  So I’ve opted for a few more steps so the example is easier to understand.

Step 4: Finish configuration of your Raspberry Pi.  The good news?  This is now going to be very easy.

First, use npm to install nforce and faye (“npm install nforce faye“).

Next, get the basic code required to connect Salesforce to the Hue.  When you get it on the Raspberry Pi and save it as “hueforce.js”, you’ll want to use nano or another editor to update the field values to yours.  You’ll need to add your user info, your OAuth / Connected App info and your Hue info.

Projects_—_pi_raspberrypi____Projects_hueblog_—_ssh_—_115×25-18

And now you can run your app using “node hueforce.js“.  Now all those great blue buttons are controlling your Hue!

Step 5.  Finally, turn it into a mobile app using Salesforce1 (iTunes, Google Play).  In Salesforce, you’ll need to navigate to the tab configurations and edit the “Hue” tab.

Custom_Tabs___salesforce_com_-_Developer_Edition-9

In the Hue tab settings, make sure you have “Mobile Ready” checked.  Be sure to save your changes.

Edit_Visualforce_Custom_Tab__Hue___salesforce_com_-_Developer_Edition-5

Now you are ready to add this page to the Mobile Configuration.  Click on Setup, select Mobile Administration, and click on Mobile Navigation.

Mobile_Navigation___salesforce_com_-_Developer_Edition-6

Once that’s done, you simply login to the Salesforce1 app, touch the menu selector in the upper left, then scroll down until you see “Hue” listing under “APPS”. The UI is exactly the same.

image__2_-6  image (3)

I’ve also added a fun trigger that automatically fires the “siren” setting when a new lead comes in.

That’s it.  Questions, comments, I’d love to hear them.

Control an Arduino with a Raspberry Pi Using Node.js and I2C

8

You might also find this post helpful: Read Data from Multiple Arduinos with a Raspberry Pi B+ using I2C and Node.js

As a software developer, I usually stay away from lower level communication protocols. My logic has historically been: they’re a lot of work, and my time is better spent higher up the stack.

A couple of weeks ago, after suffering through a variety of failures and uncertainty higher up the stack, I decided the only way out was to go at least a little deeper. So I bit the bullet and connected a Raspberry Pi to an Arduino using the I2C protocol, and then was able to control the Arduino using Node.js. This post covers how I did it.

Raspberry-Pi-Wild-Thumper.jpg

My use case was fairly simple.  I decided to drive a Wild Thumper using the Salesforce1 mobile app.  The Wild Thumper is controlled by an Arduino compatible board, aptly named the “Wild Thumper Controller“.  You might remember I had a couple of these with me at the Connected Device Lab this Dreamforce.  In order to communicate with Salesforce, it needs to have some kind of a gateway that can talk to the Internet using HTTPS, which is where the Raspberry Pi comes in.  If you have a different flavor or Arduino sitting around this should still work.

There are a lot of really great technical introductions to I2C (including — gasp — one from 2001), but you don’t really need them to get started.  Keep these two basic ideas in mind:

  • You’re going to work in a Master-Slave configuration.
  • You need to connect three pins.  SDA, SCL and Ground.

That’s it.

Step 1: Slave Configuration on the Arduino compatible Wild Thumper Board is pretty easy.  In fact, you can simply use the “Wire > Slave Receiver” sample code included with the IDE to get started (below). Load this in the Arduino IDE as is, send to your device and then start the serial monitor.  Put it aside.

// Wire Slave Receiver
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>

void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop()
{
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

Step 2: Setting up the Raspberry Pi is a little more difficult, but it’s well documented.  If you are using a standard Raspbian distro, the I2C port is not yet enabled.  Adafruit has an excellent post on enabling the I2C port.  Follow those instructions, then c’mon back.

Step 3: Wire your Raspberry Pi and your Arduino together and make sure the RPi can see the Arduino.  Pinouts on the RPi are a little irritating.  I use the Pi Cobbler.  It gives you a handy, easy to read guide to which pins are where.  If you are connecting directly to the GPIO pins, be sure to consult a pinout digram.

Before you connect everything, your RPi should produce this when you use the i2cdetect command.

Raspberry-Pi-Before-Arduino.png

The basic configuration is really simple.  Master SDA pin to Slave SDA, Master SCL pin to Slave SCL, Master GND pin to Slave GND.  On the Wild Thumper Controller, SDA is A4, SCL is A5 and GND is any pin on the outside edge of the board.  And an Arduino Uno R3, there are special pins for I2C, above the AREF pin, clearly labeled on the back side of the board. In my case, the result looks like this (that’s the Wild Thumper Controller on the right, Pi Cobbler on the left):

Raspberry-Pi-Arduino-I2C-Wiring.jpg

After connected, your RPi should produce this (note that there is now a device on 4).

Raspberry-Pi-Arduino-After-I2C.png

Step 4: Install Node.js on to your Raspberry Pi using this simple link.  If you prefer to be a bit more hands on, you can follow these instructions.  If you prefer to be really hands on, you can install it by compiling from the source, but it will probably take > 2 hours and so far in my experience it’s no different.

Step 5: Install something that lets Node.js talk to the Raspberry Pi’s I2C system.  You should use the I2C library.  There are a couple of others out there, but this is easy and popular.  Now you should be able to do something like this:

var i2c = require('i2c');
var device1 = new i2c(0x18, {device: '/dev/i2c-1', debug: false});
device1.setAddress(0x4);
device1.writeByte(0x2, function(err) { console.log("error"); console.log(err); });

And see a “2” in the Arduino serial port monitor (like so).

Arduino-Serial-Monitor.png

There you have it — the basics of controlling an Arduino using a Raspberry Pi with Node.js and I2C. My original goal was to control the Wild Thumper via the Salesforce1 app.  I was able to accomplish that pretty easily.  Here’s my basic controller for the Thumper, and here’s the Node.js app running on the RPi.  I created a simple UI on the Salesforce1 mobile app (below)  that sends commands to the Thumper using the Streaming API and connects to Salesforce using the excellent nforce.

Salesforce1-Arduino.png

%d bloggers like this: