Archive for the ‘Level 5’ Category

Arduino Computer Vision

Difficulty Level = 5 [What’s this?]

The Video Experimenter shield can give your Arduino the gift of sight. In the Video Frame Capture project, I showed how to capture images from a composite video source and display them on a TV. We can take this concept further by processing the contents of the captured image to implement object tracking and edge detection.

The setup is the same as when capturing video frames: a video source like a camera is connected to the video input. The output select switch is set to “overlay”, and sync select jumper set to “video input”. Set the analog threshold potentiometer to the lowest setting.

Object Tracking

Here is an Arduino sketch that captures a video frame and then computes the bounding box of the brightest region in the image.




You can download the sketch here. The code first calls tv.capture() to capture a frame. Then it computes a simple bounding box for the brightest spot in the image. After computing the location of the brightest area, a box is drawn and the coordinates of the box are printed to the TVout frame buffer. Finally, tv.resume() is called to resume the output and display the box and coordinates on the screen.

Keep in mind that there is no need to display any output at all — we just do this so we can see what’s going on. If you have a robot with a camera on it, you can detect/track objects with Arduino code, and the output of the Video Experimenter doesn’t need to be connected to anything (although the analog threshold potentiometer would probably need some adjustment).

If you use a television with the PAL standard (that is, you are not in North America), change tv.begin(NTSC, W, H) to tv.begin(PAL, W, H).

#include <TVout.h>
#include <fontALL.h>
#define W 128
#define H 96

TVout tv;
unsigned char x,y;
unsigned char c;
unsigned char minX,minY,maxX,maxY;
char s[32];


void setup()  {
  tv.begin(NTSC, W, H);
  initOverlay();
  initInputProcessing();

  tv.select_font(font4x6);
  tv.fill(0);
}


void initOverlay() {
  TCCR1A = 0;
  // Enable timer1.  ICES0 is set to 0 for falling edge detection on input capture pin.
  TCCR1B = _BV(CS10);

  // Enable input capture interrupt
  TIMSK1 |= _BV(ICIE1);

  // Enable external interrupt INT0 on pin 2 with falling edge.
  EIMSK = _BV(INT0);
  EICRA = _BV(ISC01);
}

void initInputProcessing() {
  // Analog Comparator setup
  ADCSRA &= ~_BV(ADEN); // disable ADC
  ADCSRB |= _BV(ACME); // enable ADC multiplexer
  ADMUX &= ~_BV(MUX0);  // select A2 for use as AIN1 (negative voltage of comparator)
  ADMUX |= _BV(MUX1);
  ADMUX &= ~_BV(MUX2);
  ACSR &= ~_BV(ACIE);  // disable analog comparator interrupts
  ACSR &= ~_BV(ACIC);  // disable analog comparator input capture
}

// Required
ISR(INT0_vect) {
  display.scanLine = 0;
}


void loop() {
  tv.capture();

  // uncomment if tracking dark objects
  //tv.fill(INVERT);

  // compute bounding box
  minX = W;
  minY = H;
  maxX = 0;
  maxY = 0;
  boolean found = 0;
  for(int y=0;y<H;y++) {
    for(int x=0;x<W;x++) {
      c = tv.get_pixel(x,y);
      if (c == 1) {
        found = true;
        if (x < minX) {
          minX = x;
        }
        if (x > maxX) {
          maxX = x;
        }
        if (y < minY) {
          minY = y;
        }
        if (y > maxY) {
          maxY = y;
        }
      }
    }
  }

  // draw bounding box
  tv.fill(0);
  if (found) {
    tv.draw_line(minX, minY, maxX, minY, 1);
    tv.draw_line(minX, minY, minX, maxY, 1);
    tv.draw_line(maxX, minY, maxX, maxY, 1);
    tv.draw_line(minX, maxY, maxX, maxY, 1);
    sprintf(s, "%d, %d", ((maxX+minX)/2), ((maxY+minY)/2));
    tv.print(0, 0, s);
  }

  tv.resume();
  tv.delay_frame(2);
}

