Project tutorial

Low Power RF Beacon for Remote Sensing & Communication © GPL3+

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

  • 1,539 views
  • 0 comments
  • 12 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project

Introduction

It's all about low profile, low power remote sensing or blinks messaging over short range. This project can be re-purposed for door position sensing, water, sound, light, temperature sensing or sending blink encoded messaging.

Blink encoded messaging means predefined meaning for each consecutive blinks. For example 1 blink means MISSION FAILED, 2 blinks mean I AM IN PINCH, 3 blinks mean OK etc.

Similarly, blinks can represent water level:

  • 1 blink - 25% full
  • 2 blinks - 50% full
  • 3 blinks - 75% full
  • 4 blinks - 100% full

Building the Hardware

There are total 3 modules in this system. Since, each picture is worth a thousand words, check the images with captions to understand the build procedure in details.

Step 1: Making the Receiver Module

Step 2: Building the Transmitter Module

Step 3: Creating the Programmable Beacon

Step 4: Attaching Transmitter on the Beacon

Developing and Uploading the Code

Before programming the ATtiny85, it is removed from IC Base and placed on a breadboard to burn bootloader with 1 MHz internal clock setting. To program ATtiny85, an Arduino UNO board is converted to ISP programmer by uploading the " ArduinoISP" from File > Example > ArduinoISP sketch. This sketch is available in Arduino IDE.

Programming ATtiny85 requires following steps:

  • Developing and Uploading Code using Arduino UNO as ISP

Following circuit is prepared to burn bootloader program and then the application program on ATtiny85 flash:

1 / 2 • Burning Bootloader and Uploading code using Arduino Uno as ISP

ATtiny85 Low Power

Lowering power consumption on ATtiny85 can be achieved by taking following actions:

  • Lower system clock (1MHz is better than 8 or 16)
  • Low Vcc (3v is better than 5v)
  • Disabling unused peripherals like ADC, BOD
  • Entering sleep/power down mode while no operations required
  • Reducing frequent active time

By making appropriate change in hardware and software above actions are achieved. Here is a nice article on Sparkfun about this!

To ensure that the transmitter is off when not required (local blink only mode), one of the ATtiny pin is used to power the Vcc of the transmitter during operation only by making that pin high. At 3 volts the transmitter only takes 12-14 mA current which the Digital pin of ATtiny85 can provide.

In case external Vcc (up to 12V) is supplied to power the transmitter for long range, there is a jumper to detach Vcc pin of the transmitter from the ATtiny pin. A 9V battery can supply the transmitter.

Antenna Design

From high school physics, we all know c = f * lambda , where c is the speed of light or EM radiation, f is the frequency and lambda is the wavelength.

A general purpose antenna would be 1/4 the wavelength. By using the above formula:

A piece of wire which has 17.3 cm length will do the job for low range operation.

Check out this improved 433 antenna design instructable.

Range Extension

Range of the transmitter-receiver pair can be increased by taking following actions:

  • Using the improved version of the antenna
  • Supplying higher Vcc on transmitter (up to 12 Volts) by removing the jumper and applying Vcc external on the transmitter module (RED/BLACK) pins
  • Maintaining less obstacles (walls, metal grids) between transmitter and receiver, best if Line of Sight is maintained.
  • Keeping both antenna on the same plane (like 90 degrees up)

Conclusion

The low bit rate allows simple and reliable communication with only one microcontroller. Although, it is possible to send complex data by using another micro on the receiving end.

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 //////////////

Schematics

RF Beac Tx and Rx
Rf beacon oxl8gsyc3t

Comments

Similar projects you might like

Arduino Bluetooth Basic Tutorial

by Mayoogh Girish

  • 454,970 views
  • 42 comments
  • 239 respects

Home Automation Using Raspberry Pi 2 And Windows 10 IoT

Project tutorial by Anurag S. Vasanwala

  • 285,663 views
  • 95 comments
  • 672 respects

Security Access Using RFID Reader

by Aritro Mukherjee

  • 229,745 views
  • 38 comments
  • 239 respects

OpenCat

Project in progress by Petoi

  • 196,299 views
  • 154 comments
  • 1,364 respects
Add projectSign up / Login