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

buzzing mindfulness bracelet code plus some new functions

Post by bozzaglia »

I am a beginner and for my first project I have built the circuit from the “buzzing mindfulness bracelet” on a Gemma M0 with the following differences:

I am trying to write code to buzz randomly once every 30 minutes
I added a pushbutton on pin D2 in order to log my feedback on a file every time the buzzer vibrates (single click log “ok”, double click log “no”)
This is the circuitpython code I have written so far and I know there are gaps and mistakes and I am trying to solve them one by one.

Code: Select all

import datetime
from random import randint
import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Button 

# vibrating disc mini motor disc connected on D1
vibrating_disc = DigitalInOut(board.D1)
vibrating_disc.direction = Direction.OUTPUT
pulsante = DigitalInOut(board.D2)  
pulsante.direction = Direction.INPUT
pulsante.pull = Pull.UP
switch = Button(pulsante)  

on_time = 2     # Vibration motor run time, in seconds
now = datetime.now()
begin = datetime.datetime.strptime("07:00", "%H:%M")
end = datetime.datetime.strptime("23:00", "%H:%M")
delta = datetime.timedelta(minutes=30)

while begin <= end:

    r = begin + datetime.timedelta(seconds=randint(0, 1800))
    if now >= r and now <= (r + on_time):
        vibrating_disc.value = True

    elif now >= (r + on_time):
        vibrating_disc.value = False

   
begin = begin + delta 

When I load on the gemma I get the following message from MU REPL:
Traceback (most recent call last):
File "code.py", line 2, in <module>
ImportError: no module named 'datetime'

The led is going green-yellow-flashing blue.

One other thing I need to make sure of is the capability to append data to a file stored on the board and I have read this topic https://learn.adafruit.com/circuitpytho ... on-storage which is making me think that if I put the BOOT.PY file on the Gemma I will be no longer able to edit the code from my pc. Is this correct? What is going to happen?

Any help really precious!
Angelo

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

Re: buzzing mindfulness bracelet code plus some new function

Post by dastels »

