mirror of
https://gitlab.waag.org/make/fablab/interns/2025/sam.git
synced 2025-08-04 04:14:56 +00:00
repo cleanup + MCU lectures 13-02-2025
This commit is contained in:
BIN
docs/Assignments/week_4_programming/image-1.png
Normal file
BIN
docs/Assignments/week_4_programming/image-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
BIN
docs/Assignments/week_4_programming/image-2.png
Normal file
BIN
docs/Assignments/week_4_programming/image-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
BIN
docs/Assignments/week_4_programming/image.png
Normal file
BIN
docs/Assignments/week_4_programming/image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 201 KiB |
158
docs/Assignments/week_4_programming/lecuteNotes.md
Normal file
158
docs/Assignments/week_4_programming/lecuteNotes.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Lecture notes
|
||||
## Architecture
|
||||
RISC-V (Reduced instruction set)
|
||||
Use EEPROM to save configuration or other things (easy to write to from program)
|
||||
FLASH (harder to write to)
|
||||
|
||||
|
||||
## Microcontrollers
|
||||
* AVR
|
||||
* ARM
|
||||
|
||||
RP2040
|
||||
With PIO you can create custom periphirals
|
||||
|
||||
## Programming
|
||||
Python recommended but I'm using C++ anyway.
|
||||
Rust is also usable but very hard to set up.
|
||||
|
||||
bootloader, Program to load programs
|
||||
|
||||
Arduino
|
||||
board + toolchain + libraries + IDE + bootloader + Header programming
|
||||
|
||||
|
||||
Simulation: WowKi
|
||||
tinkercircuit
|
||||
|
||||
|
||||
this week:
|
||||
Browse through the datasheet of your microcontroller
|
||||
write a program for a microcontroller
|
||||
simulate it.
|
||||
|
||||
try multiple dev environments
|
||||
|
||||
## Lecture notes local thursday
|
||||
|
||||
First C got introduced and then 20 years ago C++ got introduced. And the arduino IDE by a clever italian.
|
||||
|
||||
LED's blink at 400-600 Terahertz humans can't see that but chickens can.
|
||||
Micropython can't run on every microcontroller
|
||||
C++ runs on anything
|
||||
Rust isn't matured enough for microcontrollers and embedded
|
||||
|
||||
|
||||
sending code to the avr microcontrollers
|
||||
`avrdude`
|
||||
|
||||
You can run AVR's without bootloader's
|
||||
|
||||
Arduino bootloader connects the board to the arduino software.
|
||||
|
||||
The bus in a microcontroller is a data highway
|
||||
I2C multiplexer. Can add more pins to a microcontroller using I2C or you can add several devices with the same address.
|
||||
ADC - analog digital convertor
|
||||
DAC - digital analog converter
|
||||
|
||||
In the past 5 volt was used. Nowadays a lot of 3.3 volt is used.
|
||||
|
||||
Always add a LED on a custom board.
|
||||
|
||||
Arduino uno made 20 years ago.
|
||||
|
||||
PlatformIO
|
||||
|
||||
### RP2040
|
||||
Add the board library to the arduino boards manager.
|
||||
`File > Prefrences > additional boards url's`
|
||||
then add it in this link. `https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json`
|
||||
Then you can select the board in the connect menu and then it installs the toolchain.
|
||||
|
||||
|
||||
comment in your code. Comment why it works.
|
||||
|
||||
What happens when you press compile and upload
|
||||
`Starts compiling > Starts linking > opens communication with microcontroller > uploads firmware > done`
|
||||
|
||||
|
||||
basic arduino commands
|
||||
* digitalWrite(pin, LOW/HIGH)
|
||||
|
||||
|
||||
One of the most used things. Pulse Width Modulation (PWM).
|
||||
|
||||
Current flows from high to low
|
||||
|
||||
Connecting a LED using the microcontroller as a ground is better but it also reverses the programming LOW and HIGH.
|
||||
It's better because it can handle more power when it is the ground of the led
|
||||
|
||||
## PlatformIO + vscode
|
||||
|
||||
benefits using vscode
|
||||
* Intellisense
|
||||
* Git in the editor
|
||||
|
||||
First create new project
|
||||
|
||||
Then you can select the MCU and the framework
|
||||
|
||||
### For unsupported boards:
|
||||
Click the nearest board. And follow the community instructions
|
||||
|
||||
|
||||
Change platformio.ini
|
||||
from
|
||||
```ini
|
||||
[env:pico]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
board = pico
|
||||
framework = arduino
|
||||
board_build.core = earlephilhower
|
||||
```
|
||||
|
||||
to
|
||||
```ini
|
||||
[env]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
framework = arduino
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
[env:seeed_xiao_rp2040]
|
||||
board = seeed_xiao_rp2040
|
||||
```
|
||||
### What is every folder
|
||||
* src - for source code
|
||||
* lib - project specific libraries
|
||||
|
||||
### How to add libraries
|
||||
Click the platformIO icon
|
||||
Then click the libraries button
|
||||
Then you can search a library and click add to project.
|
||||
|
||||

