Flickering Flames

information

This is a guide that brings together a series of guides and information I discovered when looking for fun projects. It uses deadbugging to create a stand-alone functioning circuit. This is based on the beautiful project on Tinker Log for a ‘geeky advent’. It’s my first circuit sculpture!

I will be making this flickering lights, light-activated, to put in a forest area nearby where I live, to give it to other walkers in the area, that will be seen at night. It is a very low light so will not disturb the environment. I am going to modify it to add a little solar panel to keep the battery charged so it should last for a very long time!

the Project

The project as detailed on Tinker Log is a great starting point to have a look at the circuit and how they have reduced it to it’s simplest of parts. They also have code provided and reference other sites that have similar circuits.

The function is to have a small all-in-one flickering circuit, it is programmed on an ATtiny and runs off a small coin cell battery. One of the LEDs is also used to sense the amount of light, and when it is dark, this circuit produces the flickering light effect.

The circuit and code we are building as on Tinker Log:
“The nice thing about this circuit is, that it needs no special components to detect darkness. It uses an LED for that. An LED is also a photodiode that can detect light of the same wavelength it emits. See here for more details. Sprite ( Sprite’s minimalistic version ) used an available ADC of the ATtiny13 instead of the “Reverse Bias” method.”

component list

image of components
  • ATtiny13 (or 25/45/85 etc)
  • 4 LEDs use 3mm (not 5mm as shown in the photo)
  • 3V Coin Cell Battery CR2032 (230 mAh)
  • extra wire (I used enamelled copper wire)/ mounting method

A simple component list, this can be made very cheaply! (and would make fun gifts for people)

ATtiny details

For information about ATtiny IC you can read about it on RS. I’ve included the pinout information as well as an image of the chip https://www.rs-online.com/designspark/basics-of-attiny85

attiny
ATtiny

pin information for ATtiny

  • Pin 1: analogue pin ADC0 and is used for analogue sensors
  • Pin 2: is analogue pin ADC3, also for crystal oscillator XTAL1
  • Pin 3: analogue pin ADC2 and used for crystal oscillator XTAL2
  • Pin 4: should be connected to GND
  • Pin 5: used as MOSI for SPI communication, and SDA for I2C communication
  • Pin 6: used as MISO for SPI communication
  • Pin 7: used as SCK for SPI communication and SCL for I2C communication
  • Pin 8: the Vcc Pin 5V
pin out information

next Step: Programming

arduino in case

There is a comprehensive guide online
https://www.electronics-lab.com/project/how-to-program-attiny13attiny13a-using-arduino-ide/ that demonstrates step-by-step how to program your ATTiny. First, program the bootloader onto the chip so you can then program it as you would for an Arduino board.

connecting the ATtiny to your Arduino Uno

Connect Arduino 5V to ATtiny Pin 8. Also, connect GND to Pin 4, Pin 13 to Pin 7, Pin 12 to Pin 6, Pin 11 to Pin 5, and finally Pin 10 to Pin 1.

ATtiny85 Arduino Board: How to Flash the Arduino Bootloader and ...
Great circuit diagram from Maker Portal with
Electrolytic Capacitor (10uF), I didn’t use one.

You should follow the guide on electronics lab but the general steps are after hook up:

  1. Program ATtiny13: set Arduino as a programmer. This happens by uploading ArduinoISP sketch to Arduino following this path (Files -> Examples -> ArduinoISP) in the IDE.
  2. Install core files needed:
    To install these files, open your Arduino IDE and navigate to the files drop-down menu, then select preferences. Paste this URL “https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json” where it says “Additional Boards Manager URLs:”. If you already have a URL here and want to add more, separate the URLs with a comma and a space.
  3. Now, navigate to tools-board and click on Boards Manager…. Now scroll down until you see DIY ATtiny and click the install button.
  4. In order to start programming ATtiny 13, we must burn Bootloader to it. There are two steps to achieve this: first, go to Tools >Board and select ATtiny13,
    Note: Pay attention to your ATtiny version, navigate to Tools > Processor Version and select either ATtiny13 or ATtiny25 depending on your chip. (mine is a ATtiny25)
  5. tools > programmer > Arduino as ISP
  6. and second, click the Burn Bootloader button at the bottom of the tools drop-down menu.

success?

If you see the success message then you are ready to try the ATtiny.
Try an Arduino IDE example like the Blink sketch.

How the circuit will look when completed.

simple LED Blink sketch

