RFM12B Sleep Mode [SOLVED]

Started by rwormbird, September 03, 2013, 06:22:10 PM

rwormbird

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

Felix

Did you try the sleep() and wakeup() function in the RFM12B lib?

rwormbird

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

Sorry - I believe you're using the jeelib or another variant of it, which I don't support.

rwormbird

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

Here's my implementation of the sleep function on the RFM12B:

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:

void RFM12B::Sleep() { Sleep(0); }
void RFM12B::Wakeup() { Sleep(-1); }

rwormbird

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

Great, thanks for the update!

Tonio5978

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