Shahariar
Published © GPL3+

Low Power RF Beacon for Remote Sensing & Communication

A CR2032-powered beacon to communicate over 433MHz RF band with blinks encoded message using ATtiny85 and 433MHz RF trans-receiver Modules

BeginnerFull instructions provided3 hours15,099

Things used in this project

Hardware components

ATtiny85
Microchip ATtiny85
×1
Arduino UNO
Arduino UNO
×1
General Purpose Quad Op-Amp
Texas Instruments General Purpose Quad Op-Amp
×1
SparkFun 433 MHz Transmitter
×1
SparkFun 433 MHz Receiver
×1
Coin Cell Battery CR2032
Coin Cell Battery CR2032
×1
Coin Cell Battery Holder
Coin Cell Battery Holder
×1
Veroboard
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

RF Beac Tx and Rx

Code

RF Beacon

C/C++
ver 1.0.0 Blinky only Final
// *** Watchdog Timer (WDT) can wake up MCU from sleep when expires
// *** Sleep allows longer operation for Battery powered device
// *** User Switch is Interrupt Enabled 
// *** Blinking can be programmed up to 4 blinks with User Switch
// *** Blinking can be turned off with pressing User Switch during 4 blinks 

#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>

#define PUSH_SWITCH 2
#define BLUE_LED    4
#define POWER_RFD   3

volatile int Press_Counter = 0;


void setup() 
{
//Bootloader configured to run ATtiny85@1MHz internal clock,lower clock yields less power consumption   
sleep_adc_disable();                 // saves power since ADC not used thus disabled
sleep_bod_disable();                 // saves more power and provides longer 
                                     // operation by draining battery deep
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Power down everything, except WDT
sleep_enable();                      // Short naps are allowed between blinks
switch_init();                       // enable interrupt on push switch
led_init();                          // enable LED driving GPIO pin as Output
rf_433mhz_init();                    // enable 433 MHz Tx driving GPIO pin as Output
}


void loop() 
{ 
/////// 1 Blink ////////
  while(Press_Counter == 1)
    {
    short_blink();   // powers LED for 5 ms 
                     // but persistance of vision makes it look longer
    no_blink_long(); // sleep 1 sec to save power 
    }

/////// 2 Blinks ////////
  while(Press_Counter == 2)
    {
    short_blink();
    short_blink();
    no_blink_long();
    }

/////// 3 Blinks ////////
  while(Press_Counter == 3)
    {
    short_blink();
    short_blink();
    short_blink();
    no_blink_long();
    }

/////// 4 Blinks ////////    
  while(Press_Counter == 4)
     {
    short_blink();
    short_blink();
    short_blink();
    short_blink();
    no_blink_long();
    }

/////// Stop Blinking ////////    
 while(Press_Counter == 5)
   {
    // Just Stay in sleep, no Blinking, LED OFF - most power saving 
    no_blink_long();
    no_blink_long();
    
   }
///////// Enter RF Mode to Transmit Remote Blink ///////
      for(int i=0;i<4;i++)
      {
       digitalWrite(4,HIGH);
       delay(250);
       digitalWrite(4,LOW);
       delay(250);
       }
    powerup_rf_433mhz();
     while(Press_Counter == 6)
     {
      short_blink();
      no_blink_long(); 
     }
    

   
    while(Press_Counter == 7)
     {
    short_blink();
    short_blink();
    no_blink_long();
     }
      
    while(Press_Counter == 8)
     {
    short_blink();
    short_blink();
    short_blink();
    no_blink_long();
     }

    while(Press_Counter == 9)
     {
    short_blink();
    short_blink();
    short_blink();
    short_blink();
    no_blink_long();
     }

  powerdown_rf_433mhz();
   
   for(int i=0;i<2;i++)
      {
       digitalWrite(4,HIGH);
       delay(250);
       digitalWrite(4,LOW);
       delay(250);
       }

// exits rf mode, enters standalone beacon mode      
}
//////// Void Loop Ends Here ///////


