The Bus Pirate & my High-2-Sea Adventure.. Arrrrrrr !

This past week I’ve been busy hacking on an Arduino project that uses the I2C bus. It’s been ages since I’d used the Wire library so I was more than a little rusty. Thankfully when it came time to test the code I’d written I could reach into my test equipment box and yank out my Bus Pirate. I’ve been saving up that post title for a while now.

Looking in the test equipment box I noticed at some point in the past I’d purchased one of the SeeedStudio v4 bus pirates which I’d forgotten about. Until now I’d typically used the Sparkfun v3.6 design. Hmm don’t remember when I purchased the new unit, must be old age.. Anyway seemed like a good time to take the plunge with the updated unit.

This new Arduino project monitors the voltage and current in a few external supply rails. Which can then be read by another device over the I2C. I’m sure at some point you’ll find the project code sitting in a public repository along with some hardware files as I complete and test a bit more of the project.

The bus pirates are great if you need to drive and interact with I2C devices. It implements a very simple macro style interface which means you can also edge case test and send out of order I2C signals to make sure your code is working.

So the first surprise with the new v4 unit was when I plugged it into my Windows 7 Dev machine, it needed a driver. I found it here here in the bus pirate archive (click), it actually wasn’t that easy to find. Once I’d updated the “driver” Win 7 it then did its usual thing and turned into a Serial Port.

Connecting to the Bus Pirate with PuTTY is relatively straight forward once you’ve found the serial port number, serial speed is 115200. It was then time to connect the wires. Dangerous Prototypes have a great page on how to do this, you can find it here (click). In a nutshell on my v4 board MOSI connected to SDA, CLK to SCK and GND to GND. Now back to the console. Firstly we need to get the Bus Pirate into I2C mode, so I used the following commands;

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

I2C mode:
 1. Software
 2. Hardware
(1)>1

Set speed:
 1. ~5KHz
 2. ~50KHz
 3. ~100KHz
 4. ~400KHz
(1)>2
Ready
I2C>

As you will see I decided to select I2C software mode and a speed of 50kHz to start with. So now we need to turn on the power supplies and turn on the pull-up resistors to talk to the Arduino.

I2C>W
Power supplies ON
I2C>P
Pull-up resistors ON
Warning: no voltage on Vpullup pin
I2C>

Umm… hold the boat ! What’s happened to the pull-ups? That one threw me for a bit, I don’t remember the Sparkfun v3.6 units doing this.

Well if you’ve only skim read the Dangerous Prototypes v4 page like I had you would have missed you need to connect the Vpu pin to one of the internal supplies, so in my case I used another wire to short Vpu to the 3V3 pin, conveniently they were adjacent to each other.

If you look closely you can see a yellow wire in the top right of the image above, that joins Vpu to 3V3 and is the secret sauce to making this work. Ok so now that’s solved I could then try to get the power supplies and pull-ups working again;

I2C>W
Power supplies ON
I2C>P
Pull-up resistors ON
I2C>

From here it was straight forward to the rest of the testing. Another good tid bit is the following macro is great for checking things work as expected, essentially it scans the bus and will report all of the devices it can talk to;

I2C>(1)
Searching I2C address space. Found devices at:
0x40(0x20 W) 0x41(0x20 R)
I2C>

Sweet. The Bus Pirate found my device and tells me I can read and write to it. More importantly I know what address to use, sometimes things get a little screwy due to the 7-bit I2C address and the read-write bit. Dangerous Prototypes have a good guide that allow you to work out what macros you need to use to build your I2C commands (click).

Here’s an example of me reading a single register from a specific address from within my Arduino I2C firmware;

