5. Embedded Programming¶
This week is all about embedded programming. Most of the work here is programming and simulation in Wokwi, I decided I’d give Arduino on the RP2040 a try. I’ve done plenty of Python before but C++ is something I haven’t touched in a while so I figured it’d be a nice change of pace.
Things to do: - Browsed and document information from the microcontroller’s datasheet - Programmed and simulated board to interact and communicate - Describe the programming processess(es) used - Include source ode - Include ‘hero shot(s)
Hero Shot¶
It spins! Check the Serial printout at the bottom.
RP2040 Datasheet¶
I’ve had to read datasheets for things before, But this gargantuan 636 page beast was a new undertaking. Obviously I won’t be reading the whole thing as I don’t think I’ll be able to comprehend half of it. But it’s good to know where to find information when needed.
Here’s what I interpret as most important to know:
- The RP2040 has two ARM Cortex-M0+ processors. ARM is an architecture most commonly used in modern smartphones and some laptops/desktops (Mostly Apple M-series and Qualcomm Snapdragon X machines)
- It has USB hardware support.
- 264kB of SRAM
- a 4 channel Analog to Digital Converter (ADC) with internal temperature sensor. (Full name: “Successive Approximation Register Analogue to Digital Converter) The ADC can sample 48MHz at 12 bit depth.
- Plenty of PIO, (57 pages worth)
- Plenty of Peripheral support, (A breezy 227 pages)
Reading through this is daunting but it’s surprisingly easy to get caught up in detailed descriptions and it’s surprisingly legible. I don’t understand what a DMA Controller Interface stricly is but I do like reading about the RP2040’s burst transaction length on the SSI’s DMA interface being fixed to four transfers.
There’s a good chance I’ll be bashing my head against this datasheet more in the future.
Seeed Studio Xiao RP2040¶
The RP2040 board I have on hand is a Seeed Studio Xiao Rp2040, Doing a quick read-through of the “Getting Started” page on the seeedstudio wiki.
Specifications from the Wiki:
Item | Value |
---|---|
CPU | Dual-core ARM Cortex M0+ processor up to 133 MHz |
Flash Memory | 2MB |
SRAM | 264KB |
Digital I/O Pins | 11 |
Analog I/O Pins | 4 |
PWM Pins | 11 |
I2C Interface | 1 |
SPI Interface | 1 |
UART Interface | 1 |
Power supply and downloading interface | Type-C |
Power | 3.3V/5V DC |
Dimensions | 21x17.8x3.5mm |
Notes: - The Digital I/O Pins double as PWM. - I2C is a controller used for intra-board communication - SPI(System Packet INterface) is used for Serial network communication between ICs - UART(Universal Asynchronous receiver-transmitter) - Voltage input to pins is 3.3V, Exceeding this can cause chip damage - The built-in DC-DC converter circuit can change 5V to 3.3V to power the device via VIN-PIN and 5V-PIN - These pins can be used to power it using a battery.
Here’s the pinout:
Wokwi¶
Starting off in Wokwi was surprisingly easy. I looked around the demo projects untiL I found this one made by Uri Shaked. The program is fairly simple, It has an A4988 Stepper Motor Driver and Stepper. The driver is connected from DIR to GP2 on the RP2040 and STEP to GP3. DIR controls the direction and each pulse from HIGH to LOW on STEP equals one step or 1/200th of a full rotation. The program itself loops through 200 steps clockwise before waiting and then doing 200 steps counterclockwise. I decided to modify this by adding a button to control it and printing relevant info like how many steps were taken and when the button was pressed and released.
Here’s the original demo code:
// Raspberry Pi Pico + Stepper Motor Example
#define DIR_PIN 2
#define STEP_PIN 3
void setup() {
pinMode(STEP_PIN, OUTPUT);
pinMode(DIR_PIN, OUTPUT);
digitalWrite(STEP_PIN, LOW);
}
void loop() {
// Move 200 steps (one rotation) CW over one second
digitalWrite(DIR_PIN, HIGH);
for (int i = 0; i < 200; i++) {
digitalWrite(STEP_PIN, HIGH);
digitalWrite(STEP_PIN, LOW);
delay(5); // 5 ms * 200 = 1 second
}
delay(500); // Wait half a second
// Move 200 steps (one rotation) CCW over 400 millis
digitalWrite(DIR_PIN, LOW);
for (int i = 0; i < 200; i++) {
digitalWrite(STEP_PIN, HIGH);
digitalWrite(STEP_PIN, LOW);
delay(2); // 2 ms * 200 = 0.4 seconds
}
delay(1000); // Wait another second
}
and here’s the diagram:
Connecting the button¶
Adding the button was simple, I defined Pin 4 as the button pin using INPUT_PULLUP to enable the internal pull-up resistor to “clean” up the signal (Limiting it to HIGH or LOW). PIN 4 to button and button to GND.
My modified diagram:
The Code¶
I haven’t touched C++ in quite a while so this was surprisingly challenging. The hardest part was getting the program to only print “Pushed!” once if the button was held for multiple cycles. This required creating a boolean to track whether the button was pushed and only changing it once the button is lifted. I also made the program print out how many steps it’s taking per loop. (200). I commented everything as I went.
Here’s the full program:¶
// Raspberry Pi Pico + Stepper Motor Example by Uri Shaked
// Modified by Magnús Pétursson
#define DIR_PIN 2 // Defines the pin controlling direction as 2
#define STEP_PIN 3 // Defines the pin controlling the step count as 3
#define BUTT_PIN 4 // Defines the button as pin 4
void setup() { //Runs all the following once:
pinMode(DIR_PIN, OUTPUT); //Sets DIR_PIN as an output.
pinMode(STEP_PIN, OUTPUT); //Sets STEP_PIN as an output.
pinMode(BUTT_PIN, INPUT_PULLUP); // Sets BUTT_PIN as an input, "INPUT_PULLUP" enables the internal pull-up resistor.
// The Internal Pull-up resistor makes sure the signal is HIGH when the button is not pushed and LOW when pushed.
digitalWrite(STEP_PIN, LOW); // Makes sure STEP_PIN starts on LOW, Stepper motors always go from LOW to HIGH per step.
Serial.begin(115200); //Sets Serial Baud Rate
}
boolean WasPushed = false; //Sets "WasPushed" to false. This helps prevent multiple "Pushed!" printouts while holding down the button.
void loop() { //The main loop of the program.
if (digitalRead(BUTT_PIN) == LOW) { //Checks if the BUTT_PIN input is LOW
if (!WasPushed){ // If the "WasPushed" is false, Print "Pushed!"
Serial.println("Pushed!");
}
WasPushed = true; //sets "WasPushed" to true. This prevents multiple printings of "Pushed!" while holding down the button.
digitalWrite(DIR_PIN, HIGH); //Sets the Direction pin to HIGH, Meaning Clockwise.
int steps = 0; //Defines a step counter
for (int i = 0; i < 200; i++) { // repeats for increment step of "steps" up to 200, sending 200 pulses to the stepper.
digitalWrite(STEP_PIN, HIGH); // sets step pin to HIGH, Finishing the first step defined in the setup.
digitalWrite(STEP_PIN, LOW); // sets step pin to LOW, Starting another step.
steps++; //increments step counter by one.
delay(5); // 5ms delay to help Wokwi.
}
Serial.print("Steps Taken: "); //prints "Steps Taken: " into current line
Serial.println(steps); // prints the value of "steps" into the line then starts a new line.
if (digitalRead(BUTT_PIN) == HIGH && WasPushed){ //Checks if the button is released and whether "WasPushed" is True.
Serial.println("Released!"); //Prints "Released!"
WasPushed = false; //Resets "WasPushed" to prepare for next loop.
}
}
}
Group Assignment:¶
Here is this week’s group assignment page. I played around with Arduino/C++ on the Seeed Xiao RP2040. This proved surprisingly difficult.