Random timer circuit using a Attiny24A

This random timer circuit is based on a Atmel ATTINY24 avr driving one power relay. You can use this circuit to switch on and off other circuits randomly. For example, when using this circuit on a model railroad you can turn on and off parts of the animated or moving scenery to create a more dynamic view.

attiny24 random timer circuit prototype

This circuit was designed to be used on a modular model railroad. This model railroad contains different flashing light on ambulances, police cars and fire engines. These lights are on all the time, with this circuit I hope to keep visitors of a model railroad exposition more interested while watching all the action.

attiny random timer circuit schematic

The schematic of the random timer circuit is divided into different functionality blocks. The power supply block stabilizes the 12V and protects the power input for reverse polarity. There is a standard 7805 voltage stabilizer to supply 5V to the microcontroller.

The input block consists of 3 potentiometers and one button. The potentiometers can be used to configure the on and off time, and the amount of random time. ADC0 is connected the the potentiometer which configures the amount of random time between 0% and 500% extra time.
ADC1 configures the off time between 1 and 60 seconds. ADC2 configures the on time in the random timer circuit. The button is there just because I like buttons, it has no functionality. Actually, the prototype of the random timer circuit I made was using one of my other boards (the tiny dcc decoder for 8 leds), this board already has the button, so there you go.

The processor block is where all the math takes place. The ATTINY24 reads the inputs and calculates the on and off times in the random timer circuit. The ATTINY24 contains a program with predefined random number generated with my online random number generator. These random numbers is what makes this circuit random. You might say that when it is predefined these random numbers aren’t really random, yes, but… for the purpose of this circuit is works just fine. Even when duplicating this circuit and programming the same hexfile into another microcontroller they both seem random. In the beginning they will be somewhat synchronized random, but because of the unstable internal RC oscillator they will drift over time in clock speed and then they both appear to be random.

Lastly the output block contains a relay which is driven by a transistor. The transistors base (input) is connected to the microcontroller. I have chosen for this prototype to be a 1 channel random timer circuit, but the ATTINY24 microcontroller has 5 pins unused which can be combined into a 6 channel random timer circuit.

Here is my prototype of the random timer circuit:

attiny24 random timer circuit prototypeThere are some parts used that are different in type, but are still have the same functionality. The 7805 is AMS1117 and the transistor that drives the relay is a SMD 2N2222 (on the bottom). You can see I connected a red 5MM led to the random timer circuit so I can see when the relay is switched on.

Here is the program that runs in the attiny24 microcontroller:

/*
 * AvrStudioRandomTimer.c
 *
 * Created: 13-12-2012 21:30:06
 *  Author: Marc, https://atoomnet.net/
 */

#include <avr/io.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/signature.h>

#include "random.h"

//Used for programming the production ELF file.
LOCKBITS = LB_MODE_3; //Further programming and verification disabled
FUSES =
{
  .low = (FUSE_CKSEL3 & FUSE_CKSEL2 & FUSE_CKDIV8 & FUSE_CKSEL0 & FUSE_SUT0), //Internal 8MHz rc oscillator, CKDIV8, 64ms startup time.
  .high = (FUSE_SPIEN & FUSE_BODLEVEL0), //Enable Serial programming, Brown-out 1.8V
  .extended = EFUSE_DEFAULT,
};

#define mintime 1
#define maxtime 60

#define maxadc 65472

//Access bits like variables
struct _io_reg {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
};
#define REGISTER_BIT(port,pin) ((*(volatile struct _io_reg*)&port).b##pin)

#define RELAY1     REGISTER_BIT(PORTA, 7)
#define RELAY1_DDR REGISTER_BIT(DDRA,  7)
#define LED        REGISTER_BIT(PORTB, 1)
#define LED_DDR    REGISTER_BIT(DDRB,  1)

#define EV100ms _BV(0)

#define event GPIOR0

//This ISR runs every 100ms.
ISR(TIM0_COMPA_vect)
{
  event |= EV100ms;
}

uint16_t readadc(uint8_t channel)
{
  uint16_t adcvalue = 0;

  ADCSRA = 0;
  ADCSRA |= _BV(ADEN) | _BV(ADPS2); //ADC enable, Prescaler 16

  ADMUX = channel & 0b00111111;

  //Discard 1st conversion.
  ADCSRA |= _BV(ADSC); //start conversion
  loop_until_bit_is_clear(ADCSRA, ADSC); //wait for end of conversion

  for(uint8_t i=0;i<64;i++)
  {
    ADCSRA |= _BV(ADSC); //start conversion
    loop_until_bit_is_clear(ADCSRA, ADSC); //wait for end of conversion
    adcvalue += ADC;
  }

  return adcvalue;
}

uint8_t GetRandomValue(uint16_t amplitude)
{
  return ((uint32_t)READrnd() * amplitude) / maxadc;
}

