Dancing Rumba with the vacuum cleaner

WARNING – this is a bit more dangerous than the usual stuff (higher voltage, expensive equipment, moving machine). I reject any responsibility for anything.

Once upon a time there was one of the first autonomic vacuum cleaners. It had a nice fancy feature, namely a serial interface to play around with the machine. I had buyed one such thing a while ago – a iRobot roomba 620 – and did not know there was such an interface. When I heard that there was an interface, I could not see it. So the first obstacle here was to find the hidden Mini-DIN 7 interface under the white front  plastic cover of the roomba.

mini_Din_7

The second obstacle was, that the documentation of the producer didn’t match the more recent models any more.

Especially the default serial speed of the interfaces differed in the older docs. I got at least some things working with the interface specification document for the 500 Series.
And this spec mentioned the default baud rate of 115200.

Open Interface Spec:

https://web.archive.org/web/20160116040028/http://irobot.lv/uploaded_files/File/iRobot_Roomba_500_Open_Interface_Spec.pdf

From the spec you can also see the mapping of the pins.

But what would a autonomous device be useful when it’s cable bound to the “programmer”?  So here the HC-06 Bluetooth / Serial module comes really handy.
My plan was to control the vacuum cleaner from a PC program – a python script in this case.

The arduino + HC-06 are just the relay for the serial commands that are send from the PC (using Bluetooth).

Kind of HC-06 Spec that was useful to me:

https://web.archive.org/web/20150404121407/http://www.micro4you.com/files/ElecFreaks/Bluetooth%20HC-06.pdf

The HC-06 reveals itself after connection as a COM / Serial-Port on the PC. So it’s ultra convenient to access from most programming languages.

Ingredients:

– iRobot Roomba 620

– Level Shifter 3,3 <=> 5,0

– Transformer x V => 5,0 V

– (Transformer 5 V => 3,3 V, if using no arduino)

– Arduino Uno

– HC-06 Bluetooth to serial dongle, default speed 9600 Baud (if using no arduino this has to be set to the speed of the roomba => 115200 Baud)

– Bluetooth Dongle for the PC or a Laptop with integrated Bluetooth

– Python for scripting

aufbau_Steckplatine

The arduino does nothing more than to forward the signals it gets from the HC-06 to the serial interface of the vacuum cleaner and translate between the speeds.

It might look a little indirect but this was the version that finally did what it should. There were effects that data was lost if I directly forwarded without the “readSerial” flag stuff. Maybe it is a different serial speed issue. Don’t know. Just wanted a quick and dirty prototype to see if this stuff is possible in principle. There are also some risks that the serial commands you want to forward get interpreted by the HC-06, so this is really just for first experimenting.

In the end the arduino inclusive breadboard and co sat on the vaccuum cleaner fed by its voltage.
The following script established the Bluetooth / Serial bridge:

#include <SoftwareSerial.h> SoftwareSerial softSerial(2,3); byte dataSerial = 0; boolean readSerial = false; byte dataSoft = 0; boolean readSoft = false; void setup() { Serial.begin(115200); softSerial.begin(9600); } void loop() { if (softSerial.available()) { dataSerial = softSerial.read(); readSerial = true; } if (readSerial) { Serial.write(dataSerial); readSerial = false; } if (Serial.available()) { dataSoft = Serial.read(); readSoft = true; } if (readSoft) { softSerial.write(dataSoft); readSoft = false; } }

A corresponding python script that I run on the PC part, that plays around with the LEDs:

from serial import Serial import time # COMx must be the right COM port that opens  # after coupling the HD-06 # /UPDATE: use speed of 115200 instead of 9600 if using the "direct" configuration # without the arduino in the middle serOut = Serial('COM14', 9600, timeout=1) # start / wake up: serOut.write(chr(128)) # full control mode serOut.write(chr(132)) # mode 133 powers down for i in range(0,255):  leds = i % 8  # cmd to access the LEDs 4 bytes, see spec  serOut.write(chr(139))  serOut.write(chr(leds))  serOut.write(chr(i))  serOut.write(chr(255))  time.sleep(0.1) serOut.close() 

Update:

All works better when not using the arduino indirection.

  • Therefore an additional 5V => 3.3V Transformator is needed for adjusting the Level for the Levelshifter.
  • The speed of the HC-06 has to be configured to the speed of the roomba serial interface (115200), the command is:
    • AT+BAUD8

