buzzing mindfulness bracelet code plus some new functions

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

Dave, regarding measuring current, I looked up the nordic semiconductor power meter mentioned on your website and saw it is almost 100€, outside of my budget for this project :-( So, unless there is a cheaper way to do power measuring, I think I'll skip that step.

Not knowing what else to do, I started working at the code with deep sleep, and I post below what I came up with, which I could not really test, because when I load it on the QT Py RP2040 I get the following message on the REPL:

File "code.py", riga 17, in <module>
NotImplementedError: Sleep Memory not available


This really puzzled me, because the adafruit learn page doesn't mention boards not having sleep memory (apart those not having the alarm module maybe), plus I verified that the RP2040 has 264K of RAM.

[I edited the post to add this: I found this link https://github.com/adafruit/circuitpython/issues/3789 where it says that "Most chips with deep sleep capability provide backup RAM that remains energized during deep sleep. Allow access to this RAM, say via a microcontroller.nvm-style mechanism". I couldn't however find the exact format to code the said "microcontroller.nvm-style mechanism" for my code and I don't want to do too many trials because your page says that microcontroller.nvm writes on the flash with limited life... ]

The other thing I am not sure about is the format of struct.pack / struct.unpack. I have long forgotten my binary / bytes notions and I am supposing for multiple digit variables I might have to allocate more than one byte in sleep_memory... I didn't get any sintax errors and the code checks green, but I don't think that's enough...

I set up the code with two "phases", one in which it determines the random variable and goes to sleep, and the other in which it buzzes, logs the feedback and goes to sleep for the 30 minutes complement.
I used two stored counters (one to track the phase of the program and one to count the cycles) and one stored variable for the random sleeping times.

Looking forward to see your thoughts!

Angelo

Code: Select all

import time
import board
import random
import alarm  # NUOVO
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Button
import struct

pulsante = DigitalInOut(board.A0)
pulsante.direction = Direction.INPUT
pulsante.pull = Pull.UP
vibrating_disc = DigitalInOut(board.A2)
vibrating_disc.direction = Direction.OUTPUT
switch = Button(pulsante)

if not alarm.wake_alarm:  # zeroize counters on very first run
    alarm.sleep_memory[1] = 1  # program phase: 1 sleeep / 2 buzz then sleep
    alarm.sleep_memory[2] = 0  # program cycles (1+2) counter 

if alarm.sleep_memory[1] == 1:  # we are in code phase 1
    alarm.sleep_memory[1] = 2  # after sleep we'll be in code phase 2
    alarm.sleep_memory[2] = (alarm.sleep_memory[2] + 1)  # update cycles counter
    start_buzzing = random.randint(1, 1731)  # 6.3" buzz, 60" pulsante e compl. 1800
    delta = 1800 - (start_buzzing + 6.3 + 60)
    alarm.sleep_memory[3] = struct.pack(delta)  # UNSURE ON FORMAT - NEED MORE BYTES?
    al = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + start_buzzing)
    alarm.exit_and_deep_sleep_until_alarms(al)

elif alarm.sleep_memory[1] == 2:  # we are in code phase 2
    alarm.sleep_memory[1] = 1  # after sleeep we'll go back to phase 1
    delta = struct.unpack(alarm.sleep_memory[3])  # UNSURE ABOUT FORMAT
    vibrating_disc.value = True
    time.sleep(0.3)
    vibrating_disc.value = False
    time.sleep(1.7)
    vibrating_disc.value = True
    time.sleep(0.3)
    vibrating_disc.value = False
    time.sleep(1.7)
    vibrating_disc.value = True
    time.sleep(0.3)
    vibrating_disc.value = False
    time.sleep(1.7)
    vibrating_disc.value = True
    time.sleep(0.3)
    vibrating_disc.value = False
    print_contatore = repr(alarm.sleep_memory[2])  # converte var in stampabile
    start_time = time.monotonic()
    while True:  
        switch.update()  # all'inizio di ogni loop controlla il pulsante
        timer = time.monotonic() - start_time 
        if timer < 60 and switch.short_count == 1:
            file1 = open("mindfulness_log.txt", "a")
            file1.write(print_contatore + "ok ")
            file1.close()
        elif timer < 60 and switch.short_count == 2:
            file1 = open("mindfulness_log.txt", "a")
            file1.write(print_contatore + "no ")
            file1.close()
    al = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + delta)
    alarm.exit_and_deep_sleep_until_alarms(al)

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Ugh. That's a bait & switch :(