The timedate module isn't supported in CircuitPython. Usually you use the time module. If you're just using time to schedule things (i.e. you don't really care what the time is, just how much has passed) you usually use time.monotonic() to get a seconds value (as a float so you get fractional values).

As for writing files, see https://learn.adafruit.com/circuitpytho ... on-storage. Since you already have a button wired in you can use that as the "make the file system writable" input: press the button and reset to have it come up with a writable filesystem. reset without pressing it to be able to edit/copy via USB. You can use the button the other way (reset with it pressed for editing) if that makes more sense.

Dave

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

Re: buzzing mindfulness bracelet code plus some new function

Post by bozzaglia »

Thanks Dave!
That was really bad news, as my code was completely based on the datetime library, so now I have no idea on how to make it work without it...
I saw there is a library named "adafruit_datetime" but is seems that doesn't work on the gemma as well (I get the same error message).
I looked up the time library but it doesn't seem to have a "now" function or a "timedelta" function.
Any tips?

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

Re: buzzing mindfulness bracelet code plus some new function

Post by dastels »

Use time.monotonic() (millisecond resolution) or time.monotonic_ns() (if you need nanosecond resolution). See https://docs.circuitpython.org/en/lates ... odule-time. There are time/dat related functions but they are meaningless unless you have battery backed hardware RTC connected or WiFi hardware to be able to fetch the time.

Generally in this sort of project you just need to know the passage of time so you know when to do something (buzz in your case). See https://learn.adafruit.com/multi-taskin ... cuitpython for examples and ideas.

Dave

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

Re: buzzing mindfulness bracelet code plus some new function

Post by bozzaglia »

ok. For now I came up with this code, but it makes the motor vibrate almost continuosly... I've put the "delta" there with the intention of not having more than one buzzing every 30 minutes, but something must be off.. Now it's bedtime here in Italy, tomorrow I'll have another look. I am hoping I just have a problem of time unit of measure (seconds vs milliseconds or something like that)...

Code: Select all

import time
import board
import random
from digitalio import DigitalInOut, Direction

vibrating_disc = DigitalInOut(board.D1)
vibrating_disc.direction = Direction.OUTPUT

on_time = 2     # Vibration motor run time, in seconds

start_time = time.monotonic()
while True:

    interval = random.randint(1, 1800)
    delta = (1800 - interval) 
    timer = time.monotonic() - start_time 

    if timer >= interval and timer <= (interval + on_time):  
        vibrating_disc.value = True
        
    elif timer >= (interval + on_time):  
        vibrating_disc.value = False
        
    elif timer >= (interval + on_time + delta):
        start_time = time.monotonic()  

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

Re: buzzing mindfulness bracelet code plus some new function

Post by dastels »

Right away I see that you are redoing he value of interval every time through the loop. The order of the elif clauses looks to be reversed as well.

Dave

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

Re: buzzing mindfulness bracelet code plus some new function

Post by bozzaglia »

dastels wrote: Thu Aug 11, 2022 6:57 pm The timedate module isn't supported in CircuitPython. Usually you use the time module. If you're just using time to schedule things (i.e. you don't really care what the time is, just how much has passed) you usually use time.monotonic() to get a seconds value (as a float so you get fractional values).

As for writing files, see https://learn.adafruit.com/circuitpytho ... on-storage. Since you already have a button wired in you can use that as the "make the file system writable" input: press the button and reset to have it come up with a writable filesystem. reset without pressing it to be able to edit/copy via USB. You can use the button the other way (reset with it pressed for editing) if that makes more sense.

Dave
Dave, going back to your answer about file writing, I understand that to be able to use the button to make the file writable I need to add this code for the Gemma (found at the link you mentioned):

Code: Select all

import board
import digitalio
import storage

switch = digitalio.DigitalInOut(board.D2)

switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.UP

storage.remount("/", switch.value)
I am just unsure about how the reset button comes into play, since it is not mentioned in the code. Do I need to add other lines?

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

No. The rest button is a purely hardware thing. It causes the MCU to stop what it's doing and restart the board. Pressing reset generally has the same effect as disconnecting and reconnection power (eight by disconnecting the power source or using the Gemma's power switch). Specifically in the case of CircuitPython, it restarts the CP runtime and causes boot.py to be reloaded/reevaluated (and subsequently code.py).

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.... So I am wondering: if I use the button to switch the filesystem to writable, which I understand is done using the code

Code: Select all

storage.remount("/", switch.value)
, then how can I still use the button to do the other thing I need, which is log my feedback in a txt file?

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

boot.py just looks at the button while the board is booting. Once code.py starts running you're locked into read/write mode until the next reset. Using it in boot.py just takes advantage of it being there already.

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 Dave, thanks! I think I got the boot.py piece, hopefully!
Now I am trying to write the code to use the button to store my feedback in a txt file named "log".
This is the part of the code dedicated to that (I have removed all the part relative to the random buzzing for extra clarity.
I am trying detect double presses, and I've read this guide (https://docs.circuitpython.org/projects ... e/api.html which looks like was written by you :-))
though about using the function "short_count = 2", but I keep getting a sintax error... What am I mistaking?

Code: Select all

import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Button
import storage  # aggiunto

pulsante = DigitalInOut(board.D2)
pulsante.direction = Direction.INPUT
pulsante.pull = Pull.UP
storage.remount("/", pulsante.value)
switch = Button(pulsante)


while True:
    switch.update() 
    
    if pulsante.fell:
        file1 = open("log.txt", "a")
        file1.writelines("interval, ok")
        file1.close()
    elif pulsante.short_count = 2:
        file1 = open("log.txt", "a")
        file1.writelines("interval, no")
        file1.close()
Thanks again for walking me through this!
Angelo

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

The storage remount call has to be only in boot.py... not code.py.

By the time it gets to code.py, boot.py has been executed and the mounting mode of the flash drive has been set.

I did the original work on the debouncer, but the Button class was done later. It looks ok, except that you need to use == to do the comparison. = is assignment and short_count doesn't have a setter.

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 »

The storage remount call has to be only in boot.py... not code.py
I had completely overlooked that the code was for the boot.py! :-O

ok for the ==!
Thanks a lot again!

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 just tried loading the boot.py file and the full code (vibration + button feedback log), I did it twice and always got the same final result, that is the led flashing different colors and finally going in a permanent loop "steady green - steady yellow - blinking green", and nothing else happening (no buzzing, no saving files, etc).
I used the boot.py version for circuitpython 7.x as I read it is the latest supported by gemma m0 (in the bundle file there was also the one for circuitpython 8.x).
I pressed the button first and then the reset, with the button held down.
Here is the full code I put in the code.py. Any idea where the problem might be?

Code: Select all

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

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

on_time = 4     # Vibration motor run time, in seconds
interval = random.randint(1, 1800)
delta = (1800 - interval)

start_time = time.monotonic()  
while True:
    switch.update()
    timer = time.monotonic() - start_time  # timer è t tra start_time e time.monotonic

    if timer >= interval and timer <= (interval + on_time):  # avvia il motore
        vibrating_disc.value = True

    elif timer >= (interval + on_time) and timer <= (interval + on_time + delta):
        vibrating_disc.value = False
        if pulsante.fell:
            file1 = open("mindfulness_log.txt", "a")
            file1.writelines("interval, ok")
            file1.close()
        elif pulsante.short_count == 2:
            file1 = open("mindfulness_log.txt", "a")
            file1.writelines("interval, no")
            file1.close()

    elif timer > (interval + on_time + delta):
        start_time = time.monotonic()  
        interval = random.randint(1, 1800)  
        delta = (1800 - interval)

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

Re: buzzing mindfulness bracelet code plus some new functions

Post by dastels »

The flashing lights indicate an error. Can you post what you see in the REPL when the code runs? That should give a better idea of what's happening.

If you aren't familiar with using the REPL (or even just the serial connection), see
https://learn.adafruit.com/welcome-to-c ... al-console
https://learn.adafruit.com/welcome-to-c ... al-console
https://learn.adafruit.com/welcome-to-c ... n/the-repl

Dave

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

Return to “Adafruit CircuitPython”