Staircase project, part 2: Raspberry Pi and i2c

After rediscovering the Dimmer Plug  a few days ago, the time had come to see if I could use the Dimmer Plug directly from a Raspberry Pi.

Before I could connect the Dimmer Plug to the Raspberry Pi, I had to enable i2c on the Raspberry Pi; because out of the box, i2c is disabled (because there’s not much to learn about i2c? ;-))

Here’s a short list of what had to be done:

  • Remove i2c from blacklist

The file /etc/modprobe.d/raspi-blacklist.conf had to be modified so that it looked like this:

#blacklist spi-bcm2708
#blacklist i2c-bcm2708

The ‘#’ turns the 2 lines into comment lines, so that those 2 modules are no longer blacklisted/disabled; I also enabled spi which is not really necessary for this.

  • 2 lines had to be added to /etc/modules:

i2c-bcm2708
i2c-dev

  • Installing i2c-tools:
sudo apt-get install i2c-tools
  • Sufficient access rights for user pi:
sudo adduser pi i2c && reboot

After the reboot, I had 2 new devices:

pi@rpi3 ~ $ ls -rtl /dev/i2c*
crw-rw---T 1 root i2c 89, 0 Sep 12 21:43 /dev/i2c-0
crw-rw---T 1 root i2c 89, 1 Sep 12 21:43 /dev/i2c-1

And after I connected the Dimmer Plug, a scan of the i2c bus resulted in the following:

pi@rpi3 ~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          03 -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
pi@rpi3 ~ $

Well that wasn’t too hard… The Dimmer Plug with address 0×40 is being detected, so we’re ready to go… The next thing that had to be done was getting i2c working from Node.JS. Fortunately there’s a Node module for i2c, so that part is already covered. A driver for the PCA9635 IC wasn’t hard either – all I had to do was sending the same bytes to the PCA9635 as the JeeLib driver did.

The things I want to do with the LED strips involves sending certain ‘patterns’ to the LED driver at specific intervals. Will the Raspberry be able to do this in a reliable way? I don’t know yet, cause right now the Raspberry which I’m using to test this LED driver, has (almost) nothing else to do than run a single Node app that uses this LED driver. But what if more drivers are running, all consuming CPU cycles, or what if the OS feels it’s time to do something else for a change, just when the LED strips need to be adjusted in brightness? We’ll see.. maybe not now, but too much delay or other irregularities should be visible right away, so I decided to just wait and see how this turns out in practice.

The PCA9635 driver code is quite small and simple, actually:

/**
 * PCA9635 LED driver I2C library for Node.JS
 * Based on the JeeLib Dimmer Plug driver
 * (https://github.com/jcw/jeelib)
 */

i2c = require('i2c');

var modes = {
        MODE1:0, MODE2:1,
        PWM0:2, PWM1:3, PWM2:4, PWM3:5, PWM4:6, PWM5:7, PWM6:8, PWM7:9,
        PWM8:10, PWM9:11, PWM10:12, PWM11:13, PWM12:14, PWM13:15, PWM14:16, PWM15:17,
        GRPPWM:18, GRPFREQ:19,
        LEDOUT0:20, LEDOUT1:21, LEDOUT2:22, LEDOUT3:23,
        SUBADR1:24, SUBADR2:25, SUBADR3:26, ALLCALLADR:27};

function DimmerPlug(device, address) {
  this.device = device || '/dev/i2c-1';
  this.address = address || 0x40;
}

DimmerPlug.prototype.initialize = function() {
  this.i2cdev = new i2c(this.address, {device : this.device});
  this.setReg(modes.MODE1, 0x00); // normal
  this.setReg(modes.MODE2, 0x14); // inverted, totem-pole
  this.setReg(modes.GRPPWM, 0xff); // set group dim to max brightness
  this.setMulti(modes.LEDOUT0, [0xff, 0xff, 0xff, 0xff]); // all LEDs group-dimmable
}

DimmerPlug.prototype.setReg = function (reg, value) {
  this.i2cdev.writeBytes(reg, [value]);
}

DimmerPlug.prototype.setMulti =  function(reg, values){
  this.i2cdev.writeBytes(reg | 0xe0, values);
}

module.exports = DimmerPlug;
module.exports.modes = modes;

Now the Node app… I decided to follow the dimmer_demo sketch, cause if I’d get the same results with the RPi as with the JeeNode I knew everthing was OK. And now the code for the Node app becomes  a bit awkward… it’s a demo, constantly changing the brightness of all the LEDs, but there are no real events, so there’s nothing to trigger on.

This app does its job totally isolated from the rest of the world.. and things get even ‘uglier’, cause the JeeLib demo contains a few delay() statements – which (for the obvious reasons) is not available in Node – yes, there’s setTimeout(), but that doesn’t pause execution! This was the first time I had to think about how to do something in Node.. I needed something to control the program flow; normally (in my case) a driver gets its events from either MQTT messages or incoming data from the hardware, but both are not the case here (yet). I decided to use the async module for that and create a series of functions that should be executed after each other. This is how the Node version of the dimmer demo looks like:

var dimmerplug = require('./dimmerplug');
var async = require('async');

var level = 0x1fff;
var dimmer = new dimmerplug();

async.series(
  [
    function(callback) {
      dimmer.initialize();
      dimmer.setMulti(dimmerplug.modes.PWM0, [255, 255, 255, 255,
                                        255, 255, 255, 255,
                                        255, 255, 255, 255,
                                        255, 255, 255, 255]);
      // set up for group blinking
      dimmer.setReg(dimmerplug.modes.MODE2, 0x34);
      // blink rate: 0 = very fast, 255 = 10s
      dimmer.setReg(dimmerplug.modes.GRPFREQ, 50);
      // blink duty cycle: 0 = full on, 255 = full off
      dimmer.setReg(dimmerplug.modes.GRPPWM, 100);
      // let the chip do its thing for a while
      setTimeout(function(){callback(null, '1');},10000);
    },
    function(callback) {
      // set up for group dimming
      dimmer.setReg(dimmerplug.modes.MODE2, 0x14);
      // gradually decrease brightness to minimum
      for (i = 100; i < 255; ++i) {
          dimmer.setReg(dimmerplug.modes.GRPPWM, i);
      }
      setTimeout(function(){callback(null, '2');},2000);
    },
    function(callback) {
      while(true){
        brightness = ++level;
        if (level & 0x100){
            brightness = ~ brightness;
        }
        r = level & 0x0200 ? brightness : 0;
        g = level & 0x0400 ? brightness : 0;
        b = level & 0x0800 ? brightness : 0;
        w = level & 0x1000 ? brightness : 0;
        // set all 16 registers in one sweep
        dimmer.setMulti(dimmerplug.modes.PWM0, [w, b, g, r,
                                      w, b, g, r,
                                      w, b, g, r,
                                      w, b, g, r]);
      }

    },
  ],
  function(err, response) {
    console.log(response);
  }
);

A bit weird, but it works. The Node demo worked just as well like the JeeNode version, so another part of this staircase project is done – the power MOSFETs have already been ordered, so as soon as they arrive I can connect real LED strips the the Dimmer Plug – can’t wait to see the results!

Dimmer Plug connected to Raspberry Pi

Oh, and in the meantime, it might be good to start working on the real renovation job as well.. ;-)

Tagged , , . Bookmark the permalink.

3 Responses to Staircase project, part 2: Raspberry Pi and i2c

  1. Hello,

    Which mosfet are you going to use?

    -Wilco

  2. Pingback: LED Stair Lighting Hack with Raspberry Pi | Homautomation

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>