I am trying to get a yearly predicted current consumption for a battery LoPy with one DS18B20 based on 1 reading/hour as a baseline
I am keen to get some feedback on calculated values below?
@geraldm As discussed in another thread, it's difficult to combine the flexibility of a high-level language like (micro)python on a device with 2 fast cores, Wi-Fi, BLE, and more with the optimisation available when programming in C (or even assembler) on a controller optimised for very low power applications. Different MCUs have different power profiles, performance, RAM/flash capabilities, sleep modes, etc.
A LoPy is probably overkill for most LoRa applications where you just get a few bits of data from a sensor or two and send them over LoRaWAN (the small PIC on the Pysense or Pytrack is probably more than enough for that!). But it enables you to quickly prototype things, and if you need to, you can do a lot more with it than you can in simpler LoRa devices.
Note that 1.01 seconds cannot be a complete cycle for a LoRaWAN-compliant device (unless it always receives a response in RX1 from the network). It is a requirement for the device to be awake during both RX1 and RX2 unless it received a downlink in RX1. And RX1 is at least 1 second after end of transmission, and RX2 is always 1 second later. RX2 is also quite a bit longer as it needs to accommodate the slower data rate of SF12.
But yes, with a carefully chosen MCU and optimised firmware, you can get down to just over 2 seconds at the fastest data rates, with most of it actually spent sleeping!
Will take a closer look. Need to translate. To help others too, English would help. I see the time to awake and sleep again a great to be a challenge to Pycom products.
I have one brand device I have dissected and tested, it’s complete cycle is barely 1.01 seconds. SF7BW127 with only 2 spikes of current worth noting for that duration. Also, newer processes have deep sleep down to 0.1 microamps, a significant factor delta to 25.4 microamps exhibited by LoPy L01.
Anyway we continue to innovate.
@jcaron Thanks. Shall review with team in the morning. I understand. We have a good consumption baseline now, any gains will soon be realised.
Shall post results.
rcolistete last edited by
What about building a Pycom firmware with your modules, including main.py ? Or at least using .mpy files ?
The time to load modules is decreased a lot. See section "4.2. Tempo e RAM gastos para importar módulos" of "Using WiPy3" tutorial (but in portuguese, I need to create an english version...).
@geraldm In your code, you have 4 threads running:
- one tries to get the temperature
- one tries to read battery levels
- one tries to setup LoRaWAN
- one tries to send the data
Each of the first three run until they have done their work and set a global with the result. The last one (
Send_Data) is a
whileloop which continuously tests if all other threads have done their work (by testing the global variables set by each), and then sends the data. This means it hogs the CPU, which both increases power consumption and slows down the other threads (IIRC all threads run on the same core, only networking runs on the other core).
Instead of doing that:
- Change the
Send_Datafunction to only do the test once (remove the
while True:). If the test is successful, send data and go to deep sleep as it currently does. If not, just return (remove the
_thread.exit()at the end).
- Do not start a thread with this function.
- At the end of each of the 3 other threads, after setting the global, call
Send_Data. If any of the other threads hasn't finished working, it will do nothing. It all three threads have done their work, it will send the data.
An alternative would be to use some kind of lock, but I think this would be overkill here.
Also, your Send_Data thread is not very efficient, looping like that. Instead, just switch the loop to a single test that everything is ready, and call it at the end of the other processing threads.
Hi, I am not sure I fully understand Your comment on the in-efficient loop, s/w ignorance on my part?
@geraldm My guess is that the spike at 6 seconds is the LoRa TX, and the much smaller spikes at 7 and 8 are the RX1 and RX2 windows.
This would mean a lot of time is spent getting the data from the sensor. Also I wonder what all the tall but very narrow spikes between 4 and 8 seconds are. The time to go to sleep is puzzling. Timestamped logs will tell us more.
It's commented in your code, but I suppose you have run wifi_on_boot(false) at some point (and that likewise, pybytes is disabled)?
IIRC there have been dramatic variations in startup times between firmware versions, though I don't remember which versions are good or bad in that respect. There should be some discussion on the topic elsewhere in the forum.
Shall add log in the morning. Hopefully that should help align a process with time.
OK on Send_Data thread efficiency, shall review and measure.
The data points are a good baseline to work with, any delta are hopefully gains.
@geraldm can you add a time stamp (time since boot is fine, with at least 0.1s precision, ideally ms) to your logs and provide the logs for one cycle? This would help determining exactly where the time is spent.
Also, your Send_Data thread is not very efficient, looping like that. Instead, just switch the loop to a single test that everything is ready, and call it at the end of the other processing threads. It shouldn’t change the total time much but it should use a bit less current.
I have managed to capture in time down to mS the entire LoRa AU915 cycle we need to achieve our goal.
Assuming, Deep Sleep, to wake, process DS18B20 Data, Process ADC Batt V data, idle, TX and back to deep sleep.
The attached are all the data points with deep sleep to receive starting at data point 571 and going back to deep sleep at 9288, this equates to 8.717 seconds total cycle.
This is the best we have achieved with optimised current with SF8.
I cannot load/attach the excel file, but can send as PM for review.
We are struggling to optimise and achieve any further gains/reduction, but if someone has an idea, please share, maybe a old stable version where boot time is significantly smaller which is critical in this case to conserve battery life.
Current is via 0.3R resistor on negative via HP-34401A multi-meter recorded via Video. I have no way to log in time the current, only match readings with taking video and what the oscilloscope provides visually.
The initial 2.24 seconds boot is not a solid block, actually many individual spikes to the ave. value as illustrated. However the overall boot time is 2.24.
There was a mention of about 5 seconds overall, I would love to see that, but I am not sure if this can be achieved. I am OK with the current consumption, +20dBm TX power is what it is, receive is what it is, but we cannot find methods to shorten receive gaps of no activity to preserve battery life. Worst case 5 seconds would be Utopia for Pycom!
How can boot/load be 1s, temp to be read and processed and sent and go directly back to sleep, thus 5S seems possible.
I am not a software expert, nether are the guys helping, thus this is a journey for us.
Thank you in advance.
@geraldm Can you share your code? I'm really puzzled by the intermittent nature of the current consumption:
- The boot/load period should be a line, not a solid block which seems to indicate constant variation of current
- TX @ SF7 should be a short spike, followed by a wait of 1 second, the a very short and low spike for the RX1 window, then a wait of another second, and another short and low spike for RX2.
How/where are you measuring current?
Attached may help with timing. Excel snippet is measured relative current.
Revised coding has assisted in brining down time to 8.72 s in slots as per photo below.
Not sure how to achieve SF7 @ 100mS. Not doing much on LoPy at all.
Basic 9 bit Temp and ADC read batt V via divider, 910K/91K...
@geraldm I'm not sure I understand the 4 seconds to transmit at SF7, or the 3 seconds prior to deep sleep?
Transmitting at SF7 should take less than 100 ms, possibly as low as 50 ms, depending on how much data you send. Even if you send over 200 bytes, it's still less than 400 ms.
You then have time waiting for the RX windows (a total of 2 seconds with the default LoRaWAN settings), but you should definitely not draw 225 mA during that time.
Also, what exactly are you doing on the LoPy? I'm not sure I understand what could take 3.6 seconds in acquisition time and 3 seconds in processing time?
Can you clarify what each part of the graph is? Are the two series of spikes between 4 and 5 seconds and between 6 and 7 seconds acquisition? Processing? Transmission?
If they're LoRa transmission, I wonder:
- I hope you're not doing an OTAA join on each cycle?
- Are you sure you're sending at SF7? This would look a lot more like SF12, or you would be sending a LOT of frames.
I'm puzzled by the "solid block" during startup, is the current consumption really that irregular? This doesn't quite match by memory of what I observed or other graphs I've seen around here.
An update on overall current consumption and boot time. We have been able to minimise boot time from 15.2s to 8.72s. this is significant with latest release 1.20.2.rc10
Actually, we had about 8.9s and with the aid of threading, we squeezed another few hundred milliseconds out of it.
The upfront (start) component is still the boot/load after deep sleep of 2.24 seconds.
This is based on 1 x DS18B20 and batt voltage via ADC, very simply RTU function running SF7.
I am keen to find out if others have been able to achieve better target end goal and is their any scope to squeeze another few seconds?
FYI. I opened up another popular brand IoT temp and humidity sensor and their complete deep sleep to acquire, TX and deep sleep cycle is 1.4 s, phenomenal, with deep sleep current less than .5uA and TX current at +20dBm at or around 180mA.
@Antonis-Gotsis ,thanks for the feedback.
@geraldm Seems reasonable. You get close to 0.57 mA consumption per hour, so to reach 1 year life-time you'll need a LiPo close to 7200 mAh capacity, assuming 70% effective capacity (