ProjectSteve: Cylon attachment

My friend Johnny has brought into work a Roomba clone. Apparently it is not particularly effective at cleaning, so we have decided to hack it. It is named ProjectSteve. He’s already has his vacuum cleaning parts removed and he is pretty good at carrying stuff. When discussing what to build we came up with the idea of building a light strip like KIT or a Cylon. It seems someone else already had the idea of Cylons and has added one to a Roomba.

I have loads of 3mm red LEDs and I’m going to use 25 of them to make this LED strip. I want each LED to be independently addressable so I have decided to configure the LEDs in a matrix. I’ve previously discussed how to use an LED matrix with an Arduino. If you were to wire the LEDs individually you would need 25 pins, one to control each LEDs. Using a matrix can reduce this.

I begin by wiring up the LED matrix. I decided to use 5 groups of 5 Leds

For each group, of LEDs, solder all the cathodes together. I have attached a black wire to this group and this will be used to connect to the MCU.

Close up of the back of the LED strip

Close up of the back of the LED strip

The group’s anodes are then wired together with the corresponding anode from the other groups; the first LED’s anode, from the first group, is wired to the anode of the first LED in each of the other groups. This gives ten wires to control all the LEDs. I’ve soldered each wire to a pin on some PCB header so I should be able to plug it into breadboard, or alternatively a female header when I have made the PCB.

Wiring completed

Wiring completed

The LEDs are mounted in a bent strip of acrylic. I bent this over my kitchen hob but I didn’t get particularly good quality results.

LED strip front

The finished LED strip from the front

As usual I first prototype the design on my Arduino. I’ve connected the ground pins to digital pins 2 to 6 and the positive pins to 7 to 11. I’ve again used Port Manipulation for the Arduino. The Arduino wiki advises against using it because it makes things more complicated, but I feel that it actually makes things simpler in this case. 

Here is the Arduino source. The ‘anim’ array contains the display information. Each byte is used to represent the five LED group. You should be able to see the pattern, 1’s mean LED on 0’s mean LED off.

