Close
0%
0%

sloth badge

I guess I can't stop doing badges. Really love the @pimoroni #bearables - but they don't have sloths :(

Similar projects worth following
there are some nifty tricks hidden in the bearables badges, a cool menu etc. I want to replicate the behaviour with an ATTINY13A.

.

sloth.ino

ino - 3.81 kB - 01/01/2018 at 13:32

Download

sloth_final.sch

sch - 310.99 kB - 01/01/2018 at 13:30

Download

sloth_final.brd

brd - 154.46 kB - 01/01/2018 at 13:30

Download

sloth_final.pdf

Adobe Portable Document Format - 21.78 kB - 11/24/2017 at 16:36

Preview

sloth_final_production.dxf

AutoCAD DXF - 76.72 kB - 11/24/2017 at 16:36

Download

View all 6 files

  • new design!

    davedarko02/20/2018 at 22:59 2 comments

    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.

  • current code, anyone any ideas to save space?

    davedarko02/19/2018 at 10:28 8 comments

    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 »

  • everything ready for a small run

    davedarko01/01/2018 at 13:41 2 comments

    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. 

  • ahhh... I need help, I don't see it

    davedarko12/09/2017 at 22:53 8 comments

    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:
          ;
      }
    }

  • bearables power consumption

    davedarko11/30/2017 at 14:32 0 comments

    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

View all 5 project logs

Enjoy this project?

Share

Discussions

Blecky wrote 09/14/2018 at 14:49 point

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?

  Are you sure? yes | no

davedarko wrote 09/14/2018 at 16:11 point

oof, good one, I just bought them cheap on ebay, but they had this:

https://cdn.hackaday.io/images/7008311536941468707.jpg

  Are you sure? yes | no

Blecky wrote 09/15/2018 at 03:38 point

Perfect :D

  Are you sure? yes | no

davedarko wrote 09/17/2018 at 08:56 point

I'd be happy to add you here if you want to share any of your changes btw

  Are you sure? yes | no

Dylan Brophy wrote 11/30/2017 at 05:36 point

I want to give this as a gift for Christmas.  DO I have to order boards or do you sell them?

  Are you sure? yes | no

davedarko wrote 11/30/2017 at 09:29 point

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 :)

  Are you sure? yes | no

EK wrote 11/25/2017 at 21:34 point

CUTE!

  Are you sure? yes | no

deʃhipu wrote 11/25/2017 at 10:29 point

Oh, and I see you have a push-button for a switch — experimenting with the sleep modes?

  Are you sure? yes | no

davedarko wrote 11/25/2017 at 10:47 point

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

  Are you sure? yes | no

deʃhipu wrote 11/25/2017 at 10:28 point

An interesting way of doing dithering. Have you considered using dots instead, like the newspapers do for grey-scale?

  Are you sure? yes | no

davedarko wrote 11/25/2017 at 11:35 point

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

  Are you sure? yes | no

deʃhipu wrote 11/25/2017 at 16:54 point

Oh, I see, that makes sense now!

  Are you sure? yes | no

davedarko wrote 11/25/2017 at 07:39 point

well great, now I need a sloth suit :D

  Are you sure? yes | no

oshpark wrote 11/25/2017 at 00:21 point

Love the design!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates