KiCAD version of JeeLabs JeeNode v6

I’ve been following Jean-Claude Wippler’s blog over at jeelabs.org, he has done some lovely work on a little board called the JeeNode.

The JeeNode is a wireless micro-controller board designed for a variety of Physical Computing tasks. From measuring and reporting temperature, humidity, and other environmental data to tracking and controlling energy consumption around the house. It was inspired by the Arduino Duemilanove and Uno boards, and by the “Real Bare Bones Board” (RBBB) from Modern Device.

The JeeNode V6 artwork on JeeLabs is done with Eagle. I’d like to make one and decided to rework the artwork in KiCad.

The schematic:

KiCAD versoin of JeeNodeV6 - Schematic

KiCAD versoin of JeeNodeV6 – Schematic

The artwork:

KiCAD versoin of JeeNodeV6 - PCB

KiCAD versoin of JeeNodeV6 – PCB

There possible I’ve used the same part references as the original. You can download the full artwork: KiCAD-JeeNodeV6.tar

So time to make this PCB. It will be tricky, lots of through holes and vias, but I’m up for a challenge!

 

MQTT Client on the Carambola using Lua

No electronics today… all about the code!

With the Carambola i2c IO board hardware built, time to turn to the software. My first thoughts were to run a Python web server that would listen on the network for requests to turn on and off the relays.  But a while ago I was watching a video by Jon Oxer [ SuperHouse.tv ] about home automation, in which he mentions MQTT [Message Queuing Telemetry Transport].

I’ve not done much with Python on the Carambola, any thing that I’ve read says it to heavy to be of any use, and that Lua is the way to go. So what about a Lua MQTT client?  Well there is one, a guy called Andy Gelme has done the business, and the code is on GitHub, mqtt_lua.

Took a little playing around but I got it installed on my Carambola.  Here is what you’ll need to do:

Install PenLight

  1. Download this Lua Penlight package: https://github.com/stevedonovan/Penlight/archive/master.zip
  2. On desktop machine unzip it and go into “/Penlight-master/lua/” directory.
  3. Copy the “pl” directory to the following location on your Carambola: /usr/lib/lua

Install Lua MQTT

  1. Download this Lua MQTT package: https://github.com/geekscape/mqtt_lua/archive/master.zip
  2. On desktop machine extract zip file and go into the /mqtt_lua-master/lua/ directory
  3. Copy the “mqtt-library.lua” and “utility.lua” files to “/usr/lib/lua”

Your good to go!

Now your going to have to install a MQTT server on a box somewhere.  I have Ubuntu running on a server here so I installed Mosquitto on it. The really nice thing about MQTT is it’s simplicity.. I searched the net for HowTos and any information on setting MQTT up but it’s really easy, I guess that is why there is so few intros. Just jump in and give it a go!

So here is the client code (or the subscriber code) [ Only new to Lua so there are probably far nicer ways of doing this… but hay it works. It’s based on one of the examples that Andy has on his Git page ]:

#!/usr/bin/lua
-- A little lua script that subscribes to a MQTT server
-- and waits for instructions from a topic
--
-- Usage:
-- mqtt_relays.lua -t relay/#
-- 
-- MQTT server is hard coded.. look toward the end of this file
--
-- MMcK (20130306)

function hasbit(x, p)
  return x % (p + p) >= p       
end

function setbit(x, p)
  return hasbit(x, p) and x or x + p
end

function clearbit(x, p)
  return hasbit(x, p) and x - p or x
end

function getRelayStatus( )
  -- get current i2c relay status
  local i2c_cmd = "i2cget -y 0 0x27 0x12 > relay_status"
  os.execute( i2c_cmd )
  local relay_status_file = io.open("relay_status", "r")
  local file_data = relay_status_file:read("*all")
  relay_status_file:close()
  local status = string.sub( file_data, 3, 4 );
  local status_int = tonumber(status, 16)
  return(status_int)
end

function num2hex(num)
  local hexstr = '0123456789abcdef'
  local s = ''
  while num > 0 do
    local mod = math.fmod(num, 16)
    s = string.sub(hexstr, mod+1, mod+1) .. s
    num = math.floor(num / 16)
  end
  if s == '' then s = '0' end
  if string.len(s)==1 then
      return('0x0' .. s)
      end
  return ('0x' .. s)
end

function callback(
  topic,    -- string
  message)  -- string

  relay_status = getRelayStatus()
--  print ( "Current Status :" .. relay_status )

  message = string.upper( message )
  relay_no = string.sub( topic, -1 )
  relay_no = tonumber( relay_no )
--  print("Topic: " .. topic .. ", message: '" .. message .. "'" .. ", Relay no: " .. relay_no)
  relay_no = ( 2 ^ (relay_no-1) )
