Search Results : Arduino

Nov 292009
 

[2014-May-9: updated to work with Arduino 1.0 and moved into github]

One of the challenges of working with I2C (aka “two-wire” or “TWI” or “Wire”) devices is knowing the I2C address of the device. Older devices have a fixed address, or a “choose one-of-four” approach. But newer I2C devices have fully programmable addresses, leading to cases of not knowing what address a device is at.

Fortunately, there’s a technique one can use to “scan” an I2C bus and determine these addresses. Conceptually it’s very similar to a network “ping”. Below is an Arduino sketch “I2CScanner.pde” that turns an Arduino into an I2C bus scanner.

I2CScanner.ino — Turn Arduino into I2C bus scanner (github repo)

When loaded up on an Arduino, the sketch will immediately scan the I2C network, showing which addresses are responding.

i2cscanner-out

For example, the above output is from an I2C bus with four slave devices on it (one BlinkM MaxM, three regular BlinkMs).
I2CScanner with BlinkMs
(Notice the 2 pull-up resistors on SDA & SCL. This is needed for longer bus lengths)

One thing to notice about the I2CScanner output is that although there are four devices on the bus, only three addresses were detected. This is because unlike IP networks and “ping”, you can’t tell if two devices have the same address. They’ll both respond to commands sent to them just fine, you just can’t read back data from them.

How it works

In I2C, the first byte transmitted/written by the master to a slave is the address of the slave. If there is a slave at that address, the slave will signal the I2C bus, otherwise it leaves it alone. We can use this to implement a bus scanner.

The Arduino “Wire” library utilizes a set of C functions called “twi.c”. One of those functions is “twi_writeTo()”. This function is used to both send the address of the slave down the bus and also to write data to slaves. It returns 0 if it was able to successfully transmit a byte or non-zero if it couldn’t. Since the very first write to a slave is its address, a very simple bus scanner using it would be:

void scanI2CBus(byte from_addr, byte to_addr) {
  byte data = 0; // not used, just a ptr to feed to twi_writeTo()
  for( byte addr = from_addr; addr < = to_addr; addr++ ) {
    byte rc = twi_writeTo(addr, &data, 0, 1, 0);
    if( rc == 0 ) {
      Serial.printl("device found at address "); 
      Serial.println(addr,DEC);
    }
  }
}

In the I2CScanner sketch, this function is extended a bit to support a callback function. The callback function is called with the result of every address scan. In I2CScanner, this callback function is called “scanFunc()” and just prints out “found!” or nothing, but it could be modified to do more complex tasks like doing additional I2C transactions to figure out what kind of device it is, or setting all the devices to a known state, etc.

 Posted by at 2:28 pm
Jul 302009
 

[I posted this to the Arduino developer’s mailing list, but figured others might find it useful too]

When I first started with Arduino, I thought Serial.available() was a very loose wrapping of the RXC bit in the USCRA register, i.e. if I didn’t get data out of there fast, it’d be gone. That led to convoluted code like:

 if( Serial.available() ) {
   val1 = Serial.read();
   while( !Serial.available() );
   val2 = Serial.read();
   // and so on
 }

Yuck. So you end up designing protocols that are too terse. Or maybe you think you need to buffer so you don’t lose it:

 while( Serial.available() ) {
   commandbuffer[i++] = Serial.read();
 }

Then parsing becomes a two step process: read serial, parse buffer. Confusing to newbies perhaps, but at least it allows for a better protocol down the line. (And descend into madness as you gaze into the maw of strtok())

Because Serial contains these big comfy buffers, we often don’t need a second buffer to let us easily implement good protocols. My current favorite is to do something like this:

 // protocol is "CCaaaa", two bytes of command, four bytes of args
 if( Serial.available() >= 6 ) {  // command length is 6 bytes
   cmd0 = Serial.read();
   cmd1 = Serial.read();
   arg0 = Serial.read();
   arg1 = Serial.read();
  // ...etc...
 }

I don’t think I’ve seen any Serial examples that check for a specific number of bytes available. It’s really handy.

Implementing a human-friendly protocol like “command arg0 arg1 arg2”, where command and args are space-separated strings like “servo 12 0xff”, is currently hard with Serial. I do this right now with a 2nd buffer and lots of C hackery:

 char* cmdbuf; char c; int i;
 while( Serial.available() && c!= '\n' ) {  // buffer up a line
   c = Serial.read();
   cmdbuf[i++] = c;
 }

 int i = 0;
 while( cmdbuf[++i] != ' ' ) ; // find first space
 cmdbuf[i] = 0;          // null terminate command
 char* cmd = cmdbuf;     //
 int cmdlen = i;         // length of cmd

 int args[5], a;         // five args max, 'a' is arg counter
 char* s; char* argbuf = cmdbuf+cmdlen+1;
 while( (s = strtok(argbuf, " ")) != NULL && a < 5 ) {
   argbuf = NULL;
   args[a++] = (byte)strtol(s,NULL,0); // parse hex or decimal arg
 }
 int argcnt = a;         // number of args read

