Kivy OpenGL console controlling MBED via MQTT

Some time ago, IBM released a very cool project to the open source community. MQTT or message queue telemetry transport was originally used for communicating with orbiting satellites. Today, MQTT is a machine-to-machine (M2M)/”Internet of Things” connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport and it is useful in practical applications from push notification in mobile Apps to distributed Sensor networks via message brokers.

In this particular project I am using the IBM Really Small Message Broker that supports MQTT, the download has executables for just about every platform out there.. Get it from here

My goal with this project was to create a quick operations console to interface with embedded hardware for messaging and switching. As I am part of an active project called Kivy.org I figured it would be a perfect tool to provide the user interface for the console. Kivy is a cross platform development framework based on Python and the C language. For further reading I urge you to click over to the http://kivy.org website and download a copy of the framework for your operating system and run some examples. The API is ultra easy and very feature rich including 2D & 3D support with standard widget libraries and Advanced multitouch gesturing support that all runs in the hardware GPU on Microsoft windows operating systems, Apple Mac OSx operating systems including IOS for the iPhone and iPad as well as support for Android and Linux. The example code I am providing in this blog entry can easily be built simultaneously for each of the above operating systems.

figure 1 – MQTT Topology for Messaging

The 1st step however in the project is to wire the circuit for the MBED Arm Cortex-M3 based system on chip. I chose the MBED for its power however you could equally use and Arduino with an MQTT library (1) to support the same function as the MBED. the MBED contains four pin configurable LEDs that I wanted to link to buttons in the Kivy UI Console, this can easily demonstrate the function of unlocking a door, turning on a fan, or switching on light. Additionally I also want to be able to send messages from the console in human readable text and have them show up on an LCD screen connected to the MBED.

I am assuming that you will be connecting to either a MAGJACK RJ45 Female connecter or use anMBED Dev board with one already connected. At the time of writing I could not find one in the Fritzing Part list.

figure 2 – Breadboard layout

figure 2 – Circuit Schema

figure 4 – Circuit Board – Missing MAGJACK connection…

For configuration of the ethernet take a look here

Ok so now onto the MBED code, I have published the program to mbed.org for a quick start.

I have used the mbed MQTT Client Library found here and the TextLCD library.

#include “mbed.h”
#include “EthernetNetIf.h”
#include “MQTTClient.h”
#include “TextLCD.h”

EthernetNetIf ethernet;

Serial pc(USBTX, USBRX);

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);

TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2B); // rs, e, d4-d7

IpAddr serverIpAddr(192,168,0,2); /*Sever ip address*/

void callback(char* topic, char* payload); /*Callback function prototype*/

MQTTClient mqtt(serverIpAddr, 1883, callback);

void callback(char* topic, char* payload) {
printf(“Topic: %s\r\n”, topic);
printf(“Payload: %s\r\n\r\n”, payload);
//Send incoming payloads back to topic “/mbed”.
printf(“Topic: “);
printf(topic, “\r\n”);
printf(“Payload: “);
printf(payload, “\r\n”);

char *string_1 = “LED1”;
char *string_2 = “LED2”;
char *string_3 = “LED3”;
char *string_4 = “LED4”;

if (strcmp(payload, string_1)==0) {
printf(payload);
printf(“Setting LED1”);
myled1 = 1;
} else if (strcmp(payload, string_2)==0) {
printf(payload);
printf(“‘Setting LED2”);
myled2 = 1;
} else if (strcmp(payload, string_3)==0) {
printf(payload);
printf(“Setting LED3”);
myled3 = 1;
} else if (strcmp(payload, string_4)==0) {
printf(payload);
printf(“Setting LED4”);
myled4 = 1;
} else {
lcd.printf(payload);
}

//pc.printf(payload);
//while(1) {pc.putc(pc.getc()

mqtt.publish(“/mbed”, payload);

}

