Author Topic: RFM12B Sleep Mode [SOLVED]  (Read 4265 times)

rwormbird

  • Newbie
  • *
  • Posts: 14
RFM12B Sleep Mode [SOLVED]
« on: September 03, 2013, 06:22:10 PM »
Having trouble getting the RFM12B into sleep (oscillator off).

I do the following:

Read Status Reg (0x0000)
Write PA OFF (8208)
Write Osc OFF (8200)

oscillator is still running (draws about 1mA)

Please Advise
« Last Edit: September 05, 2013, 07:59:16 AM by Felix »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 5992
  • Country: us
    • LowPowerLab
Re: RFM12B Sleep Mode
« Reply #1 on: September 03, 2013, 06:50:57 PM »
Did you try the sleep() and wakeup() function in the RFM12B lib?

rwormbird

  • Newbie
  • *
  • Posts: 14
Re: RFM12B Sleep Mode
« Reply #2 on: September 03, 2013, 09:53:50 PM »
After initialization, if button is not pressed, I do this:

   RFM12_Write(0x8208 );          //CLOSE PA
   RFM12_Write(0x0000);          // clear TX empty IRQ
    RFM12_Write(0x8200);         // Turn off oscillator
   delay_ms(10);
   sleep();                  // put PIC to sleep
   delay_cycles(1);

Here is all the transmit code, ported for CCS-C




#opt 9
#include <18F25K20.h>
#device ICD=true
#device *=16
#device ccs3
#include <stdlib.h>
#include <25Ksfr.h>
#use delay(clock=16000000,restart_wdt)
#fuses INTRC_IO,NOWDT,NOMCLR

#define SEL                 pin_A3
#define LED                pin_A5
#define SerClk            pin_C0
#define SerOut            pin_C1
#define SerIn            pin_C2
#define IRQ               pin_B3
#define Button1            pin_B4

//#define RFM12FREQ(freq)     ((freq-430.0)/0.0025)
#define RFM12FREQ(freq)    ((freq-900.0)/.0075)

long RFM12_Write(long data);
long RSSI = 0;
byte Tick = 0;
byte LEDperiod = 0;
byte RSSIThresh = 130;
byte TXbuffer[15];

