Author Topic: REG_OCP setting for RFM69CW  (Read 3244 times)

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
REG_OCP setting for RFM69CW
« on: December 28, 2016, 09:36:56 PM »
I've noticed something interesting, with the  RFM69CW it's supposed to have 45mA TX current. With over-current protection in REG_OCP turned off I measured it at > 75mA! When I programmed REG_OCP to turn on over-current protection I had to set it to limit at it's lowest level of 45mA, I then measured just under 50mA. I notice that REG_OCP in the library is set at default of 95mA for this level.

I suspect this was due to a poorly matched wire antenna with non-ideal ground plane, but nevertheless people might want to set the REG_OCP value to 0x10 if they are using 45mA for their battery life calculations, the TX current may well be significantly more than you think.

Mark.

joelucid

  • Hero Member
  • *****
  • Posts: 868
Re: REG_OCP setting for RFM69CW
« Reply #1 on: December 29, 2016, 02:06:14 AM »
Quote
With over-current protection in REG_OCP turned off I measured it at > 75mA!

That is interesting. There's also a discrepancy between the sx1231 and the MKW01xxRM datasheets here. SX1231:

Quote
It helps preventing surge currents required when the transmitter is used at its highest power levels

MKW01xxRM:

Quote
that helps prevent surge currents when the transmitter is used at its highest power levels

SX1231 reads as if you need OCP to limit surge currents with low power settings while these surge currents are required at high power settings.

MKW01xxRM reads as if you primarily use OCP with highest power levels, which is clearly wrong because above 17 dBm OCP needs to be switched off.

So it seems OCP should be set to the power level as spec'd in the datasheet per TX power. Yuck!

joelucid

  • Hero Member
  • *****
  • Posts: 868
Re: REG_OCP setting for RFM69CW
« Reply #2 on: December 29, 2016, 03:17:16 AM »
Weird - I can't reproduce this at all. Tried with a RFM69W, 13 dBm. With or without OCP to 45mA I get exactly the same current waveform. This is with a well tuned small loop - maybe that's the difference?

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: REG_OCP setting for RFM69CW
« Reply #3 on: December 29, 2016, 07:03:10 AM »
I suspect something to do with matching. My setup uses a 65mm x 95mm PCB with ground plane and a 86mm wire antenna at 868MHz. I used a 1 ohm resistor as a current sensor in the ground line and looked at it with a 'scope, this was a real thing (it wasn't just me getting the scaling wrong, all the other measurements were correct). It will be interesting to see if you can replicate it.
Mark.

joelucid

  • Hero Member
  • *****
  • Posts: 868
Re: REG_OCP setting for RFM69CW
« Reply #4 on: December 29, 2016, 12:28:50 PM »
I repeated the measurement with a coin cell Tino with l/4 antenna. To measure I just graph vcc, the internal resistance of the battery provides the current sensor. With or without OCP I get exactly the same trace.

Joe

joelucid

  • Hero Member
  • *****
  • Posts: 868
Re: REG_OCP setting for RFM69CW
« Reply #5 on: December 29, 2016, 12:36:00 PM »
BTW a useful exercise anyway. I noticed this way (scoping) that the si7021 lib for arduino keeps the 328p awake while waiting >10ms for the measurement. What a waste of power. I now use powerDown while waiting. That will be a big improvement for nodes that measure often but only send on significant changes.

perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: REG_OCP setting for RFM69CW
« Reply #6 on: December 29, 2016, 01:02:32 PM »
I repeated the measurement with a coin cell Tino with l/4 antenna. To measure I just graph vcc, the internal resistance of the battery provides the current sensor. With or without OCP I get exactly the same trace.

This is odd. Just to be clear, you didn't use the RF_OCP_ON #define did you? This seems to be #defined to 0x1A which is 95mA. I explicitly put 0x10 into REG_OCP for 45mA.
Mark.

ChemE

  • Sr. Member
  • ****
  • Posts: 419
  • Country: us
Re: REG_OCP setting for RFM69CW
« Reply #7 on: December 29, 2016, 01:18:49 PM »
BTW a useful exercise anyway. I noticed this way (scoping) that the si7021 lib for arduino keeps the 328p awake while waiting >10ms for the measurement. What a waste of power. I now use powerDown while waiting. That will be a big improvement for nodes that measure often but only send on significant changes.

Yup, the HTU21D code I found likes to make the same measurements using HOLD thus keeping the uC awake and wasting energy.  By switching to sleep for 15ms immediately after issuing a NO_HOLD command, the uC is only awake for 440uS during one entire temp/RH measurement cycle.  30ms asleep vs. 10ms awake is no comparison.  I also noticed when I dug deeply into the HTU21D code that the two wire library uses a pretty slow baud rate thus prolonging the wake period unnecessarily.  I don't have a Si7021 to play with but see if this code can be adapted to reduce the wake cycle.

HTU21D Code
Code: [Select]
#define   BAUD_RATE                     8000000ul
#define   TRIGGER_TEMP_MEASURE_NOHOLD   0xF3
#define   TRIGGER_HUMD_MEASURE_NOHOLD   0xF5
#define   WRITE_USER_REGISTER           0xE6
#define   ELEVEN_BIT_TEMP               B10000011
#define   EIGHT_BIT_RH                  B00000011
#define   SLA_W                         TWDR = (0x40 << 1)
#define   SLA_R                         TWDR = ((0x40 << 1) + 0x01)
#define   START_TWI                     TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); WAIT_FOR_TWI_INT
#define   RESTART_TWI                   TWCR = (1<<TWINT) | (1<<TWEN);              WAIT_FOR_TWI_INT
#define   RESTART_TWI_ACK               TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);  WAIT_FOR_TWI_INT
#define   WAIT_FOR_TWI_INT              while (!(TWCR & (1<<TWINT)) && ++counter)
#define   STOP_TWI                      TWCR = (1<<TWINT)|(1<<TWEN)| (1<<TWSTO);    while ((TWCR & (1<<TWSTO)) && ++counter)
#define   NOT_READY                     (TWSR & 0xF8) == 0x48 && ++counter

