13 Output Devices
This week we made boards with sensors that we can manipulate through code to do different things. Some of the options included servos, motors, speakers or LCD displays, and varied in difficulty. I went with an LED board, where several LEDs are run from 1 pin.
This method, called Charlieplexing, makes it possible to power up to 100 LEDs with a tiny microprocessor (we used the ATtiny44, which has 10 i/o pins. I think this means that it would power up to 50 LEDs) Each pin can output 200 mA total. So if every LED requires 20mA, and each pin is serving as an in and out at once, requiring 40mA, that means that it can power 5 LEDs.
The batches of 5 LEDs share a pin across either their anodes or cathodes (depending on the model). Each pin can serve as an in or output, just not at the same time (so an LED's a and c couldn't be connected to the same pin since one is receiving power and the other is passing it on) To wire them, think of a matrix something like this:
In our schematic, every LED needs a resistor, which serves as jumper, and a larger resistor to control the power going into the array. This is what our schematic looked like:
And the board - imagine soldering so many LEDs!
After stuffing the board, I connected it to a battery and tried to flash Neil's code. Got this hated error, that I've gotten with so many boards :/
avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override this check
All the solding looked fine, the chip was on the right way, etc. It turned out that to flash the program, the board had to be connected via FTDI cable to the computer, for some reason it can't run off a battery just yet. Once I connected it that way, it worked with no trouble!
After that, I modified Neil's code, using a former student's work as an example to spell a cheesy message for my boyfriend. Diane in my class also had the brilliant idea to lay out the 2-letter code for each LED in an excel spreadsheet, so it would be easier to draw out each frame of the array. I switched the reading of the array from top left to bottom left, since I wanted 5 columns rather than 5 rows.
My first attempt was not so good, the letters were pretty wonky:
fab 13 try 1 from Kate Balug on Vimeo.
After some modification, this is what my excel looked like:
The final code:
//
//
// hello.array.44.c
//
// Charlieplex LED array hello-world
//
// Neil Gershenfeld
// 11/13/10
//
// (c) Massachusetts Institute of Technology 2010
// Permission granted for experimental and personal use;
// license for commercial sale available from MIT.
//
#include <avr/io.h>
#include <util/delay.h>
#define output(directions,pin) (directions |= pin) // set port direction for output
#define input(directions,pin) (directions &= (~pin)) // set port direction for input
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define led_delay() _delay_ms(1) // LED delay
#define led_port PORTA
#define led_direction DDRA
#define A (1 << PA1) // row 1
#define B (1 << PA2) // row 2
#define C (1 << PA3) // row 3
#define D (1 << PA4) // row 4
#define E (1 << PA5) // row 5
void flash(uint8_t from, uint8_t to, uint8_t delay) {
//
// source from, sink to, flash
//
static uint8_t i;
set(led_port,from);
clear(led_port,to);
output(led_direction,from);
output(led_direction,to);
for (i = 0; i < delay; ++i)
led_delay();
input(led_direction,from);
input(led_direction,to);
}
void led_cycleK(uint8_t number, uint8_t delay) {
//
// cycle through LEDs
//
uint8_t i;
for (i = 0; i < number; ++i) {
//flash(A,E,delay);
//flash(B,E,delay);
//flash(C,E,delay);
//flash(D,E,delay);
flash(A,D,delay);
flash(B,D,delay);
flash(C,D,delay);
flash(E,D,delay);
//flash(A,C,delay);
//flash(B,C,delay);
flash(D,C,delay);
//flash(E,C,delay);
//flash(A,B,delay);
flash(C,B,delay);
//flash(D,B,delay);
flash(E,B,delay);
flash(B,A,delay);
//flash(C,A,delay);
//flash(D,A,delay);
//flash(E,A,delay);
}
}
void led_cycleB(uint8_t number, uint8_t delay) {
//
// cycle through LEDs
//
uint8_t i;
for (i = 0; i < number; ++i) {
//flash(A,E,delay);
//flash(B,E,delay);
//flash(C,E,delay);
//flash(D,E,delay);
flash(A,D,delay);
flash(B,D,delay);
flash(C,D,delay);
flash(E,D,delay);
//flash(A,C,delay);
flash(B,C,delay);
//flash(D,C,delay);
flash(E,C,delay);
//flash(A,B,delay);
flash(C,B,delay);
//flash(D,B,delay);
flash(E,B,delay);
//flash(B,A,delay);
flash(C,A,delay);
flash(D,A,delay);
flash(E,A,delay);
}
}
void led_cycleL(uint8_t number, uint8_t delay) {
//
// cycle through LEDs
//
uint8_t i;
for (i = 0; i < number; ++i) {
flash(A,E,delay);
flash(B,E,delay);
//flash(C,E,delay);
//flash(D,E,delay);
flash(A,D,delay);
flash(B,D,delay);
flash(C,D,delay);
//flash(E,D,delay);
//flash(A,C,delay);
flash(B,C,delay);
flash(D,C,delay);
flash(E,C,delay);
flash(A,B,delay);
flash(C,B,delay);
flash(D,B,delay);
//flash(E,B,delay);
flash(B,A,delay);
flash(C,A,delay);
//flash(D,A,delay);
//flash(E,A,delay);
}
}
void led_cycleN(uint8_t number, uint8_t delay) {
//
// cycle through LEDs
//
uint8_t i;
for (i = 0; i < number; ++i) {
//flash(A,E,delay);
//flash(B,E,delay);
//flash(C,E,delay);
//flash(D,E,delay);
flash(A,D,delay);
flash(B,D,delay);
flash(C,D,delay);
flash(E,D,delay);
//flash(A,C,delay);
flash(B,C,delay);
//flash(D,C,delay);
//flash(E,C,delay);
//flash(A,B,delay);
//flash(C,B,delay);
flash(D,B,delay);
//flash(E,B,delay);
flash(B,A,delay);
flash(C,A,delay);
flash(D,A,delay);
flash(E,A,delay);
}
}
void led_cycleC(uint8_t number, uint8_t delay) {
//
// cycle through LEDs
//
uint8_t i;
for (i = 0; i < number; ++i) {
//flash(A,E,delay);
//flash(B,E,delay);
//flash(C,E,delay);
//flash(D,E,delay);
flash(A,D,delay);
flash(B,D,delay);
flash(C,D,delay);
flash(E,D,delay);
flash(A,C,delay);
//flash(B,C,delay);
//flash(D,C,delay);
flash(E,C,delay);
flash(A,B,delay);
//flash(C,B,delay);
//flash(D,B,delay);
flash(E,B,delay);
flash(B,A,delay);
//flash(C,A,delay);
//flash(D,A,delay);
flash(E,A,delay);
}
}
void led_cycleA(uint8_t number, uint8_t delay) {
//
// cycle through LEDs
//
uint8_t i;
for (i = 0; i < number; ++i) {
flash(A,E,delay);
flash(B,E,delay);
flash(C,E,delay);
flash(D,E,delay);
flash(A,D,delay);
flash(B,D,delay);
flash(C,D,delay);
flash(E,D,delay);
flash(A,C,delay);
flash(B,C,delay);
flash(D,C,delay);
flash(E,C,delay);
flash(A,B,delay);
flash(C,B,delay);
flash(D,B,delay);
flash(E,B,delay);
flash(B,A,delay);
flash(C,A,delay);
flash(D,A,delay);
flash(E,A,delay);
}
}
int main(void) {
//
// set clock divider to /1
//
CLKPR = (1 << CLKPCE);
CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
//
// main loop
//
while (1) {
led_cycleK(75,1);
led_cycleB(75,1);
led_cycleL(75,1);
led_cycleN(75,1);
led_cycleC(75,1);
//led_cycle(1,100);
//led_cycle(3,20);
led_cycleA(100,1);
}
}
And the final video!
fab 13 try 2 from Kate Balug on Vimeo.