lancaster-university / microbit-samples

http://lancaster-university.github.io/microbit-docs
Other
114 stars 72 forks source link

Interupts, Timer issues #38

Open Salva-OA opened 1 year ago

Salva-OA commented 1 year ago

Do you have any code examples to manage several peripherals without disturbing them?

For instance, if we want to use 2 to 4 wheels (pwm output + quadrature decoder inputs), an ultrasonic distance sensor (echo-trigger), a line-follower (reflected light) add-on, and a 7-segment or matrix-led display (shift-registers) to represent data, plus a remote ble or uart-wifi gamepad ... I mean elements that are time-dependent on their process.

Do you know what the limit on elements we can attach to the v1 micro:bit board is? Is available a possibility to access interrupts, so we can move from the main code to the peripherals processing code?

Last, do you know which sample and hold we could achieve coding with dal, to measure input values, without losing data, or delaying other parts of the model we build with micro:bit v1 arm processor and some expansion boards?

In these examples, could you please explain how to organize the code in files, compile and send into micro:bit board, plus the manner to debug it?

Regards Salva.

Salva-OA commented 1 year ago

In case of splitting the model into two or more micro:bit v1 boards, it would be nice to join them by cable (uart -tx, rx, gnd-; i2c -clk, data, gnd) instead of radio, ... but in this case; Can you give us some examples of how we can buffer the code transmitted between boards to process it in an asynchronously way, or also through an interrupt to manage it right away?

I am thinking this could be the combination of some boards like the enviro:bit to analyze the room environment and another board to move vents and represent values on a I2c 16x2 display.

finneyj commented 1 year ago

Hello @Salva-OA. Wow - that's a lot of questions at once! :)

Generally speaking microbit-dal (and codal-microbit-v2 for micro:bit v2 boards) provide a combination of asynchronous operations and a scheduler to help you achieve these kind of goals. Briefly answering each of your questions in turn:

PWM: micro:bit v1 has (if I recall correctly!) three hardware PWM channels. Each of these channels share a core frequency, but can have their own duty cycle. Take a look here: MicroBitPin::setAnalogValue(). As these are hardware PWMs, you won't see any contention related side effects.

Ultrasonic sensor. Assuming you're using something like an SRF04, you just need to measure the length of a pulse. There are also interrupt driven APIs that will sample and hold this for you. See https://lancaster-university.github.io/microbit-docs/ubit/io/#eventon. This API was a bit on the edge with microbit v1, but was accurate provided the pulse was about 50uS or longer in length. v2 perfoms much better.

line-following: I guess this is just GPIO interface? If so, again, using the same API as above will get you a long way. Note you can use the MessageBus to create asynchronous callbacks, as described here: https://lancaster-university.github.io/microbit-docs/ubit/messageBus/. Note also if you really want your callback to be triggered in an interrupt context, adding the MESSAGE_BUS_IMMEDIATE flag at the end of your call to listen() will have that effect. Take care though - it's MUCH safer to use the default settings, which run your callback in a thread context. Most DAL calls are NOT safe to execute from an interrupt context.

7 segment display/shift register: General purpose output is not really real-time on v I'm afraid. micro:bit V2 does provide support for a hardware accelerated pulse train to be generated, but there is no equivalent support on a V1. it may be possible to set up a GPIOTE channel to do that, but we're pretty short on hardware timers on V1 too... A 7 segment shift register isn't normally very time critical though... so perhaps you would be fine to just use the normally GPIO outputs? https://lancaster-university.github.io/microbit-docs/ubit/io/#setdigitalvalue

There's no hard limit on he number of peripherals you can add, but I imagine you might run out of GPIO pins if you're not careful. Check here to make sure you have enough for your application: https://lancaster-university.github.io/microbit-docs/ubit/io

The micro:bit dal / CODAL build system will compile any and all .cpp and .h files it finds in the source folder. So it's completely up to you how to arrange them into different code modules if you wish to do so. There are no explicit constraints there beyond the normal C/C++ expectations.

There is a hardware UART that can be configured to be connected to the edge connector pins. There is also a built-in character buffer that means your software does not need to react quickly to single character inputs. See the documentation here: https://lancaster-university.github.io/microbit-docs/ubit/serial. I think the https://lancaster-university.github.io/microbit-docs/ubit/serial/#int-read-microbitserialmode-mode function is probably the one you need.

Building and debugging is described on the README on this repo https://github.com/lancaster-university/microbit-samples/ It is worth noting that the yotta build tool is no longer supported by Arm. We do have an action to replace that with same one we use for micro:bit v2. If you have issues getting yotta to run, do let us know and we'll try to expedite that.

Bluetooth is however, a different story when it comes to soft real-time behaviour. Bluetooth is enabled on micro:bit by Nordic's SoftDevice stack. This runs at the highest level of interrupt priority... and interrupts can sometimes take a long time to complete. Therefore, do expect all the systems I describe above to act less predictably once BLE is enabled...

I hope this helps a little @Salva-OA. Good luck with your development.

--Joe

Salva-OA commented 1 year ago

Thanks a lot, Joe. I will study your links