battery drain fast

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
soggycashew
Posts: 55
Joined: Sat Sep 18, 2021 10:21 pm

battery drain fast

Post by soggycashew » Fri Apr 08, 2022 9:30 pm

Hello, I have a few sensors running (3 capacitive moisture sensors, I2C 128x64 OLED, MQ135 Air Quality Sensor, and a DHT22 Humidity and Temperature Sensor) on a 3.7V 1200mAh LIPO battery. Anyways, the battery drains really fast like within a day..... What do I need to make this thing last? I don't need it to run constantly I just need it to run when I want to look at OLED. What can I change in the code to achieve this? Please give me an example.... Thanks!

Code: Select all

# Load Libraries--------------------------------
import machine, time, random
from machine import I2C, Pin, ADC
from dht22 import DHT22 #  Temperature & Humidity Sensor module
from sh1106 import SH1106_I2C # I2C Serial 128x64 SSH1106 OLED Display Module
from csms import CSMS # Calculates Hi/Low values sensor values module
from mq135 import MQ135 # Gas/CO2 sensor module

# Define/Initialize GPIO Pins--------------------
i2c2 = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
dht22 = DHT22(machine.Pin(2,machine.Pin.IN,machine.Pin.PULL_UP))

adc0 = machine.ADC(machine.Pin(26)) # Moisture sensor 1
adc1 = machine.ADC(machine.Pin(27)) # Moisture sensor 2
adc2 = machine.ADC(machine.Pin(28)) # Moisture sensor 3
adc3 = MQ135(29) # Gas sensor 4

# OLED Display-----------------------------------
oled_width = 128 # Width of OLED screen
oled_height = 64 # Height of OLED screen

oled = SH1106_I2C(oled_width, oled_height, i2c2)

# Scroll in OLED screen vertically---------------
def scroll_in_screen_v(screen):
  for i in range (0, (oled_height+1), 1):
    for line in screen:
      oled.text(line[2], line[0], -oled_height+i+line[1])
    oled.show()
    if i!= oled_height:
      oled.fill(0)

# Scroll out OLED screen vertically--------------
def scroll_out_screen_v(speed):
  for i in range ((oled_height+1)/speed):
    for j in range (oled_width):
      oled.pixel(j, i, 0)
    oled.scroll(0,speed)
    oled.show()

# CSMS ADS moisture Hi/Low values----------------
csms0 = CSMS(adc0, min_value=54967, max_value=29563) # old:  min_value=60000, max_value=24854
csms1 = CSMS(adc1, min_value=54967, max_value=29563) # old:  min_value=60000, max_value=24854
csms2 = CSMS(adc2, min_value=54967, max_value=29563) # old:  min_value=60000, max_value=24854

# Variable-------------------------------------------
i = 0

while True:
    
    # Create a .csv file-------------------------
    filename = ("data" + str(random.getrandbits(16)) + ".csv") # Log given a random name to minimise risk of overwriting data upon power loss
    file = open(filename, "w")
    file.close()