What if you want to find the darkest area in an image instead of the brightest? That’s easy — just invert the captured image before processing it. Simply call tv.fill(INVERT).

Edge Detection

The Arduino is powerful enough to do more sophisticated image processing. The following sketch captures a frame then performs an edge detection algorithm on the image. The result is the outline of the brightest (or darkest) parts of the image. This could be useful in object recognition applications or
robotics. The algorithm is quite simple, especially with a monochrome image, and is described in this survey of edge detection algorithms as “Local Threshold and Boolean Function Based Edge Detection”.

Download the edge detection code here.




Published by Michael, on March 20th, 2011 at 3:02 pm. Filed under: Arduino,Level 5,Video. | 74 Comments |

Wireless Temperature Sensor using RF Transmitter/Receiver

Difficulty Level = 5 [What’s this?]

UPDATE: Also see this project for an easy way to display a temperature reading: Digit Shield Temperature Display.


A while back, I did a wireless temperature sensor project using XBee radios. XBee radios are really powerful devices with good reliability and the ability to read and transmit sensor readings without a microcontroller. BUT, they are difficult for people to configure, the documentation is hard to understand, and it’s really difficult to parse the API data packets at the receiving station. So I decided to try the same project using inexpensive RF devices. I used a 434MHz transmitter ($4) and receiver ($5) from Sparkfun, and had great success with these cheap devices. I also used a simple LM34 Fahrenheit temperature sensor, two Arduinos (one was a homemade breadboard version), and a two-digit LED display to show the temperature at the receiver end.

The Receiver

RF receiver with temperature display

I used a single 74LS247 BCD to 7-segment driver chip for the display. The segment pins of the two digits are connected together, so I need to multiplex between the digits to show only one at a time. The multiplexing is so fast, there’s no flicker. The segments have common anodes and I used two PNP transistors to provide current to the anodes. Don’t ever drive the anodes directly from an Arduino output pin because it’s too much current!

The RF receiver’s data pin is connected to the RX pin on the Arduino so we can just use the Serial library to read data at a slow 1200 bps. That is fast enough for temperature sensor readings. A 17cm antenna (the green wire) is attached to the ANT pin on the RF receiver.

RF Receiver Schematic (click to enlarge)

Here is the code running on the receiver Arduino. These RF devices can pick up a lot of noise, so drawing on the work of others, I used a simple protocol which includes a packet header with a network identifier and target address, the data, and a checksum to catch errors. This provides robustness for the communication link.

Read more…


Published by Michael, on December 26th, 2010 at 8:07 pm. Filed under: Arduino,Level 5,RF Wireless. | 101 Comments |

A Halloween Costume with Source Code

Difficulty Level = 5 [What’s this?]

Like many parents, we make hand-made costumes for our kids instead of buying cheaply-made (and expensive) costumes based on licensed characters. This year, my youngest son wanted to be a robot. My wife did a great job making the costume, but I just had to add some cool electronics to take it to the next level.

The electronics are nothing fancy — a simple Atmel ATtiny13 microcontroller that interfaces with two 74HC595 shift registers to light up LEDs randomly. The technical details are below, but in the process of building this, I was really struck by how electronics and computing are being embedded into everything. This week I was making a TODO list and one of the items was “finish source code for robot costume”.

OMG, now the costumes we make have source code.

This is a great example of how technology is becoming increasingly ubiquitous. Ten years ago, this would have been far beyond my reach. But in 2010 I can build this easily. The microcontroller cost $1.04, the shift register chips are $0.25 each, the resistors are a penny each, and the LEDs probably average $0.20 each. Definitely less than $5 for everything.

Technical Details

Here’s the schematic:

Schematic for robot costume circuit

Here is a closeup of the circuit board. There is a piece of clear acrylic protecting it. I ran out of 16 pin IC sockets, so the shift registers are in 20 pin sockets.

Circuit on front of costume. ATtiny13 microcontroller and two 74HC595 shift registers.

And finally, the simple source code that runs on the chip. I use CrossPack for AVR development. I use avrdude and a Bus Pirate to upload the code onto the ATtiny13 chip.

/*
 * ATtiny13 driving two 74HC595 shift registers
 *
 * Randomly turns on/off output pins of the shift
 * register ICs.
 * A random number of outputs are set high, then
 * a random time delay occurs.  Then the cycle
 *  repeats.
 *
 */

#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>

#define DATA PB0
#define CLOCK PB1
#define LATCH PB2

int main(void) {
  int d;
  char n;
  char i;

  // set DATA, LATCH and CLOCK pins to OUTPUT
  DDRB |= (1 << DATA);
  DDRB |= (1 << LATCH);
  DDRB |= (1 << CLOCK);
  PORTB = 0;

  for(;;) {
    // choose number of LEDs to light up.
    // n will be between 4 and 16
    n = 4 + (random() % 13);

    for(i=0;i<16;i++) {
      // for each LED, probability of it being lit
      // is n/16
      if ((random() % 16) <= n) {
	PORTB |= (1 << DATA);  // set DATA pin high
      } else {
	PORTB &= ~(1 << DATA); // set DATA pin low
      }

      // toggle shift register clock pin
      PORTB |= (1 << CLOCK);
      _delay_ms(2);
      PORTB &= ~(1 << CLOCK);
    }

    // once we've shifted out all 16 values, toggle
    // the latch pin.
    PORTB |= (1 << LATCH);
    _delay_ms(2);
    PORTB &= ~(1 << LATCH);

    // delay random amount of time between
    // 100ms and 500ms
    d = 100 + (random() % 400);
    for(i=0;i<d;i++) {
      // _delay_ms function must be called with a
      // constant value, not a variable!
      _delay_ms(1);
    }

  }
  return 0; // not reached
}

Published by Michael, on October 28th, 2010 at 8:55 pm. Filed under: AVR,Level 5,Robotics. | No Comments |

Wireless Temperature Sensor

Difficulty Level = 5 [What’s this?]

UPDATE: I have re-done this project using simple 434MHz RF transmitter/receiver devices. Check out the new project!.


UPDATE: Also see this project for an easy way to display a temperature reading: Digit Shield Temperature Display.


I decided to explore the more advanced features of XBee radios by building a remote temperature sensor. You can get quite a bit of control over an XBee radio without a microcontroller at all. You can configure the radio to send sensor readings at particular intervals when it detects changes on certain input pins. For the details on configuring XBee radios, see the documentation at Digi International.

For this project, I configured the radio at the sensor end to read the analog input of pin 19 every 4 seconds and to send a sensor reading packet. Both the sender and receiver radios must be running the API firmware. This does not work if they are running the default AT firmware. And the “API” parameter is not the same as running the API firmware. You literally need to write a different firmware image to your radios using the X-CTU tool from Digi. I have Series 2 radios, so if you are using Series 1, you need to read the correct documentation for your radios and modify the code.

Input pin 19 on my sensor radio is configured (parameter D1) with value ‘2’ which means that it will read analog input, and the IO sampling rate (parameter IR) is set to ‘1000’ which sends a sample every 4096ms.

An LM34 temperature sensor outputs a variable voltage depending on the temperature. The mapping is extremely simple: 10mV for every Fahrenheit degree. So, at 72 degrees F, the output is 720mV.

Why did I choose pin 19? I started with pin 20, but I burned it out. The pins can only handle an analog input of up to 1.2V, and I think I may have sent too much into the pin. How? Well, let’s say it involved holding a cold Pepsi can on the circuit to cool off the temperature sensor, and I shorted out a connection with the can. Oops. I’m lucky I didn’t burn out the entire XBee chip.

Remote temperature sensor

Remote temperature sensor

Here is the circuit for the remote sensor:

Schematic for remote sensor circuit

Schematic for remote sensor circuit

For the receiving side, I used an Arduino with an XBee shield and a two digit LED display:

Read more…


Published by Michael, on November 1st, 2009 at 12:50 pm. Filed under: Arduino,Level 5,XBee. | 124 Comments |