A solar supercap powered Moteino (15Farad charged by BQ25504)

Started by WhiteHare, February 07, 2017, 05:31:03 PM

perky

Mmm. Looking at the supercap spec it shows the attached discharge curve (this is for the 15F 5.6V variant discharged at 15mA) but is shows it being linear only between the two threshold voltages given in the test part of the spec, and it does appear to drop quite rapidly below that. Now since the 4.2V variant is just a 3 cell version the curve should be scalable and the same shape. So it appears it may only linear during the first 1V drop :(

Maybe this time to look for another capacitor, with maybe a different construction?

Edit: Just looking around, there are other types that have a significantly lower ESR, and some show linear discharge curves down to 0V. So I think the Vishay caps have a different construction, and don't act like real capacitors at lower voltages. They may be older generation 'single layer' types, the later ones are EDLC (double layer) types.

Here's one that might be OK, it's only 7.5F but you could parallel two of them if you wanted to. Note the discharge curve goes down to ground, and they are technically non-polarized although they recommend using the polarity as marked as they may not be fully discharged:

http://www.mouser.co.uk/search/ProductDetail.aspx?R=0virtualkey0virtualkeySCMT32C755MRBA0

Mark.

WhiteHare

Why is it that linearity is important?   I think at the end of the day the likely  trade-offs in capacitor choice are going to be: cost, size, capacity, and self-discharge rate.  Linearity might be nice to have, but compared to those I have trouble imagining that linearity will be a deciding factor.

Now that I have some working code, I'm going to try some run-til-exhaustion tests on some of the different supercaps I already somewhat randomly collected.  I'm hoping that if I do a run-til-exhaustion test over a short time span (say, a few hours), and then another after charging up but then waiting a few days.  Then the difference in packets sent before exhaustion between the two may be a crude way of gauging the self-discharge rate.    Maybe there's a better way (?), but so far that's all I've come up with for a self-discharge rate test that's both practical and meaningful.  For that matter, maybe just measuring the voltage after a single packet transmission will be enough to roughly gauge the amount of self discharge.  Then, I could send one packet per day, measure the lowest voltage during transmission, and plot the voltage drop for each day as the days tick by.   8)

Before that, though, I want to see how long the 15F supercap will last in the remote-control use case, where it's in listen mode with listen-idle intervals of, say, 100ms.  Then I'll have a better confirmation as to whether I'm even starting near the correct ballpark.

I did do one final test with this 15F supercap, where each transmission conveys the lowest voltage (i.e. the last one) measured during the prior transmission.  That provides a tighter upper bound on the voltage at the time of failure.  We know from the last transmission that the lowest voltage which occured during the second to last transmission was 1.68v.  Here's the log:  http://pastebin.com/Hd4f13mf


perky

OK, linearity means it drops consistently from any voltage, you may find you only get a small proportion of the time you could have had especially if it drops off rapidly after only a volt below rated voltage which is what the Vishay curves seem to show. I've edited my above post with a version that might be more suitable (if it's small enough) but if you're happy with the Vishay parts then use it ;)

Edit: I'm actually going to go out on a limb here and say linearity is so important that you're likely to get twice the life from the 7.5F version than you get from the 15F one if those curves are real. The two linearily voltages for the 4.2V Vishay part are 4.0V to 3.1V, you're starting at 3.5V which is half way through that already.

Mark.

WhiteHare

Cool!  I just ordered the supercap you referenced:  http://www.mouser.co.uk/search/ProductDetail.aspx?R=0virtualkey0virtualkeySCMT32C755MRBA0

I'm hopeful it will arrive by Friday, as the American mouser is not far from where I live.

perky

Nice. Hopefully you'll get much less voltage drop due to the ESR as well, so I look forward to seeing the results from that test.

Mark.

ChemE

Quote from: WhiteHare on February 21, 2017, 07:15:42 AM
Have you ever succeeded in getting auto mode to work for transmission?  My first attempt failed, and I'm not finding anything outside the datasheet when I do topic searches for it.

I was able to automode transmit: https://lowpowerlab.com/forum/low-power-techniques/speeding-up-the-rfm69-library/msg17363/#msg17363

It is actually really straight forward.  You put the radio in sleep mode and then later set the automode to have an intermediate mode of transmit.  You enter intermediate mode when the FIFO is not empty and you exit intermediate mode on packet sent. Now as soon as you start filling the FIFO, the radio spins up and starts transmitting.  Don't fill the FIFO slowly I guess but I'm running my SPI bus at 8MHz.

#define         AUTO_TRANSMITTER                        B01011011    // Enter = FIFO level; Exit = Packet Sent;

static inline void RadioInit(void) {
    SPI_INIT();
    CHANGE_OP_MODE(SLEEP_MODE);  // Put the radio to sleep ASAP to save power
    writeReg( REG_BITRATEMSB, RF_BITRATEMSB_300000 );	// 0x03
    writeReg( REG_BITRATELSB, RF_BITRATELSB_300000 );	// 0x04
    writeReg( REG_FDEVMSB, RF_FDEVMSB_300000 );	// 0x05
    writeReg( REG_FDEVLSB, RF_FDEVLSB_300000 );	// 0x06
    writeReg( REG_RXBW, RF_RXBW_DCCFREQ_111 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0 );	// 0x19
    writeReg( REG_RSSITHRESH, 220 );	// 0x29
    writeReg( REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 );	// 0x2E - 2 sync bytes
    writeReg( REG_SYNCVALUE1, 0xAA );	// 0x2F
    writeReg( REG_SYNCVALUE2, NETWORKID );	// 0x30
    writeReg( REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_OFF | RF_PACKET1_CRCAUTOCLEAR_OFF | RF_PACKET1_ADRSFILTERING_OFF );  // 0x37	// 0x37
    writeReg( REG_AUTOMODES, AUTO_TRANSMITTER );  // 0x3B - Put the radio in automatic mode
    writeReg( REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF );	// 0x3D
    SET_POWER_LEVEL(0);

WhiteHare

Quote from: perky on February 21, 2017, 09:29:18 PM
Nice. Hopefully you'll get much less voltage drop due to the ESR as well, so I look forward to seeing the results from that test.

Mark.

I look forward to that as well.  In addition, if it really is highly linear, then I imagine it will also be much easier to measure the self-discharge rate.  To that end, I have a 24-bit ADC breakout board that might be helpful.  I wouldn't say the useful resolution is the full 24 bits, but it's definitely more than the atmega328p's 10 bits.   :)

WhiteHare

Quote from: ChemE on February 21, 2017, 10:11:14 PM
I was able to automode transmit: https://lowpowerlab.com/forum/low-power-techniques/speeding-up-the-rfm69-library/msg17363/#msg17363

It is actually really straight forward.  You put the radio in sleep mode and then later set the automode to have an intermediate mode of transmit.  You enter intermediate mode when the FIFO is not empty and you exit intermediate mode on packet sent. Now as soon as you start filling the FIFO, the radio spins up and starts transmitting.  Don't fill the FIFO slowly I guess but I'm running my SPI bus at 8MHz.

#define         AUTO_TRANSMITTER                        B01011011    // Enter = FIFO level; Exit = Packet Sent;

static inline void RadioInit(void) {
    SPI_INIT();
    CHANGE_OP_MODE(SLEEP_MODE);  // Put the radio to sleep ASAP to save power
    writeReg( REG_BITRATEMSB, RF_BITRATEMSB_300000 );	// 0x03
    writeReg( REG_BITRATELSB, RF_BITRATELSB_300000 );	// 0x04
    writeReg( REG_FDEVMSB, RF_FDEVMSB_300000 );	// 0x05
    writeReg( REG_FDEVLSB, RF_FDEVLSB_300000 );	// 0x06
    writeReg( REG_RXBW, RF_RXBW_DCCFREQ_111 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0 );	// 0x19
    writeReg( REG_RSSITHRESH, 220 );	// 0x29
    writeReg( REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 );	// 0x2E - 2 sync bytes
    writeReg( REG_SYNCVALUE1, 0xAA );	// 0x2F
    writeReg( REG_SYNCVALUE2, NETWORKID );	// 0x30
    writeReg( REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_OFF | RF_PACKET1_CRCAUTOCLEAR_OFF | RF_PACKET1_ADRSFILTERING_OFF );  // 0x37	// 0x37
    writeReg( REG_AUTOMODES, AUTO_TRANSMITTER );  // 0x3B - Put the radio in automatic mode
    writeReg( REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF );	// 0x3D
    SET_POWER_LEVEL(0);


Great!  I'm glad to hear that it actually does work.

Looking at a zoom (see attached) of the earlier scope capture, it looks like there about 90 uSecs of time wasted in Tx, while the atmega328p reacts to the packetSend detection and issues the RFM69 command to switch to standby-mode.  As that is more than 10% of the total high current Tx time, it's probably a worthwhile optimizaton to do at some point.

WhiteHare

Is around 40ma current draw during Tx about as low as the RFM69HW goes?  Because that's what I'm getting even after:
radio.setPowerLevel(0);


Out of curiosity, I also checked RegOCP.  Even after radio.setPowerLevel(0), it reads:
REG_OCP=B00001111

which indicates the overcurrent protection is off, and the current trim is the maximum allowed.  I'm not sure that it matters, though, because I'm under the impression the PA's shouldn't be active (?) after radio.setPowerLevel(0).

Nonetheless, I went ahead and set the REG_OCP register to B00010000, which should both activate the overcurrent protection and trim off all possible overcurrent.  Then I took the attached scope shot.  As you can see, in this instance adjusting REG_OCP had no effect.

Table 4 in the HopeRF RFM69HW datasheet says that the transmit current at -1dbm is 16ma.   ???  So, how do I get it to be that low?  Is there some other setting that I'm overlooking?  Or is the HopeRF RFM69HW datasheet in error?

WhiteHare

In contrast, attached are a couple scopeshots of a similarly configured RFM69W, also set to power level zero.  In this instance, it looks as though the current drawn during Tx is around 16ma, as per the RFM69W datasheet. 

WhiteHare

So..... Looks like I'll want to switch over to a RFM69CW.

joelucid

QuoteIs around 40ma current draw during Tx about as low as the RFM69HW goes?

The lowest the HW's go is -2 dBm which should be < 16 mA. However RFM69 doesn't support these low power levels. Here's the code I use which you could adapt:

void SX1231Driver::setPowerLeveldBm( int8_t powerLevel )
{
	if( powerLevel > _maxPowerLevel ) powerLevel = _maxPowerLevel;
	if( powerLevel < _minPowerLevel ) powerLevel = _minPowerLevel;
	_powerLevel = powerLevel;
	uint8_t paSetting;
	uint8_t pwl18 = _powerLevel + 18;
	if (_isHW) {
		if( _powerLevel <= 13 ) // 0 - 13: -2 - +13, formula -18 + pwr
			paSetting = SX1231_PALEVEL_PA1_ON | pwl18;
		else  // 14-20: +5 - +20, formula -11 + pwr
			paSetting = SX1231_PALEVEL_PA1_ON | SX1231_PALEVEL_PA2_ON |
				( 11 + _powerLevel );
	}
	else paSetting = SX1231_PALEVEL_PA0_ON | pwl18;
	writeReg( SX1231_REG_PALEVEL, paSetting );
	setHPRegisters();
}

WhiteHare

Quote from: joelucid on February 23, 2017, 06:47:17 AM
The lowest the HW's go is -2 dBm which should be < 16 mA. However RFM69 doesn't support these low power levels. Here's the code I use which you could adapt:

void SX1231Driver::setPowerLeveldBm( int8_t powerLevel )
{
	if( powerLevel > _maxPowerLevel ) powerLevel = _maxPowerLevel;
	if( powerLevel < _minPowerLevel ) powerLevel = _minPowerLevel;
	_powerLevel = powerLevel;
	uint8_t paSetting;
	uint8_t pwl18 = _powerLevel + 18;
	if (_isHW) {
		if( _powerLevel <= 13 ) // 0 - 13: -2 - +13, formula -18 + pwr
			paSetting = SX1231_PALEVEL_PA1_ON | pwl18;
		else  // 14-20: +5 - +20, formula -11 + pwr
			paSetting = SX1231_PALEVEL_PA1_ON | SX1231_PALEVEL_PA2_ON |
				( 11 + _powerLevel );
	}
	else paSetting = SX1231_PALEVEL_PA0_ON | pwl18;
	writeReg( SX1231_REG_PALEVEL, paSetting );
	setHPRegisters();
}


Are there any other settings involved?  For the simplest case of minimum Tx power, I translated your code to:

  uint8_t newPaLevel;
  newPaLevel = (B01000000 | 18);
  radio.writeReg( REG_PALEVEL, newPaLevel);
  while (radio.readReg(REG_PALEVEL) != newPaLevel) {  // block until the new register setting is confirmed
    radio.writeReg( REG_PALEVEL, newPaLevel);
  }


which I inserted at the end of  setup(), but the scope trace doesn't show a change in the amount of Tx current used.

perky

Interesting, I wonder if the high power registers are set to high power because _isRFM69HW is true? If you look at this you'll see similar current levels you're getting with PA1+PA2 enabled, however this graph does not show what happens if you set the high power registers to high power but only enable PA1:

https://www.andrehessling.de/2015/02/07/figuring-out-the-power-level-settings-of-hoperfs-rfm69-hwhcw-modules/

According to this you should only need to set the high power registers to high if you're demanding +17dB to +20dB.

It's a bit complex here as to what's going on, the setMode() function for example overrides the high power registers by calling setHighPowerRegs(true) when going into TX mode if _isRFM69HW is true. So some hacking might need to be done to make all this consistent. You might want to set that call to setHighPowerRegs(false) as a quick test.

Mark.

WhiteHare

Yes.  Also, I just now noticed that there's a notation at the bottom of Table 11 which says, "Note: High Power settings MUST be turned off when using PA0, and in Receive mode."

I'll try that.  If nothing else, it sounds like I should be doing it anyway.