# Begin Loop---------------------------------------------------------------------------------------

    while True:
        
        # Empty cache and assess memory strain---
        csvdata = []
        with open(filename,'r') as file:
            for line in file:
                csvdata.append(line.rstrip('\n').rstrip('\r').split(','))
        if len(csvdata) > 300:
            break
        
        # Update Temperature & Humidity Sensor---
        T, H = dht22.read() # Gets Temp & Hum from dht22.py library
        temp_f = T * (9/5) + 32.0 # Converts the (T) temperature to Fahrenheit degrees
        
        # Update Gas/CO2 sensor------------------
        rzero = adc3.get_rzero()
        corrected_rzero = adc3.get_corrected_rzero(T, H)
        resistance = adc3.get_resistance()
        ppm = adc3.get_ppm()
        corrected_ppm = adc3.get_corrected_ppm(T, H)
        
        # Iterate lognum-------------------------
        i += 1
        if len(str(i)) == 1:
            lognum = ("Log0000" + str(i))
        elif len(str(i)) == 2:
            lognum = ("Log000" + str(i))
        elif len(str(i)) == 3:
            lognum =  ("Log00" + str(i))
        elif len(str(i)) == 4:
            lognum =  ("Log0" + str(i))
        else:
            lognum =  ("Log" + str(i))
            
        # Get Min/Max values---------------------
        sm1set = [x[4] for x in csvdata]
        sm2set = [x[5] for x in csvdata]
        sm3set = [x[6] for x in csvdata]
        csvdata = []
        if sm1set ==[]:
            row3 = "High " + "N/A" + " " + "N/A" + " " + "N/A"
            row5 = "Low  " + "N/A" + " " + "N/A" + " " + "N/A"
        else:
            row3 = "High " + max(sm1set) + " " + max(sm2set) + " " + max(sm3set)
            row5 = "Low  " + min(sm1set) + " " + min(sm2set) + " " + min(sm3set)
        sm1set = []
        sm2set = []
        sm3set = []
        
        # Update capacitive sensors using CSMS---
        soilz1 = csms0.read(25)
        soilz2 = csms1.read(25)
        soilz3 = csms2.read(25)
        
        if len(str(soilz1)) == 1: # Normalises the length of the values
            soil1 = ("0" + str(soilz1) + "%")
        elif len(str(soilz1)) == 2:
            soil1 = (str(soilz1) + "%")
        else:
            soil1 = ("Max")
        if len(str(soilz2)) == 1: # Normalises the length of the values
            soil2 = ("0" + str(soilz2) + "%")
        elif len(str(soilz2)) == 2:
            soil2 = (str(soilz2) + "%")
        else:
            soil2 = ("Max")
        if len(str(soilz3)) == 1: # Normalises the length of the values
            soil3 = ("0" + str(soilz3) + "%")
        elif len(str(soilz1)) == 2:
            soil3 = (str(soilz3) + "%")
        else:
            soil3 = ("Max")
        
        # Write to OLED screen-------------------
        # %m.kf Converts a value of type float (or double) to m decimal positions with k digits after the period.
        OLED_screen1 = [[0, 21 , "Temp: %3.0fF" %temp_f], [0, 37, "Humidity: %3.0f%%" %H]]
        OLED_screen2 = [[0, 8, "SNSR  1   2   3"],
                        [1, 12, "____________________"],
                        [0, 29, (row3)],
                        [0, 42, "Now  " + str(soil1) + " " + str(soil2) + " " + str(soil3)], 
                        [0, 55, (row5)]]
        OLED_screen3 = [[0, 8, "CO2 LEVEL"],
                        [1, 12, "____________________"],
                        [0, 29, str(corrected_ppm)+" ppm"]]
        
        # Scroll in, stop, scroll out (vertical)
        scroll_in_screen_v(OLED_screen1)
        time.sleep(5) # Sleep for 5 seconds
        scroll_out_screen_v(2)

        scroll_in_screen_v(OLED_screen2)
        time.sleep(5) # Sleep for 5 seconds
        scroll_out_screen_v(2)
        
        scroll_in_screen_v(OLED_screen3)
        time.sleep(5) # Sleep for 5 seconds
        scroll_out_screen_v(2)
        
        oled.text('Saving Data...', 0, 25, 1)
#         oled.line(9,35,120,35,1) # draw a line from 9,35 to 120,35 colour=1
        oled.show()
                    
        # Write values to .csv file--------------
        # %m.kf Converts a value of type float (or double) to m decimal positions with k digits after the period.
        # time.time() is saved in Epoch Unix Timestamp
        file = open(filename, "a+")
        file.write(str(lognum) + "," + str(time.time()) + "," + str("%3.0fF" %temp_f) + "," + str("%3.0f%%" %H) + "," + str(soil1) + "," + str(soil2) + "," + str(soil3) + "\n")
        file.close()
        
        oled.fill(0) #Clear OLED for next loop

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: battery drain fast

Post by davef » Sat Apr 09, 2022 6:27 am

Firstly, you have to do a current budget. How much current does each sensor take? How much current does the Pi board take?

Then maybe a solution is to turn all the sensor off. Is the Pi port able to do deepsleep and wake on an button press?

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: battery drain fast

Post by pythoncoder » Sat Apr 09, 2022 9:11 am

1200mAH for 24 hours is 50mA which is quite plausible with all that kit.

Achieving battery operation usually needs an external device to turn off power to the sensors and display before entering machine.deepsleep. You turn the power on again when you wake. Some devices provide LiPo charging and a switched source on board, notably the Pyboard D with WBUS-DIP28 or the ESP32-S2 from UnexpectedMaker. Otherwise you'll need to use a transistor switched by an I/O pin.
Peter Hinch
Index to my micropython libraries.

Post Reply