Sunday, June 30, 2013

MCP23017 and the Bus Pirate

So I wired up an MCP23017 GPIO expander to my Bus Pirate and couldn't understand why it wasn't acknowledging commands. Upon closer inspection of the datasheet I discovered that it expects an extra bit set in the I2C device address byte. The datasheet refers to this as the "Device Opcode".


Thus, if your device address lines are all tied to ground, ie. an address of 0x20, the address to write to is 0x40.


Once you've connected everything, the first step is to put your Bus Pirate in I2C mode and turn on the power:


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

(1)>1
Ready
I2C>W
POWER SUPPLIES ON

This example assumes you've tied all three address lines from the MCP23017 to ground, making its I2C address 0x20. Now we'll configure both IO banks to be all outputs; the 0:3 notation tells the Bus Pirate to write the value three times. The first 0 selects the IODIRA register address. The second and third 0s clear all the bits in the IODIRA and IODIRB registers, thus configuring them as outputs.


I2C>[0x40,0:3]
I2C START BIT
WRITE: 0x40 ACK 
WRITE: 0x00 ACK 0x00 ACK 0x00 ACK 
I2C STOP BIT

Finally, we turn on all eight GPIOA pins by writing 0xFF to register 0x12.


I2C>[0x40,0x12,0xFF]
I2C START BIT
WRITE: 0x40 ACK 
WRITE: 0x12 ACK 
WRITE: 0xFF ACK 
I2C STOP BIT

As always, read the fine datasheet!

Quickstart guide: TI MSP430 on OSX Mountain Lion

I had all of this stuff working on my other OSX laptop but for some reason it wasn't as trivial to setup on my new laptop as it was last time around, mainly due to the USB driver. So I thought I'd save some notes for Google's (and possibly my!) future reference.


If this all fails on Mavericks when it arrives, I'll try to remember to update it.


  1. Install Xcode (I installed the commandline tools from inside Xcode too [Xcode menu => Preferences => Downloads tab]; these are probably not actually required)
  2. Install MacPorts
  3. Install the toolchain bits:
    sudo port install msp430-{binutils,gcc,gdb,libc}
  4. Get the fixed kernel extension source code - the TI download is broken under Mountain Lion and possibly Lion as well:
    git clone https://github.com/freespace/ez430rf2500.git
  5. Follow the README.md instructions included with the ez430rf2500 source to install the driver
  6. Plug in your Launchpad
  7. If everything is working, this should get you to an mspdebug shell: sudo mspdebug rf2500
[jslee@shamata Release] $ sudo mspdebug rf2500
MSPDebug version 0.21 - debugging tool for MSP430 MCUs
Copyright (C) 2009-2012 Daniel Beer 
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Trying to open interface 1 on 002
Initializing FET...
FET protocol version is 30066536
Set Vcc: 3000 mV
Configured for Spy-Bi-Wire
fet: FET returned error code 4 (Could not find device or device not supported)
fet: command C_IDENT1 failed
fet: identify failed
Trying again...
Initializing FET...
FET protocol version is 30066536
Set Vcc: 3000 mV
Configured for Spy-Bi-Wire
Sending reset...
Device ID: 0xf201
  Code start address: 0xf800
  Code size         : 2048 byte = 2 kb
  RAM  start address: 0x200
  RAM  end   address: 0x27f
  RAM  size         : 128 byte = 0 kb
Device: MSP430F2012/G2231
Number of breakpoints: 2
fet: FET returned NAK
warning: device does not support power profiling
Chip ID data: f2 01 01

Available commands:
    =           erase       isearch     opt         run         setwatch_w  
    alias       exit        load        power       save_raw    simio       
    break       fill        load_raw    prog        set         step        
    cgraph      gdb         locka       read        setbreak    sym         
    delbreak    help        md          regs        setwatch    verify      
    dis         hexout      mw          reset       setwatch_r  verify_raw  

Available options:
    color           gdb_loop        iradix          
    fet_block_size  gdbc_xfer_size  quiet           

Type "help " for more information.
Press Ctrl+D to quit.