char anim[][5] = {
{ B00000, B00000, B11111, B00000, B00000},
{ B00000, B00000, B00111, B11000, B00000},
{ B00000, B00000, B00011, B11100, B00000},
{ B00000, B00000, B00000, B11111, B00000},
{ B00000, B00000, B00000, B01111, B10000},
{ B00000, B00000, B00000, B00111, B11000},
{ B00000, B00000, B00000, B00001, B11110},
{ B00000, B00000, B00000, B00000, B11111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B11111},
{ B00000, B00000, B00000, B00001, B11110},
{ B00000, B00000, B00000, B00111, B11000},
{ B00000, B00000, B00000, B01111, B10000},
{ B00000, B00000, B00000, B11111, B00000},
{ B00000, B00000, B00011, B11100, B00000},
{ B00000, B00000, B00111, B11000, B00000},
{ B00000, B00000, B11111, B00000, B00000},
{ B00000, B00011, B11100, B00000, B00000},
{ B00000, B00111, B11000, B00000, B00000},
{ B00000, B11111, B00000, B00000, B00000},
{ B00001, B11110, B00000, B00000, B00000},
{ B00011, B11100, B00000, B00000, B00000},
{ B01111, B10000, B00000, B00000, B00000},
{ B11111, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11111, B00000, B00000, B00000, B00000},
{ B01111, B10000, B00000, B00000, B00000},
{ B00011, B11100, B00000, B00000, B00000},
{ B00001, B11110, B00000, B00000, B00000},
{ B00000, B11111, B00000, B00000, B00000},
{ B00000, B00111, B11000, B00000, B00000},
{ B00000, B00011, B11100, B00000, B00000},
};
void setGnd(int i)
{
  PORTD &= B10000011;
  PORTD |= (~(1 << (i+2))) & B01111100;
}
void clearGnd()
{
  PORTD |= B01111100;
}
void setLeds(unsigned int frame, unsigned int block)
{
  PORTD &= B01111111;
  PORTD |= B10000000 & (anim[frame][4 – block] << 7);
  
  PORTB &= B11110000;
  PORTB |= B00001111 & (anim[frame][4 – block] >> 1);
}
void setup()
{
  DDRD |= B11111100;
  DDRB = B00001111;
}
void loop()
{
  int frames = sizeof(anim) / (5 * sizeof(char));
  unsigned int t = millis();
  unsigned int f = (t / 40) % frames;
  for (int i = 0; i < 5; ++i)
  {
    setGnd(i);
    setLeds(f, i);
    delay(1);
    clearGnd();
  }
}
char anim[][5] = {
	{ B00000, B00000, B11111, B00000, B00000},
	{ B00000, B00000, B00111, B11000, B00000},
	{ B00000, B00000, B00011, B11100, B00000},
	{ B00000, B00000, B00000, B11111, B00000},
	{ B00000, B00000, B00000, B01111, B10000},
	{ B00000, B00000, B00000, B00111, B11000},
	{ B00000, B00000, B00000, B00001, B11110},
	{ B00000, B00000, B00000, B00000, B11111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B11111},
	{ B00000, B00000, B00000, B00001, B11110},
	{ B00000, B00000, B00000, B00111, B11000},
	{ B00000, B00000, B00000, B01111, B10000},
	{ B00000, B00000, B00000, B11111, B00000},
	{ B00000, B00000, B00011, B11100, B00000},
	{ B00000, B00000, B00111, B11000, B00000},
	{ B00000, B00000, B11111, B00000, B00000},
	{ B00000, B00011, B11100, B00000, B00000},
	{ B00000, B00111, B11000, B00000, B00000},
	{ B00000, B11111, B00000, B00000, B00000},
	{ B00001, B11110, B00000, B00000, B00000},
	{ B00011, B11100, B00000, B00000, B00000},
	{ B01111, B10000, B00000, B00000, B00000},
	{ B11111, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11111, B00000, B00000, B00000, B00000},
	{ B01111, B10000, B00000, B00000, B00000},
	{ B00011, B11100, B00000, B00000, B00000},
	{ B00001, B11110, B00000, B00000, B00000},
	{ B00000, B11111, B00000, B00000, B00000},
	{ B00000, B00111, B11000, B00000, B00000},
	{ B00000, B00011, B11100, B00000, B00000},

};

void setGnd(int i)
{
  PORTD &= B10000011;
  PORTD |= (~(1 << (i+2))) & B01111100;
}

void clearGnd()
{
  PORTD |= B01111100;
}

void setLeds(unsigned int frame, unsigned int block)
{
  PORTD &= B01111111;
  PORTD |= B10000000 & (anim[frame][4 - block] <> 1);
}

void setup()
{
  DDRD |= B11111100;
  DDRB = B00001111;
}

void loop()
{
  int frames = sizeof(anim) / (5 * sizeof(char));
  unsigned int t = millis();
  unsigned int f = (t / 40) % frames;
  for (int i = 0; i < 5; ++i)
  {
    setGnd(i);
    setLeds(f, i);
    delay(1);
    clearGnd();
  }
}

As Arduino has much much than I need  I want to simplify the design. Here is a simple circuit using an ATTiny2313 to control the LEDs. The capacitors and the chip on the right are a voltage regulator. The orange LED is a power indicator. This is the first circuit I’ve made using this chip, so I’ve yet to figure it out how to properly program it. I’ve manage to brick two chips so far, so I’m going to investigate fixing them before I continue with the next stage of this project.

ATTiny2312 LED controller

Breadboard ATTiny2312 LED controller

Advertisements
This entry was posted in ATTiny2313, AVR, Electronics. Bookmark the permalink.

One Response to ProjectSteve: Cylon attachment

  1. MMM says:

    Nice project, would love to see it in action… i.e. video. Kitten optionally 🙂 http://www.youtube.com/watch?v=c4-KHTb2LmM

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s