void RFM12_Init(void);
void RFM12_SetBandwidth(byte bandwidth, byte gain, byte drssi);
void RFM12_SetFreq(long freq);
void RFM12_SetBaud(long baud);
void RFM12_SetPower(byte power, byte mod);
void RFM12_Ready(void);
void RFM12_TxData(byte *data, byte length);
void RFM12_RxData(byte *data, byte length);
void receive(void);
void transmit(void);
void MeasureARSSI(void);                   
//*******************************************************************************
void main(void)
{
   byte index,TEMP;
   set_tris_A(0b00000000);
   set_tris_B(0b00111000);
   set_tris_C(0b00000100);
   PortA = 0;
   PortB = 0;
   PortC = 0;
   setup_oscillator(OSC_16MHZ);
   Setup_CCP1(CCP_OFF);
   Setup_CCP2(CCP_OFF);
   SSPCON1 = 0;
   SSPCON2 = 0;
   T1CON = 0b00110101;
   IOCB = 0b00010000;
   bit_set(INTCON,PEIE);
   TEMP = PORTB;
   bit_clear(INTCON,RBIF);
   bit_set(INTCON,RBIE);   // Port B Change
    output_high(SEL);      // Idle State
    output_low(SerClk);      //
    delay_ms(100);         // wait until POR done
    RFM12_Write(0x0000);   // init RFM12 module
    RFM12_Write(0xC0E0);    // clockout: 10MHz
    RFM12_Write(0x80F8);    // enable FIFO , 915MHz band
    RFM12_Write(0xC2AB);    // data filter: internal
    RFM12_Write(0xCA81);    // set FIFO mode
    RFM12_Write(0xE000);    // disable wakeuptimer
    RFM12_Write(0xC800);    // disable low duty cycle
    RFM12_Write(0xC4F7);    // AFC settings: autotuning: -10kHz...+7,5kHz
    RFM12_SetFreq(RFM12FREQ(915.00)); // Rx/Tx
    RFM12_SetBandwidth(4,0,4); // 200kHz Bandwidth, -20dB LNA gain, RSSI threshold: -79dBm
    RFM12_SetBaud(19200);    // 19200 baud 521uS/byte
    RFM12_SetPower(3,6);     // -7.5db output power, 120kHz frequency shift
RFM12_Write(0x8200);   //
   bit_set(INTCON,GIE);
// ----------------------------
    while (true)
    {
   if (!Input(Button1))
      {
      sprintf(TXbuffer,"\r&00>203R/");
      RFM12_TxData(TXbuffer,11);
      }
   while (!Input(Button1))
      {
      }
   RFM12_Write(0x8208 );          //CLOSE PA
   RFM12_Write(0x0000);          // clear TX empty IRQ
    RFM12_Write(0x8200);         // Turn off oscillator
   delay_ms(10);
   sleep();                  // put PIC to sleep
   delay_cycles(1);
    }
}
/*****************************************************************************/
long RFM12_Write(long data)
{
long data_in = 0;
byte bit;
output_low(SEL);       // select RFM12 module
for (bit=0; bit < 16; bit++)
   {
    if (data & 0x8000)   // transmit bit per bit, MSB first
       output_high(SerOut);
   else
       output_low(SerOut);
   delay_us(1);
    output_high(SerClk); // toggle clock
    data <<= 1;
    data_in <<= 1;      // get bit from RFM12 module
    if (Input(SerIn))
       data_in |= 1;                  
   output_low(SerClk);
    }
output_high(SEL);       // deselect RFM12 module
return (data_in);
}
/*****************************************************************************/
void RFM12_SetBandwidth(byte bandwidth, byte gain, byte drssi)
{
    RFM12_Write(0x9400|((bandwidth&7)<<5)|((gain&3)<<3)|(drssi&7));
}
/*****************************************************************************/
void RFM12_SetFreq(long freq)
{
    /* 430.24, 900.27*/
    if (freq < 96)
        freq = 96;
    /* 439.7575, 929.27 */
    else if (freq > 3903)
        freq = 3903;
    RFM12_Write(0xA000 | freq);
}
/*****************************************************************************/
void RFM12_SetBaud(long baud)
{
    if (baud < 663)
       return; 
    if (baud < 5400)    /* Baudrate= 344827,58621/(R+1)/(1+CS*7) */
        RFM12_Write(0xC680|((43104/baud)-1));
    else
        RFM12_Write(0xC600|((344828UL/baud)-1));
}
/*****************************************************************************/
void RFM12_SetPower(byte power, byte mod)
{   
    RFM12_Write(0x9800|(power&7)|((mod&15)<<4));
}
/*****************************************************************************/
void RFM12_Ready(void)
{   
    output_low(SerOut);
    output_low(SEL); 
   Output_High(LED);
    while (!(Input(SerIn)));   /* wait until FIFO ready */
   Output_Low(LED);
}
/*****************************************************************************/
void RFM12_TxData(byte *data, byte length)
{
    byte i;

    RFM12_Write(0x8238);      /* enable TX */
    RFM12_Ready();

   delay_ms(50);

    RFM12_Write(0xB8AA);       /* send preamble (0xAA) */
    RFM12_Ready();
    RFM12_Write(0xB8AA);
    RFM12_Ready();
    RFM12_Write(0xB8AA);
    RFM12_Ready();
    RFM12_Write(0xB82D);      /* send sync word 0x2DD4 */
    RFM12_Ready();
    RFM12_Write(0xB8D4);

    for (i=0; i < length; i++)   /* send data buffer */
       {
         RFM12_Ready();
        RFM12_Write(0xB800|(*data++));
       }
    RFM12_Ready();
    RFM12_Write(0xB800);    /* transmit 2 dummy bytes to avoid that last bytes of real payload don't */
    RFM12_Ready();
    RFM12_Write(0xB800);    /* get transmitted properly (due to transmitter disabled to early) */
    RFM12_Ready();
    RFM12_Write(0x8200);   /* disable TX */
}
/*****************************************************************************/
void RFM12_RxData(byte *data, byte length)
{
    byte i;
    for (i=0; i < length; i++)
       {   
        RFM12_Ready();      // When FIFO has byte, return (??? Move outside of for loop???)
        *data++=RFM12_Write(0xB000);
       }
RSSI = read_adc();
LEDperiod = (RSSIthresh - RSSI)/5;
}
/*****************************************************************************/
/*****************************************************************************/
#INT_RB
void RadioIRQ(void)
{
byte Temp;
Temp = PortB;
}

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 5992
  • Country: us
    • LowPowerLab
