.
I guess I can't stop doing badges. Really love the @pimoroni #bearables - but they don't have sloths :(
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
.
sloth.inoino - 3.81 kB - 01/01/2018 at 13:32 |
|
|
sloth_final.schsch - 310.99 kB - 01/01/2018 at 13:30 |
|
|
sloth_final.brdbrd - 154.46 kB - 01/01/2018 at 13:30 |
|
|
sloth_final.pdfAdobe Portable Document Format - 21.78 kB - 11/24/2017 at 16:36 |
|
|
sloth_final_production.dxfAutoCAD DXF - 76.72 kB - 11/24/2017 at 16:36 |
|
After 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.
I 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...
Read more »
After 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.
Somewhere 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:
;
}
}
seems 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
Create an account to leave a comment. Already have an account? Log In.
oof, good one, I just bought them cheap on ebay, but they had this:
I'd be happy to add you here if you want to share any of your changes btw
I want to give this as a gift for Christmas. DO I have to order boards or do you sell them?
not selling them yet, I don't even have my first prototype boards here :D if you still want to try it, feel free to do your own sanity check for the boards and order them, I can't make any promises, but it should work. Software isn't done either, but I wanted to work on it this evening. Thank you for your interest :)
Oh, and I see you have a push-button for a switch — experimenting with the sleep modes?
yup :) got a proof of concept for the power down to 0.1uA (if I recall correctly, what my multimeter showed (correctly?) :D that was important to me, to play around with that and get to know the registers etc a bit better
An interesting way of doing dithering. Have you considered using dots instead, like the newspapers do for grey-scale?
definitely thought of that, but this is in the style of the bearables by pimoroni and it's supposed to blend in ;) https://shop.pimoroni.com/collections/bearables/products/bearables-bear-led-badge
Become a member to follow this project and never miss any updates
Heya Dave, just a quick one. What are the rough specs (forward V, current and intensity) of the LEDs you are using to swap some out to maintain similar brightness?