🎄⛄❄️🎁 It's beginning to look a lot like ADABOX-mas! The next ADABOX from Adafruit ships soon! Get yours now, or give as a gift! 🎄⛄❄️🎁
0

Make it Pulse in MakeCode
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Make it Pulse in MakeCode

by KathyCeceri on Fri Nov 01, 2019 3:34 pm

I want to use CPX with a group of teens who are new to coding to create heart rate monitors. Any suggestions on how to replicate this project in CircuitPython in MakeCode? Accuracy is not as important as getting the code to demonstrate how a heart rate monitor works. Being really simple (for me and for the students) is a must.

https://learn.adafruit.com/make-it-pulse/circuitpython

KathyCeceri
 
Posts: 40
Joined: Sun Mar 02, 2014 7:30 pm

Re: Make it Pulse in MakeCode

by johnpark on Mon Nov 04, 2019 4:16 pm

Great question, I'll give it a try -- I think the key will be the 'ambient color' block. It does most of the work of flashing the pixel 1 through R,G, & B and reading the reflected color with the sensor next to it.

johnpark
 
Posts: 617
Joined: Wed Mar 25, 2009 2:15 pm

Re: Make it Pulse in MakeCode

by V2man on Tue Nov 05, 2019 2:03 am

This was my attempt at a direct translation from CircuitPython to Makecode of plotting the pulse rate.
It does not work at all!

I am not sure how a function works in Makecode.
The CircuitPython code had float, sum and sign that I did not know how to interpret.
There was also one statement: lasttime = time.monotonic() that I did not understand.
This may help or hinder you. Maybe you can see where I went wrong.
I did turn the brightness down to from 255 to 128.

Pulse1.JPG
Pulse1.JPG (93.94 KiB) Viewed 316 times


circuitplayground-Pulse1.uf2
(319 KiB) Downloaded 15 times

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by adafruit2 on Thu Nov 07, 2019 1:31 pm


adafruit2
Site Admin
 
Posts: 18790
Joined: Fri Mar 11, 2005 7:36 pm

Re: Make it Pulse in MakeCode

by V2man on Thu Nov 07, 2019 3:44 pm

No it does not work. You have function sign2 but you call for a function sign twice in the for loop.
Is that how functions work? You have to rename a function something else but the internal variable is what you call for? What are function parameters for?

I get error 1111010110 or 0x3D6 after I download to CPX.

With the error showing on the CPX in red and blue neopixels when I press Show Console Simulator and then the play arrow I get a message in orange that says:
Program Error: Function expected

The attached uf2 fixes function(sign) to function(sign2) on the two entries in the for loop.
I would say it still does not work. Its behavior is much different that with the circuitpython equivalent.
Is there a way using timers to measure the number of zero crossings to get a heart beats/minute reading?
Attachments
circuitplayground-Heartbeat-Feb-Yay1.uf2
(285 KiB) Downloaded 6 times

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Thu Nov 07, 2019 5:12 pm

@ adafruit2 Thanks for looking into this. I also notice you have the last statement in the for loop: pause set to 100 ms instead of 25 ms.

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by adafruit2 on Thu Nov 07, 2019 5:14 pm

looking at my history that code was never working so if you can fix it, let us know and we'll make the page live

we do not have an ETA on when we might revisit the code

adafruit2
Site Admin
 
Posts: 18790
Joined: Fri Mar 11, 2005 7:36 pm

Re: Make it Pulse in MakeCode

by V2man on Fri Nov 08, 2019 4:41 pm

Here' where I am now. I think I have the translation from CircuitPython to Makecode blocks correct now but the behavior is not the same as the CircuitPython version. Try out the attached uf2 and please give me some feedback.
Secondary Problem: When you first plug in the USB cable from your computer the CPX will be in Bootloader mode. Press the reset button on the CPX and the Heart rate program will run. Maybe that's just my setup because I have a CPX board mounted to an unpowered Crickit board. Its ok if I just turn on power to the Crickit without a USB connection. All the neopixels on the CPX board go to red to indicate there is no USB connection than turn off and the program starts to run.

HeartBeat-Feb-Yay-Fix.JPG
HeartBeat-Feb-Yay-Fix.JPG (119.77 KiB) Viewed 180 times


circuitplayground-Heartbeat-Feb-Yay-Fix.uf2
(286.5 KiB) Downloaded 6 times
Last edited by V2man on Fri Nov 08, 2019 5:24 pm, edited 2 times in total.

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Fri Nov 08, 2019 4:48 pm

These two methods are equivalent.


V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Fri Nov 08, 2019 6:20 pm

Forgot to put a set variable assignment to set NUM_SAMPLES to 20 (for loop) in the previous comparison post.

Here's a plot of sample(index) - mean from Show console device in Makecode:

plot.png
plot.png (245.27 KiB) Viewed 169 times


As you can see without time tics I don't know what I am looking at.

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Sat Nov 09, 2019 1:52 am

Now if we
set brightness to 255
NUM_OVERSAMPLE to 20
NUM_SAMPLE to 40

We get a waveform that resembles a pulse rate and the behavior mimics the CircuitPython code.

LooksLikePulseRate.png
LooksLikePulseRate.png (302.44 KiB) Viewed 140 times