LED Matrix and Shift-Registers

I had a slightly rough start with a standard LED Matrix (1588BS).

There was no data sheet easily available for my particular LED matrix, just the principle way of working was explained in pictures like this:

 matrix_01

With the connector pins for the “-” Pole / Anode on the top and the connectors to the

+ Pole / Cathode on the left. So in this picture the connectors on the left side select the row and with the top connectors you select the column of the LEDs to light up.

Unfortunately my matrix seems to be the other way around (‘+’ – selects the column and ‘-‘ selects the row) :)))

To make the things even more complicated, there was no real order in the pins which was what. So it had to be figured out. The first thing to do was to find one of the corner pins to start with as LED Matrix Pin No. 1.  The other pins (2, 3, …, 16) just were numbered clock wise. matrix_02

A multimeter (with Diode Testing Option) was handy to find combinations which pin was for “+” and which other pin was for “-” and which was responsible for which row and which column. The result is in the table below.

matrix_03

 To make it more useful:

 matrix_04

To make the LED in column 1, row 1 light up, a voltage has to be applied from pin 05 (+) to pin 12 (-).

2 x 8 Pins from the LED Matrix are quite a lot pins on the Micro-Controller. To cope with this, shift registers may be the right choice.

Two shift-registers (74HC164) were used to control the matrix. In this particular one DSA and DSB pins are input ports for the serial data (both have to be connected, with the same input – AND logic).
Q0 .. Q7 are the parallel output ports. CP is the clock input port. MR is the master reset which fires on low level (hence we have connect it to the positive voltage in normal operation). Vcc is connected to the operational voltage (2.0 .. 5 V) and GND to ground.

 matrix_05

One shift register I used to control the rows (Q0 .. Q7 connected to pins 12, 03, 04, 14, 06, 15, 10, 09 of the LED matrix) and one for the cols (Q0 .. Q7 connected to to pins 05, 02, 07, 01, 13, 08, 11, 16).

The LED matrix itself is difficult to put properly on a breadboard. I found this nice trick somewhere on instructables, to make the pins accessible and don’t want to use a second bread board:

breadboard

On the micro-controller:

 matrix_06