I2C>[0x40 0x50[0x41 r]
I2C START BIT
WRITE: 0x40 ACK
WRITE: 0x50 ACK
I2C START BIT
WRITE: 0x41 ACK
READ: 0x08
NACK
I2C STOP BIT
I2C>

So the macro above can be read from left to right and in words;

  • send a start condition
  • the write address (0x40)
  • a data byte (0x50)
  • a second start condition
  • the read address (0x41)
  • read byte
  • stop condition

.The bus pirate then prints that it READ a value of 0x08 from that register. Actually that value tells me there are 8 bytes in that register strucutre, so I can modify my macro and read the entire contents;

I2C>[0x40 0x50[0x41 r:8]
I2C START BIT
WRITE: 0x40 ACK
WRITE: 0x50 ACK
I2C START BIT
WRITE: 0x41 ACK
READ: 0x08 ACK 0x20 ACK 0x1C ACK 0x00 ACK 0x00 ACK 0x98 ACK 0x3A ACK 0x00                       NACK
I2C STOP BIT
I2C>

You’ll see that the last part of the above macro is now set to read 8 bytes and you can see the response from the unit appears to have data in it. The nice thing with an Arduino is you can have it print out messages on it’s serial port and then check the responses match, so I’m gong to call that working !

Now all I need to do is write a script that can then test all of the I2C edge cases to ensure my code really works and I’ll be able to move on to a more interesting part of the project.

Arduino Micro from Scratch

For a while I’ve been building small projects and widgets with combinations of either the Arduino Micro or Leonardo’s. These platforms both use the Atmel ATmega32U4 which is now owned by Microchip. So while working on a recent “ham radio widget” I decided to embed my own custom made Arduino based on the micro platform. This design used DIN rail enclosures which require a fairly funky shaped PCB, so it was time to take the plunge and stop using modules purchased from eBay.

Finding a suitable schematic and parts list was not difficult, laying out the PCB was also uneventful. Since this module would be mounted vertically in an enclosure, I decided to simply squash up the pins on the micro into a double header. This was neat as it then allowed me to re-use the standard Arduino Micro pin map. Anyway a picture speaks a thousand words;

This board is fairly straight forward by design, however it did end up requiring 4 layers to fit within my enclosure with components I could see with my naked eye.

Once built I could then use the 6 pin ISP connector which you can see in the foreground above and my trusty AVRisp mk2 programmer. So now for the crux of the problem and the reason for this post, programming the bootloader.

Since I use AVR Studio and my AVRisp mk2 for professional software development, I had not swapped the usb drivers to libusb-win32 which meant I could not simply use the “burn bootloader” option in the Arduino IDE. So I had to do it the “hard way”.

After a bit of googling I found the bootloader hex file was already on my machine conveniently located within a the standard Arduino IDE directory. I found it in the following sub-directory here;

hardware\arduino\avr\bootloaders\caterina\caterina-micro.hex

The next question is what fuse settings are required. Now I struggled to find any references with practical solutions to this question on google. Searches ended up taking me off to ATmega328p or Arduino Pro bootloaders, not the micro. There are a many different fuses that can be set and if you get it wrong you can brick your processor, so playing around can lead to bad things.

Anyway after much nashing of teeth I found a practical guide to setting the fuses for a Leonardo, so I figured they should be the same or similar. So before simply blasting in these fuses I spent a bit of time to understand what exactly would change. There was nothing sinister there other than turning off the JTAG (unused) and swapping to an external 16MHz oscillator, jeez I hope I’ve got the right crystal and caps.

Below is the fuse settings I ended up with;

Low:  0xff
High: 0xd8
Ext:  0xfb

After programming the FLASH and fuses I then unplugged the programmer and external power supply and attached it to my PC via USB. I was happily greeted with detected new USB device, installing drivers, device is ready to use on COM62. Phew it worked !

All that was left was to fire up the Arduino IDE and create the ubiquitous blinky led program like so;

void setup() {
  // put your setup code here, to run once:
  pinMode( 13, OUTPUT );
  digitalWrite( 13, LOW );

}

void loop() {
  // put your main code here, to run repeatedly:

  delay(100);
  digitalWrite( 13, HIGH );
  delay(100);
  digitalWrite( 13, LOW );
}

Hitting the “upload” button saw the code compiled, AVR dude did it’s thing and my RED led flashing merrily. Problem solvered ! Now to continue putting these modules together and getting this board setup in PlatformIO.