square signal for buzzer

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
vchaps
Posts: 3
Joined: Tue Apr 23, 2019 7:08 am

square signal for buzzer

Post by vchaps » Tue Apr 23, 2019 7:44 am

Hello,
In order to make a teacher's presentation of micro:bit and to compare C language for arduino and micropython for micro:bit, I'd simply like to generate a square wave as Arduino can easily make it, and to supply a buzzer

[code]
void setup() {
pinMode(9, OUTPUT);
Serial.begin(9600); // Set serial out if we want debugging
}

void loop() {
digitalWrite(9,HIGH);
delayMicroseconds(1136);
digitalWrite(9, LOW);
delayMicroseconds(1136);
}
[/code]

I have tried with what I thought equivalent in micropython:

[code]
from microbit import *
import utime

while True:
pin0.write_digital(1)
utime.sleep_us(1136)
pin0.write_digital(0)
utime.sleep_us(1136)
[/code]

unfortunately, it seems that the functions write_digital and sleep_us are too slow to generate a clean signal and moreover buzzer's frequency is not accurate at all (15% less than expected).
Have you got any solution? I precise that the goal is to decompose the signal generation, not to use high level functions like music.pith or even set_analog_period_microseconds.
Thank you for your help.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: square signal for buzzer

Post by pythoncoder » Tue Apr 23, 2019 8:00 am

Please note I have no experience of programming the micro:bit.
The 15% reduction corresponds to a function call overhead of 85μs. This is slow compared to the Pyboards but probably reflects the micro:bit hardware performance.

On Pyboards and many other MicroPython platforms it is possible to achieve high frequency accuracy in at least two ways: by using a callback from a hardware timer, or by using PWM. I don't know if the micro:bit supports these options.
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: square signal for buzzer

Post by Roberthh » Tue Apr 23, 2019 9:39 am

For Arduino, the code in the sketch is the only that's running.
Using Micropython, there are quite a few background tasks active, including the communication stack. This causes a "square" wave loop like yours not being regular and the average execution time per loop being extended. 85µs for a function call seems a little bit too long, compared to 2-4µs on Pyboard.
Peter mentioned the methods to ensure better timing precision. But you seem not like to use them for your educational purpose.

vchaps
Posts: 3
Joined: Tue Apr 23, 2019 7:08 am

Re: square signal for buzzer

Post by vchaps » Tue Apr 23, 2019 12:16 pm

Thanks for your replies. This issue seems to be a limit of micropython, nevertheless it is interesting for my presentation to illustrate with such an easy physical example the difference between the two kind of language.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: square signal for buzzer

Post by pythoncoder » Tue Apr 23, 2019 5:29 pm

Indeed. If I were presenting the topic I'd illustrate the C code, straight Python as per your sample, and timer-driven Python to illustrate a way to achieve high frequency precision.

In the latter solution any latency in issuing the callback is cancelled out because it is the same for each output transition. If latency is constant you should see an exact frequency with a 1:1 m/s ratio.
Peter Hinch
Index to my micropython libraries.

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: square signal for buzzer

Post by OutoftheBOTS_ » Tue Apr 23, 2019 10:13 pm

Create local instances of the 2 function u need to be called with low latency

e.g
local_pin_write = pin0.write_digital()
local_sleep = utime.sleep_us()

while True:
local_pin_write(1)
local_sleep(1136)
local_pin_write(0)
local_sleep(1136)

vchaps
Posts: 3
Joined: Tue Apr 23, 2019 7:08 am

Re: square signal for buzzer

Post by vchaps » Wed Apr 24, 2019 7:22 am

to pythoncoder,
unfortunately, micro:bit doesn't seem to have a timer such as pyboard, its machine module is not so complete:
https://microbit-micropython.readthedoc ... chine.html
so I can't make a timer object for callback
to Outofthebots,
defining functions as you suggest seems to improve a bit the frequency, but still far away from expected.
anyway, Thanks.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: square signal for buzzer

Post by pythoncoder » Wed Apr 24, 2019 8:59 am

@vchaps You're right: lacking a timer you could measure the latency and take it into account. Something along these lines:

Code: Select all

from utime import ticks_us, ticks_diff
toggle = lambda : pin0.write_digital(not pin0.read_digital())
t = ticks_us()
toggle()
latency = ticks_diff(ticks_us(), t)
delta = 1136 - latency
while True:
    t = ticks_us()
    while ticks_diff(ticks_us(), t) < delta:
        pass
    toggle()
Peter Hinch
Index to my micropython libraries.

Post Reply