int main() {
printf(“\r\n############### MQTTClient Session ###########\r\n\r\n”);

EthernetErr ethErr = ethernet.setup();
if (ethErr) {
printf(“Ethernet Error %d\r\n”, ethErr);
return -1;
}

char clientID[] = “mbed”; /*Client nanme show for MQTT server*/
char pub_topic[] = “/mbed”; /*Publish to topic : “/mbed” */
char sub_topic[] = “/kivy”; /*Subscribe to topic : “/mirror” */

if (!mqtt.connect(clientID)) {
printf(“\r\nConnect to server failed ..\r\n”);
return -1;
}
printf(“\r\nConnect to server sucessed ..\r\n”);

mqtt.publish(pub_topic, “Hello here is mbed…”);
mqtt.subscribe(sub_topic);

int flag = 0;
/*Keep alive for 300s or 5mins*/
while (flag < 300) {
Net::poll();
wait(1);
flag++;
mqtt.live();
}

mqtt.disconnect();

printf(“#### End of the session.. ####\r\n\r\n”);
}

Compile and deploy this code to the mbed.

The Kivy.org code can be downloaded from http://kivy.org/#download as a binary and simply installed, there are a few more steps for IOS and Android App Packaging, links to this documentation can be found in the download page.

The Kivy Console consists of two files. The python language file..

runlayout.py

from kivy.app import App
import mosquitto
client = mosquitto.Mosquitto(“kivy-client”)
client.connect(“192.168.0.2”)

def send(text):
print text

class MyApp(App):
def send_text(self, text_input, *args):
send(text_input.text)
uni = text_input.text
msg = uni.encode(‘utf-8’)
client.publish(“/kivy”, msg, 1)
text_input.text = ”

def callback(self, instance):
print ‘The button <%s> is being pressed’ % instance.text
client.publish(“/kivy”, instance.text, 1)
instance.text = ”

if __name__ == ‘__main__’:
MyApp().run()

And the KV language file. See the language and file format at http://kivy.org/docs/guide/kvlang.html

#:kivy 1.3.0

#:import App kivy.app.App

BoxLayout:
orientation: ‘vertical’
BoxLayout:
Button:
text: ‘LED1’
on_press: App.get_running_app().callback(self)
Button:
text: ‘LED2’
on_press: App.get_running_app().callback(self)
Button:
text: ‘LED3’
on_press: App.get_running_app().callback(self)
Button:
text: ‘LED4’
on_press: App.get_running_app().callback(self)

FloatLayout:
Button:
pos_hint: {‘center_x’: .5, ‘center_y’: .5}
size_hint: None, None
size: 200, 100

BoxLayout:
TextInput:
id: text_input
Button:
size_hint: None, 1
width: 50
on_press: App.get_running_app().send_text(text_input)

Start the really small message broker with ./broker from your command line.

run “python runlayout.py” from your command line.

This video will walk you through the steps

 

 

 

The “Don’t bug me” bug, on mbed

Towards the end of school holidays is always a frustrating time for parents. You back at home from the annual trip away and your kids are bored or at least tell you they are bored constantly every hour on the hour. This would be good if you yourself weren’t actually back to work. With my son and daughter constantly in and out of my office my memory recalled a device that create a Youth Repellent Sound.

Upon further study adults have difficulty hearing above the 16 khz range. and for a frequency of 16khz we need a wavelength of 1/16000 = 6.25 10 to the minus 5. Pulse Width Modulation is basically a square wave so we can us it to generate sound.

To fit in with PWM we need to interpret a period to mark the wave high and the duty cycle to 0.5 to get a symmetrical square wave.

#include “mbed.h”

PwmOut speaker(p21);

int main() {
speaker.period_us(62.5);
speaker = 0.5;
}

Schematic
wpid-youthrepellent_schem-2011-09-11-15-56.png

Breadboard
wpid-youtrepellentbb-2011-09-11-15-56.png

PCB

wpid-youthrepellent_pcb-2011-09-11-15-56.png

Code

This displays an LED on the mbed to confirm that the script is running

#include “mbed.h”

PwmOut speaker(p21);
DigitalOut myled(LED1);

int main() {
speaker.period_us(62.5);
speaker = 0.5;
myled = 0;
while (1) {
myled = !myled;
wait(1);
}
}

Wii Nunchuk Servobot

After a healthy dose of Avatar on my new LG Passive 3D TV I decided to attempt a bit of Mech building myself to build the weapon to defeat the Blue creatures wtih the Green agenda.

<a href="“>

Bill of Materials: wiithing.fz

Sunday, September 11 2011, 16:08:18
Assembly List

Label
Part Type
Properties
Arduino1 Arduino processor ATmega; variant Arduino
J1 Basic Servo

J2 Basic Servo

U1 3-Axis Accelerometer Breakout axes 3 (x, y, z); chip ADXL

Shopping List

Amount
Part Type
Properties
1 3-Axis Accelerometer Breakout axes 3 (x, y, z); chip ADXL
1 Arduino processor ATmega; variant Arduino
2 Basic Servo

Schematic
wpid-wiithing_schem-2011-09-1-18-27.png

Breadboard

wpid-wiithing_bb-2011-09-1-18-27.png

Arduino Sheild
wpid-wiithing_pcb-2011-09-1-18-27.png

Code

nclude <Wire.h>
#include <string.h>
#include <stdio.h>

uint8_t outbuf[6];

int cnt = 0;
int ledPin = 13;

int servoPin = 7;
int servoPin2 = 6;

int pulseWidth = 0;
int pulseWidth2 = 0;

long lastPulse = 0;
long lastPulse2 = 0;

int z_button = 0;
int c_button = 0;

int refreshTime = 20;

int minPulse = 1000;
int minPulse2 = 500;

int dtime=10;

#define pwbuffsize 10
long pwbuff[pwbuffsize];
long pwbuffpos = 0;
long pwbuff2[pwbuffsize];
long pwbuffpos2 = 0;

void setup()
{
Serial.begin (19200);
Wire.begin ();
nunchuck_init ();
pinMode(servoPin, OUTPUT);
pinMode(servoPin2, OUTPUT);

pulseWidth = minPulse;
pulseWidth2 = minPulse2;
Serial.print (“Finished setup\n”);
}

void nunchuck_init()
{
Wire.beginTransmission (0x52);
Wire.send (0x40);
Wire.send (0x00);
Wire.endTransmission ();
}

void send_zero()
{
Wire.beginTransmission (0x52);
Wire.send (0x00);
Wire.endTransmission ();
}

int t = 0;

void loop()
{
t++;
long last = millis();

if( t == 1) {

t = 0;

Wire.requestFrom (0x52, 6);

while (Wire.available ()) {
outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());
digitalWrite (ledPin, HIGH);
cnt++;
}

if (cnt >= 5) {

printNunchuckData();

int z_button = 0;
int c_button = 0;

if ((outbuf[5] >> 0) & 1)
z_button = 1;
if ((outbuf[5] >> 1) & 1)
c_button = 1;

switch (c_button) {
case 1:
switch (z_button) {
case 0:
break;
case 1:
muovi();
break;
}
break;
case 0:
switch (z_button) {
case 0:
delay(10000);
break;
case 1:
delay(3000);
break;
}
break;
}
}

cnt = 0;
send_zero();

} // if(t==)

updateServo();

delay(dtime);
}

void updateServo() {

if (millis() – lastPulse >= refreshTime) {

digitalWrite(servoPin, HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(servoPin, LOW);

digitalWrite(servoPin2, HIGH);
delayMicroseconds(pulseWidth2);
digitalWrite(servoPin2, LOW);

lastPulse = millis();
}
}

int i=0;
void printNunchuckData()
{
int joy_x_axis = outbuf[0];
int joy_y_axis = outbuf[1];
int accel_x_axis = outbuf[2]; // * 2 * 2;
int accel_y_axis = outbuf[3]; // * 2 * 2;
int accel_z_axis = outbuf[4]; // * 2 * 2;

int z_button = 0;
int c_button = 0;

if ((outbuf[5] >> 0) & 1)
z_button = 1;
if ((outbuf[5] >> 1) & 1)
c_button = 1;
if ((outbuf[5] >> 2) & 1)
accel_x_axis += 2;
if ((outbuf[5] >> 3) & 1)
accel_x_axis += 1;

if ((outbuf[5] >> 4) & 1)
accel_y_axis += 2;
if ((outbuf[5] >> 5) & 1)
accel_y_axis += 1;

if ((outbuf[5] >> 6) & 1)
accel_z_axis += 2;
if ((outbuf[5] >> 7) & 1)
accel_z_axis += 1;

Serial.print (i,DEC);
Serial.print (“\t”);

Serial.print (“X: “);
Serial.print (joy_x_axis, DEC);
Serial.print (“\t”);

Serial.print (“Y: “);
Serial.print (joy_y_axis, DEC);
Serial.print (“\t”);

Serial.print (“AccX: “);
Serial.print (accel_x_axis, DEC);
Serial.print (“\t”);

Serial.print (“AccY: “);
Serial.print (accel_y_axis, DEC);
Serial.print (“\t”);

Serial.print (“AccZ: “);
Serial.print (accel_z_axis, DEC);
Serial.print (“\t”);

Serial.print (z_button, DEC);
Serial.print (” “);
Serial.print (c_button, DEC);
Serial.print (“\r\n”);
i++;
}

char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}

void muovi (){
float tilt = (700 – outbuf[3]*2*2);
float tilt2 = outbuf[2]*2*2;

tilt = (tilt);
pulseWidth = (tilt * 5) + minPulse;

tilt2 = (tilt2-288);
pulseWidth2 = (tilt2 * 5) + minPulse2;

pwbuff[pwbuffpos] = pulseWidth;
pwbuff2[pwbuffpos2] = pulseWidth2;

if( ++pwbuffpos == pwbuffsize ) pwbuffpos = 0;
if( ++pwbuffpos2 == pwbuffsize ) pwbuffpos2 = 0;

pulseWidth=0;
pulseWidth2=0;

for( int p=0; p<pwbuffsize; p++ ){
pulseWidth += pwbuff[p];
pulseWidth2 += pwbuff2[p];
}

pulseWidth /= pwbuffsize;
pulseWidth2 /= pwbuffsize;

}

Don’t trust a plumber, “Trust in Arduino” – Hydrogen Sulfide Gas Detector

Some time ago I had nasty smells in my kitchen and no I didn’t leave an egg salad on the table for a few weeks or a bucket of prawns in the sun… The smell was hydrogen sulfide or commonly know as sewer gas. My first step was to get a plumber in to try and trace the issue, it was intermittent and not constant so it was quite difficult to pinpoint. To me it was an issue with the venting of the outside main sewer link into my house but the plumber assured me that the venting was done fine as he worked on the house originally when it was renovated. About once a day, usually in the mornings we got this horrific stink only for a few minutes or so. Not trusting the plumber after all this I decided to look into Gas Sensors and found the Figaro TGS 2602 sensor which does loads of other gasses apart from hydrogen sulfide see data sheet http://www.figarosensor.com/products/2602pdf.pdf. I bought a bunch of these and hooked them up to Arduino UNOs and placed them all over the house. Well believe it or not the first sensor to go off was not in my kitchen but in my attic and as hydrogen sulfide is a heavy gas I was in a quandary. So I had a look inside the roof to attic cavity and lo and behold the vent pipe did not go out onto the roof. This meant that the gas while heavy was going down the wall cavity three flights and under the kitchen floor to the other side of the room. Problem solved, plumber on end of angry phone call….

I threw the design into Fritzing to share to all for the next time your plumber is a lazy #*^%$# and won’t look in the roof.

Full project is here http://fritzing.org/projects/hydrogen-sulfide-gas-detector-sewer-gas/

Here is the Fritzing part for the 2602 gas sensor Download

I used an xbee shield on the Arduino UNOs so I could do it wirelessly around the house with multiples. I won’t go into how to setup an xbee mesh try here http://www.digi.com/pdf/wp_zigbeevsdigimesh.pdf

The base code is simple

int gasSensor = 0; // select input pin for gasSensor
int val = 0; // variable to store the value coming from the sensor

void setup() {
Serial.begin(9600);
}

void loop() {
val = analogRead(gasSensor); // read the value from the pot
Serial.println( val );
delay(100);
}

Lets link it to Pachube so I can monitor it on my iPhone. This requires another Arduino UNO with an xbee and an Arduino Ethernet Shield. See http://Pachube.com

#include <SPI.h>
#include <Ethernet.h>

// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
byte ip[] = {
10,0,1,95 };
byte gateway[] = {
10,0,1,1};        
byte subnet[] = {
255, 255, 255, 0 };

// The address of the server you want to connect to (pachube.com):
byte server[] = {
173,203,98,29 };

// initialize the library instance:
Client client(server, 80);

long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const int postingInterval = 10000; //delay between updates to Pachube.com

void setup() {
// start the ethernet connection and serial port:
Ethernet.begin(mac, ip);
Serial.begin(9600);
// give the ethernet module time to boot up:
delay(1000);
}

void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);