Upload the sketch to the ATtiny13 (using the Uno board and the ‘Arduino as ISP’ programmer and wiring) – then you have a fully-functional Arduino ATtiny13!

int led_pin = 4; 

void setup() {
pinMode(led_pin,OUTPUT);
}

void loop(){
digitalWrite(led_pin,HIGH);
delay(1000);
digitalWrite(led_pin,LOW);
delay(1000);
}
Adding a single cell battery to power the chip and leds!

modified code for flicker LED effect

Once you have been able to load up the blink code successfully, you can upload the flickering LEDs code that has been provided in the original post at Tinker Log. There was only a tiny modification to get it to work in Arduino.

Choose the correct board and board settings. Below are some of the settings I’ve used.

Options in Arduino
Options in Arduino accessed via the Tools menu.

/* -----------------------------------------------------------------------
 * Title:    advent.c
 *           Flicker 4 LEDs
 *           
 * Author:   Alexander Weber
 *           http://tinkerlog.com
 * Date:     22.11.2009
 * Hardware: ATtiny13v
 * Software: CrossPack-AVR-20090415
 *
 * Credits:
 * This code is based heavily on sritesmods version.
 * Find the original at http://spritesmods.com/?art=minimalism&f=gpl
 *
 * Changes:
 * - support 4 LEDs
 * - added a bit of sampling for light detection
 * - moved the "power down" out of the ISR, was always resetting
 * - removed callibration, replaced by hardwired value.
 */


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/wdt.h>


#define LED1  PB4 
#define LED2  PB3
#define LED3  PB2
#define LED4  PB1
#define ADC2 2
#define AMBIENT_LIGHT 300

#define TRUE 1
#define FALSE 0


//Bunch o' random numbers: I'm too lazy to write or port a real random number
//generator.
//generated using bash:
//for x in `seq 0 255`; do echo -n $(($RANDOM%256)),; done
uint8_t const randomvals[] PROGMEM = {
 234,191,103,250,144,74,39,34,215,128,9,122,144,74,137,105,123,218,158,175,205,
 118,149,13,98,7,173,179,194,97,115,110,213,80,220,142,102,102,36,152,90,135,
 105,176,173,49,6,197,48,140,176,122,4,53,83,216,212,202,170,180,214,53,161,
 225,129,185,106,22,12,190,97,158,170,92,160,194,134,169,98,246,128,195,24,
 198,165,156,77,126,113,136,58,156,196,136,41,246,164,84,138,171,184,42,214,
 203,128,89,39,198,85,140,148,149,36,215,78,170,234,131,124,152,239,154,214,
 130,194,49,3,69,248,120,179,101,163,131,124,184,148,213,118,213,81,177,149,
 58,213,33,201,63,10,195,215,190,7,86,245,128,9,8,40,102,51,125,94,92,5,159,
 75,253,158,40,4,6,178,241,92,124,73,248,1,157,61,50,86,136,113,22,16,171,209,
 230,144,240,14,188,2,167,22,88,57,50,86,171,73,114,175,34,226,245,57,180,111,
 220,186,170,242,141,229,49,158,30,82,161,49,124,65,139,24,95,14,133,65,238,
 116,180,190,49,130,30,30,59,93,173,139,19,187,2,163,102,26,255,23,239,196,19,
 6,162
};

uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
static volatile uint8_t sleep = 0;

// Gets a semi-random number between 0 and 255
uint8_t getRandom(void) {
  //This'll probably give a warning because we use it uninitialised. Little 
  //does the compiler know: that's actually what we _want_ :)
  static uint8_t random1, random2;
  random1++;
  if (random1 == 0) {
    random2 += 0x41;
  }
  return pgm_read_byte(randomvals + random1) ^ random2;
}


uint16_t getLight(void) {
  uint16_t val = 0;
  uint8_t i;

  // measure pb4 using internal ref
  ADMUX = (1 << REFS0) | ADC2;             
  
  // enable ADC, prescaler 8
  ADCSRA = (1 << ADEN) | 3;
  
  // kill all leds
  PORTB &= ~((1 << LED1) | (1 << LED2) | (1 << LED3) | (1 << LED4));
  _delay_ms(5);

  // let led generate some voltage
  DDRB &= ~(1 << LED1);
  _delay_ms(5);

  // warm up the ADC, discard the first conversion
  ADCSRA |= (1 << ADSC);
  while (ADCSRA & (1 << ADSC)); 
  
  for (i = 0; i < 4; i++) {
    _delay_ms(5);
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADSC)); 
    val += ADC;
  }
  val >>= 2;
  
  ADCSRA = 0;             // disable adc
  DDRB |= (1 << LED1);    // re-enable led

  return val;
}