You could manage the "sleep memory" yourself using an external FRAM board (which also avoids concerns about multiple Flash writes): https://www.adafruit.com/product/1897.

Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

So you mean it's not possible to implement sleep memory on my board?
What about this page where the QT Py is listed as having NVM? https://docs.circuitpython.org/en/lates ... index.html

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

No, I don't mean that. I mean it's a backup plan.

Dan asys it uses a "microcontroller.nvm-style mechanism", not microcontroller.nvm literally. sleep memory seems to be extra non-volatile storage separate from flash. It uses RAM:
Store raw bytes in RAM that persists during deep sleep. The class acts as a bytearray. If power is lost, the memory contents are lost.
What does alarm.sleepmemory return?

After all that I checked the alam.sleepmemory implementation for the RP2040. It isn't available. Specifically, circuitpython/blob/ports/raspberrypi/common-hal/alarm/SleepMemory.c:

Code: Select all

uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) {
    mp_raise_NotImplementedError(translate("Sleep Memory not available"));
    return 0;
}

bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t *values, uint32_t len) {
    mp_raise_NotImplementedError(translate("Sleep Memory not available"));
    return false;
}

void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t *values, uint32_t len) {
    mp_raise_NotImplementedError(translate("Sleep Memory not available"));
}
So your project really doesn't do anything other than run the buzzer occasionally. And the light sleep instead of delay() doesn't make much difference to the battery life. My thought is that it's running the buzzer that is the most significant power use (which makes sense since it's running a motor). As an experiment you could try changing the buzz to a single short buzz and compare battery life to what you currently have.

Short of monitoring the current usage, that would IMO be the best way to figure out what's using the current.

If what I describe is the case, a deep sleep won't help much.

Dave
Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

Ok, I'll definitely do the test shortening the buzzing, even if I remember the first versions of the code had single buzzes up to 4 seconds long (!) and my memory is that the battery duration was pretty much the same. But I might be wrong, I'll let you know.
Regarding the sleep memory, I confess I didn't understand some pieces, in detail:
1) can I use a "microcontroller.nvm-style mechanism" to enable it on my board? If so what does such mechanism look like?
2) I didn't understand the code you posted, looks complicated for my level. Is that the test you ran on the RP2040? What exactly does it mean?

And finally, I am expecting delivery of a QT Py ESP32-S3 NO PSRAM that I ordered to implement the BTLE capability. Will that board have the sleep_memory?

Thanks!
Angelo

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

1) Dan means that using alert.sleepmemory is similar to using microcontroller.nvm
2) That code is the RP2040 implementation of the sleepmemory functions. They just raise a NotImplemented exception. I.e. sleepmemory isn't available on the RP2040.

Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

I am still running tests with shorter buzzes, I am not sure of the outcome yet because yesterday I was out all day and the buzzer went off only once (either there was a problem or I didd't feel it buzz)...

In the meantime I saw a couple other strange things happen:
1) it's been a while now that every time I save the code, the REPL shows it restarting twice instead of once. It does this always since I started having problems with the USB connection, which BTW keeps stopping working after a couple of plug/unplug even after I nuked the flash..
Code stopped by auto-reload. Reloading soon.
soft reboot

L'auto-reload è attivo. Salva i file su USB per eseguirli o entra nel REPL per disabilitarlo.
code.py output:

Code stopped by auto-reload. Reloading soon.
soft reboot

L'auto-reload è attivo. Salva i file su USB per eseguirli o entra nel REPL per disabilitarlo.
code.py output:
2) Today I saved some text into my mindfulness_log.txt file into CIRCUITPY while I had MU and the REPL open in another window and when I hit save I saw the code restarting... just once, not twice like it does when I save from MU. I checked several times and it's consistent...

