Den LED-Cube werde ich über einen ArduinoMega mit den unten aufgeführten C-Code ansteuern.
Der ArduinoMega hat folgende Eigenschaften
Microcontroller: ATmega2560
Operating Voltage: 5V
Input Voltage (recommended): 7-12V
Input Voltage (limits): 6-20V
Digital I/O Pins: 54 (of which 15 provide PWM output)
Analog Input Pins: 16
DC Current per I/O Pin: 40 mA
DC Current for 3.3V Pin: 50 mA
Flash Memory: 256 KB of which 8 KB used by bootloader
SRAM: 8 KB
EEPROM: 4 KB
Clock Speed: 16 MHz
Davon nutzen werde ich folgenden Teil:
Ebenen (von unten nach oben, z = 0..3) an Pins A0, A1, A2, A3
LEDs erste Reihe (y = 0) an Pins 22, 23, 24, 25
LEDs zweite Reihe (y = 1) an Pins 26, 27, 28, 29
LEDs dritte Reihe (y = 2) an Pins 30, 31, 32, 33
LEDs letzte Reihe (y = 3) an Pins 34, 35, 36, 37
/* cube */ #define LAYERs 4 #define COLs 4 #define ROWs 4 /* global variable definitions */ unsigned char LEDs[LAYERs][COLs * ROWs]; unsigned char pwmpos = 0; // actual step of the PWM unsigned char layer = 1; // actual controlled layer /* * cmp_carry_shift_left compares the two parameters * which results in the carry bit to be set/unset * that carry bit is rotated into para_io * the complete function consumes only 2 cycles */ static inline unsigned char cmp_carry_shift_left ( unsigned char para_io, unsigned char cmp_para_1, unsigned char cmp_para_2 ) { asm volatile ( // compare the parameters // (get the carry flag set/unset) "cp %r[cmp2], %r[cmp1]" "\n\t" // rotate carry bit into paramter "rol %r[out]" "\n\t" // output operand : [out] "+r" (para_io) // input operands : [in] "r" (para_io), [cmp1] "r" (cmp_para_1), [cmp2] "r" (cmp_para_2) ); return para_io; } /* * The timer3 overflow interrupt routine builds the pin states * to be output. the actual output is done in the beginning * (of the next execution) of the routine to achieve a more * constant time behaviour */ ISR ( SIG_OVERFLOW3 ) { static unsigned char porta, portc, portf; PORTB = 0x80; // turn on pin B7 for measuring the time consumption PORTA = porta; // turn on the pins of PORTA and B in resull of PORTC = portc; // the previous cycles outcome PORTF = portf; pwmpos++; if ( pwmpos >= 128 ) pwmpos = 0; if ( pwmpos == 0 ) { layer++; if (layer == LAYERs) { layer = 0; PORTB |= 0x10; // get an impulse on Pin B4 as debug output PORTB &= ~0x10; // -"- PORTA = 0; PORTC = 0; } portf = 1 <= LAYERs * COLs * ROWs ) ? 0 : RX_pos + 1; } PORTB &= ~0x08; // turn off B3 as debug output } void setup() { unsigned char i; // Initialize port directions and output values DDRA = 0xFF; PORTA = 0xFF; // first 8 LEDs DDRC = 0xFF; PORTC = 0xFF; // second 8 LEDs DDRF = 0x0F; PORTF = 0x01; // 4 layers DDRB = 0xFF; PORTB = 0x00; // debug output LEDs // Initialize timer TCCR3A = (1 << WGM31) | (1 << WGM30) | (0x00 << COM3B0); TCCR3B = (0x01 << CS30) | (1 << WGM32) | (1 << WGM33); TIMSK3 |= 1 << TOIE3; OCR3A = 0xFF; // */ // init LEDs array for ( i = 0; i < LAYERs * COLs * ROWs; i++ ) ( (unsigned char *) LEDs )[i] = 1; // Enable interrupts sei(); // listen on RS232 for new data Serial.begin(115200); } void loop() { PORTB ^= 0x02; // debug output (toggles pin B1 if nothing else is done) }
Der Programmcode wird ganz simple mit der eigenen Arduino-Applikation via USB auf den Microkontroller in einem Rutsch kompiliert und hochgeladen. Code in das Fenster einfügen und Upload-Button klicken. Fertig!