(mspdebug) regs
    ( PC: 0ffff)  ( R4: 0dfde)  ( R8: 0fbef)  (R12: 0ffdf)  
    ( SP: 0ffff)  ( R5: 0f613)  ( R9: 07ffc)  (R13: 0feff)  
    ( SR: 00000)  ( R6: 0edff)  (R10: 0ffff)  (R14: 07bef)  
    ( R3: 00000)  ( R7: 0fbef)  (R11: 0cff7)  (R15: 0f5fc)  
0xffff:
    0ffff: ff                        
(mspdebug) 

If all this works, you should be able to compile stuff and use mspdebug to load it into MSP430 flash via the Launchpad.

Friday, June 21, 2013

Van Halen @ Tokyo Superdome 2013-06-21 set list

  1. Unchained
  2. Runnin' with the devil
  3. She's the woman
  4. Show your love
  5. Tattoo
  6. Everybody wants some
  7. Somebody get me a doctor
  8. Downtown
  9. Hear about it later
  10. Pretty woman
  11. Drum & weird stuff
  12. You really got me
  13. Dance the night away
  14. ??? Synth song
  15. And the cradle will rock
  16. Hot for teacher
  17. Women in love
  18. Tora Tora???
  19. Mean streets
  20. Beautiful girls
  21. --- Dave lee Roth (as gaijin yakuza) short film
  22. DLR guitar acoustic intro to ice cream man
  23. Panama
  24. EVH solo thing
  25. Ain't talkin' 'bout love
  26. Encore: Jump

Sunday, September 2, 2012

i2c and the Freetronics Leostick

So I picked up some MCP23017 GPIO expanders after hearing about them from a friend. The only spare Arduino-compatible boards I had were Leosticks. It seems that the i2c pins aren't in the same places.

Uno: A4/A5
LeoStick: D2/D3


There's a good tutorial for using the MCP23017 with the Arduino programming environment here.

Sunday, June 3, 2012

Putting the Linux automounter to good use

I think filesystem automounters (eg. Linux autofs) are dramatically underused. They bring a lot of benefits to the table and can save you lots of typing. As an example, this evening I was building a VM on my laptop to be a build server for more Redhat-alike VMs, such as CentOS. I wanted it to be usable when disconnected (eg. flying), so I downloaded both of the CentOS 6.2 x86_64 DVDs and saved them in my ISO folder on the VM host (my MacBook Pro running OSX, but I'm sure it'd work equally well with a Linux or Windows host).


I figured I'd use VirtualBox's shared folders feature, rather than move or copy all the ISOs into the VM. This requires the VirtualBox guest additions to be installed, and provides a new filesystem type vboxsf. You mount a shared folder (for this example, named iso) thusly:


mkdir /mnt/iso
mount -t vboxsf iso /mnt/iso


If the stars all align nicely, you can access your iso folder in the VirtualBox guest, under /mnt/iso. Now you can loopback-mount an ISO file:


mkdir /mnt/centosdvd
mount -o loop,ro -t iso9660 /mnt/iso/centosdvd.iso /mnt/centosdvd


Wheeee, CentOS! This is all mildly annoying, though. Computers are supposed to make our lives easier! And going through this process over and over for lots of ISOs gets old very rapidly indeed. Thankfully, we can use the Linux automounter to simplify both tasks. First, we tell autofs about the two automount maps we're going to create; one for the shared folders, and one for the ISOs, by adding these two lines somewhere in /etc/auto.master


/vbox /etc/auto.vbox -n 5
/iso /etc/auto.iso -n 5


Then we create the two map files. They only contain one line each. This goes in /etc/auto.vbox:


* -fstype=vboxsf :&

... and this goes in /etc/auto.iso (replace iso with the name of your VBox shared folder containing ISO files, and possibly a further path inside that share, if appropriate, eg. /vbox/myshare/isofiles):


* -fstype=iso9660,ro,loop :/vbox/iso/&


Now reload the automounter:


/etc/init.d/autofs reload


... and that should be that. Try browsing your shares in /vbox. If you have an ISO file /vbox/iso/foo.iso, you should be able to see inside it by merely looking in /iso/foo.iso. Transparent, automatic, and, best of all, you only solve the problem once.

Sunday, September 25, 2011

And if your Xbee shield is behaving strangely...

