-
new design!
02/20/2018 at 22:59 • 2 commentsAfter a fallout with pimoroni I'm no longer allowed to use the sloth badge design. So here is the new design:
Just kidding! I've bought a soic8 adapter that I will solder into place and make this a dedicated SOIC8 programmer for the kit chips! I haven't heard from pimoroni in a while though, need to ping them in a tweet some time.
-
current code, anyone any ideas to save space?
02/19/2018 at 10:28 • 8 commentsI won't lie, this feels messy. This currently features 5 animations, where 2 of them are just "played accelerating" .
Some things I'm not happy with:
- the button does not work within the animations, so you need to push the button until the animation cycle is over
#include <avr/sleep.h> #define nop() asm volatile("nop") boolean leds_on = true; byte badly_programmed_counter = 0; byte animation_counter_max = 5; byte animation_counter = 0; // we need two frames with 8 bits for 12 LEDs byte frame1 = 0; byte frame2 = 0; // animation where every third LED is glowing // I could shift that continuosly and drop 4 bytes const byte three_apart_length = 6; const byte three_apart[three_apart_length] PROGMEM = { 0b10010010, 0b01000000, 0b01001001, 0b00100000, 0b00100100, 0b10010000, }; // this one is huge // is there a math function to do that instead? const byte updown_length = 14; const byte updown[updown_length] PROGMEM = { 0b00100000, 0b00000000, 0b01010000, 0b00000000, 0b10001000, 0b00000000, 0b00000100, 0b00010000, 0b00000010, 0b00100000, 0b00000001, 0b01000000, 0b00000000, 0b10000000, }; // that's just blinking each led // maybe inverting the data bitwise does the trick const byte two_apart_length = 4; const byte two_apart[two_apart_length] PROGMEM = { 0b10101010, 0b10100000, 0b01010101, 0b01010000, }; // should have taken a switch, sleep stuff is huge ISR(INT0_vect) { sleep_disable(); leds_on = true; } void setup() { // this is for the button setup PORTB |= (1 << PB1); DDRB &= ~(1 << PB1); shutdown_chip(); } void loop() { if (leds_on) { cli(); leds_on = false; // I call it that, because the millis stuff // and the interrupts collided and broke badly_programmed_counter = 0; } // fancy way of checking the button state if (!(PINB & (1 << PB1))) { badly_programmed_counter++; my_100ms_delay(); // check if button was released before time // so animation index can be incremented // maybe a modulo with animation_counter_max // safes space if ( (PINB & (1 << PB1)) ) { badly_programmed_counter = 0; animation_counter++; if (animation_counter == animation_counter_max) { animation_counter = 0; } charlie(animation_counter); // calling a function instead of writing it down // 5 times helps already for (byte b = 0; b < 5; b++) my_100ms_delay(); } if (badly_programmed_counter >= 7) { // blink when shutdown is immanent for (byte b = 0; b < 5; b++) blip(); shutdown_chip(); } } else { animate_leds(); badly_programmed_counter = 0; } } // this is probably already at it's best void charlie (byte var) { leds_off(); switch (var) { case 0: // 1 DDRB |= (1 << PB0) | (1 << PB2); // output PORTB |= (1 << PB0); // HIGH break; case 1: // 2 DDRB |= (1 << PB0) | (1 << PB2); // output PORTB |= (1 << PB2); // HIGH break; case 2: // 3 DDRB |= (1 << PB2) | (1 << PB3); // output PORTB |= (1 << PB2); // HIGH break; case 3: // 4 DDRB |= (1 << PB2) | (1 << PB3); // output PORTB |= (1 << PB3); // HIGH break; case 4: // 5 DDRB |= (1 << PB3) | (1 << PB4); // output PORTB |= (1 << PB3); // HIGH break; case 5: // 6 DDRB |= (1 << PB3) | (1 << PB4); // output PORTB |= (1 << PB4); // HIGH break; case 6: // 7 DDRB |= (1 << PB0) | (1 << PB3); // output PORTB |= (1 << PB0); // HIGH break; case 7: // 8 DDRB |= (1 << PB0) | (1 << PB3); // output PORTB |= (1 << PB3); // HIGH break; case 8: // 9 DDRB |= (1 << PB2) | (1 << PB4); // output PORTB |= (1 << PB2); // HIGH break; case 9: // 10 DDRB |= (1 << PB2) | (1 << PB4); // output PORTB |= (1 << PB4); // HIGH break; case 10: // 11 DDRB |= (1 << PB0) | (1 << PB4); // output PORTB |= (1 << PB0); // HIGH break; case 11: // 12 DDRB |= (1 << PB0) | (1 << PB4); // output PORTB |= (1 << PB4); // HIGH break; default: ; nop(); } } void shutdown_chip() { animation_counter = 0; leds_off(); /* Clear WDRF in MCUSR */ MCUSR &= ~(1 << WDRF); /* Write logical one to WDCE and WDE */ /* Keep old prescaler setting to prevent unintentional time-out */ WDTCR |= (1 << WDCE) | (1 << WDE); /* Turn off WDT */ WDTCR = 0x00; ADCSRA &= ~(1 << ADEN); // turn off adc GIMSK |= (1 << INT0); GIMSK |= (1 << PCIE); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sei(); // Enable global interrupts sleep_cpu(); sleep_disable(); } void animate_leds() { switch (animation_counter) { case 0: animate_frames( three_apart_length, three_apart, 512 ); break; case 1: for (byte acc_counter = 1; acc_counter < 64; acc_counter += 2) { animate_frames( three_apart_length, three_apart, acc_counter * 8 ); } break; case 2: animate_frames( updown_length, updown, 512 ); break; case 3: animate_frames( two_apart_length, two_apart, 2048 ); break; case 4: for (byte acc_counter = 1; acc_counter < 64; acc_counter += 2) { animate_frames( updown_length, updown, (63-acc_counter) * 4 ); } break; default: leds_off(); break; } } void animate_frames( byte animation_length, const byte* animation_array, uint16_t frame_duration ) { for (byte i = 0; i < animation_length; i += 2) { // save the last time you blinked the LED frame1 = pgm_read_byte_near(animation_array + i); frame2 = pgm_read_byte_near(animation_array + i + 1); show_frame(frame_duration); } } // this just looks ugly, but needs to be done // for loop through frame bytes to set the LEDs with // the charlie plex function void show_frame(uint16_t byteframe_length) { for (uint16_t j = 0; j < byteframe_length; j++) { //iterate through bit mask for (byte i = 0; i < 12; i++) { // if bitwise AND resolves to true if ( ( i < 8 && 1 << i & frame1 ) || ( i > 7 && 1 << (i - 4) & frame2 ) ) { charlie(i); } else { charlie(255); } } } } void leds_off() { DDRB &= ~(0b00011101); PORTB &= ~(0b00011101); } void blip() { charlie(11); // delay(100); my_100ms_delay(); charlie(255); // delay(100); my_100ms_delay(); } void my_100ms_delay() { for (uint32_t i=0;i<40000;i++) nop(); }
-
everything ready for a small run
01/01/2018 at 13:41 • 2 commentsAfter a little email exchange with Paul from pimoroni we agreed on me doing a small run of badges on @Tindie is alright with everyone, including their designer, so I will finally do a batch run with @oshpark for the first time.
The code has some potential, needs some cleaning up and some options for animations like I have added to my #K.I.T.T. - KNIGHT RIDER badge/brooch. I should use a higher value of resistors for the LEDs, they blink quite bright.
Part wise I'm all set, everything is ordered so I can sell them as kits, but might add soldered up options like I did with Kitt.
-
ahhh... I need help, I don't see it
12/09/2017 at 22:53 • 8 commentsSomewhere along I had it go to sleep just fine, but it didn't wake up. Now it wakes up fine, but doesn't want to go to sleep. Seems like I don't have the millis stuff right anymore, I don't get to where the comment "// HOW DO I GET HERE?" is. Too tired to see it, gonna go to bed.
#include <avr/sleep.h> boolean leds_on = true; unsigned long previousMillis = 0; unsigned long currentMillis = 0; const long interval = 1000; ISR(INT0_vect) { sleep_disable(); leds_on = true; } void setup() { // put your setup code here, to run once: PORTB |= (1 << PB1); // input DDRB &= ~(1<<PB1); shutdown_chip(); } void loop() { if (leds_on) { cli(); leds_on = false; } currentMillis = millis(); if ( !(PINB & (1 << PB1)) ) { charlie(3); if (currentMillis - previousMillis >= interval) { // HOW DO I GET HERE? charlie(5); delay(2000); shutdown_chip(); } else { charlie(2); } } else { animate_leds(); previousMillis = currentMillis; } } void shutdown_chip() { leds_off(); /* Clear WDRF in MCUSR */ MCUSR &= ~(1 << WDRF); /* Write logical one to WDCE and WDE */ /* Keep old prescaler setting to prevent unintentional time-out */ WDTCR |= (1 << WDCE) | (1 << WDE); /* Turn off WDT */ WDTCR = 0x00; ADCSRA &= ~(1 << ADEN); // turn off adc GIMSK |= (1 << INT0); GIMSK |= (1 << PCIE); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sei(); // Enable global interrupts sleep_cpu(); sleep_disable(); } void animate_leds() { for (int i = 0; i < 12; i++) { charlie(i); delay(50); } for (int i = 0; i < 12; i++) { charlie(11 - i); delay(50); } } void leds_off() { DDRB &= ~( (1 << PB0) | (1 << PB2) | (1 << PB3) | (1 << PB4) ); PORTB &= ~( (1 << PB0) | (1 << PB2) | (1 << PB3) | (1 << PB4) ); } void charlie (int var) { leds_off(); switch (var) { case 0: // 1 DDRB |= (1 << PB0) | (1 << PB2); // output PORTB |= (1 << PB0); // HIGH PORTB &= ~(1 << PB2); // LOW break; case 1: // 2 DDRB |= (1 << PB0) | (1 << PB2); // output PORTB |= (1 << PB2); // HIGH PORTB &= ~(1 << PB0); // LOW break; case 2: // 3 DDRB |= (1 << PB2) | (1 << PB3); // output PORTB |= (1 << PB2); // HIGH PORTB &= ~(1 << PB3); // LOW break; case 3: // 4 DDRB |= (1 << PB2) | (1 << PB3); // output PORTB |= (1 << PB3); // HIGH PORTB &= ~(1 << PB2); // LOW break; case 4: // 5 DDRB |= (1 << PB3) | (1 << PB4); // output PORTB |= (1 << PB3); // HIGH PORTB &= ~(1 << PB4); // LOW break; case 5: // 6 DDRB |= (1 << PB3) | (1 << PB4); // output PORTB |= (1 << PB4); // HIGH PORTB &= ~(1 << PB3); // LOW break; case 6: // 7 DDRB |= (1 << PB0) | (1 << PB3); // output PORTB |= (1 << PB0); // HIGH PORTB &= ~(1 << PB3); // LOW break; case 7: // 8 DDRB |= (1 << PB0) | (1 << PB3); // output PORTB |= (1 << PB3); // HIGH PORTB &= ~(1 << PB0); // LOW break; case 8: // 9 DDRB |= (1 << PB2) | (1 << PB4); // output PORTB |= (1 << PB2); // HIGH PORTB &= ~(1 << PB4); // LOW break; case 9: // 10 DDRB |= (1 << PB2) | (1 << PB4); // output PORTB |= (1 << PB4); // HIGH PORTB &= ~(1 << PB2); // LOW break; case 10: // 11 DDRB |= (1 << PB0) | (1 << PB4); // output PORTB |= (1 << PB0); // HIGH PORTB &= ~(1 << PB4); // LOW break; case 11: // 12 DDRB |= (1 << PB0) | (1 << PB4); // output PORTB |= (1 << PB4); // HIGH PORTB &= ~(1 << PB0); // LOW break; default: ; } }
-
bearables power consumption
11/30/2017 at 14:32 • 0 commentsseems like they use 1.1mA in sleep mode, which isn't really good for a coin cell that has around 230mAh of power - 9 days of doing nothing o.O so with the right settings my sloth badge will already last a lot longer! nice :3