--  print ( "Relay power no: " .. relay_no )
  if hasbit(relay_status, relay_no) and message=='OFF' then 
--    print ( "Off time for relay: " .. relay_no )
    relay_status = clearbit(relay_status, relay_no)
    end
  if not hasbit(relay_status,relay_no) and message=='ON' then
--    print ( "On time for relay: " .. relay_no )
    relay_status = setbit(relay_status,relay_no)
    end
--  print ( "New status: " .. relay_status )
  i2c_cmd = "i2cset -y 0 0x27 0x12 " .. num2hex(relay_status)
--  print ( "Cmd: " .. i2c_cmd )
  os.execute( i2c_cmd )
end

-- ------------------------------------------------------------------------- --

function is_openwrt()
  return(os.getenv("USER") == "root")  -- Assume logged in as "root" on OpenWRT
end

-- ------------------------------------------------------------------------- --

-- print("[mqtt_relays v0.1 2013-03-06]")

if (not is_openwrt()) then require("luarocks.require") end
local lapp = require("pl.lapp")

local args = lapp [[
  Subscribe to a specified MQTT topic
  -d,--debug                                Verbose console logging
  -i,--id            (default mqtt_sub)     MQTT client identifier
  -k,--keepalive     (default 60)           Send MQTT PING period (seconds)
  -t,--topic         (string)               Subscription topic
  -w,--will_message  (default .)            Last will and testament message
  -w,--will_qos      (default 0)            Last will and testament QOS
  -w,--will_retain   (default 0)            Last will and testament retention
  -w,--will_topic    (default .)            Last will and testament topic
]]

-- initialise the MCP23017
-- port A all outputs
i2c_cmd = "i2cset -y 0 0x27 0x00 0x00"
os.execute( i2c_cmd )

local MQTT = require("mqtt_library")

if (args.debug) then MQTT.Utility.set_debug(true) end

if (args.keepalive) then MQTT.client.KEEP_ALIVE_TIME = args.keepalive end

local mqtt_client = MQTT.client.create( '<MQTT server IP>', 1883, callback)

if (args.will_message == "."  or  args.will_topic == ".") then
  mqtt_client:connect(args.id)
else
  mqtt_client:connect(
    args.id, args.will_topic, args.will_qos, args.will_retain, args.will_message
  )
end

mqtt_client:subscribe({args.topic})

local error_message = nil

while (error_message == nil) do
  error_message = mqtt_client:handler()
  socket.sleep(0.5)  -- seconds
end

if (error_message == nil) then
  mqtt_client:unsubscribe({args.topic})
  mqtt_client:destroy()
else
  print(error_message)
end

-- ------------------------------------------------------------------------- --

This script is run with a “-t” option, which sets the topic that it will listen to.  For this example I’ve set the topic to “relay/#”, which listens for all “relay” topics.

On my desktop machine I type the following:

mosquitto_pub -h <MQTT server IP> -t relay/1 -m "on"

And the first relay comes on..

mosquitto_pub -h <MQTT server IP> -t relay/1 -m "off"

And it goes off again.  For the other relays just change the -t option: relay/2 – second relay, relay/3 – third relay, etc.  So simple it’s gift.

Carambola i2c IO board – PCB

Late last week the parts arrived from my Carambola i2c IO board and I was busy over the weekend making and assembling the PCB.  Here are the results!

I used KiCad to create the artwork and my ink-jet printer to print it out onto OHP film.  Got better results with my ink-jet than my laser printer, the ink is a lot darker than toner.  As this is a double sided PCB I spent a good while getting the alignment correct, which was tricky!

For a UV source, I got an external 24W CLF bulkhead light which at a five minute exposure time worked the business. The back of the PCB worked out fine apart from the dodgy cheep FR4 board I got from Radionics.  The photo resist film on the copper was really crappy as you can see in the photo below (look in the centre of the PCB, the artwork was black but you can see the Cu has been etched in patches).

Carambola i2c IO Board PCB back side

Carambola i2c IO Board PCB back side

The top side was a little better apart from the PCB area at the top right of the board where there was a big blotch of resist.. Also the alignment of the top and bottom artwork was a little out on the right despite my best efforts.

Carambola i2c IO Board PCB front side

Carambola i2c IO Board PCB front side

Here is a close up of the track detail where they are at their closest, nice crisp tracks.

Carambola i2c IO Board PCB track detail

Carambola i2c IO Board PCB track detail

The switcher PSU with the 3.3V regulator:

Carambola i2c IO Board PSU

Carambola i2c IO Board PSU

And finally the assembled PCB..

Carambola i2c IO Board working

Carambola i2c IO Board working

The good news: it works!

Well I haven’t tried the Ethernet UTP connection yet, but the WiFi, PSU, input stage and relays work fine.