Heartbeat-Nov.JPG
Heartbeat-Nov.JPG (89.51 KiB) Viewed 131 times
Attachments
circuitplayground-Heartbeat-Nov.uf2
(286.5 KiB) Downloaded 3 times

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Sat Nov 09, 2019 1:48 pm

You do have to wait for at least 3 passes before the large fluctuations pass and the console plotter re-scales before you see anything. In this regard I like the MU plotter for its speed. It takes some experimentation to find the best way to old your finger or thumb over the green led and the light sensor(eye).
The index > 0 loop is there to prevent an unknown sign0 from being used. sample(index - 1) results in sample(-1) when the index is 0. The calculation does not begin until the index is greater than 0 or 1. With the index = 1 you have sample(0) which is known to calculate sign0.
You will also notice that when you are not providing an input the console still shows some spiking. One can be ruled out by setting the pixel color at 9 to black or using a physical barrier to keep the light sensor from seeing the red neopixel. Maybe starting with an external sensor like https://www.adafruit.com/product/1093 which you could put in a tube would yield more reliable readings.

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Sat Nov 09, 2019 3:29 pm

@ adafruit2 Thanks for providing an example so I could see how functions work and how someone else would translate the pulse CircuitPython code.

So if I take the Heartbeat-Feb-Yay.uf2 and apply the following changes I get the attached uf2 below.
Rename variable Sign to sign.
Rename function Sign2 to Sign.
Change set mean to sum/20 to sum/NUM_SAMPLES
Add set brightness 255
Change NUM_OVERSAMPLES from 10 to 20
Change NUM_SAMPLEs from 20 to 40
Add 20 more zeroes to list array to make a length of array list = 40
The fixed list array is not scalable. I prefer a for loop.
Set neopixel 1 to green instead of neopixel 0.
We get to a similar conclusion.
The minor differences between my version and yours is that in my version, circuitplayground-Heartbeat-Nov.uf2 retains the array name, samples instead of the name, list from the original CircuitPython code and it has the scalable for loop for zeroing the array.
In the course of making the translation I encountered many strange results that I cannot explain.
Even the two uf2s though not quite the same should have yielded exactly the same results. The results are similar but not exactly the same.
It is amazing that you can even do a pulse rate measurement with the CPX using CircuitPython or Makecode. I just think most people will think it does not meet their expectations. They do not have the patience to hold their finger for the length of time it takes to get a plot. I think a BPM result and a plot is what they are looking for.
Attachments
circuitplayground-Heartbeat-Feb-Yay-Fix.uf2
(287.5 KiB) Downloaded 2 times

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Sat Nov 09, 2019 11:07 pm

One thing that bothers me is that the vertical scale for the CircuitPython is like +-500 and in Makecode its much smaller. That 's something for me to look into.


PulseMUplot.png
PulseMUplot.png (15.82 KiB) Viewed 97 times

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Re: Make it Pulse in MakeCode

by V2man on Sun Nov 10, 2019 3:31 am

I decided to work from the other direction, CircuitPython. The question all along has been is the sum() the same as a for loop calculation of the sum. So I replaced the sum(samples) with a for loop that calculates the sum. Same behavior as in Makecode. So I am satisfied that the translation of CircuitPython to Makecode Block is correct. I question the plotting vertical scale numbers in Makecode.

PulseWforloopMUplot.png
PulseWforloopMUplot.png (52.23 KiB) Viewed 86 times


PulseSumMUplot.png
PulseSumMUplot.png (54.52 KiB) Viewed 86 times


Code: Select all | TOGGLE FULL SIZE
import time
import analogio
import board
import neopixel

pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=1.0)
light = analogio.AnalogIn(board.LIGHT)

# Turn only pixel #1 green
pixels[1] = (0, 255, 0)

# How many light readings per sample
NUM_OVERSAMPLE = 10
# How many samples we take to calculate 'average'
NUM_SAMPLES = 20
samples = [0] * NUM_SAMPLES
lasttime = time.monotonic()

# def sum_array(x):
#    s = 0
#    for j in range(NUM_SAMPLES):
#        s = s + x[(j)]
#    return s
   
def sign(value):
    if value > 0:
        return 1
    if value < 0:
        return -1
    return 0

while True:
    for i in range(NUM_SAMPLES):
        # Take NUM_OVERSAMPLE number of readings really fast
        oversample = 0
        for s in range(NUM_OVERSAMPLE):
            oversample += float(light.value)
        # and save the average from the oversamples
        samples[i] = oversample / NUM_OVERSAMPLE  # Find the average
       
        s = 0
        for j in range(NUM_SAMPLES):
            s = s + samples[(j)]
         
        # mean = sum(samples) / float(len(samples))  # take the average
        mean = s / float(NUM_SAMPLES)
        print((samples[i] - mean,))  # 'center' the reading

        if i > 0:
            # If the sign of the data has changed munus to plus
            # we have one full waveform (2 zero crossings), pulse LED
            if sign(samples[i]-mean) <= 0 and sign(samples[i-1]-mean) > 0:
                pixels[5] = (200, 0, 0)  # Pulse LED
            else:
                pixels[5] = (0, 0, 0)    # Turn LED off

        time.sleep(0.1)  # change to go faster/slower

V2man
 
Posts: 326
Joined: Mon Dec 03, 2018 12:38 am

Please be positive and constructive with your questions and comments.