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.
Locked
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 think I made some confusion, now it’s clear. I guess if the other features are the same, I could probably get an ESP32 board and keep the WiFi/bt disabled, just in case I want to do something with it in the future.

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Pairing BTLE with your phone could lead to some interesting features.

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 was comparing the pinouts of the Gemma and the QTPY-S3 based on the buzzing bracelet project diagram (attached images) and it looks like the equivalent of A0/D1 pin on the Gemma is the A0 pin on the QTPY. However I am not finding a pin named VOUT, just two power pins named 3.3V and 5V, I guess the 3.3V is the one I want?
And for the storage / boot.py it looks like I have to use the on-board button, which might be complicated because I am going to wrap the board in kapton tape to prevent shorting with the other components. Can I switch to an external button?
Attachments
adafruit_products_Adafruit_QT_Py_ESP32-S3_Pinout.png
adafruit_products_Adafruit_QT_Py_ESP32-S3_Pinout.png (93.96 KiB) Viewed 153 times
adafruit_gemma_Adafruit_GEMMA_M0_pinout.png
adafruit_gemma_Adafruit_GEMMA_M0_pinout.png (372.1 KiB) Viewed 153 times
projects_Buzzing_Mindfulness_Bracelet_bb.png
projects_Buzzing_Mindfulness_Bracelet_bb.png (52.88 KiB) Viewed 153 times

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Yes, 3.3v should be fine to drive the buzzer.

You'll need an external button (isn't that what you're doing now?) One onboard button is to reset the board, the other is to put into bootloader mode (hold it down when resetting).

You should be able to use any pins other than 5v, 3.3v, and ground for the button or buzzer. A0-A3 are the more usual ones though.

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 »

Dave,
great, thanks!

I have to ask you one last thing relative to the time.sleep function. I understood that it won't save any power for my code but I was playing with it a little, while I wait for the new board to arrive.

I am relly puzzed by the way it seems to work. To better understand I have come up with this very simple code, which is a subset of mine:

Code: Select all

import time
import board
from digitalio import DigitalInOut, Direction

# vibrating disc mini motor disc connected on D1
vibrating_disc = DigitalInOut(board.D1)
vibrating_disc.direction = Direction.OUTPUT

start_time = time.monotonic()  
while True:
    timer = time.monotonic() - start_time  
    time.sleep(4.0)
    if timer >= 20 and timer <= 22:  
        vibrating_disc.value = True

    elif timer >= 22:  
        vibrating_disc.value = False
        start_time = time.monotonic()  # azzera start_time
   
I thought this would make the board sleep for 4 seconds while it waits for the timer to reach 20 seconds and then buzz for 2 seconds and start over.
However I've observed that what it does is wait for a total of 24 seconds and then buzz for 4 seconds.
If I move the time.sleep(4.0) before the timer = time,monotonic() - start_time it just waits for 20 seconds and then buzzes for 4 seconds.
I've played around changing the numbers and it seems that the buzzer always stays on for the same time I set in time_sleep (????!!!!), unless I set the time.sleep to less than 2 seconds (that is the time the buzzer should stay on), then it buzzes regularly for two seconds.
If I set the time.sleep to a bigger number (say over 15 seconds), I never get any buzz....
I've been banging my head on this... Maybe for you it is very easy to see why it does it...

And finally, what can I do to express how happy I am with the way you guys are supporting me?? You guys are just great! I've never seen a better support in my life! Can I leave a review anywhere or something else?

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Part of it is that you only check update/check timer every 4 seconds due to the time.sleep(4.0).

So you on the 5th time through the loop (the loop takes 4 seconds due to the sleep) you turn the buzzer on since timer is now >= 20. The next time you look at timer will be 4 seconds later and the buzzer will turn off.