This sort of functionality would be great in a library I think. Maybe not in Serial, but a core class.

Any other protocols people like to use and the Arduino code they use to do it?

 Posted by at 8:50 pm
May 262009
 

Or: A good use for old Arduino boards

Like me, you may have a few old Arduino boards or ATmega8 chips (in the boards) laying around from when you were first playing with Arduino. Those chips can still be really useful as the heart of a tiny “Minimal Arduino” setup.

A normal Arduino board contains support components that make it easy to use. If you want a smaller footprint, you can get one of the many Arduino work-alike boards. But if you want a really small footprint, and reuse your old parts, you can make an Arduino board using just five components:
– ATmega8 chip
– single 10k resistor
– single 0.1uF capacitor
– tiny breadboard
– some hookup wire


(On the left, an IR remote controlled BlinkM. On the right an IR remote controlled RGB LED)
Continue reading »

 Posted by at 5:36 pm
May 232009
 

I’ve been working with a super minimal Arduino setup recently. After seeing Alex’s awesome Arduino/ATmega breadboard header, where he notes there’s no room on the PCB for pin labeling, I wondered if it would be possible to make a small sticker that goes on the ATmega chip, labeling the pin names.

Here’s my first attempt:
arduino-atmega-sticker

And in use:
arduino-atmega-sticker-use

This was created by printing on a full-page sticker then laser cutting it to shape. I could have also just cut out the sticker with scissors, or used regular printer paper and double-sided tape.

Some files if you want to try this out yourself:
arduino-atmega-sticker.eps — EPS of just the sticker itself.
arduino-atmega-sticker.svg — SVG version
arduino-atmega-sticker.pdf — PDF version
arduino-atmega-sticker-lasercut.cdr — Coreldraw file containing instructions & registration marks for printing then laser cutting your own sticker.

 Posted by at 9:53 pm
Jun 232008
 

Here’s a really quick 3D model of BlinkM, if anyone needs it. It’s accurate to ~0.1mm.

blinkm.skp — BlinkM SketchUp model
rgb_led_piranha.skp — Piranha RGB LED SketchUp model

And here it is plugged into the awesomely done Arduino Diecimila model by Jon-Paul from the Google 3D Warehouse.

SketchUp is pretty great, but I found a problem with it if you’re trying to make accurate to-scale electronic parts: it won’t create surfaces with an area of <1mm. Took me a while to figure that out. The solution is to make a 10x or 100x size version and then do a scale by 0.1 or 0.01 when you’re done.

 Posted by at 5:41 pm
Jun 192008
 

Arduino makes it pretty easy to store & use character strings, but those strings compete with your variables, so you can’t do as much. Here’s how to put big strings into read-only program memory and use them.

Lots of sketches can have big strings in them. Maybe you’ve built a little command-line interface or you’re storing small web pages (for net-connected Arduinos). Normally you do something like this:

char hellostr[] =  "<html><head><title>hello world</title></head>"
                   "<body><p align=center><h1>hello world</h1></p>
                   "</body></html>";

// and then sometime later

Serial.println( hellostr );

The problem with this is that “hellostr” is stored in RAM along with your variables. The ATmega chip in Arduino only has 1kB of RAM. If your code is getting complex, and you’re using big strings, and lots of libraries, you may start having mysterious problems. Arduino can’t warn you if your sketch starts using too much RAM.

Instead, you can use PROGMEM, or PROGram MEMory, to store your strings. That is, the flash ROM memory that your code lives in. Using PROGMEM strings can be tricky, but here’s a little function called “printProgStr()” to make it almost as easy.

const char hellostr[] PROGMEM = "...";     // notice added 'const' and 'PROGMEM'

// given a PROGMEM string, use Serial.print() to send it out
void printProgStr(const prog_char str[])
{
  char c;
  if(!str) return;
  while((c = pgm_read_byte(str++)))
    Serial.print(c,BYTE);
}

// and then at some point

printProgStr( hellostr );

If you have another use for the string that isn’t “Serial.print()”, just create your own function and put whatever per-character handling function in there instead.

 Posted by at 10:08 pm
Jan 022008
 

Mark Allen, instigator of Machine Project, is holding an Intro to Arduino class in a few days.

It’s called “Intro to Microcontrollers with Arduino“.

It will cover many of the same topics covered in my previous Spooky Arduino and Bionic Arduino courses. So if you’re near L.A. and want to have some fun programming computers the size of your finger, sign up now! Machine Project classes usually sell out in a day or so.

 Posted by at 4:53 pm