Marc's Public Blog - Arduino Hacking

All | Arduino | Bm | Btrfs | Cars | Clubbing | Diving | Electronics | Exercising | Flying | Hiking | Linux | Linuxha | Public | Rc | Snow | Solar | Trips
Most recent entry: 2012-01-23 00:00:00 -- Generated on 2014-11-22 14:26:48 by Rig3 0.4-440



Table of Content for arduino:

More pages: January 2011 May 2011 December 2011 January 2012 September 2013



2011/01/19 Pebble Shield from Arduino Miniconf 2010
π 2011-01-19 00:00 in Arduino
I missed the arduino miniconf in 2010, but I was able to buy the pebble shield from a former participant, along with an arduino mega board. This board was a bit better for me to first learn on than the mobsendat because it had more interactive I/O to play with (potentiometer, LDR, LEDs, LCD display, and more).

This gave me a chance to learn the Aiko framework from Andy Gelme, which allows for registering event handlers that get called at a specified interval. I ended up writing some handlers that were missing, like a button handler that calculates which combination of buttons is pressed from the combined resistance generated by the 3 buttons. I used this to tell the board at what frequency to flash an led based on potentiometer or LDR light input.


slightly improved version with LEDs connected to the relays
slightly improved version with LEDs connected to the relays

I have a video showing this live:

This was a good way to learn how to play with arduino and learn programming, as well as being a test platform for the Zigbee chips I bought. I'll get a chance to do some more serious work on my mobsendat after that.

100_Pebble 101_Pebble 102_Pebble 103_Pebble 105_Pebble_Demo
2011/01/20 Mobsendat Arduino board from Arduino Miniconf 2011
π 2011-01-20 00:00 in Arduino
After the last linux.conf.au, and my going to the arduino miniconf, I got (voluntarily I guess :) conned into learning about a new field: arduino. The learning curve was a bit steep since I started with the second miniconf which featured a pretty sweet board, the mobsendat one of the volunteers had just designed.
Mobsendat (mobile sensor data) offers pretty good IO that's useful to log to its built in sdcard: a DS18B20 1-wire temp sensor, a barometer (with 2nd temperature reading), a 3 axis accelerometer, and connectivity for a GPS, a 433Mhz radio chip, and a Zigbee chip, all this for barely over $100. It was designed to be put in rocket bodies to record the flights, but I figured I'd find other uses for it :)

I got to solder the whole thing during the miniconf:


all done
all done

Putting aside some problems due to a short in my board that came from a pre-soldered chip (not my fault :) ), it worked great. I was even able to hack in a dirty mod to let me unplug the GPS when I don't need it


Programming with arduino was reasonably easy. I haven't done much work on that specific board yet, but I have on the other one (next post).

200_MobSenDat 201_MobSenDat 205_MobSenDat 206_MobSenDat 207_MobSenDat 208_MobSenDat
2011/05/06 PC/Breadboard Xbee Adapters: Sparkfun and Adafruit
π 2011-05-06 00:00 in Arduino
When I was getting into Xbee, it wasn't too clear to me what was the recommended interface for the PC size.

While there actually are expensive-ish dedicated PC adapters, the short story is that most folks actually use the same Xbee chips that you put on your arduino shields, and use an adapter that can be connected to USB.

For this you have two to chose from, and I'll explain them both (I got both to try them out, and each has its strong points and weaknesses). This is what they look like (the sparkfun one is red):


Sparkfun