void powerDown(void) {
  // Go to sleep until we're woken up by the wdt.
}


ISR(WDT_vect) {
  //check if it's still dark
  sleep = (getLight() > AMBIENT_LIGHT) ? TRUE : FALSE;
}

int main(void) {
  uint8_t lval1, lval2, lval3, lval4;
  uint8_t i, x, y;
  uint8_t mode;

  // set up wdt
  wdt_enable(WDTO_2S);


  WDTCR |= 0x40; // WDT generates interrupts instead of resets now.
                 // We want interrupts because a reset clears our nice random
                 // seeds, and an interrupt doesn't.
     
  for (i = 0; i < 10; i++) {
    _delay_ms(100);
  }

  // retrieve mode from eeprom and write back mode + 1
  mode = eeprom_read_byte(&mode_ee);
  mode = mode % 4;
  eeprom_write_byte(&mode_ee, mode + 1);  

  sei();

  // go directly into sleep mode and lets wake up by the wdt
  sleep = TRUE;

  // enable leds
  DDRB = (1 << LED1) | (1 << LED2) | (1 << LED3) | (1 << LED4);

  while (1) {

    WDTCR |= 0x40; // make sure wdt keeps generating an int instead of a reset

    if (sleep) {
      // switch off all LEDs and power down
      PORTB &= ~((1 << LED1) | (1 << LED2) | (1 << LED3) | (1 << LED4));
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sleep_mode();
    }
    else {
      // get a random value for the leds intensity
      lval1 = getRandom();
      lval2 = getRandom();
      lval3 = getRandom();
      lval4 = getRandom();    
      // Manually do some pwm
      for (x = 0; x < 20; x++) {
  if (mode == 0) {
    PORTB |= (1 << LED1);
  }
  else if (mode == 1) {
    PORTB |= (1 << LED1) | (1 << LED2);
  }
  else if (mode == 2) {
    PORTB |= (1 << LED1) | (1 << LED2) | (1 << LED3);
  }
  else if (mode == 3) {
    PORTB |= (1 << LED1) | (1 << LED2) | (1 << LED3) | (1 << LED4);
  }
  for (y = 0; y != 255; y++) {
    if (y == lval1) {
      PORTB &= ~(1 << LED1);
    }
    if (y == lval2) {
      PORTB &= ~(1 << LED2);
    }
    if (y == lval3) {
      PORTB &= ~(1 << LED3);
    }
    if (y == lval4) {
      PORTB &= ~(1 << LED4);
    }
    _delay_us(5);
  }
      }
    }
  }
}


Soldering the initial ring of LEDs, all negative legs (cathodes) form the ring shape.

soldering the Circuit

  • All cathodes of the LEDs are connected to form the ring.

I first took 4 LEDs to sacrifice and practice bending the ground leg of them into this circle form. I then tried a few different ways to solder them together. In the end, I put the anode (positive) leg into a mini breadboard to hold them once they were already bent into shape. Then I used a crocodile clip to hold the leg together in place as I soldered it.

  • The anodes are bent inwards to be soldered to pin 2, 3, 6 and 7 of the ATtiny13.
  • Use wire to connect the common cathode (soldered) to the GND pin.
  • The GND pin is then connected to GND of the battery.

References

Dietz, P.H., Yerazunis, W.S., Leigh, D.L., “Very Low-Cost Sensing and Communication Using Bidirectional LEDs”ACM International Conference on Ubiquitous Computing (UbiComp), October 2003. PDF Download

Tutorial Online on Tinker Log [Accessed April 20, 2020].

Comprehensive guide online to programming an ATtiny Online Available:
https://www.electronics-lab.com/project/how-to-program-attiny13attiny13a-using-arduino-ide/ [Accessed April 18, 2020].

Installing additional boards,
https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json to add the ATtiny to Arduino Available Online [Accessed April 15, 2020].

Circuit diagram online available from Maker Portal [Accessed April 18, 2020].

Another version of the circuit via Sprite Sprite’s minimalistic version Available online [Accessed April 20, 2020].

Extra

Have you made an aircircuit or done deadbugging before? Do you have any small projects? What skills have you been working on? Drop me a comment!

Leave a Reply

Your e-mail address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.