// if there’s incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}

// if there’s no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println(“disconnecting.”);
client.stop();
}

// if you’re not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() – lastConnectionTime > postingInterval)) {
sendData(sensorReading);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void sendData(int thisData) {
// if there’s a successful connection:
if (client.connect()) {
Serial.println(“connecting…”);
// send the HTTP PUT request.
// fill in your feed address here:
client.print(“PUT /api/feeds/14050.csv HTTP/1.1\n”);
client.print(“Host: www.pachube.com\n”);
// fill in your Pachube API key here:
client.print(“X-PachubeApiKey: 069557631a9d5ee274840079dc8ea66c2c2758b0cdfeeae6f1c730f7f366a215\n”);
client.print(“Content-Length: “);

// calculate the length of the sensor reading in bytes:
int thisLength = getLength(thisData);
client.println(thisLength, DEC);

// last pieces of the HTTP PUT request:
client.print(“Content-Type: text/csv\n”);
client.println(“Connection: close\n”);

// here’s the actual content of the PUT request:
client.println(thisData, DEC);

// note the time that the connection was made:
lastConnectionTime = millis();
}
else {
// if you couldn’t make a connection:
Serial.println(“connection failed”);
}
}

// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
// there’s at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you’re at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
}

Create the Page

<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
        “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>

<html xmlns=“http://www.w3.org/1999/xhtml” xml:lang=“en”>
<head>
        <title>Gas Sensor Hydrogen Sulfide</title>
        
</head>

<body>
<script type=“text/javascript” src=“http://www.google.com/jsapi”></script><script language=“JavaScript” src=“http://apps.pachube.com/google_viz/viz.js”></script><script language=“JavaScript”>createViz(14050,0,600,200,”FF0066”);</script>

</body>
</html>

Pachube Output

wpid-snapzproxscreensnapz003-2011-08-21-19-55.jpg

Schematic

wpid-voila_capture-2011-08-21-19-55.png

Breadboard layout

wpid-voila_capture2-2011-08-21-19-55.png

PCB

wpid-voila_capture3-2011-08-21-19-55.png

Your done!

Enjoy smell free air 🙂

Mctouch

Bus Pirate Test – BlinkM

Just received a Bus Pirate from Coolcomponents.co.uk, its the Sparkfun Bus Pirate with their ribbon cable and not the Seeedstudio (Dangerous Prototypes) so be prepared to reverse the order of the colour pin outs. This was my first point of confusion in that the Firmware menu nicely identifies the pin outs for the colour ribbon cable but these are back to front on the Sparkfun device and ribbon cable.

HiZ>v
Pinstates:
1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk)
GND 3.3V 5.0V ADC VPU AUX CLK MOSI CS MISO
…..