static inline void initTWI() {
  DDRC |= (1<<PC3) | (1<<PC2);
  PORTC |= (1<<PC2) | (1<<PC4) | (1<<PC5);
  TWBR=1;  //TWBR = ((F_CPU / BAUD_RATE) - 16) / 2;
}

static inline void stopTWI() {
  uint16_t counter;
  STOP_TWI;
}

static inline void issueCommand(uint8_t comm, uint8_t res) {
  uint16_t counter;
  START_TWI; 
  SLA_W;
  RESTART_TWI;
  TWDR = comm;    // Send the command
  RESTART_TWI;
  if (comm == WRITE_USER_REGISTER) {  // Send the new resolution
    TWDR = res;
    RESTART_TWI;
  } else {    // Issue a stop on the I2C bus so we can enter sleep
    STOP_TWI;
  }
}

static inline void readRaw(uint8_t *ptr) {
  uint16_t counter;
  do {  // Start + SLA(R) until we get an ACK
    START_TWI;
    SLA_R;
    RESTART_TWI;
  } while (NOT_READY);

  // Measurement is ready, read back 2 bytes an store them at the address of ptr
  RESTART_TWI_ACK;    // Set the ACK bit to let the transmitter know we need another byte
  *ptr++ = TWDR; // Write the MSB
  RESTART_TWI;    // Set the NACK bit to let the transmitter know we are done
  *ptr = TWDR & 0xFC; // Write the LSB with the status bits masked off
}

Main Program Code
Code: [Select]
void setup() {
  initTWI();
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.setPowerLevel(31);
  radio.sleep();
  DDRC |= _BV(PC3) | _BV(PC2);  // Set PC3 and PC2 to be outputs
  PORTC |= _BV(PC2);    // pull PC2 high to act as 3.3V for the HTU21D 
  PORTC &= ~_BV(PC3);   // pull PC3 low to act as ground for the HTU21D
}
 
void loop(){
  uint8_t data[4];  //Temp & RH stored as 16-bit raw values; no floating point math
  uint8_t sleep_count = 0;
 
  // Make the measurements
  issueCommand(WRITE_USER_REGISTER, ELEVEN_BIT_TEMP);
  issueCommand(TRIGGER_TEMP_MEASURE_NOHOLD,0);
  LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF);
  readRaw(&data[0]);

  issueCommand(WRITE_USER_REGISTER, EIGHT_BIT_RH);
  issueCommand(TRIGGER_HUMD_MEASURE_NOHOLD,0);
  LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF);
  readRaw(&data[2]);
  stopTWI();
 
  // Send the data
  radio.send(RECEIVER, data, 4, 0); //target node Id, message as string or byte array, message length, ack requested
  radio.sleep();
 
  do {  // Sleep for 64 seconds
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  } while (++sleep_count < 8);
}
« Last Edit: December 29, 2016, 01:33:49 PM by ChemE »

ChemE

  • Sr. Member
  • ****
  • Posts: 419
  • Country: us
Re: REG_OCP setting for RFM69CW
« Reply #8 on: December 29, 2016, 01:24:50 PM »
I still find it amusing that that utterly disgusting mess of libraries which called each other to implement a Two Wire interface could be boiled down to 55 lines of code inclusive of comments.  I was never able to get any ASM implementations to work for me but I'm betting the compiler gets pretty darn close given the size of the HEX file.

joelucid

  • Hero Member
  • *****
  • Posts: 868
Re: REG_OCP setting for RFM69CW
« Reply #9 on: December 29, 2016, 06:05:33 PM »
Quote
I still find it amusing that that utterly disgusting mess of libraries which called each other to implement a Two Wire interface could be boiled down to 55 lines of code inclusive of comments.

Yeah no kidding. The si7021 library is terrible now that I've taken a look at it. I really liked this one:

Code: [Select]
void SI7021::_command(byte * cmd, byte * buf ) {
    _writeReg(cmd, sizeof( cmd ));
    _readReg(buf, sizeof( but));
}

Oh well.

I've used this (http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__ic2master.html) one in some projects. It's nice, tight and small.

I've added the powerDown into the existing si7021 lib though - just feeling lazy today ...

joelucid

  • Hero Member
  • *****
  • Posts: 868
Re: REG_OCP setting for RFM69CW
« Reply #10 on: December 29, 2016, 06:07:33 PM »
Quote
Just to be clear, you didn't use the RF_OCP_ON #define did you?

No, I set to 0x0f for no OCP and 0x10 for OCP to 45 mA. That worked, too - I could see how current was clamped at the very high power settings. But below 45 mA either way resulted in exactly the same power consumption.

Joe

ChemE

  • Sr. Member
  • ****
  • Posts: 419
  • Country: us
Re: REG_OCP setting for RFM69CW
« Reply #11 on: December 30, 2016, 07:39:45 AM »
I've used this (http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__ic2master.html) one in some projects. It's nice, tight and small.

I've tried unsuccessfully a few times to use this I2C library as it seems to be the favorite among AVR folks but I've never been able to get it working since (to me) it is in such a bizarre format and really not at all clear what needs to be downloaded and installed.