Arent't these strange behaviors?

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Not necessarily strange. Auto-reload happens when CircuitPython detects a change in the filesystem. Your OS might be tweaking something other than code.py. You can disable the auto-reload but you'll have to restart CP/code.py manually (CTRL-D). See https://learn.adafruit.com/welcome-to-c ... ly-3108374.

Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

Ok!
Back to the power consumption: today I tested again with 4 x 0.1 second buzzes and the battery is lasting around 4 hours, LESS than before when I had 4 x 0.3 seconds buzzes and it lasted around 6 hours.
I am really confused.
One thing I thought about is monitoring the battery voltage and I’ve read that BFF pin A2 is supposed to provide that but I don’t know how to set it up... Can I write code to print it?

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

For reading the voltage, see https://learn.adafruit.com/circuitpytho ... -analog-in. You'll be reading from A2 rather than A1 in the example.

Batteries can be weird. Was it fully charged to start in both cases?

I think you'll probably need to switch to a bigger battery... 100mAh is pretty puny.

Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

If I switch to a bigger battery I might have to change completely the form factor of my project and connect the QT PY and BFF side-to-side. In that case do I just use wires to connect the pads or are there specific connectors, like header pins but made to work side by side?

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Yes, you just use wires to connect the matching pins. Note that you'll only need to connect the few that are used by the BFF.

Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

Got it!
About reading the voltage, I embedded these new lines into my code

Code: Select all

from analogio import AnalogIn

analog_in = AnalogIn(board.A2)

def get_voltage(pin):
    return (pin.value * 4.1) / 65536

print(get_voltage(analog_in))

print_voltage = repr(get_voltage(analog_in))
        file1 = open("voltage.txt", "a")
        file1.write(time.monotonic() + print_contatore + print_voltage)
        file1.close()
It prints the voltage every time I reload and also writes it on a file in order for me to check how it dropped during functioning.
I used 4.1 as a factor because I understand that is the maximum voltage produced by my lipo. The exaple code had 3.3...

To make sure the battery is fully charged I am plugging the board into a USB C wall charger (with the pc I am always in doubt that power could be removed from the port for power saving)

The weird thing is that no matter the battery state (just charged or drained) it always prints / writes a number starting with 2,7 or 2.8...

Any idea what it means?

User avatar
dastels
 
Posts: 15670
Joined: Tue Oct 20, 2015 3:22 pm

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Yes, it has to be 3.3 becasue that's the reference voltag of the ADC. The QtPy is a 3.3v chip. Also, you need to double it (so * 6.6) to account for the voltage divider that halves the voltage being measured (so that it is measuring something <= 3.3v.

I'm not sure what you mean by with the pc I am always in doubt that power could be removed from the port for power saving

Dave

User avatar
bozzaglia
 
Posts: 131
Joined: Mon Aug 01, 2022 6:14 am

Re: buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

With that phrase I meant that sometimes windows stops powering USB ports depending on the pc status, so I was never sure whether my small battery was fully charged.
Anyway I don’t have that doubt anymore. I have done some more deep sleep tests because I hoped to use it at least on one “side” of the loop, and noticed another behavior I didn’t expect: my board seems to do an actual restart every time it sleeps (the led flashes yellow when it wakes up, like in a reset), and this messes up with my boot.py file as well, because the button is not depressed when it restarts and so it is no longer able to write on the file system and produces an error (red led) when it tries to write on the txt file. This would be confirmed by the fact that if I test it while plugged in my pc the problem does not happen because it is just pretending to sleep.
Is this behavior normal? Is it the same on all chips?
Now I am expecting delivery of the qt py ESP 32-S3 and another BFF, so I plan to connect them side by side and get a 250 mAh battery do sit below them in the case I will make. I am hoping that size battery is enough to power it through a day.
I also tested the deep sleep with a simpler code that just slept and buzzed 4 times and I did get a longer life out of my current 100 mah battery, but it was still less than 12 hours... I am very surprised by this because my son has a mini RC helicopter powered by a 150 mah lipo and it runs the device’s three motors for good 15 minutes!!!

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”