Don’t follow the output from the v command above for colour alignment, the below chart is for the ribbon cable for the Sparkfun Bus Pirate so GND is not Brown it is Black(which is bleeding obvious for normal conventions). Work your way across from black for the Voltage values i.e. it should really be 1.(Blk) 2.(WT) 3.(GR) etc..

wpid-buspirate-2011-08-21-11-39.png

Ok before you start grab two Jumpers and follow the instructions for the self test here http://dangerousprototypes.com/docs/Bus_Pirate_self-test_guide.

All OK? time to move on.

As I am a bit of a noob I used the Blinkm http://thingm.com/products/Blinkm to test with as it is simple and well documented. DOWNLOAD DATASHEET

The Blinkm uses I2C as a communications protocol so we need to use the black and white wires on the PWR -(GND) and +(3v) pins and the yellow and orange wires on the c(CLK) and d(MOSI) pins. In addition you need to have voltage applied to the pull up resistors (VPU) which is the blue wire. The Sparkfun ribbon doesn’t come with probes so I borrowed one from my Saleae Logic Analyser http://www.saleae.com/logic/ .

wpid-img_0461-2011-08-21-11-39.jpg

Now that everything is hooked up its time to log into the Firmware, I am primarily a Mac user so I downloaded http://homepage.mac.com/dalverson/zterm/ and followed the instructions to connect to the bus pirate serially from here http://brettinman.com/2009/07/24/using-the-bus-pirate-v2go-on-mac/ . There are loads of other terminal programs that will work like ‘screen’ in the various unix flavours.

Note that the Bus Pirate wants you to connect at its default 115200 Data Rate, zterm doesn’t want to keep this setting each time I start it up so you need to set it each time, no biggie…

So now you should be connected… and you will see something like the following in the terminal screen.

Bus Pirate v3a
Firmware v5.10 (r559) Bootloader v4.4
DEVID:0x0447 REVID:0x3043 (24FJ64GA002 B5)
http://dangerousprototypes.com
HiZ>

Help on the Firmware shell commands is quite easy, ‘?’, a questionmark will render the following.

HiZ>?
General Protocol interaction
—————————————————————————
? This help                 (0) List current macros
=X/|X Converts X/reverse X         (x) Macro x
~ Selftest                 [ Start
# Reset                 ] Stop
$ Jump to bootloader         { Start with read
&/% Delay 1 us/ms         } Stop
a/A/@ AUXPIN (low/HI/READ) “abc” Send string
b Set baudrate                 123
c/C AUX assignment (aux/CS) 0x123
d/D Measure ADC (once/CONT.) 0b110 Send value
f Measure frequency         r Read
g/S Generate PWM/Servo         / CLK hi
h Commandhistory         \ CLK lo
i Versioninfo/statusinfo         ^ CLK tick
l/L Bitorder (msb/LSB)         - DAT hi
m Change mode         _ DAT lo
o Set output type                 . DAT read
p/P Pullup resistors (off/ON)         ! Bit read
s Script engine                 : Repeat e.g. r:10
v Show volts/states                 . Bits to read/write e.g. 0x55.2
w/W PSU (off/ON) <x>/<x=         >/<0> Usermacro x/assign x/list all

One thing I can’t work out is why the ‘h’ command results in a syntax error, ‘Syntax error at char 1’. Must be something with my Firmware version. h is suppost to show my Command History…

Ok so we know we are using I2C so we can list the protocols by issuing the ‘m’ command and hitting ‘4’. More on I2C http://dangerousprototypes.com/docs/Bus_Pirate_I2C

HiZ>m
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
9. DIO
x. exit(without change)

(1)>4

resulting in:

Set speed:
1. ~5KHz
2. ~50KHz
3. ~100KHz
4. ~400KHz

(1)>

Take the default (1)> by just hitting enter.

(1)>
Ready
I2C>

Now you are at the I2C prompt, by hitting ‘i’ you will get a listing about the current Bus Pirate System Information.

I2C>i
Bus Pirate v3a
Firmware v5.10 (r559) Bootloader v4.4
DEVID:0x0447 REVID:0x3043 (24FJ64GA002 B5)
http://dangerousprototypes.com
CFG1:0xFFDF CFG2:0xFF7F
*———-*
Pinstates:
1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk)
GND 3.3V 5.0V ADC VPU AUX SCL SDA – –
P P P I I I I I I I
GND 0.00V 0.00V 0.00V 0.00V L L L L L
Power supplies OFF, Pull-up resistors OFF, Open drain outputs (H=Hi-Z, L=GND)
MSB set: MOST sig bit first, Number of bits read/write: 8
a/A/@ controls AUX pin
I2C (mod spd)=( 0 0 )
*———-*
I2C>