If you are combining the CAN-Bus and Xbee shields from SparkFun, it can be very tempting to plonk the EM406 GPS atop the nice flat prototyping area on the Xbee shield. It's a good fit there! But if stuff suddenly and inexplicably stops working, check that the GPS chassis isn't bridging the terminals on the Xbee shield's RESET switch. I felt like a real idiot :-(

Arduino: combining CAN-bus and Xbee shields


A little box of Arduino, originally uploaded by indigoid.

So I created a simple little sketch, based on the TimeGPS sample that comes with the TinyGPS library, that waits for a "p" over the Xbee interface and upon receiving it, sends back the date, time, latitude and longitude data from the GPS. The CAN-bus shield uses pins 4 and 5 for the GPS serial interface. I found that the Xbee modules I have (as supplied in the SparkFun Xbee retail kit) have rather shorter range than I'd hoped for, but at least they work and I am learning about their usage. Here's the sketch:


#include <TinyGPS.h>        //http://arduiniana.org/libraries/TinyGPS/
#include <NewSoftSerial.h>  //http://arduiniana.org/libraries/newsoftserial/
// GPS and NewSoftSerial libraries are the work of Mikal Hart

TinyGPS gps; 
NewSoftSerial serial_gps =  NewSoftSerial(4, 5);  // receive on pin 3

void setup()
{
  Serial.begin(9600);
  serial_gps.begin(4800);
  Serial.println("setup...");
}

void dump_lat_long(float flat, float flong) {
  Serial.print("lat : "); Serial.println(flat);
  Serial.print("long: "); Serial.println(flong);
}

#define pdec(x) { Serial.print(x,DEC); }
#define p(x) { Serial.print(x); }
#define s() p(" ")
#define d() p("-")
#define c() p(":")
void dump_datetime() {
  int year;
  byte month, day, hour, minutes, second, hundredths;
  unsigned long fix_age;
  gps.crack_datetime(&year, &month, &day, &hour, &minutes, &second, &hundredths, &fix_age);
  pdec(year); d(); pdec(month); d(); pdec(day);
  s();
  pdec(hour); c(); pdec(minutes); c(); pdec(second); p("."); pdec(hundredths);
  Serial.println();
}

void loop() {
  float flat, flon;
  unsigned long fix_age;
  String msg;
  byte havedata = 1;
  byte polled = 0;
  while (serial_gps.available() && !polled) {
    if(gps.encode(serial_gps.read())) {
      // returns +- latitude/longitude in degrees
      gps.f_get_position(&flat, &flon, &fix_age);
      if (fix_age == TinyGPS::GPS_INVALID_AGE) {
        msg = "No fix detected";
        havedata = 0;
      } else if (fix_age > 5000)
        msg = "Warning: possible stale data!";
      else
        msg = "Data is current.";
      polled = 1;
      if (Serial.available() && Serial.read() == 'p') {
        Serial.println(msg);
        if (havedata) {
          dump_datetime();
          dump_lat_long(flat,flon);
        }
        delay(100);
      }
    }
  }
}

I also wrote a small Perl script that (via Device::SerialPort from CPAN) interrogates the Arduino every 5 seconds or so, using a USB-attached Xbee Explorer. For Linux you will need to change the serial port device filename to /dev/ttyS0 or similar. No idea about Windows, sorry. Again, I started out with some sample code (this time from the Device::SerialPort distribution) and hacked most of it off. Code follows:


#!/usr/bin/perl

use strict;
use warnings;
use Device::SerialPort;

my $file = "/dev/tty.usbserial-A700fbpg";
my $ob = Device::SerialPort->new ($file) || die "Can't open $file: $!";

$ob->baudrate(9600)     || die "fail setting baudrate";
$ob->parity("none")     || die "fail setting parity";
$ob->databits(8)        || die "fail setting databits";
$ob->stopbits(1)        || die "fail setting stopbits";
$ob->handshake("none")  || die "fail setting handshake";
$ob->write_settings || die "no settings";
$ob->error_msg(1);              # use built-in error messages
$ob->user_msg(1);

while(1) {
  $ob->write("p");
  print $ob->input;
  sleep 5;
}