Embedded Programming
Task:
Group assignment:
- Browse through the datasheet for your microcontroller
- Compare the performance and development workflows for other architectures
- Document your work to the group work page and reflect on your individual page what you learned
The group assignment for this week is here.
Individual assignment:
- Write a program for a microcontroller development board to interact (with local input &/or output devices) and communicate (with remote wired or wireless devices)
Reading a Hall effect sensor
I started programming by using the Arduino IDE. You download, then from within it (Boards Manager
) you download the board support package for your particular platform. For the Barduino, it's "esp32 by Expressif Systems". I had problems with the latest version because some libraries are not updated to be compatible, so I had to downgrade to 2.0.11:
Then you connect your board, write your code and you hit "upload" (Cmd-u in mac). The Barduino needs to have "USB CDC on boot" enabled in the Tools menu for Serial communication to show up in the Serial Monitor.
Adai gave me a Hall effect sensor module. It has the Hall effect sensor 44E 402.
After some trial and error plus googling I managed to get it working:
The Hall sensor detects reliably the magnet when it's under ~5mm of distance. It detects it only in one orientation.
The sketch hall_effect_sensor.ino
reads the Hall effect sensor as many times as possible and counts the number of readings in an interface update cycle (0.1s). With that, I'm getting around 20,000 analogRead
s per second:
void setup() {
pinMode(HALL_SENSOR_PIN, INPUT);
Serial.begin(115200);
Serial.println("Ready to go!");
start = millis();
step = 0;
detections = 0;
}
void loop() {
now = millis();
read();
detections += reading;
if (now - start > 1000.0 / HZ) {
step += 1;
start = now;
if (step % (HZ / INTERFACE_HZ) == 0) {
show();
detections = 0;
}
}
}
(The read()
function is just an analogRead and the show()
is just a couple of Serial.println
s)
Is this enough to detect reliably a magnet as it passes in front of a sensor in a bicycle wheel? We'll see in inputs week!
MicroPython
Very cool! You can have an interactive session running on the board itself, and change values on the fly without recompiling and sending. I think it can be really useful
Downside is there's many fewer libraries and community for it, compared to Arduino.
We used Thonny to code and upload to the microcontroller. It was easy to set up. I installed in a new conda
environment:
conda create -n thonny
conda activate thonny && conda install pip && pip install thonny
And then it's run with:
conda activate thonny && thonny &
To set up the board:
1. Open Thonny preferences
2. Go to the Interpreter
tab
3. Choose RP2040 (for the QuenTorres)
4. Click "Install or update MicroPuthon"
* If it doesn't allow you to flash the board, set it on bootloader mode.
I loved having an interactive session open in the controller and being able to get instantaneous feedback on my attempts, as opposed to the ~15s when compiling Arduino code.
I took the opportunity to play around with the buzzer in the Barduino:
Imperial March in Barduino. Click to show code.
from machine import Pin, PWM
import time
# https://micropython-on-wemos-d1-mini.readthedocs.io/en/latest/basics.html#beepers
c = 262
d = 294
e_f = 311
e = 330
f = 349
g = 392
a = 440
b = 494
C = 523
buzzer_pin = Pin(14, Pin.OUT)
led_pin = Pin(48, Pin.OUT)
buzzer = PWM(buzzer_pin, freq=e, duty=512)
tempo = 112
blank_space = .05
melody = [(e, 4),
(e, 4),
(e, 4),
(c, 3),
(g, 1),
(e, 4),
(c, 3),
(g, 1),
(e, 8),
(b, 4),
(b, 4),
(b, 4),
(C, 3),
(g, 1),
(e_f, 4),
(c, 3),
(g, 1),
(e, 4),
(c, 3),
(g, 1),
(f, 8)]
for tone, duration in melody:
print(f'tone:{tone} duration:{duration}')
# buzzer.freq(tone)
PWM(buzzer_pin, freq=tone, duty=512)
led_pin.value(1)
time.sleep((60 / tempo) * duration / 4 - blank_space)
buzzer.duty(0)
led_pin.value(0)
time.sleep(blank_space)
File can be found here
Programming the QuenTorres
I wrote a small videogame for the QuenTorres. The objective is to make the LED blink as fast as possible without going over a limit. The LED speeds up when you hold the button down and slows down when you release. The game is over when it goes over 100Hz or under 1Hz.
The way I do that is by setting an initial delay of 250ms. In each turn of the while
loop, if the button is pressed, I reduce that delay time by a factor of 1.2. If it's not, I increase it. When duration
goes under 10ms or over 1000ms, we fall out of the while loop and the game is restarted (we go to another iteration of the main loop).
QuenTorres Blink game code. Click to show code.
int buttonState;
int LED = D0;
int BUTTON = D1;
float changeFactor = 1.2;
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT);
Serial.begin(115200);
}
void loop() {
int duration = 250;
int buttonState = digitalRead(BUTTON);
while (duration > 10 && duration < 1000) {
digitalWriteFast(LED, HIGH);
delay(duration);
digitalWriteFast(LED, LOW);
delay(duration);
int buttonState = digitalRead(BUTTON);
if (buttonState) {
duration /= changeFactor;
} else {
duration *= changeFactor;
}
Serial.print(buttonState);
Serial.print(", ");
Serial.println(duration);
}
}
It plays like this:
Disregard the trace patch! My fix from week 4 gave out.
Questions
- How do you handle it if different boards you are using require different, conflicting, library versions?
- Can you write a C function and call it from MicroPython?
References
https://docs.platformio.org/en/stable/tutorials/espressif32/arduino_debugging_unit_testing.html https://forum.arduino.cc/t/how-do-i-use-this-hall-sensor-44e-402/328142/6 https://forum.arduino.cc/t/how-do-i-use-this-hall-sensor-44e-402/328142/6 https://maker.pro/arduino/tutorial/how-to-use-a-hall-effect-sensor-with-arduino