int main(void)
{
  uint16_t timerrelay1 = 0;
  uint16_t onvalue;
  uint16_t offvalue;
  uint16_t onrandom = 0, offrandom = 0;
  uint8_t blinkcounter = 0;

  //Turn on power saving
  power_all_disable();
  power_adc_enable();

	//initialize 8BIT Timer0
  power_timer0_enable();
  TCCR0A |= _BV(WGM01); //CTC
	TIMSK0 |= _BV(OCIE0A); // enable timer interrupt
  //10Hz
  OCR0A = 0x61;
	TCCR0B |= _BV(CS00) | _BV(CS02); // CK/1024

  LED_DDR = 1;
  RELAY1_DDR = 1;

  PORTB |= _BV(PB0); //Switch, pull-up

  //Unused pins: pull-up
  PORTA |= _BV(PA3) | _BV(PA4) | _BV(PA5) | _BV(PA6);
  PORTB |= _BV(PB2) | _BV(PB3);

	sei(); //enable interrupts

  for(;;)
  {

    while(event == 0)
    {
      //idle code
    }

    if (event & EV100ms)
    {
      event &= ~EV100ms;

      if (timerrelay1 == 0 )
      {
        ADMUX &= (0b00111111); //Vcc ref;

        //The on and off random times are maximum 5 times the duration of the on-time.
        offrandom = GetRandomValue(readadc(0)) * 5;
        onrandom = GetRandomValue(readadc(0)) * 5;
      }

      offvalue = mintime*10 + (((uint32_t)readadc(1) * (maxtime-mintime)*10) / maxadc);
      onvalue = mintime*10 + (((uint32_t)readadc(2) * (maxtime-mintime)*10) / maxadc);

      offvalue = offvalue + (offvalue * offrandom)/0xFF;
      onvalue = onvalue + (onvalue * onrandom)/0xFF;

      //Decrease timer if new values are lower
      if (RELAY1 == 0 && timerrelay1 > offvalue)
        timerrelay1 = offvalue;

      if (RELAY1 == 1 && timerrelay1 > onvalue)
        timerrelay1 = onvalue;

      if (timerrelay1 == 0 )
      {
        //Turn on when off, off when on
        if (RELAY1 == 0)
          RELAY1 = 1;
        else
          RELAY1 = 0;

        //Load timing value into timer variable.
        if (RELAY1 == 0)
          timerrelay1 = offvalue;
        else
          timerrelay1 = onvalue;
      }

      timerrelay1--;

      //Blink the led every 1 second
      blinkcounter++;
      if (blinkcounter==10)
      {
        LED = 1;
        blinkcounter = 0;
      }
      else
      {
        LED = 0;
      }

    }

    //reset all remaining events
    event = 0;
  }
}

The code was programmed in Atmel Studio 6. You can generate the random.h using my online random number generator: Online random number generator for AVR microcontroller.
The microcontroller runs on a clock speed of 1MHz. You can download the complete project here: attiny-random-timer-source.zip

Are you going to build this random timer circuit? Let me know and sent me some pictures of it.
Did you like this post? Please give it a thumbs up by sharing it on your social network. Thanks!

2 thoughts on “Random timer circuit using a Attiny24A

  1. Aggie

    Hi, was just going through your site and your timer circuit. Just want to know if you can program the below mentioned logic in the Attiny24A, as I want to build a circuit which can do the functions as desired.

    I would appreciate if you can email me the circuit and programming details

    Regards

    Aggie

    A timer circuit with a programmable time delay of 0 to 60 seconds
    With:
    One trigger input (normally closed magnetic reed switch) Positive trigger +V
    One reset input (Normally open push button) Negative – Input
    One relay output (NO C NC)

    Operation of the system:

    On positive edge trigger (the normally closed magnetic reed switch (S1) is open) the timer starts a delay of the preset time of 15 seconds.

    At the end of the 15 seconds timing cycle the output goes high for 2 seconds and then goes low(relay is engaged for 2 seconds and resets itself)

    Reset function:

    On positive edge trigger (the normally closed magnetic reed switch (S1) is open) the timer starts a delay of the preset time of 15 seconds.

    The (normally open magnetic reed switch is closed before the time delay of 15 seconds expires) The normally open reset button (B1) is pressed and the 15 seconds time delay is cancelled. The output remains low (no pulse of 2 seconds on the output relay)

    Reset function disable:

    On positive edge trigger (the normally closed magnetic reed switch (S1) is open) the timer starts a delay of the preset time of 15 seconds.
    The (normally open magnetic reed switch (S1) is open) normally open reset button (B1) is pressed and the 15 seconds time delay is not cancelled. The output goes high for 2 seconds and then goes low (relay is engaged for 2 seconds and resets itself)
    The same process follows for every trigger input & reset.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *