I am trying to make low power with my arduino and have a problem with i2c bus. Here my config :
arduino mini pro modified (no regul and led)
BH1750 on i2c which is powered by P mosfet (bs250 for the moment)
sleep mode powerdown with pin change interrupt (no watchdog)
At starting, it reads well BH1750. Then I power off with mosfet, put A4 and A5 output=0, and go to sleep (my sleep routine is from Nick Gammon : sleep with pin change).
My problem is when I wake up from pin and power on sensor, I am unable to read again BH1750. It returns 0. In other hand, if i press reset button, it reads ok on startup. So I think I need to deal with i2c register config but I was wondering if Wire.begin does it as in BH1750 lib it uses (and arduino doc tells that it config registers). But it doesn't work for me. Maybe I need to restore another interrupt, but which one???
do you have any ideas about this?
Thanks for feedback.
I can't find information in the datasheet of the BH1750 what the power usage is. Does it have a sleep mode ?
Turning off I2C Slaves is not good. The pullup resistors keep the SDA and SCL high, and if a I2C sensor chip has no power, there will be current via SDA and SCL into the sensor chip to GND.
You could turn off the pullup resistors (I think that is what you do), but then the I2C bus is no longer valid. You might need a long startup sequence after that.
Could you show your whole sketch between code tags ?
The best option is to keep sensors and pullup resistors active. Try to put the sensor into a sleep mode. The resulting current could be only a few micro-amps.
I'm not sure what I remember about sleep mode for the I2C in the ATmega328P and the Wire library. I would expect a lot of troubles.
Did you also remove the yellow capacitors ? If they are bad quality, they can leak. I think one of them is connected to VCC. Running it on one or two 100nF capacitors is okay.
Do you know that an ATmega328P can read its own VCC ? You can read the battery voltage without external components.
Yes I have already read this link. very useful! You are right, I am turning off pullups as mosfet is enabling/disabling 3v power rail and BH1750 has pullups. So when I turn off power rail, it turns off BH1750.
I am not using directly Wire. I use BH1750 libs and Mysensors. I could put my sample sketch here if you want to check but you would need libs. I need to make some cleanings before.
I think it is maybe a problem with registers or port pin config before and after sleep mode. I tried putting A4,A5 output=0, input_pullup before sleeping. Nothing better, still 0 reading.
No I didn't remove yellow capa. For the moment, I get sub uA when mosfet turn off (bh1750+nrf24).
Are those switching converters special low-power types ? Many of those converters use a few milli-amps idle current, but some use almost nothing.
Both RF modules are switched with VCC_RF. But where do the chip-selects and interrupts go ? The interrupts are tied together, I think that is not possible. The chip selects are idle high.
I have two mosfet : one for radio and one for vcc sensors. Interrupts are not tied together. D2 for radio, D3 for wake up. radio is working well.
Thanks for i2c links. I added scanner at startup just before my first reading of sensor. And added it just after power up mosfet. And it is very strange :
at startup all is ok, Lux = 140, and scanner reads 23 for adress
after woken up and turn on mosfet, delay (2000) : scanner reads 23 adress (ok), but lux = 0 ...
I disconnect anything, press reset button, and it gets Lux= 140 .....
I am asking me what happens when arduino resets that makes my sensors reading right...
The i2c_scanner does not use the buffer of the Wire library (no data is used). The address is put on the I2C bus and the ACK is checked. The problem can be the I2C hardware of the ATmega328P or the Wire library or the sensor.
The page from Nick Gammon ( Gammon Forum : Electronics : Microprocessors : Power saving techniques for microprocessors ) shows that the Wire.begin() is called again to re-initialize the Wire library and the hardware.
I don't know if it will always be allowed to repleatedly call Wire.begin(), but at the moment it seems neccassary to make the I2C bus work again.
@Peter_N : I found my answer. You are right there was a problem with i2c hardware config before and after sleep mode. Charles from ulpnode helped me on this.
How I solved my problem, in case people have same problem, before entering sleep :
// Disable digital input buffers on all ADC0-ADC5 pins
DIDR0 = 0x3F;
// set I2C pin as input no pull up
// this prevent current draw on I2C pins that
// completly destroy our low power mode
//Disable I2C interface so we can control the SDA and SCL pins directly
TWCR &= ~(_BV(TWEN));
// disable I2C module this allow us to control
// SCA/SCL pins and reinitialize the I2C bus at wake up
TWCR = 0;
pinMode(SDA, INPUT);
pinMode(SCL, INPUT);
digitalWrite(SDA, LOW);
digitalWrite(SCL, LOW);
I know this is an old post but it made my day!
Thanks to scalz and Charles from ulpnode for the I2C reinit code, works like a charm to get my I2C LCD to wake back up after powering it off with a high side switch.