Having the sleep after updating the timer value to be used during the current pass through the loop is problematic as well. After the sleep you check the timer value, which is now 4 seconds in the past. I watch/read a lot of science fiction and have learned that temporal shifts seldom end well. It's more usual to see the sleep at the end of the loop.

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 think I hadn't understood how time.sleep works
I thought timer continued to be checked/updated during the sleep. Now it is clearer!
However I tried to put it at the end of the loop, but INSIDE the loop, and I get exactly the same problem, just starting at the second cycle.
Should I put it OUTSIDE the loop (i.e. indenting it at the same level as While True)? I tried it and it works fine but I suspect the code never gets to the time.sleep part because it is stuck in the loop...

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Right, sleep is a bad name. The Arduino framework's delay is more accurate. When you call sleep(4.0) the processor spends 4 second basically in a loop before it returns... 4 seconds later.

Putting the sleep/delay at the end of the loop is more of a stylistic convention that makes the code a bit more understandable. It doesn't change how the loop was functioning.

Right, putting sleep after (outside) the loop means it never gets called and your look runs full speed.

Without a real, power saving, sleep there's not much point of it. You're using time.monotonic() to track the passage of time to know when to do things, so there's no advantage of having a delay in the loop. I suspect things will work as desired if you simply remove the call to sleep.

Once you have the capability of a power saving sleep you should restructure the code to get the most out of it. You'll want to set an alarm for the time to wake and do something rather than have 4 second naps. There's no reason for it to periodically wake up occasionally just to check if it's time for something to happen.

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 was able to make it work and actually I noticed that if I insert a time.sleep(1.0) in the loop and make sure all of my events (i.e. buzzing time) are even multiples of 1 second, I do get some power saving (approx 10 hours instead of 6), I guess it’s because the code is not updating continuously but only once per second.
Anyway I should receive my RP2040 tomorrow (was the only qt py board I could find here in Italy) and the add on charger in a week or so, so I’ll start working at the code with the light sleep and the alarm.

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Interesting. But the code is still running all the time... just not your code. What your code is doing is a bit different with the changes in timing so that can impact the power consumption. I look forward to hearing the effect of using the low power sleep. You will need to change your code somewhat to make use of the alert module. It should be fun and educational.

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 starting to look at the light sleep + alarm code and I read the explaination on your website here https://learn.adafruit.com/deep-sleep-w ... -and-sleep.
So far I think I need to insert in my loop something like this:

Code: Select all

 time_alarm = alarm.time.TimeAlarm(timer = interval)
    alarm.light_sleep_until_alarms(time_alarm)
And then limit, say to 30 seconds, the time slice to look for the button and add an ELIF statement like this

Code: Select all

elif timer >= (interval + buzz + pause + buzz + pause + buzz + pause + buzz + 30) and \
            timer < 1800:
         time_alarm = alarm.time.TimeAlarm(timer = 1800)
         alarm.light_sleep_until_alarms(time_alarm)
I can't test it because I don't have the board yet, but what do you think?

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

I'm not very familiar with the alarm module but the argument to the TimeAlarm constructor should be something comparable to time.monotonic() rather than an interval or relative time.

It looks like you're on the right track, though.

Since you're dealing with fairly long times (many minutes) deep sleep would be advantageous, but would require quite a bit of restructuring.

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 this is my first go at the code.
As for the pins, I used A0 for the motor and A1 for the button. I think they are described as "Analog" pins, while on the Gemma they are both Analog and Digital, but I assume they work for what I need to do.
Based on your indication I understand the alarm is set at the moment the code processes the corresponding line and is set to a certain time in the future using the "monotonic_time" identifier, to be set to time.monotonic() + a certain interval...

Code: Select all

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

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

buzz = 0.3  # buzz time
pause = 1.7  # pausa tra i buzz
interval = random.randint(1, 1762)  # 8" buzz, 30" attesa pulsante e complemento a 1800
contatore = 1  # serve per contare i buzz nel file
print_contatore = repr(contatore)  # converte variabile in stringa stampabile

