microsoft / pxt-microbit

A Blocks / JavaScript code editor for the micro:bit built on Microsoft MakeCode
https://makecode.microbit.org
Other
711 stars 589 forks source link

Speed and timing #3851

Open sutnor opened 3 years ago

sutnor commented 3 years ago

I'm teaching programming to a 6-year-old using Makecode on a BBC Micro:bit. I don't know whether this issue is due to the Micro:bit, or to Makecode, or possibly more likely, to a lack of understanding on my part. I should state that while I have done a lot of programming in C, I am not familiar with Java or with Python.

I wrote the following in block code, but translated it to Python to be able to print it here. The program is a "Heavy pixel" - the lighted pixel runs to the lowest edge of the card. The A- and B- buttons increase / decrease the sensitivity.

`def setSensitivity(): global sensitivity, RangeAdj, rangeInc sensitivity = senseNum * 1.5 RangeAdj = 1024 / sensitivity rangeInc = RangeAdj 0.4 basic.show_number(senseNum) basic.pause(500)

def on_button_pressed_a(): global senseNum senseNum += 1 setSensitivity() input.on_button_pressed(Button.A, on_button_pressed_a)

def on_button_pressed_b(): global senseNum senseNum += -1 setSensitivity() input.on_button_pressed(Button.B, on_button_pressed_b)

LED_Y = 0 LED_X = 0 g_force_y = 0 g_force_x = 0 rangeInc = 0 RangeAdj = 0 sensitivity = 0 senseNum = 0 input.set_accelerometer_range(AcceleratorRange.ONE_G) senseNum = 1 setSensitivity()

def on_forever(): global g_force_x, g_force_y, LED_X, LED_Y g_force_x = input.acceleration(Dimension.X) g_force_y = input.acceleration(Dimension.Y) g_force_x += RangeAdj g_force_y += RangeAdj LED_X = int(g_force_x / rangeInc) LED_Y = int(g_force_y / rangeInc) basic.clear_screen() led.plot(LED_X, LED_Y) basic.forever(on_forever) `

The code runs on the Micro:bit, but there are timing problems I don't understand. There are other problems I don't understand either.

a) I can switch back and forth between Block code and JS, but if I switch to Python, it finds 2 errors, and will not switch back to block. The errors seem to be with type conversion in the lines

LED_X = int(g_force_x / rangeInc) LED_Y = int(g_force_y / rangeInc) rangeInc is a floating point number.

The problem I'm having in the way the program runs is in the function setSensitivity() at the top of the code. senseNum is an integer that gets incremented / decremented by the A/B button routines. At the end of the function, I show its value (Basic.show_number), then pause for 500 ms to be able to read it. It works the first time after the reset button is pressed, but after that, it flashes on the screen almost too quickly to read. Why doesn't it stay there for 500 ms?

Also, when I press the buttons, there is a long delay, and sometimes, I can press 3 times at about 1 sec intervals, and nothing happens - then after a few seconds (4, 5 secs) the numbers 6, 5, 4, will flash on the screen. It's a fast microcontroller. I can't imagine where the delay is.

What am I doing wrong?

Jaqster commented 3 years ago

@darzu ?

sutnor commented 3 years ago

Well I looked at the one-word link, but I couldn't find anything that relates to my question. Perhaps you could elaborate a little? I should add that I don't know my way around github - I have been here only a couple of times, and without much success in the past.

martinwork commented 3 years ago

@sutnor, @darzu is a person, to whom your question is being referred. I would be interested to see your original block code. You can get a URL for your project to paste here via the Share button on the MakeCode toolbar.

sutnor commented 3 years ago

Thanks for offering to look at this - but I have resolved it. If you're overwhelmed with work, you can simply mark it resolved, but if you're interested, here's the explanation.

I bought my grandson a Maqueen robotic car for Christmas. It had a V1 Micro:bit in it, and it wasn't long before the USB was connected while it was connected through the edge connector to the car, and it blew up with the "hot chip" issue that is outlined here ... https://www.electronicsweekly.com/blogs/engineer-in-wonderland/microbit-got-hot-chip-issue-2016-09/

I bought another Micro:bit, and this time it was a V2. I believe the bug has been fixed on the V2. Some resolutions were suggested by Electronics Weekly.

I used the V2 for experiments with the Maqueen car (as the V1 didn't work in it), and played with some other programs on the stand-alone card, which still worked on a USB lead, but not from battery or in the car.

The link to my (faulty) block code : https://makecode.microbit.org/_8AWLL8Koz5E5

I loaded this program onto the V1 card initially, and the apparent fault was ... 1) Both button-press routines call "setSensitivity", which ends in two statements, to Show senseNum, then wait 500 mS. My expectation was that it would display the number, and the "pause" would keep it on the screen for half a second - but that didn't work.

2) If the A-button is pressed a lot of times (say 20 times) then wait a while (30 secs, while playing with the "heavy pixel", then press the B-button lots of times (say 15 times) to reduce the sensitivity again, I had expected that sensitivity would reduce too quickly to be noticed, but in fact, it waits a long time ( > 10 secs ) then flashes the numbers on the screen (too fast to see properly), 9, 8, 7, 6, etc, about one number per second, starting only after about 10 seconds. I thought the delay might be due to the pause statement, but I took out out, and got exactly the same result.
[Moment of enlightenment] - Then I loaded the program onto the V2 card, and it behaves differently. I noticed that the right-hand column of pixels flashes random pixels, and I realised it was trying to scroll the numbers - which is also a slow operation. So now, I understand the reason for the delay. i) - The numbers are not displayed because of "clear screen" in the Forever loop.
ii) - The "On Button Pressed" routines are asynchronous with the Forever loop, so they delay the number display operation, but the Clear Screen in the forever loop prevents the numbers from displaying.

I have corrected it now by adding a "screenAvailable" variable, and it works. It is available for anybody that wants it. https://makecode.microbit.org/_iD66fk4yWEK8

Thanks for the instruction to send a link via Share. I may need it in the future.

Regards, sutnor.

martinwork commented 3 years ago

@sutnor I'm glad you found a solution. Yes, "show number" pauses or blocks the instruction sequence. While the button handler is waiting, the forever loop continues... clear screen and plot happen immediately.

While the button A handler is blocked in "show number", further A presses will queue up. The B handler will form it's own separate queue. After pressing AAAAAAABBBBBBB, the Bs will start to appear before some of the As. This makes simple things easy but in the end it's best to avoid blocking operations in the handlers.

I would move the sensitivity display into the forever loop with "screenAvailable" repurposed as "sensitivityChanged", or even move all screen display into a second forever loop, so the mathematical model isn't blocked. The Led block "stop animation" can cancel "show number" to display the latest sensitivity immediately.

martinwork commented 3 years ago

@darzu Switching either blocks example to Python translates the "truncate" blocks as int().

Changing int() to Math.trunc() fixes the errors.