4. Embedded Programming¶
Assignment for week 4:¶
- Group Assignment
-
Demonstrate and compare the toolchains and development workflows for available embedded architectures
-
individual assignment
- Browse through the data sheet for your microcontroller
-
write a program for a microcontroller,and simulate its operation, to interact (with local input &/or output devices) and communicate (with remote wired or wireless connections)
-
extra credit:
- test it on a development board
- try different languages &/or development environments
Group Assignment Highlights¶
We try to understand the difference between Von Neuman and Harvard Computer Architecture. Then we explore the differences between the microcontroller and microprocessor followed by trying to program some development board available in our lab.
Von Neumann and Harvard Architecture - Von Neumann Architecture: Proposed by John von Neumann, this architecture uses a single bus for both data and instructions, meaning that the CPU fetches both data and instructions from the same memory space. This design simplifies the structure but can lead to the “von Neumann bottleneck,” where the shared bus limits the speed of data transfer.
- Harvard Architecture: In contrast, Harvard Architecture uses separate buses for data and instructions, allowing simultaneous access to both. This improves performance and is commonly used in embedded systems and digital signal processing (DSP) where speed and efficiency are critical.
Difference Between Microcontroller and Microprocessor - Microprocessor: A microprocessor is the central processing unit (CPU) of a computer, designed to perform arithmetic and logic operations. It requires external components like memory, input/output interfaces, and peripherals to function. Microprocessors are used in general-purpose computing devices like PCs and laptops.
- Microcontroller: A microcontroller integrates a CPU with memory, input/output peripherals, and other components on a single chip. It is designed for specific tasks and is commonly used in embedded systems like appliances, automotive systems, and IoT devices. Microcontrollers are more compact, cost-effective, and power-efficient compared to microprocessors.
Here is the link to our group assignment.
List of the development board that I will be exploring.¶
i. ESP32
ii. Arduino
iii. Xiao RP2040
iv. Adafruit circuit Playground
i. ESP32¶
Exploring ESP32 data sheet
ESP32 is a series of powerful, power-efficient, cheap microcontrollers that come with integrated Wi-Fi and dual-mode Bluetooth.
Specifications:
- Xtensa dual-core (or single-core) 32-bit LX6 microprocessor, running at 160 or 240 MHz
- Memory: 520 KB SRAM
- Wi-Fi: 802.11 b/g/n
- Bluetooth: v4.2 BR/EDR and BLE
- 12-bit × 18 ADC channels
- 2 × 8-bit DACs
- 10 × touch sensors (capacitive sensing GPIOs)
- 4 × SPI
- 2 × I²S interfaces
- 2 × I²C interfaces
- 3 × UART
- SD/SDIO/CE-ATA/MMC/eMMC host controller
- SDIO/SPI slave controller
- CAN bus 2.0
- Infrared remote controller (TX/RX, up to 8 channels)
- Motor PWM
- LED PWM (up to 16 channels)
- Hall effect sensor
- Ultra-low-power analog pre-amplifier
- All security features of IEEE 802.11 standard, like WFA, WPA/WPA2, and WAPI, secure boot, Flash encryption
- Cryptographic hardware acceleration methods like AES, SHA-2, RSA, elliptic curve cryptography (ECC), random number generator (RNG)
Pinout of ESP32
Supported Development Environments - Arduino IDE: Official support via ESP32 board package.
-
PlatformIO: Supports ESP32 with multiple frameworks (Arduino, ESP-IDF, etc.).
-
ESP-IDF (Espressif IoT Development Framework): Official framework for ESP32, used with VS Code or Eclipse.
-
MicroPython: Supports ESP32 for Python-based development.
-
Lua (NodeMCU firmware): Lua scripting for ESP32.
-
Zerynth: Python-based IoT framework for ESP32.
-
Rust: Rust programming language support via esp-hal.
ii. Arduino¶
*Exploring Arduino Uno data sheet
The Arduino UNO R3 is the perfect board to get familiar with electronics and coding. This versatile development board is equipped with the well-known ATmega328P and the ATMega 16U2 Processor.
Specifications:
- ATMega328P Processor
Memory
- AVR CPU at up to 16 MHz
- 32 kB Flash
- 2 kB SRAM
- 1 kB EEPROM
Security
- Power On Reset (POR)
- Brown Out Detection (BOD)
Peripherals
- 2x 8-bit Timer/Counter with a dedicated period register and compare channels
- 1x 16-bit Timer/Counter with a dedicated period register, input capture and compare channels
- 1x USART with fractional baud rate generator and start-of-frame detection
- 1x controller/peripheral Serial Peripheral Interface (SPI)
- 1x Dual mode controller/peripheral I2C
- 1x Analog Comparator (AC) with a scalable reference input
- Watchdog Timer with separate on-chip oscillator
- Six PWM channels
- Interrupt and wake-up on pin change
ATMega16U2 Processos
- 8-bit AVR® RISC-based microcontroller
Memory
- 16 kB ISP Flash
- 512B EEPROM
- 512B SRAM
- debugWIRE interface for on-chip debugging and programming
Power
- 2.7-5.5 volts
Pinout of Arduino Uno
Supported Development Environments - Arduino IDE: Official and most widely used environment.
-
PlatformIO: Supports Arduino boards with additional features.
-
Visual Studio Code (with Arduino extension): Alternative to Arduino IDE.
-
Proteus: Simulation and development for Arduino.
-
Atmel Studio: Advanced development for AVR-based Arduino boards.
-
MicroPython: Limited support for some Arduino boards.
-
MATLAB/Simulink: For model-based design and simulation.
iii. Xiao RP2040¶
Exploring Xiao RP2040 Datasheet
The Seeed Studio XIAO RP2040 is as small as the Seeed Studio XIAO SAMD21 but it’s more powerful. On one hand, it carries the powerful Dual-core RP2040 processor that can flexible clock running up to 133 MHz which is a low-power microcontrollers. On the Seeed Studio XIAO RP2040 there is also 264KB of SRAM, and 2MB of on-board Flash memory which can provide more program to save and run. On the other hand, this little board has good performance in processing but needs less power. All in all, it is designed in a tiny size as small as a thumb(21x17.8mm) and can be used for wearable devices and small projects.
Specifications:
i. CPU: Dual-core ARM Cortex M0+ processor up to 133MHz
ii. Flash Memory: 2MB
iii. SRAM: 264KB
iv. Digital I/O Pins: 11
v. Analog I/O Pins: 4
vi. PWM Pins: 11
v. I2C interface: 1
vi. SPI interface: 1
vii. UART interface: 1
viii. Power supply and downloading interface: Type-C
ix. Power: 3.3V/5V DC
x. Dimensions: 21×17.8×3.5mm
Pinout for Xiao RP2040
Supported Development Environments
-
Arduino IDE: Supported via the RP2040 core.
-
PlatformIO: Supports RP2040-based boards like Xiao RP2040.
-
MicroPython: Officially supported for RP2040.
-
CircuitPython: Adafruit’s fork of MicroPython, supported for RP2040.
-
C/C++ SDK (Raspberry Pi Pico SDK): Official SDK for RP2040, usable with VS Code or other IDEs.
-
Rust: Rust support for RP2040 via rp-hal.
iv. Adafruit¶
Exploring data sheet for Adafruit
Specifications:
- ATmega32u4 Processor, running at 3.3V and 8MHz
- MicroUSB port for programming and debugging with Arduino IDE
- Has built-in USB support
- 10 x mini NeoPixels, each one can display any rainbow color
- 1 x Motion sensor (LIS3DH triple-axis accelerometer with tap detection, free-fall detection)
- 1 x Temperature sensor (thermistor)
- 1 x Light sensor (phototransistor)
- 1 x Sound sensor (MEMS microphone)
- 1 x Mini speaker (magnetic buzzer)
- 2 x Push buttons, left and right
- 1 x Slide switch
- 8 x alligator-clip friendly input/output pins
- Includes I2C, UART, and 4 pins that can do analog inputs/PWM output
- All 8 pads can act as capacitive touch inputs
- Green "ON" LED so you know its powered
- Red "#13" LED for basic blinking
- Reset button
Pinout of Adafruit Circuit Playground
Supported Development Environments - Arduino IDE: Supported via Adafruit board package.
-
CircuitPython: Adafruit’s official Python-based environment.
-
MakeCode: Block-based and JavaScript programming by Microsoft.
-
PlatformIO: Supports Circuit Playground with Arduino framework.
-
MicroPython: Limited support for Circuit Playground boards.
I want to explore the following list of simulator¶
i. Wokwi
ii. Tinkercad
iii. Adafruit playground
i. Wokwi (I also used Blynk with wokwi simulator)¶
Here is the link to Wokwi Documentation. I took some notes from there to understand more about the simulator.
Wokwi
Wokwi is free online Electronics simulator. You can use it to simulate Arduino, ESP32, STM32, a nd many other popular boards, parts and sensors.
Unique Features of Blynk
- WiFi simulation - Connect your simulated project to the internet. You can use MQTT, HTTP, NTP, and many other network protocols.
- Virtual Logic Analyzer - Capture digital signals in your simulation (e.g. UART, I2C, SPI) and analyze them on your computer.
- Advanced debugging with GDB - Powerful Arduino and Raspberry Pi Pico debugger for advanced users.
- SD card simulation - Store and retrieve files and directories from your code. Paying users can also upload binary files (such as images)
- Chips API - Create your own custom chips and parts, and share them with the community.
- Visual Studio Code integration - Simulate your embedded projects directly from VS Code.
Blynk
Here is the link to the Blynk Documentation.
Blynk is a comprehensive software suite that enables the prototyping, deployment, and remote management of connected electronic devices at any scale.
Whether it’s personal IoT projects or commercial connected products in the millions, Blynk empowers users to connect their hardware to the cloud and create iOS, Android, and web applications, analyze real-time and historical data from devices, remotely control them from anywhere, receive important notifications, and much more.
Blynk.Console (Blynk desktop application) features: - Configuration of connected devices on the platform, including application settings.
- Device, data, user, organization, and location management.
- Remote monitoring and control of devices
Blynk.Apps (Blynk Mobile App) features: - Remote monitoring and control of connected devices that work with Blynk platform.
- Configuration of mobile UI during prototyping and production stages.
- Automation of connected device operations.
Using wokwi simulator and Blynk, I want to set up a wifi based connection between web and the ESP32 board in wokwi simulator. Simulating this will help me understand how I can actually use it in my final project which requires communication between my NapPod(my final project) and the Phone(user).
-
Go to this link and create an account for Wokwi simulator.
-
Create a new Project using your email.
-
Choose a board you want to work with(I want to use esp32).
-
Select a Arduino template.
-
This is Wokwi Simulator interface.
-
Place all the required components by click on the “+” button.
-
I copied some part of code from here and edited for my requirement.
.
-
Go to this link and create an account for Blynk.oi so that you can use Blynk with Wokwi simulator.
-
Go to the developer mode and create a new template.
-
Add a switch here so that you can control your led via simulated wifi connection. For my project, I am planning to control speaker and lighting system integrated in my final project.
-
Give name for your switch and also the datastream and other parameters. Then save it.
-
Copy the auto generated wifi credentials and paste it on top of your code to set up remote connection between your simulator and Blynk.
-
Also add Blynk Library into wokwi simulator so that your can use blynk features in your program.
-
Run the simulation and also open the simple interface created on Blynk. I ran into this annoying issue multiple times ( almost everytime I try to simulate). To slove this issue, it is recommended that you set up the wokwi simulator with VS Code and run the simulator locally on your computer rather than relying on the web based wokwi simulator.
-
Finally a successful simulation after multiple attempt.
Some Changes I made on the existing code
I edited the existing code by giving my own wifi credential generated in Blynk webpage and also created two simple function to detect the status of button created on Blynk web page and a code controlling relay according to the status of button. This will make it easier to add more buttons and other controls as and when required. I created different functions to handle button and relay so that I can easily scale up program if I ever needed to put large number of buttons and other controls. Other than these, I could not edit much as I mainly intend to explore integration of microcontroller with Blynk app or web application.
- This is the program I tested above.
#define BLYNK_TEMPLATE_ID "TMPL3LR5e3R2r"
#define BLYNK_TEMPLATE_NAME "espAndBlynk"
#define BLYNK_AUTH_TOKEN "gCx427NjDeE38-7dZLuZ2NRSLW_Vc8wx"
// Comment this out to disable prints and save space
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
char auth[] = BLYNK_AUTH_TOKEN;
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
BlynkTimer timer;
#define button1_pin 26
#define relay1_pin 13
int relay1_state = 0;
//Change the virtual pins according the rooms
#define button1_vpin V1
//------------------------------------------------------------------------------
// This function is called every time the device is connected to the Blynk.Cloud
// Request the latest state from the server
BLYNK_CONNECTED() {
Blynk.syncVirtual(button1_vpin);
}
//--------------------------------------------------------------------------
// This function is called every time the Virtual Pin state change
//i.e when web push switch from Blynk App or Web Dashboard
BLYNK_WRITE(button1_vpin) {
relay1_state = param.asInt();
digitalWrite(relay1_pin, relay1_state);
}
int i;
void setup()
{
// Debug console
Serial.begin(115200);
pinMode(button1_pin, INPUT_PULLUP);
pinMode(relay1_pin, OUTPUT);
//During Starting all Relays should TURN OFF
digitalWrite(relay1_pin, HIGH);
Blynk.begin(auth, ssid, pass);
// You can also specify server:
//Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
//Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);
}
void loop()
{
Blynk.run();
timer.run();
// You can inject your own code or combine it with other sketches.
// Check other examples on how to communicate with Blynk. Remember
// to avoid delay() function!
}
void listen_push_buttons(){
if(digitalRead(button1_pin) == LOW){
delay(200);
control_relay(1);
Blynk.virtualWrite(button1_vpin, relay1_state); //update button state
}
}
void control_relay(int relay){
if(relay == 1){
relay1_state = !relay1_state;
digitalWrite(relay1_pin, relay1_state);
Serial.print("Relay1 State = ");
Serial.println(relay1_state);
delay(50);
}
}
ii. Tinkercad¶
I will try to simulate Neopixel with Arduino in Tinkercad as I am also exploring how to integrate a Neopixel lighting in my Nap Pod. I might use it to indicate Activated status of my nappod to the users. For that I wnat to try programing a sequence of neopixel lighting which can give a nice feeling for user when they power up my Nappod.
Also, it worth mentioning about the Prompt Enginnering course I took on Udemy. I found out that the result generated by the LLMs model can be quite effictive depending on the way you give a Prompt. So, I want to see how good I in coming up with good prompt so that I can get a the LLMs model to generated a result I desired.
-
Go to this link and create an account for Atuodesk Tinkercad.
-
Create new design
-
This is your blank project where you can build your circuit and program it.
-
Search and add electronic components. I tried to use two Neopixel but I found it bit confusing for me so I decided to try programming just one neopixel Ring.
-
For this, I tried using ChatGPT and Deepseek to program intersting sequence of lighting on 16 Neopixel Ring. This is the prompt I have given to the them.
"I need a program for an Arduino that controls a circular strip of 24 NeoPixels. The program should create a 'snake effect' where a single pixel moves around the strip, leaving a trail of unlit pixels behind it. The snake should run for a specified number of rounds, and the color of the snake should be customizable. The program should include the following:
i. Use the Adafruit NeoPixel library to control the NeoPixels.
ii. Define three colors: blue, red, and green.
iii. Implement a function called clearPixels that turns off all the pixels.
iii. Implement a function called snakeEffect that takes two parameters: the color of the snake and the number of rounds it should run. The snake should move pixel by pixel around the strip, turning on the current pixel and turning off the pixel 20 steps behind it to create a trail of 4 unlit pixels.
iv. In the setup function, initialize the NeoPixel library and ensure all pixels are off at the start.
v. In the loop function, run the snake effect with blue for 2 rounds, then clear the pixels, then run the snake effect with red for 2 rounds, then clear the pixels, and finally run the snake effect with green for 2 rounds, followed by clearing the pixels again.
vi. The program should be written in C++ for Arduino and should include comments explaining each part of the code."
Disclaimer: I used Deekseek to refine my prompt as well and it took some time to really get Deepseek to generate the program I intended it to generate.
- Code generated by Deepseek
#include <Adafruit_NeoPixel.h>
// Define the number of NeoPixels and the pin they are connected to
#define NUM_PIXELS 24
#define PIN 8
// Initialize the NeoPixel object
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
// Define colors
uint32_t BLUE = pixels.Color(0, 0, 255); // Blue
uint32_t RED = pixels.Color(255, 0, 0); // Red
uint32_t GREEN = pixels.Color(0, 255, 0); // Green
// Function to clear all pixels
void clearPixels() {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, 0); // Turn off all pixels
}
pixels.show();
}
// Function to create a snake effect with a specific color
void snakeEffect(uint32_t color, int rounds) {
for (int r = 0; r < rounds; r++) { // Run for the specified number of rounds
for (int i = 0; i < NUM_PIXELS; i++) {
// Turn on the current pixel
pixels.setPixelColor(i, color);
// Turn off the pixel 20 steps behind (to leave a trail of 4 unlit pixels)
int trailingPixel = (i - 20 + NUM_PIXELS) % NUM_PIXELS;
pixels.setPixelColor(trailingPixel, 0);
// Update the NeoPixels
pixels.show();
// Wait a bit before moving to the next pixel
delay(100);
}
}
}
void setup() {
// Initialize the NeoPixel library
pixels.begin();
clearPixels(); // Ensure all pixels are off at the start
}
void loop() {
// Blue snake running for 2 rounds
snakeEffect(BLUE, 2);
clearPixels(); // Clear pixels after the blue snake
// Red snake running for 2 rounds
snakeEffect(RED, 2);
clearPixels(); // Clear pixels after the red snake
// Green snake running for 2 rounds
snakeEffect(GREEN, 3);
clearPixels(); // Clear pixels after the green snake
}
- Simulation Result
-
This sequence did not really satisfy my requirment and I learned that it is a bit of a challage to get the intended program. so I Edited the code.
-
Some changes I made on the code generated by DeepSeek are:
i. Function to blink all the pixel one by one is already generated by Deepseek. So I added another function which can turn on all the pixels at once and this function can take two variable when I call the function from the main loop. The two variable are color and time.
ii. I also added another function to turn of all the pixels one by one. It is quite similar to the function generated by the Deepseek but it just turn off pixels one by one instead of dynamically changing the the on and off pixels which creates the sequence of running pixels.
iii. Now I have three functions, one function to turn on all the pixels one by one, another function to turn on all the pixels smoothly and the last function to turn off all the pixels one by one. And I called these different functions with different input variables to get a good pixels lighting sequences. And the intersting part of this edited code is that I can use these three different function to creaate different lighting sequences. This will help me easily program different lighting sequence according to where and when I want to use the lighting sequence in my Nappod.
- Here is my code which I edited on top of the one generated by the Deepseek.
#include <Adafruit_NeoPixel.h>
// Define the number of NeoPixels and the pin they are connected to
#define NUM_PIXELS 24
#define PIN 8
// Initialize the NeoPixel object
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
// Define colors
uint32_t RED = pixels.Color(255, 0, 0); // Red
uint32_t BLUE = pixels.Color(0, 0, 255); // Blue
uint32_t GREEN = pixels.Color(0, 255, 0); // Green
// Function to clear all pixels
void clearPixels() {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, 0); // Turn off all pixels
}
pixels.show();
}
// Function to smoothly blink all pixels with a specific color
void blinkColor(uint32_t color, int blinkDuration) {
// Fade in
for (int brightness = 0; brightness <= 255;brightness += 50) {
for (int i = -1; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(
(color >> 16) & 0xFF, // Red component
(color >> 8) & 0xFF, // Green component
color & 0xFF // Blue component
));
pixels.setBrightness(brightness); // Adjust brightness
}
pixels.show();
delay(blinkDuration); // Smooth transition
}
}
// Function to turn on all pixel one by one
void snakeEffect(uint32_t color, int rounds) {
for (int r = 0; r < rounds; r++) { // Run for the specified number of rounds
for (int i = 0; i < NUM_PIXELS; i++) {
// Turn on the current pixel
pixels.setPixelColor(i, color);
// Update the NeoPixels
pixels.show();
// Wait a bit before moving to the next pixel
delay(100);
}
}
}
// Function to turn off all pixels one by one
void snakeEffectOff(uint32_t color, int rounds) {
for (int r = 0; r < rounds; r++) { // Run for the specified number of rounds
for (int i = 0; i < NUM_PIXELS; i++) {
// Turn off the current pixel
pixels.setPixelColor(i, 0);
// Update the NeoPixels
pixels.show();
// Wait a bit before moving to the next pixel
delay(100);
}
}
}
void setup() {
// Initialize the NeoPixel library
pixels.begin();
clearPixels(); // Ensure all pixels are off at the start
}
bool sequenceCompleted = false; // Flag to track if the sequence is done
void loop() {
if (!sequenceCompleted) {
// Blink red, blue, and green in sequence
snakeEffect(RED, 1);
clearPixels(); // Clear pixels after the red snake
blinkColor(RED, 300); // Blink red for 0.3 seconds
blinkColor(BLUE, 300); // Blink blue for 0.3 seconds
blinkColor(GREEN, 300); // Blink green for 0.3 seconds
snakeEffectOff(GREEN, 1);
clearPixels(); // Clear pixels after the green snake
sequenceCompleted = true; // Set the flag to true after the sequence
clearPixels(); // Ensure all pixels are off at the start
}
}
- And here is the simulation.
iii. Adafruit Circuit playground¶
I learn how to simulate on Adafruit circuit playground so that I can help in one of the Programming classes for children cordinated in our lab. I found it really fun and decide to simulate something else on it as I hope maybe my documentation can reach out to programming teacher or the small children who are embarking their programming and fabrication journey.
-
To use Adafruit circuit playground, go to this link and create an account.
-
Create a new Project.
-
The interface looks very user friendly and fun.
-
You don’t really need to make any circuit connection as the Adafruit circuit board comes with several cool sensors inbuilt on the board itself. So we just have to know what sensors it has onboard.
-
Directly programming the board using the Block code. I did a simple cute block coding. Check it with your voulme turned on.
-
Simulation
Program Files¶
i. Code for Remote Led control using Blynk in Wokwi Simulator.
ii. Code for Neopixel lighting Sequence generated by DeepSeek and simulated on Tinkercad.
iii. Code for Neopixel lighting Sequence written by myself on top of the one generated by DeepSeekl.