start_time = time.monotonic()  # definisce start_time come il tempo attuale
while True:  # loop
    switch.update()  # all'inizio di ogni loop controlla il pulsante
    timer = time.monotonic() - start_time
    
    time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + interval)  
    # NUOVO
    alarm.light_sleep_until_alarms(time_alarm)  # NUOVO
    
    # definisce timer come il tempo trascorso in ogni loop
    if timer >= interval and timer <= (interval + buzz):
        vibrating_disc.value = True  # buzz on

    elif timer >= (interval + buzz) and timer <= (interval + buzz + pause):
        vibrating_disc.value = False  # buzz off

    elif timer >= (interval + buzz + pause) and \
            timer <= (interval + buzz + pause + buzz):
        vibrating_disc.value = True

    elif timer >= (interval + buzz + pause + buzz) and \
            timer <= (interval + buzz + pause + buzz + pause):
        vibrating_disc.value = False

    elif timer >= (interval + buzz + pause + buzz + pause) and \
            timer <= (interval + buzz + pause + buzz + pause + buzz):
        vibrating_disc.value = True

    elif timer >= (interval + buzz + pause + buzz + pause + buzz) and \
            timer <= (interval + buzz + pause + buzz + pause + buzz + pause):
        vibrating_disc.value = False

    elif timer >= (interval + buzz + pause + buzz + pause + buzz + pause) and \
            timer <= (interval + buzz + pause + buzz + pause + buzz + pause + buzz):
        vibrating_disc.value = True

    elif timer >= (interval + buzz + pause + buzz + pause + buzz + pause + buzz) and \
            timer < (interval + buzz + pause + buzz + pause + buzz + pause + buzz + 30):
        vibrating_disc.value = False
        if switch.short_count == 1:
            file1 = open("mindfulness_log.txt", "a")
            file1.write(print_contatore + " ok" + "\n")  # writelines non funziona
            file1.close()
        elif switch.short_count == 2:
            file1 = open("mindfulness_log.txt", "a")
            file1.write(print_contatore + " no" + "\n")  # writelines non funziona
            file1.close()
            
    elif timer >= (interval + buzz + pause + buzz + pause + buzz + pause + buzz + 30) \
            and timer <= 1800:  # NUOVO
        delta = 1800 - (interval + 4 * buzz + 3 * pause + 30)  # NUOVO
        time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + delta)  
        # NUOVO
        alarm.light_sleep_until_alarms(time_alarm)  # NUOVO

    elif timer >= 1800:  # aggiornamento contatori per prossimo loop
        start_time = time.monotonic()
        interval = random.randint(1, 1762)
        contatore = (contatore + 1)
        print_contatore = repr(contatore)  # converte variabile in stringa stampabile

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

Most A pins are analog capable but work as digital as well.

A good first go I think. You are, however doing the same sort of thing you did before: computing timer = time.monotonic() - start_time then doing the sleep, then using timer which by then interval seconds out of date.

Once you have it working, there are some improvements/refinements you can explore.

Generalizing that "if tree". As it is, it's easy to introduce errors if you need to change it and doesn't easily let you experiment with timing, number of buzzes, etc. It's also lots of code and the Gemma doesn't have much room for code so being more space efficient will be beneficial in the long run. And you'll become a better programmer in the process.

Thinking about power reduction, there's no point sleeping while the buzzer if going since it'll use more power than the MCU, probably much more, but between buzzes it can sleep... 1.7 seconds is forever to an MCU.

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 »

Thanks Dave!
I need a clarification about this sentence:
... “then using timer which by then interval seconds out of date”. I am not sure I understand what you mean, it’s probably my English...

One thing about the board: As I said I had to get the RP2040 because it’s the only one I found readily available in Italy. However I really would like to use the ESP32-S3 with the Bluetooth but I couldn’t find any reseller having that in stock in Europe. I understand it’s a pretty new board. I even tried getting it on adafruit website but just the shipping is 40$!...
And I understand I will need to solder the add on charger on the back of the board so it won’t be easy to swap the board at a later time...
Do you have any suggestion on how to get the ESP32-S3?
Ps. I didn’t consider the ESP32-S2 because I don’t think I can pair it to my phone with the WiFi only and your site says it doesn’t save power on light sleep...

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

Return to “Adafruit CircuitPython”