Example Code:

 byte bm_1[8] = {               0b00111100,                0b01000010,               0b10000001,               0b10000001,               0b10000001,               0b10000001,                0b01000010,               0b00111100             };              byte bm_2[8] =             {               0b00000000,                0b00111100,               0b01000010,               0b01000010,               0b01000010,               0b01000010,                0b00111100,               0b00000000             }; byte bm_3[8] =             {               0b00000000,                0b00000000,               0b00111100,               0b00100100,               0b00100100,               0b00111100,                0b00000000,               0b00000000             };                void setup() {   pinMode(5, OUTPUT);   pinMode(4, OUTPUT);   pinMode(3, OUTPUT);   pinMode(2, OUTPUT);    } void loop() {      // shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[0]);   // shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b01111111); for (int x =0 ; x < 20 ; x++) {   matrixLED(2, 3, 4, 5, bm_1, 1); } delay(5); for (int x =0 ;x <20; x++) {   matrixLED(2, 3, 4, 5, bm_2, 1); } delay(5); for (int x =0; x < 20 ; x ++) {   matrixLED(2, 3, 4, 5, bm_3, 1); } delay(5); } void matrixLED(int dataPinCols, int clockPinCols, int dataPinRows, int clockPinRows, byte bColumns[8], int timeDelay) {       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[0]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b01111111);       delay(timeDelay);                   shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[1]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b10111111);       delay(timeDelay);       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[dataPinCols]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b11011111);       delay(timeDelay);       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[clockPinCols]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b11101111);       delay(timeDelay);       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[dataPinRows]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b11110111);       delay(timeDelay);       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[clockPinRows]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b11111011);       delay(timeDelay);       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[6]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b11111101);       delay(timeDelay);       shiftOut(dataPinCols, clockPinCols, LSBFIRST, bColumns[7]);       shiftOut(dataPinRows, clockPinRows, LSBFIRST, 0b11111110);       delay(timeDelay); } 20160208_193856

Let’s start from an Arduino perspective

The language, the Arduino IDE uses, hides a lot of the things that happen under the cover.

In pure C, the most activities to handle the controller would be writing to certain addresses and hardware registers or reading from certain addresses and hardware registers.
This is usually done by the use of C macros and compiler directives that ensure the right addresses on the device are accessed.

To get into contact with the ‘outer world’ you need to somehow access the peripheral units of the device.

Let’s look at this Arduino example first:

 // declaration of global variables int readOutValue = 0; // run once per startup void setup() { // setup pin nr. 13 as output     pinMode(13, OUTPUT); // and pin 12 as input     pinMode(12, INPUT);       // Activate pullup resistor for the input     digitalWrite(12, HIGH); } // run endless void loop() {     // write pin 13 / LED to HIGH     digitalWrite(13, HIGH);     // wait a second     delay(1000);     // read value on pin 12 // I know, alone regarding the debouncing of inputs // would be alot to say...     readOutValue = digitalRead(12);     // write pin 13 / LED to LOW     digitalWrite(13, LOW); } 

This is more or less the blink sketch.  Turn the onboard LED on and off in an intervall of one second and read the value of pin 12.

On the Arduino DUE / the SAM3X8E  a simple statement like…

 pinMode(13, OUTPUT); 

…would need a lot more preparation in C below the Arduino ‘layer’. The [SAM3X Reference], Chapter 31 – Parallel Input/Output Controller (PIO), gives detailled information about the PIO controller.  You see that certain pins are attached to certain controller ports. They need some preparation before they can be used.
For Arduino the digital pin 13, is attached to PORTB, and addressed as B.27 – as you can look up in the [pin out diagram].
Lets configure the pin as output:

 // declaration of the pin // uint32_t  ledPin = PIO_PB27; void setup() { // put your setup code here, to run once: // pinMode(13, OUTPUT); // Output Enable Register set to Pin 27 PIOB->PIO_OER = pin; } void loop() { // put your main code here, to run repeatedly: // Set Output Data Register drives pin 27 high PIOB->PIO_SODR = pin; // this is still the arduino instruction // is a bit more complicated with native code so I leave it delay(1000); // Clear Output Data Register drives the pin to low PIOB->PIO_CODR = pin; //  digitalWrite(13, LOW); } 

The whole defiinitions and header files can be found in the Arduino package directory, e.g.:

C:\Users\username\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system\CMSIS\Device\ATMEL\sam3xa\include

  • sam3x8e.h
  • pio/pio_sam3x8e.h

 

 

Literature:

  • [SAM3X], SAM3X/SAM3A Series Complete, [1]
  • [pin out diagram], Pinout Diagram Arduino DUE [2]

 

Introduction and Background

This blog is meant to document my starting attempts with micro controllers (since the terms mu – as abbreviation for the micro in micro controller and noob – for newbie – suggests).
The name might be a bit misleading, since the blog focuses on a very small selection, primary the ones produced by ATMEL.

After playing around with the ubiquitous 8-Bit AVR 328p, plugged in the Arduino UNO and Co, I took a look on the 32Bit products, particularly the SAM3X8E used in the Arduino DUE.
It was somewhat disappointing.
For me it seems the community around the latter is really small and the Arduino crew doesn’t pay much effort to the devices special abilities and the supported features are still not mature at time.
So using just the Arduino functions soon reached its limits, especially when (computing) speed and memory resources are important.
Don’t get me wrong. The Arduino crew does a great job for people to get the things started.
And the life time you save is mostly of more value than the loss of efficiency on the device – at least when prototyping.
The boards themselves are really useful for prototyping.
So, I won’t abandon the Arduino world completely, just extend it.
Some resources for the start:

  • Specification and datasheets of the used Hardware
  • A mapping diagram for the pinouts from ATMEL versus Arduino:
  • The Arduino IDE and toolchain:
  • If you want to invest some money  in a book (program AVRs like the 328p  at low level): Make: AVR Programming: Learning to Write Software for Hardware

I also tried Atmel Studio and just used bossac for the upload of the byte code (Hints under the “Getting started/Installation” heading of this article).
The auto completion feature is really helpful and convenient. But the Studio software is sometimes so slow, it outraged me.
Alternativly there are other environments like emBlocks – a modified version of Codeblocks IDE – that looks promising.

The notions especially regarding the DUE hardware can be quiet confusing. Its heart is an ARM ‘processor’. ARM provides just the architecture of a controller to vendors like ATMEL.
I found dozens of documents from ARM itself around the ARM Cortex M3 – but with almost no ‘practical’ value . The implementation according to the architecture is done by vendors (like ATMEL). So, this was the entry point to start with.