//////////////////////////////////////////
/////////// Functions Body ///////////////
//////////////////////////////////////////

void led_init(void)
{
  pinMode(BLUE_LED,OUTPUT);
 digitalWrite(BLUE_LED,LOW);

}

void short_blink(void)
{
    digitalWrite(4,HIGH);// turn on LED
    delay(3);            // keep LED on
    digitalWrite(4,LOW); // ture off LED 
    setup_watchdog(4);   // 250 ms length for watchdot timer
    sleep_mode();        // sleep until watchdog barks
    wdt_disable();       // hush the dog after waking up from sleep
}

void no_blink_long(void)
{
// 1 second sleeping
    setup_watchdog(6);   // 1000 ms length for watchdog timer
    sleep_mode();        // sleep until watchdog barks
    wdt_disable();       // hush the dog after waking up from sleep
 
}

void sleep_adc_disable(void)
{
   ADCSRA &= ~(1<<ADEN); //Disable ADC, saves power
}

void adc_enable (void)
{
  ADCSRA |= (1<<ADEN);  //Enable ADC if needed, not used here
}

void switch_init(void)
{
// push switch input stays High through internal pullup resistor
// push switch goes Low when user presses the switch and interrupt occurs  
  pinMode(PUSH_SWITCH, INPUT_PULLUP);
// Only level interrupt can wake from sleep, neither can rising nor falling edge
  attachInterrupt(0, SW_ISR, LOW); 
}



//Sets the watchdog timer to wake us up, but not reset
//0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
//6=1sec, 7=2sec, 8=4sec, 9=8sec

// http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/

void setup_watchdog(int timerPrescaler) 
{
//Limit incoming amount to legal settings
  if (timerPrescaler > 9 ) timerPrescaler = 9;   
  byte bb = timerPrescaler & 7; 
  if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary

/////////// This order of commands is important and cannot be combined ////////
  MCUSR &= ~(1<<WDRF);             //Clear the watch dog reset
  WDTCR |= (1<<WDCE) | (1<<WDE);   //Set WD_change enable, set WD enable
  WDTCR = bb;                      //Set new watchdog timeout value
  WDTCR |= _BV(WDIE);              //Set the interrupt enable, this will keep unit from resetting after each int
}

void rf_433mhz_init(void)
{
   pinMode(POWER_RFD,OUTPUT);
   digitalWrite(POWER_RFD,LOW);
}

void powerup_rf_433mhz(void)
{
   digitalWrite(POWER_RFD,HIGH);  
   delay(50);
}

void powerdown_rf_433mhz(void)
{
   digitalWrite(POWER_RFD,LOW);  
   delay(20);
}
void rf_short_blink(int n)
{
     wdt_disable();
    powerup_rf_433mhz();
    for(int j=0; j<n;j++)
    {
    digitalWrite(4,HIGH);// turn on LED
    delay(100);
    digitalWrite(4,LOW); // ture off LED 
   }
    powerdown_rf_433mhz();
 
}

//////////Interrupt Service Routines ///////////////////
/////////////////////// ISR ////////////////////////////

///////// SW_ISR Runs when switch is pressed ///////////

void SW_ISR()
{
 wdt_disable();
 Press_Counter++;
 if (Press_Counter >9)
 Press_Counter = 1;
// To avoid happening chain interrupts while switch is low
// Next option will selece only after release and new press of switch
    while(digitalRead(PUSH_SWITCH) == 0)
    {
      cli(); // Disables all Interrupt (except reset)
    }
 sei();      // Enables all Interrupt

 }

//// ISR runs when Watchdog expires ////

ISR(WDT_vect)
{
            // need to do nothing here   
}

////////////// END OF CODE //////////////

Credits

Shahariar
75 projects • 270 followers
"What Kills a 'Great life' is a 'Good Life', which is Living a Life Inside While Loop"
Contact

Comments

Please log in or sign up to comment.