.
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
By using our website and services, you expressly agree to the placement of our performance, functionality, and advertising cookies. Learn More
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?