The assignment for this week is add an output device to a microcontroller board you've designed and program it to do something. We covered examples of RGB color changing LEDs, Charlieplexing an array of LEDs, LCD displays, video, sound, DC motors, servo motors, stepper motors and more. I was most curious about the Charlieplexing so I decided to make a circuit that used only 5 pins to control a linear array of 20 LEDs.
hello.array.44 example with the various circuit paths color coded.
ladder diagram of 20 Charlieplexed LEDs
ladder diagram with red dots where circuit points overlap.
Circuit traces
Some of the gaps between traces were too small for the 1/64" endmill to fit. Note the hole to the left side was 1/64"
There were three areas that did not cut the way I needed them to.
Just a few modifications solved the problems. I also made most of the traces wider.
Notice alternating orientation of each LED. This matches the ladder diagram.
// // // linear.array.44.pbv1.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. // // Modified 4/22/2014 by Scott Zitek #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 input_port PORTB #define input_direction DDRB #define input_pin (1 << PB2) #define input_pins PINB #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 uint8_t pbstate; //button state uint8_t pblast; //button last pass uint8_t pboneshot; //button pressed oneshot uint8_t mode; //0-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_cycle(uint8_t number, uint8_t delay) { // // cycle through LEDs // uint8_t i; for (i = 0; i < number; ++i) { // LEDs 20 to 1 flash(D,E,delay); // LED20 flash(E,D,delay); // LED19 flash(C,D,delay); // LED18 flash(D,C,delay); // LED17 flash(B,C,delay); // LED16 flash(C,B,delay); // LED15 flash(A,B,delay); // LED14 flash(B,A,delay); // LED13 flash(C,E,delay); // LED12 flash(E,C,delay); // LED11 flash(A,C,delay); // LED10 flash(C,A,delay); // LED9 flash(B,D,delay); // LED8 flash(D,B,delay); // LED7 flash(B,E,delay); // LED6 flash(E,B,delay); // LED5 flash(A,D,delay); // LED4 flash(D,A,delay); // LED3 flash(A,E,delay); // LED2 flash(E,A,delay); // LED1 // LEDs 1 to 20 flash(E,A,delay); // LED1 flash(A,E,delay); // LED2 flash(D,A,delay); // LED3 flash(A,D,delay); // LED4 flash(E,B,delay); // LED5 flash(B,E,delay); // LED6 flash(D,B,delay); // LED7 flash(B,D,delay); // LED8 flash(C,A,delay); // LED9 flash(A,C,delay); // LED10 flash(E,C,delay); // LED11 flash(C,E,delay); // LED12 flash(B,A,delay); // LED13 flash(A,B,delay); // LED14 flash(C,B,delay); // LED15 flash(B,C,delay); // LED16 flash(D,C,delay); // LED17 flash(C,D,delay); // LED18 flash(E,D,delay); // LED19 flash(D,E,delay); // LED20 } } void led_cycle2(uint8_t number, uint8_t delay) { // // cycle through LEDs // uint8_t i; for (i = 0; i < number; ++i) { // LEDs alternate sides towards center flash(D,E,delay); // LED20 flash(E,A,delay); // LED1 flash(E,D,delay); // LED19 flash(A,E,delay); // LED2 flash(C,D,delay); // LED18 flash(D,A,delay); // LED3 flash(D,C,delay); // LED17 flash(A,D,delay); // LED4 flash(B,C,delay); // LED16 flash(E,B,delay); // LED5 flash(C,B,delay); // LED15 flash(B,E,delay); // LED6 flash(A,B,delay); // LED14 flash(D,B,delay); // LED7 flash(B,A,delay); // LED13 flash(B,D,delay); // LED8 flash(C,E,delay); // LED12 flash(C,A,delay); // LED9 flash(E,C,delay); // LED11 flash(A,C,delay); // LED10 // LEDs alternate sides towards outside flash(A,C,delay); // LED10 flash(E,C,delay); // LED11 flash(C,A,delay); // LED9 flash(C,E,delay); // LED12 flash(B,D,delay); // LED8 flash(B,A,delay); // LED13 flash(D,B,delay); // LED7 flash(A,B,delay); // LED14 flash(B,E,delay); // LED6 flash(C,B,delay); // LED15 flash(E,B,delay); // LED5 flash(B,C,delay); // LED16 flash(A,D,delay); // LED4 flash(D,C,delay); // LED17 flash(D,A,delay); // LED3 flash(C,D,delay); // LED18 flash(A,E,delay); // LED2 flash(E,D,delay); // LED19 flash(E,A,delay); // LED1 flash(D,E,delay); // LED20 } } void led_cycle3(uint8_t number, uint8_t delay) { // // cycle through LEDs // uint8_t i; for (i = 0; i < number; ++i) { // LEDs 20 to 1 flash(D,E,delay); // LED20 flash(E,D,delay); // LED19 flash(C,D,delay); // LED18 flash(D,C,delay); // LED17 flash(B,C,delay); // LED16 flash(C,B,delay); // LED15 flash(A,B,delay); // LED14 flash(B,A,delay); // LED13 flash(C,E,delay); // LED12 flash(E,C,delay); // LED11 flash(A,C,delay); // LED10 flash(C,A,delay); // LED9 flash(B,D,delay); // LED8 flash(D,B,delay); // LED7 flash(B,E,delay); // LED6 flash(E,B,delay); // LED5 flash(A,D,delay); // LED4 flash(D,A,delay); // LED3 flash(A,E,delay); // LED2 flash(E,A,delay); // LED1 // LEDs 1 to 20 flash(E,A,delay); // LED1 flash(A,E,delay); // LED2 flash(D,A,delay); // LED3 flash(A,D,delay); // LED4 flash(E,B,delay); // LED5 flash(B,E,delay); // LED6 flash(D,B,delay); // LED7 flash(B,D,delay); // LED8 flash(C,A,delay); // LED9 flash(A,C,delay); // LED10 flash(E,C,delay); // LED11 flash(C,E,delay); // LED12 flash(B,A,delay); // LED13 flash(A,B,delay); // LED14 flash(C,B,delay); // LED15 flash(B,C,delay); // LED16 flash(D,C,delay); // LED17 flash(C,D,delay); // LED18 flash(E,D,delay); // LED19 flash(D,E,delay); // LED20 // LEDs alternate sides towards center flash(D,E,delay); // LED20 flash(E,A,delay); // LED1 flash(E,D,delay); // LED19 flash(A,E,delay); // LED2 flash(C,D,delay); // LED18 flash(D,A,delay); // LED3 flash(D,C,delay); // LED17 flash(A,D,delay); // LED4 flash(B,C,delay); // LED16 flash(E,B,delay); // LED5 flash(C,B,delay); // LED15 flash(B,E,delay); // LED6 flash(A,B,delay); // LED14 flash(D,B,delay); // LED7 flash(B,A,delay); // LED13 flash(B,D,delay); // LED8 flash(C,E,delay); // LED12 flash(C,A,delay); // LED9 flash(E,C,delay); // LED11 flash(A,C,delay); // LED10 // LEDs alternate sides towards outside flash(A,C,delay); // LED10 flash(E,C,delay); // LED11 flash(C,A,delay); // LED9 flash(C,E,delay); // LED12 flash(B,D,delay); // LED8 flash(B,A,delay); // LED13 flash(D,B,delay); // LED7 flash(A,B,delay); // LED14 flash(B,E,delay); // LED6 flash(C,B,delay); // LED15 flash(E,B,delay); // LED5 flash(B,C,delay); // LED16 flash(A,D,delay); // LED4 flash(D,C,delay); // LED17 flash(D,A,delay); // LED3 flash(C,D,delay); // LED18 flash(A,E,delay); // LED2 flash(E,D,delay); // LED19 flash(E,A,delay); // LED1 flash(D,E,delay); // LED20 } } int main(void) { // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // initialize pins // input(input_direction, input_pin); // // main loop // while (1) { pbstate=pin_test(input_pins,input_pin);//read button & store pboneshot=pbstate && !pblast; //oneshot pblast=pbstate; //remember last pass result if(pboneshot){ mode++; if(mode > 11) mode=0; } switch(mode){ case 0: led_cycle(1,100); break; case 1: led_cycle(3,20); break; case 2: led_cycle(5,10); break; case 3: led_cycle(10,1); break; case 4: led_cycle2(1,100); break; case 5: led_cycle2(3,20); break; case 6: led_cycle2(5,10); break; case 7: led_cycle2(10,1); break; case 8: led_cycle3(1,100); break; case 9: led_cycle3(3,20); break; case 10: led_cycle3(5,10); break; case 11: led_cycle3(10,1); break; } _delay_ms(400); // Debouncing - delay longer than bounce time } }
I did eventually figure out how to use pushbuttons to select various modes as part of my final project.
For the "interface and applications programming" assignment I created a GUI program to display values from a FTDI interface. This made it much easier to understand what the microcontroller program was doing in situations like these. This interface made it easy to view in near real time how the program modified certain variables. So it very useful in testing and debugging.
I also realized that occasionally when I flashed a program to the microcontroller, it didn't always "take". The program did not update for some reason and microcontroller continues to run the previous program. I have witnessed this happen a few times since when the results of the program change would be obvious. If so, this would explain some of the problems I initially had with this assignment.