Ok so now we need to apply some power to the Blinkm. Hit capital ‘W’

I2C>W
Power supplies ON
I2C>

The Blinkm should now light and run into its default script of cycling through colours.

To be able to sniff and write commands to the Blinkm we need to raise pull up resistors in the Bus Pirate to high. http://dangerousprototypes.com/docs/Practical_guide_to_Bus_Pirate_pull-up_resistors

I2C is an open-collector bus, it requires pull-up resistors to hold the clock and data lines high and create the data ‘1’. I2C parts don’t output high, they only pull low, without pull-up resistors there can never be a ‘1’.
So to get the pullup resistors to high issue a capital ‘P’.
I2C>P
Pull-up resistors ON
To save time you can issue a ‘WP’ to turn on the power and raise the pull up resistor.
I2C>PW
You should now have the power on and the pull up resistors on, to check this issue an ‘i’ again.

1I2C>i
Bus Pirate v3a
Firmware v5.10 (r559) Bootloader v4.4
DEVID:0x0447 REVID:0x3043 (24FJ64GA002 B5)
http://dangerousprototypes.com
CFG1:0xFFDF CFG2:0xFF7F
*———-*
Pinstates:
1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk)
GND 3.3V 5.0V ADC VPU AUX SCL SDA – –
P P P I I I I I I I
GND 3.28V 4.96V 0.00V 3.28V L H H H H
Power supplies ON, Pull-up resistors ON, Open drain outputs (H=Hi-Z, L=GND)
MSB set: MOST sig bit first, Number of bits read/write: 8
a/A/@ controls AUX pin
I2C (mod spd)=( 0 0 )
*———-*
I2C>

Notice that the voltages have changed on the pins and that power and pull-ups is ON.
Here is where I’m going to help you cheat a bit, normally we would run a macro I2C>(1) or enter (1) at the prompt, this sniffs the available addresses for you but for now lets get straight to issuing a few commands against the Blinkm.

The default Blinkm script is still running so we need to stop it.
[0x00 “o”] stop the running script on the Blinkm

I2C>[0x00 “o”]
I2C START BIT
WRITE: 0x00 ACK
WRITE: “o ACK”
I2C STOP BIT
I2C>

The Blinkm default script should now be off and the led will be lit at the colour the script happened to be in when we issued the stop command. In the image below I stopped it when it was in the off cycle.
wpid-img_0463-2011-08-21-11-39.jpg

The Blinkm address is 7-bit plus one bit for R/W. Blinkm 0x09 is 0x12 for writing and 0x13 for reading.