|
||||
|
||||
After that it will edit platformio.ini and there you will see the library added to the project. It's also in `.pio/libdeps`
|
||||
|
||||
## Micropython
|
||||
With micropython an OS is installed.
|
||||
You can get the firmware for here. https://micropython.org/download/RPI_PICO/
|
||||
|
||||
To upload the firmware you need to connect it to your laptop and set the microcontroller in boot mode by pressing: hold boot > click reset > release boot. Now it will appear on your laptop as a drive. Now you can delete the old UF2 file and drop in the new micropython firmware. It should automaticly unmount itself and start the micropython firmware.
|
||||
|
||||
Now if you install the Raspberry Pi Pico package on vscode you can create a new project and once the project is created and you've connected the microcontroller. A new project will pop up with a terminal under it.
|
||||
|
||||

|
||||
|
||||
`Control + Shift + P` in vscode
|
||||
|
||||

|
||||
|
||||
Make sure the file is named boot.py otherwise it won't start when the microcontroller gets power.
|
||||
|
||||
Pulseview - to view .vcd files from logic analysers
|
||||
|
||||
## Very important
|
||||
On linux machines you need to install platformio-udev. Otherwise you can't upload to your board.
|
||||
|
||||
|
153
docs/Assignments/week_4_programming/programming.md
Normal file
153
docs/Assignments/week_4_programming/programming.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Embedded programming
|
||||
|
||||
## Introduction
|
||||
I'm very familiar with coding in C++ because of my university. At the moment im studying computer sciences at the Applied University of Amsterdam.
|
||||
|
||||
## First code before deciding to using existing code
|
||||
I first wanted to create the drone firmware myself. But then I looked through some research papers and existing programs and saw all the math that was needed to keep it upright. Then I decided to modify an existing program.
|
||||
This was my first attempts at getting the sensor to read
|
||||
|
||||
### Issues with old code
|
||||
|
||||
### Using the wrong library for the BNO085
|
||||
First used the wrong library I used the Adafruit bno0xx library instead of the Sparkfun bno08x library. The Example script below this reads the BNO085 sensor and returns the values in the arduino serial console.
|
||||
|
||||
??? failure
|
||||
|
||||
```cpp
|
||||
#include "conf.h"
|
||||
#include <Adafruit_BNO08x.h>
|
||||
#include <sh2.h>
|
||||
#include <sh2_SensorValue.h>
|
||||
#include <sh2_err.h>
|
||||
#include <sh2_hal.h>
|
||||
#include <sh2_util.h>
|
||||
#include <shtp.h>
|
||||
|
||||
Adafruit_BNO08x bno08x(BNOINTERRUPTSIG);
|
||||
sh2_SensorValue_t sensorValue;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("setup started");
|
||||
// Setup all ESC
|
||||
// ledcAttach(MOTOR1, PWMFREQ, PWMRESOLUTION);
|
||||
// ledcAttach(MOTOR2, PWMFREQ, PWMRESOLUTION);
|
||||
// ledcAttach(MOTOR3, PWMFREQ, PWMRESOLUTION);
|
||||
// ledcAttach(MOTOR4, PWMFREQ, PWMRESOLUTION);
|
||||
Serial.print("Setup Started");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
sleep(3)
|
||||
if (!bno08x.begin_I2C()) {
|
||||
Serial.println("Failed to find BNO08x chip");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Game Rotation Vector - r: ");
|
||||
Serial.print(sensorValue.un.gameRotationVector.real);
|
||||
Serial.print(" i: ");
|
||||
Serial.print(sensorValue.un.gameRotationVector.i);
|
||||
Serial.print(" j: ");
|
||||
Serial.print(sensorValue.un.gameRotationVector.j);
|
||||
Serial.print(" k: ");
|
||||
Serial.println(sensorValue.un.gameRotationVector.k);
|
||||
}
|
||||
|
||||
//https://randomnerdtutorials.com/esp32-pwm-arduino-ide/
|
||||
//https://github.com/adafruit/Adafruit_BNO08x/blob/master/examples/rotation_vector/rotation_vector.ino#L25
|
||||
```
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
#include <SparkFun_BNO080_Arduino_Library.h>
|
||||
#include <Wire.h>
|
||||
#include "conf.h"
|
||||
|
||||
BNO080 myIMU;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("setup started");
|
||||
// Setup all ESC
|
||||
// ledcAttach(MOTOR1, PWMFREQ, PWMRESOLUTION);
|
||||
// ledcAttach(MOTOR2, PWMFREQ, PWMRESOLUTION);
|
||||
// ledcAttach(MOTOR3, PWMFREQ, PWMRESOLUTION);
|
||||
// ledcAttach(MOTOR4, PWMFREQ, PWMRESOLUTION);
|
||||
Serial.print("Setup Started");
|
||||
|
||||
Wire.begin();
|
||||
myIMU.begin();
|
||||
Wire.setClock(400000); //Increase I2C data rate to 400kHz
|
||||
myIMU.enableRotationVector(50); //Send data update every 50ms}
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
if (myIMU.dataAvailable() == true) {
|
||||
float roll = (myIMU.getRoll()) * 180.0 / PI; // Convert roll to degrees
|
||||
float pitch = (myIMU.getPitch()) * 180.0 / PI; // Convert pitch to degrees
|
||||
float yaw = (myIMU.getYaw()) * 180.0 / PI; // Convert yaw / heading to degrees
|
||||
|
||||
Serial.print(roll, 1);
|
||||
Serial.print(F(","));
|
||||
Serial.print(pitch, 1);
|
||||
Serial.print(F(","));
|
||||
Serial.print(yaw, 1);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
void calibrateESC() {
|
||||
ledcWrite(MOTOR1, 1100);
|
||||
ledcWrite(MOTOR2, 1100);
|
||||
ledcWrite(MOTOR3, 1100);
|
||||
ledcWrite(MOTOR4, 1100);
|
||||
}
|
||||
|
||||
//https://randomnerdtutorials.com/esp32-pwm-arduino-ide/
|
||||
//https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/blob/main/examples/Example24-UncalibratedGyro/Example24-UncalibratedGyro.ino
|
||||
```
|
||||
|
||||
## New driver
|
||||
After researching for a while and looking through other fab academy projects I found out that other people also made drones with micro controllers and used a pre-made driver that they customized (https://fab.cba.mit.edu/classes/863.23/Architecture/people/Zhixing/finalproject.html). After doing some research on how to keep the drone upright I also decided to use an existing driver because the math required for that is way above my level. Im gonna be using the [dRhemFlightVTOL](https://github.com/nickrehm/dRehmFlight/tree/master) driver. The only problem is that it doesn't support my Inertial measuring unit (BNO085). So I will have to customize the driver to make it work with it.
|
||||
|
||||
### Implementing the BNO085
|
||||
|
||||
### Hijacking the controls
|
||||
I need to reverse engineer the controls because now it just calls a function called radiocontrols() that manages the controls. There are 4 pwm channel that controls where the drone is going. I wanna make my own controller and simulate these pwm signals.
|
||||
```cpp
|
||||
thro_des = (channel_1_pwm - 1000.0) / 1000.0; // Between 0 and 1
|
||||
roll_des = (channel_2_pwm - 1500.0) / 500.0; // Between -1 and 1
|
||||
pitch_des = (channel_3_pwm - 1500.0) / 500.0; // Between -1 and 1
|
||||
yaw_des = (channel_4_pwm - 1500.0) / 500.0; // Between -1 and 1
|
||||
```
|
||||
From looking further in the code it has safety protocols when the channels go too low or too high so using that we have a range where the pwm speed should be.
|
||||
|
||||
```cpp
|
||||
// Triggers for failure criteria
|
||||
// Line 1260
|
||||
if (channel_1_pwm > maxVal || channel_1_pwm < minVal)
|
||||
check1 = 1;
|
||||
if (channel_2_pwm > maxVal || channel_2_pwm < minVal)
|
||||
check2 = 1;
|
||||
if (channel_3_pwm > maxVal || channel_3_pwm < minVal)
|
||||
check3 = 1;
|
||||
if (channel_4_pwm > maxVal || channel_4_pwm < minVal)
|
||||
check4 = 1;
|
||||
if (channel_5_pwm > maxVal || channel_5_pwm < minVal)
|
||||
check5 = 1;
|
||||
if (channel_6_pwm > maxVal || channel_6_pwm < minVal)
|
||||
check6 = 1;
|
||||
```
|
||||
In this case minVal is 800 an maxVal is 2200. So we need to stay between these ranges to control the drone. In theory you can send any value to the ESC because it calibrates to the lowest and highest values you give it but there is a range. From past experiences I have experienced that 12bit PWM is not sufficient, 16 bit is needed.
|
||||
|
||||
[ESC calibration](https://ardupilot.org/copter/docs/esc-calibration.html)
|
||||
|
||||
#### Attaching the esc's to the correct pin.
|
||||
|
Reference in New Issue
Block a user