Re: RFM12B Sleep Mode
« Reply #3 on: September 03, 2013, 09:56:48 PM »
Sorry - I believe you're using the jeelib or another variant of it, which I don't support.

rwormbird

  • Newbie
  • *
  • Posts: 14
Re: RFM12B Sleep Mode
« Reply #4 on: September 03, 2013, 10:13:44 PM »
The first time it runs after power up, it goes to sleep (78uA total)

After each successive wake up and transmission, it keeps the RFM oscillator running (965uA)

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 5992
  • Country: us
    • LowPowerLab
Re: RFM12B Sleep Mode
« Reply #5 on: September 03, 2013, 10:21:24 PM »
Here's my implementation of the sleep function on the RFM12B:

Code: [Select]
void RFM12B::Sleep(char n) {
  if (n < 0)
    Control(RF_IDLE_MODE);
  else {
    Control(RF_WAKEUP_TIMER | 0x0500 | n);
    Control(RF_SLEEP_MODE);
    if (n > 0)
      Control(RF_WAKEUP_MODE);
  }
  rxstate = TXIDLE;
}

Then to sleep and wakeup I call:

Code: [Select]
void RFM12B::Sleep() { Sleep(0); }
void RFM12B::Wakeup() { Sleep(-1); }

rwormbird

  • Newbie
  • *
  • Posts: 14
Re: RFM12B Sleep Mode
« Reply #6 on: September 04, 2013, 07:51:39 PM »
I found it, 0x8208 does not put it in the low power mode and neither does 0x8200

I used 0x8201 and now it sleeps and draws only about 10uA

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 5992
  • Country: us
    • LowPowerLab
Re: RFM12B Sleep Mode
« Reply #7 on: September 05, 2013, 07:58:46 AM »
Great, thanks for the update!

Tonio5978

  • Newbie
  • *
  • Posts: 1
Re: RFM12B Sleep Mode [SOLVED]
« Reply #8 on: February 08, 2015, 09:32:19 AM »
Hi,

I have a problem with my RFM12B module. When I put my module and my micro in sleep mode, I have always my IRQ pin active (low state). I have a pull up on this pin. When I remove this pull up, my module consumnes 23ľA. Can you help about my problem please ?

 Write_CMD(RF_SLEEP_MODE); // 0x8201

        __delay_ms(10);
        SLEEP();

My init sequence :
    Write_CMD(0x80D8);
    Write_CMD(0x8208);    /* clockout: 10MHz */
    Write_CMD(0xA640);    /* enable FIFO */
    Write_CMD(0xC647);    /* data filter: internal */
    Write_CMD(0x94A0);    /* set FIFO mode */
    Write_CMD(0xC2AC);    /* disable wakeuptimer */
    Write_CMD(0xCA80);    /* disable low duty cycle */
    Write_CMD(0xCA83);    /* AFC settings: autotuning: -10kHz...+7,5kHz */
    Write_CMD(0xC49B);
    Write_CMD(0x9850);
    Write_CMD(0xE000);
    Write_CMD(0xC80E);
    Write_CMD(0xC000);

Thanks