The sparkfun adapter costs a bit more, but it has the built in FTDI chip, so it comes with a mini USB connector and it ready to connect to your PC: no fuss. It also comes with a very handy set of LEDs: serial RX/TX, and RSSI (which shows if RF data was received). The big plus is also that it's already all soldered and ready to use. Oh, the module also easily supports longer Xbee Pro modules.
Its only shortfalls are the lack of AI LED (which comes in handy to show that the module has joined an active network) and no reset jumper, which can be required to blind flash modules or reset modules with ZB END device firmware (which goes to sleep by itself and can't be talked to with X-Ctu without a reset).

Ladyada

Those modules need to be soldered. It's not very hard, but it's time consuming and it's easy to put solder inside the xbee headers. One of my modules wasn't working right until I figured that the problem were the headers had a bit of solder and prevented a consistent good contact. The other shortfalls are the lack of serial RX/TX LEDs which are crutial for knowing that your blind flashing is working, and the default build doesn't accomodate Xbee Pro modules well (you have to bend the resistor and capacitor out of the way like in the picture above).

On the plus side, there is no FTDI chip on there, so they're cheap ($10) and you can use a 3rd party 5 pin adapter cable you may already have, or if you buy one now, you'll be able to reuse it later to flash some arduinos like the AT mega 328.

If you're planning on mostly plugging your Xbee into a breadboard, the Ladyada option is cheaper since you can solder header pins and use the adapter without ever paying for an FTDI cable (or more generally share one cable for multiple modules).

Hardware Reset

Sometimes you have a flash a non responsive Xbee module, it may be a ZB End device firmware that is in sleep all the time, or you just don't know the module speed and don't feel like finding out, you can flash the module with X-ctu and reset the module when it tells you to.
But to do this, you need a reset switch, which neither of those two modules has.

I ended up foldering a PC jumper on both modules as shown in the pictures, and that would be a worthwhile addition to both modules by default.


The procedure for blind flashing is explained here and there:

  • Set speed to 38400, API disabled
  • in modem conf, select right firmware
  • set baud rate in serial interacing option to 38400
  • set always update firmware and start write with module not plugged in
  • when error message on pushing reset appears, plug module in
  • 100_Xbee_Adapters 101_Xbee_Adapters 102_Xbee_Adapters 103_Xbee_Adapters
    2011/05/11 Reducing Xbee Power Consumption on my Mobsendat Board
    π 2011-05-11 00:00 in Arduino
    TL;DR: By using Xbee pin sleep, I was able to bring my board power consumption from 100mA-ish to 35mA-ish average by ensuring that the Xbee radio is off most of the time (unfortunately, it doesn't have a mode where you can just have it be send only and wake up the RF radio only when you give it serial data).

    Longer version:
    I've been using my Mobsendat Board to log my [sleep positions|], and both for fun, and because I'm lazy, I've been using Xbee to send data from the mobsendat to my PC.
    I used some Xbee Pro modules because I wanted to get as long a range as possible, and because the data may have to go through my body, which is some kind of RF shield.

    First, I tried the Xbee 1 modules, because they were easier to get and a bit easier to program since more people were using them. My mobsendat board was using 33mA and with the Xbee 1 module, would go between 80 and 110mA. This is of course a fair amount of power.

    I then upgraded the modules to Xbee 2.5 ZB Pro modules, and that shaved off 10mA or so. It was however clear that I would have to put the modules to sleep to save further.

    To do this, I used some of the free pins on the AT mega 328, and wired up:

  • AT Mega Pin 14 (Digital 8) -> Xbee DTR
  • AT Mega Pin 16 (Analog 2) <- Xbee RSSI
  • AT Mega Pin 17 (Analog 3) <- Xbee Assoc
  • The Xbee was flashed with the latest ZB end device AT firmware with pin sleep (be careful, the default setting of cyclic sleep puts the module to sleep as soon as it's flashed, so even X-Ctu can't re-read its settings without having the module be reset). See my page Xbee Adapter page with reset pin hack.
    I left the pullup resistor enabled in the Xbee, so I was able to use simple wires to connect the pins.


    Xbee sleep works like this: bringing DTR up puts the module to sleep if it's not in the process of sending/resending data (that's nice, you don't have to worry about waiting for an ACK which you can't read in AT mode before putting the device to sleep, you can just fill its buffer, give it the sleep signal and it'll go to sleep when it's done sending).

    This works great: by putting the module to sleep for 95% of the time or so (I transmit every 5 sec), the power use goes back to 33mA for most of the time (with quick peaks to 100mA during send).

    Now, for how to deal with sleep more intelligently:

    If you have AI/RSSI LEDs and your module is not associated, you can easily see that sleep will not put the module to sleep after sending data until all the retries have failed.
    In my case, I wired the RSSI and Assoc outputs to my arduino inputs so that I could read the analog values. If you're sending data from an end device, you can read RSSI as a poor's man ack value by keeping track of last time it was high (defined as between 32 and 1024 on my system since it a signal strength value and anything below 32 has been noise in my experience). What this means is that by reading RSSI multiple loop cycles in a row, I can detect when I'm not receiving any data (and therefore missing acks) and not put the module to sleep at all with the hope that it will "reconnect" on its own.

    One might thing that you can read the Assoc value to guess whether AI=0 (associated) or not. Note that the LED actually shows solid when not associated and will blink when associated, so it's not as easy as just getting an on/off value. To deal with this one, I actually read the LED output value multiple times, average it, and if it's flashing, I'll get less than 800 avg (out of 1024).

    Now, this is where it gets more counter intuitive: AI (association) unfortunately does not go back to unassociated when I remove the router or coordinator in my network. What this means is that I can't detect if my module can't talk to the network by using AI (only getting ACK return values can really tell me that, and I'd have to switch to API mode for that). But, there is a trick: if the module is waiting for ACKs, it will not go to sleep, and AI will normally flash. When that happens, I will read Assoc analog values that are less than 800 and by averaging a few, I can tell that the LED is flashing and therefore that the module isn't going to sleep.
    Neat, eh?

    This is what my data looks like when I have RF issues:

    "2011/05/24 05:53:29",,X:0.13,Y:-1.00,Z:0.11,V:4.96,left,rssi:904(DC:0),assoc:847(avg:844)
    "2011/05/24 05:53:34",,X:0.15,Y:-1.00,Z:0.14,V:4.92,left,rssi:904(DC:0),assoc:844(avg:844)
    "(DC:4),assoc:0(avg:337|ANS)
    "2011/05/24 05:53:59",,X:0.14,Y:-1.00,Z:0.13,V:4.97,left,rssi:0(DC:5),assoc:842(avg:337|ANS)
    "2011/05/24 05:54:04",,X:0.14,Y:-1.00,Z:0.12,V:4.97,left,rssi:0(DC:6|RNS),assoc:842(avg:336|ANS)
    It shows rssi dropping to 0 with DC:5 (down count due to RSSI being 0), and assoc average having dropped from 844 to 337 (we don't see instant low assoc values since they were not transmitted outside of the truncated line).

    Next step is lowering down the Mobsendat power base consumption from 33mA to 12mA by simply disabling two of its status LEDs.

    100_MobSenDat_XBee_Power_Hacking 101_MobSenDat_XBee_Power_Hacking
    2011/05/12 Putting my Mobsendat Board to work to review my Rematee Bumper Belts
    π 2011-05-12 00:00 in Arduino, Osa
    Since my sleep apnea turned out not to be fully cured by my MMA surgery (it helped, but it wasn't entirely enough), the two other known fixes that do not include CPAP are to stop my tongue from being lazy and roll back in and partially my airway, and sleep on my back, which causes the previous point to be worse.

    Funny thing though is that I am used to falling asleep on my tummy (I don't fall asleep easily on my back), but then I will turn on my back while I'm sleeping, every single night. When I half wake up, I'll go back on my tummy and when I sleep again, go on my back again, making my apnea worse (mind you, sleeping on my tummy is not so good for my neck muscles and spine, but I can deal with that). One would say that I should sleep on my side, but that's an unstable position for me and I don't stay there long.

    This is where rematee comes in: I got the Rematee Bumper Belt.
    It is a belt with air pouches that you put on your back and that are supposed to stop you from turning on your back at night. I figured I'd give it a shot, but I soon found out that I quite obviously turned on my back anyway and woke up sleeping on the belt, which hurt my back a fair amount and just gave me an even worse night ("obviously" due to back pain and waking up on my back). One is supposed to wear that belt under the armpits, but for me it didn't make a huge difference, except for where the resulting back pain would be.

    This was discouraging, but I thought I'd give it another shot and got the next size up from rematee. My size is 36, so the large belt with 3 smaller air pouches was technically a little bit too big for me, but my rationale was that once I have the momentum to turn on my back, a few air pouches in my back aren't going to stop me, and apparently I stay sleeping on them and just get a back acke. It made sense at the time that if the air pillows spilled over to my side a bit, they would be more likely to stop my initial rotatioin to my back.

    Long story short, some testing showed that I still turned on my back with the 3 pouch belt. I didn't do detailled testing between the two, but while it seemed to work slightly better, it wasn't good enough.
    At that point, I came to wonder if things would work better with wearing both belts. Long story short is that yes, things worked better with both belts. My suggestion to the designers however, is would for the large belt to have 2 big pouches on the outside to provide maximum leverage against body rotation, and a smaller pouch in the middle to fill the void (the extra large belt does have 3 large air pouches, but that one is just too big for my body).

    both belts
    both belts

    So the big question, is how do you get quantitative data on this? Well, I just happened to be working on an arduino microcontroller board that had a built in 3 axis accelerometer amongst other things. While it was originally meant for attaching to rockets and location tracking with GPS, I figured I could also use it to simply track my body position at night, so I wrote some code to do that (and log it both to the sdcard on the board as well as send the data wirelessly via Xbee to my computer so that I don't have to pull out the card and read it every day).

    You can read this page on Xbee Power Consumption on my Mobsendat Board for details on the board I've been using but basically I get this end result from the board:

    "2011/05/24 06:20:04",,X:0.11,Y:-1.00,Z:0.13,V:4.97,left,rssi:0(DC:2),assoc:843(avg:842)
    "2011/05/24 06:20:09",,X:0.10,Y:-1.00,Z:0.13,V:4.96,left,rssi:0(DC:3),assoc:843(avg:842)
    "2011/05/24 06:20:14",,X:0.04,Y:-0.54,Z:-0.90,V:4.92,down,rssi:903(DC:0),assoc:843(avg:842)
    "2011/05/24 06:20:19",,X:-0.05,Y:0.39,Z:-0.93,V:4.96,down,rssi:903(DC:0),assoc:841(avg:842)

    The important part is the "left" which changed to "down" (Y axis went from -1g to less than .5, and Z went from 0 to -0.9g). I then have a script that parses the output and gives a summary for each night which I then enter in my detailled spreadsheet.

    gandalfthegrey [mc]$ ./scan_file night63_twobelts_home_sun.csv 
    up,     down,   left,   right,  unkwn,  pos changes,     hours sleep
    11.4%,  52.6%,  26.9%,  09.0%,  00.0%,   19 pos chg,     7.7 H sleep

    the microcontroller and battery pack fit nicely inside
    the microcontroller and battery pack fit nicely inside

    what it looks like inside
    what it looks like inside

    And the results are that I slept an average of 26% of my night on my back without belts, 13% with one belt, and down to 7% with both belts. On one side, this is encouraging, although on the other side, it's a bit eery that I still manage to sleep 7% of my night on my back, either by rotating the belts just enough, or by plain sleeping on them. You'll however see if you check the detailled spreadsheet that with the belts on, I have many nights when I didn't sleep on my back at all, and that the average gets messed up by a few nights when I slept more than 20% of the night on my back. It is possible that the optiona shoulder straps will help fix that.

    So how much better is my sleep? That one I don't have quantitative numbers for since I haven't been able to get an SPO2 sensor that I can interface with yet, or easily measure my breathing patterns vs my body position (I did use nose canulas in other take at home sleep tests and I tended to rip them out by sleeping on my face anyway).
    While I don't have exact data, my sleep did feel better with the belts, I also know that my apnea is worse when I'm on my back, so it's fair to say that belts help. How much exactly? Not sure yet, I'll get more data on that later hopefully. I also have to note that my data isn't perfect because at the same time I had to wear a heavy dental piece at night that kept my teeth from moving back to their old place (this is related to my post MMA surgery dental works). I was able to stop using that bulky mouthpiece at day 51, and my sleep improved noticeably at that time.

    So while the data is not perfect since I at least changed the mouth piece part during the samples, here's my summary spreadsheet, and the detailled spreadsheet.

    Interesting bit I got from the data are: I tend to flip-flop about the same amount regardless of whether I have the belts on, and outside of the amount of time on my back, the belts didn't change other sleep parameters I was measuring:

    Position:backtummyleftrightunknownhours sleptposition changesSample Count
    No Belts26.24%49.93%19.44%3.35%1.03%7.4615.0812
    3 cushion belt around chest13.00%51.83%32.07%2.83%0.30%7.4212.507
    both belts6.94%55.91%32.18%4.26%0.67%7.6714.1937
    Average15.39%52.56%27.90%3.48%0.67%7.5213.92

    100_MobSenDat_Rematee 101_MobSenDat_Rematee 102_MobSenDat_Rematee 103_MobSenDat_Rematee 104_MobSenDat_Rematee 105_MobSenDat_Rematee
    2011/12/12 GCC-AVR-4.5.3-2 Breaks Arduino NewSoftSerial
    π 2011-12-12 00:00 in Arduino
    Dear Google, please index this.

    TL;DR: gcc-avr 4.5.3 breaks Arduino NewSoftSerial on 328p. I had to downgrade back to 4.3.5.

    Full story:
    I had my arduino mobsendat board (328P based) working fine and after uploading some changes, it startsending a few of my characters over my Xbee, mixed with garbage. Most characters actually seemed lost.

  • https://github.com/lukeweston/RocketInstrumentation/blob/master/RocketInstrumentation-board.png
  • https://github.com/lukeweston/RocketInstrumentation/blob/master/RocketInstrumentation-schematic.png
  • In other words, I got less traffic than I should, a few were original characters, and some were garbage on a board and Xbee that were sending traffic at 38,400bps just fine for the last year.

    I used my xprotolab to decode the sending pin on the xbee directly to rule out RF issues, and I see the garbage there too. If you want to know what I mean, look at the last picture on http://www.gabotronics.com/product-info/xprotolab-pictures.htm

    So I was bit confused. The Xbee worked fine separately from the board and the serial bits getting to the xbee pins were damaged before they were sent on a simple program like this:

    #include <NewSoftSerial.h>
    

    const int XBEE_SLEEP = 8; // pin 14

    NewSoftSerial mySerial = NewSoftSerial(2, 3);

    void setup(void) { Serial.begin(38400); mySerial.begin(38400); // Switch pin to digital mode with pullup. pinMode(XBEE_SLEEP, OUTPUT); digitalWrite(XBEE_SLEEP, LOW); while (1) { Serial.println("AB12"); mySerial.println("AB12"); delay(1000); } }

    void loop(void) { }

    Arduino IDE is 0.22ubuntu0.1 on ubuntu oneiric. I thought that maybe an update to the arduino IDE broke it when I went from ubuntu marverick/natty to oneiric, but that wasn't it.

    Then I thought that maybe I damaged my hardware (maybe the clock/crystal is messed up, but then I suppose serial over USB wouldn't work either, and it does work), or if upgrading ubuntu recently broke NewSoftSerial in some subtle way, but I verified I had NewSoftSerial 10, and upgrading to 11 beta did not help.

    This is where it got wild: if I listened to the serial traffic going to the xbee from NewSoftSerial (I had version 10), and if I used the RX UART decoding pin of my Xprotolab, it could see the traffic ok. If I used the TX pin on the Xprotolab, then the same traffic mostly looked like garbage (actually most characters were lost). Putting 2 stop bits did not help.

    I talked to Gabriel Anzziani who made the Xprotolab and he said 'The RX and TX decoding are done differently in the Xprotolab. The RX is done by the XMEGA hardware, and the TX is done in firmware.'

    So clearly, there was a timing issue in what NewSoftSerial was doing at 38400 even though it had worked with the same NewSoftSerial library for about a year and NewSoftSerial 11 did not help.

    So, out of desperation, I took the nfs backup from my laptop before I upgraded from ubuntu maverick to ubuntu oneiric. While it was a bit hard to get the arduino IDE to work over an NFS chroot, I eventually got it to run, compile and upload my same Hello world serial program. And it worked!

    From there, it took a binary search to pin this down to the gcc-avr upgrade.

    gandalfthegrey:/var/local/src/arduino# dpkg -i gcc-avr-4.3.5-1.deb
    dpkg: warning: downgrading gcc-avr from 1:4.5.3-2 to 1:4.3.5-1.
    Yes, that really was the fix :(

    My guess is that the new gcc-avr changes some compilation timings/optimizations in a way that NewSoftSerial breaks :(

    2012/01/23 LiquidCrystal driver support LCD3Wire hardware (pebble and others)
    π 2012-01-23 00:00 in Arduino
    TL;DR: Get code here.

    All the code is arduino 1.0 compatible

    After coming back from the Arduino Miniconf at Linux.conf.au, I ended up with a freshly soldered freetronics pebble v2.

    Like the Pebble V1 (schematics here), it uses MC14094 8 bit shift register to drive the LCD using only 3 wires instead of 6 or more.

    The Pebble designers thankfully used the same shift register wiring than shown on the LCD3wire page on arduino playground. However, the code that came with it only had limited functionality for talking to the LCD, and the code on the LCD3wires page is also limited in functionality (on top of being incompatible with arduino 1.0).

    So, I ended up finding Francisco Malpartida's cool work on virtualizing the stock arduino LiquidCrystal library (very featureful and optimized timings). In turn, Ragnar used that codebase to design his own shift register library for 2 or 3 wires.

    Ragnar's wiring and code is somewhat complex because it exploits some interesting hacks:

  • it is designed to work with cheaper non latching shift registers.
  • it can be made to work with just 2 wires instead of 3 for non latching shift registers.
  • because of the design, the code is less obvious and exploits some tricks, but it sure works :)
  • his code can work for latching shift registers, but I do not recommend using the more complicated wiring and code if you can afford 3 wires and a shift register. Just use the LCD3Wires wiring and the code from this page.
  • In other words, if you have a non latching shift register, use his code and wiring. If you have a latching shift register, you should use the code from this page and the more widespread LCD3Wires wiring.

    So, where does this bring us?
    I used Malpartida and Ragnar's work to make an LCD3Wire hardware driver for the NewLiquidCrystal Library. This brings full library support to the pebbles as well as other folks who use the reference wiring from LCD3wires.

    I called the new library NewLiquidCrystal in the hopes that it will become the new de facto library in standard arduino one day. My code is here: https://github.com/marcmerlin/NewLiquidCrystal and includes the new LiquidCrystal_SR_LCD3 driver I wrote. To be clear, all the code came from Francisco Malpartida's work, I built on top of it to write my LiquidCrystal_SR_LCD3.cpp driver for LCD3Wires compatible hardware.

    I also wrote an extended LiquidCrystal Demo which should work on all liquidcrystal supported devices (baring the character count).



    Here is a demo of my popup menu code that works with a rotary button (cursor showing what is currently selected if you click on it)


    I'm now working with Francisco to get my code included in his tree, and if we're lucky that code may eventually get included in the standard arduino libraries as a faster and more flexible LiquidCrystal replacement.


    More pages: January 2011 May 2011 December 2011 January 2012 September 2013