[0x12 “a” {0x13 r] read the address of Blinkm 0x09

I2C>[0x12 “a” {0x13 r]
I2C START BIT
WRITE: 0x12 ACK
WRITE: “a ACK”
I2C START BIT
WRITE: 0x13 ACK
READ: 0x09
NACK
I2C STOP BIT
I2C>

Lets set the LED to Red.
[0x12 “n” 0xff 0x00 0x00] set Blinkm 0x09 to Red

I2C>[0x12 “n” 0xff 0x00 0x00]
I2C START BIT
WRITE: 0x12 ACK
WRITE: “n ACK”
WRITE: 0xFF ACK
WRITE: 0x00 ACK
WRITE: 0x00 ACK
I2C STOP BIT
I2C>

wpid-img_0465-2011-08-21-11-39.jpg

Ok to confirm we have set the address for Red we can check the current colour.
[0x12 “g” {0x13 rrr] read the current colour of Blinkm 0x09

I2C>[0x12 “g” {0x13 rrr]
I2C START BIT
WRITE: 0x12 ACK
WRITE: “g ACK”
I2C START BIT
WRITE: 0x13 ACK
READ: 0xFF
READ: ACK 0x00
READ: ACK 0x00
NACK
I2C STOP BIT
I2C>

Alright, it works the term ‘Bus Pirate’ is apt but we haven’t actually done any sniffing of what is actually available to us as addresses.

Sure we can look at the Blinkm data sheet but lets do the address sniff then to see what devices we have access to.

I2C>(1)
Searching I2C address space. Found devices at:
0x00(0x00 W) 0x12(0x09 W) 0x13(0x09 R) 0x14(0x0A W) 0x15(0x0A R) 0x16(0x0B W) 0x
17(0x0B R) 0x18(0x0C W) 0x19(0x0C R) 0x1A(0x0D W) 0x1B(0x0D R) 0x1C(0x0E W) 0x1D
(0x0E R) 0x1E(0x0F W) 0x1F(0x0F R) 0x20(0x10 W) 0x21(0x10 R) 0x22(0x11 W) 0x23(0
x11 R) 0x24(0x12 W) 0x25(0x12 R) 0x26(0x13 W) 0x27(0x13 R) 0x28(0x14 W) 0x29(0x1
4 R) 0x2A(0x15 W) 0x2B(0x15 R) 0x2C(0x16 W) 0x2D(0x16 R) 0x2E(0x17 W) 0x2F(0x17
R) 0x30(0x18 W) 0x31(0x18 R) 0x32(0x19 W) 0x33(0x19 R) 0x34(0x1A W) 0x35(0x1A R)
0x36(0x1B W) 0x37(0x1B R) 0x38(0x1C W) 0x39(0x1C R) 0x3A(0x1D W) 0x3B(0x1D R) 0
x3C(0x1E W) 0x3D(0x1E R) 0x3E(0x1F W) 0x3F(0x1F R) 0x40(0x20 W) 0x41(0x20 R) 0x4
2(0x21 W) 0x43(0x21 R) 0x44(0x22 W) 0x45(0x22 R) 0x46(0x23 W) 0x47(0x23 R) 0x48(
0x24 W) 0x49(0x24 R) 0x4A(0x25 W) 0x4B(0x25 R) 0x4C(0x26 W) 0x4D(0x26 R) 0x4E(0x
27 W) 0x4F(0x27 R) 0x50(0x28 W) 0x51(0x28 R) 0x52(0x29 W) 0x53(0x29 R) 0x54(0x2A
W) 0x55(0x2A R) 0x56(0x2B W) 0x57(0x2B R) 0x58(0x2C W) 0x59(0x2C R) 0x5A(0x2D W
) 0x5B(0x2D R) 0x5C(0x2E W) 0x5D(0x2E R) 0x5E(0x2F W) 0x5F(0x2F R) 0x60(0x30 W)
0x61(0x30 R) 0x62(0x31 W) 0x63(0x31 R) 0x64(0x32 W) 0x65(0x32 R) 0x66(0x33 W) 0x
67(0x33 R) 0x68(0x34 W) 0x69(0x34 R) 0x6A(0x35 W) 0x6B(0x35 R) 0x6C(0x36 W) 0x6D
(0x36 R) 0x6E(0x37 W) 0x6F(0x37 R) 0x70(0x38 W) 0x71(0x38 R) 0x72(0x39 W) 0x73(0
x39 R) 0x74(0x3A W) 0x75(0x3A R) 0x76(0x3B W) 0x77(0x3B R) 0x78(0x3C W) 0x79(0x3
C R) 0x7A(0x3D W) 0x7B(0x3D R) 0x7C(0x3E W) 0x7D(0x3E R) 0x7E(0x3F W) 0x7F(0x3F
R) 0x80(0x40 W) 0x81(0x40 R) 0x82(0x41 W) 0x83(0x41 R) 0x84(0x42 W) 0x85(0x42 R)
0x86(0x43 W) 0x87(0x43 R) 0x88(0x44 W) 0x89(0x44 R) 0x8A(0x45 W) 0x8B(0x45 R) 0
x8C(0x46 W) 0x8D(0x46 R) 0x8E(0x47 W) 0x8F(0x47 R) 0x90(0x48 W) 0x91(0x48 R) 0x9
2(0x49 W) 0x93(0x49 R) 0x94(0x4A W) 0x95(0x4A R) 0x96(0x4B W) 0x97(0x4B R) 0x98(
0x4C W) 0x99(0x4C R) 0x9A(0x4D W) 0x9B(0x4D R) 0x9C(0x4E W) 0x9D(0x4E R) 0x9E(0x
4F W) 0x9F(0x4F R) 0xA0(0x50 W) 0xA1(0x50 R) 0xA2(0x51 W) 0xA3(0x51 R) 0xA4(0x52
W) 0xA5(0x52 R) 0xA6(0x53 W) 0xA7(0x53 R) 0xA8(0x54 W) 0xA9(0x54 R) 0xAA(0x55 W
) 0xAB(0x55 R) 0xAC(0x56 W) 0xAD(0x56 R) 0xAE(0x57 W) 0xAF(0x57 R) 0xB0(0x58 W)
0xB1(0x58 R) 0xB2(0x59 W) 0xB3(0x59 R) 0xB4(0x5A W) 0xB5(0x5A R) 0xB6(0x5B W) 0x
B7(0x5B R) 0xB8(0x5C W) 0xB9(0x5C R) 0xBA(0x5D W) 0xBB(0x5D R) 0xBC(0x5E W) 0xBD
(0x5E R) 0xBE(0x5F W) 0xBF(0x5F R) 0xC0(0x60 W) 0xC1(0x60 R) 0xC2(0x61 W) 0xC3(0
x61 R) 0xC4(0x62 W) 0xC5(0x62 R) 0xC6(0x63 W) 0xC7(0x63 R) 0xC8(0x64 W) 0xC9(0x6
4 R) 0xCA(0x65 W) 0xCB(0x65 R) 0xCC(0x66 W) 0xCD(0x66 R) 0xCE(0x67 W) 0xCF(0x67
R) 0xD0(0x68 W) 0xD1(0x68 R) 0xD2(0x69 W) 0xD3(0x69 R) 0xD4(0x6A W) 0xD5(0x6A R)
0xD6(0x6B W) 0xD7(0x6B R) 0xD8(0x6C W) 0xD9(0x6C R) 0xDA(0x6D W) 0xDB(0x6D R) 0
xDC(0x6E W) 0xDD(0x6E R) 0xDE(0x6F W) 0xDF(0x6F R) 0xE0(0x70 W) 0xE1(0x70 R) 0xE
2(0x71 W) 0xE3(0x71 R) 0xE4(0x72 W) 0xE5(0x72 R) 0xE6(0x73 W) 0xE7(0x73 R) 0xE8(
0x74 W) 0xE9(0x74 R) 0xEA(0x75 W) 0xEB(0x75 R) 0xEC(0x76 W) 0xED(0x76 R) 0xEE(0x
77 W) 0xEF(0x77 R) 0xF0(0x78 W) 0xF1(0x78 R) 0xF2(0x79 W) 0xF3(0x79 R) 0xF4(0x7A
W) 0xF5(0x7A R) 0xF6(0x7B W) 0xF7(0x7B R) 0xF8(0x7C W) 0xF9(0x7C R) 0xFA(0x7D W
) 0xFB(0x7D R) 0xFC(0x7E W) 0xFD(0x7E R) 0xFE(0x7F W) 0xFF(0x7F R)

I2C>

The problem when we issue the (1) macro is that it seems to mark the pullup resistors low even though the Firmware tells it is on.

I2C>(1)
Searching I2C address space. Found devices at:
Warning: *Short or no pull-up

I2C>i
Bus Pirate v3a
Firmware v5.10 (r559) Bootloader v4.4
DEVID:0x0447 REVID:0x3043 (24FJ64GA002 B5)
http://dangerousprototypes.com
CFG1:0xFFDF CFG2:0xFF7F
*———-*
Pinstates:
1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk)
GND 3.3V 5.0V ADC VPU AUX SCL SDA – –
P P P I I I I I I I
GND 3.27V 4.96V 0.00V 3.36V L H L H H
Power supplies ON, Pull-up resistors ON, Open drain outputs (H=Hi-Z, L=GND)
MSB set: MOST sig bit first, Number of bits read/write: 8
a/A/@ controls AUX pin
I2C (mod spd)=( 0 0 )
*———-*
I2C>

The only way I can solve this issue is to reset the Bus Pirate by entering a ‘#’ and then starting again.

I2C>#
HiZ>m
I2C>WP

Ok so I cheated for you at first but now we have a list of Address Devices. What do we do from here.

EXPERIMENT….

Start trying some of the addresses to see what you get and slowly reverse engineer the logic from the Blinkm

What next?

Use the addresses from a micro controller, lets try the Arduino.

http://www.arduino.cc/en/Reference/Wire

I am using an Arduino UNO so SDA (data line) is on analog input pin 4, and SCL (clock line) is on analog input pin 5.
There are both 7- and 8-bit versions of I2C addresses. 7 bits identify the device, and the eighth bit determines if it’s being written to or read from. The Wire library uses 7 bit addresses throughout and so does the Blinkm so for an Arduino sketch we can use 0x09.

#include “Wire.h”

void setup()
{
Serial.begin(9600);
Wire.begin(); // set up I2C
Wire.beginTransmission(0x09); // join I2C, talk to Blinkm 0x09
Wire.send(0x6f); // stop the Blinkm script
Wire.endTransmission(); // leave I2C bus

}

void loop()
{

}