Skip to content

WEEK 04 Embedded Programming

INTRO:

Embedded programming is about writing software for small, specialized computers called microcontrollers. These tiny chips control devices like smart home gadgets, robots, and industrial machines.

Key Concepts:

  • Microcontroller (MCU): A small computer on a single chip with a processor, memory, and input/output (I/O) pins. Used in embedded systems to control hardware. (Example: ATmega328P in Arduino Uno)
  • Microprocessor (MPU): A more powerful chip that only has a processor and needs external memory and peripherals. Used in computers and advanced devices. (Example: Intel Core i7 in PCs)
  • Microchip: A general term for any small semiconductor device, including microcontrollers and microprocessors.
  • Embedded System: A system where hardware and software work together for a specific task, like a smartwatch or an automatic door.
  • Firmware: Software written for a microcontroller, stored permanently in its memory.

Embedded programming involves writing code that directly interacts with hardware, using languages like C, C++, and MicroPython. Popular development tools include Arduino IDE, PlatformIO, and ESP-IDF.



GROUP ASSIGNMENTS

ARDUINO UNO REV3:

https://docs.arduino.cc/retired/boards/arduino-uno-rev3-with-long-pins/

Arduino UNO is a microcontroller board based on the ATmega328P- a small computer chip (microcontroller). It has 14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analog inputs, a 16 MHz ceramic resonator, a USB connection, a power jack, an ICSP header and a reset button.

  • PWM (Pulse Width Modulation) – A way to control things like motor speed or LED brightness by quickly turning power on and off.
  • ICSP (In-Circuit Serial Programming) – A special port used to program the microcontroller directly.

It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started.

  • AC-to-DC (Alternating Current to Direct Current) – Converts electricity from a wall outlet (AC) into a form the Arduino can use (DC).

arduinoreal.jpg

arduinoDiagram.jpg

ATmega328P

DATASHEET: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

  1. What is it?
    • A small computer chip (microcontroller) used in electronics, like the Arduino Uno.
  2. Speed: 20 MHz
    • Can process 20 million instructions per second.
  3. Memory:
    • 32 KB Flash – Stores your program (like a hard drive).
    • 2 KB SRAM – Temporary memory (like RAM in a computer).
    • 1 KB EEPROM – Saves data even when turned off (like a USB stick).
  4. Power: 1.8V – 5.5V
    • Works with small batteries or USB power.
  5. Pins (Connections):
    • 23 Digital Pins – Turn things on/off (like LEDs, motors).
    • 6 Analog Pins – Read sensors (like temperature or light).
  6. Timers:
    • Helps keep track of time, create delays, and generate signals (like dimming an LED).
  7. Communication:
    • USART (Serial Port) – Talks to a computer.
    • SPI & I²C – Talks to sensors, screens, and memory chips.
  8. Low Power Mode:
    • Can save battery by sleeping when not in use.

Arduino IDE

https://www.arduino.cc/en/software

Arduino software, called Arduino IDE (Integrated Development Environment), is used to write, edit, and upload code to Arduino boards. It supports C/C++ programming and includes built-in libraries for easy coding. The IDE connects to the board via USB and helps test and debug projects. There’s also Arduino Web Editor for online coding.

Arduino code consists of three main parts:

  1. Global Declarations – This section includes defining variables, libraries, and constants that will be used throughout the program.
  2. Setup Function (void setup()) – This function runs once when the Arduino is powered on or reset. It is used to initialize settings, such as pin modes, serial communication, or sensor configurations.
  3. Loop Function (void loop()) – This function runs continuously after setup(). It contains the main logic of the program, such as reading inputs, controlling outputs, and executing tasks repeatedly.

This structure ensures the Arduino executes code efficiently and responds to real-time events.

HELLO WORLD:

PHOTO IDE CODE VIDEO REAL

XIAO-ESP32-C3:

https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/

XIAO – A small form-factor development board series from Seeed Studio, designed for compact and low-power applications. Based on the ESP32-C3 – A microcontroller chip developed by Espressif Systems. The ESP32 family includes Wi-Fi and Bluetooth-enabled chips, and C3 is a specific variant with a RISC-V core.

  • RISC-V – A free and open-source Reduced Instruction Set Computing (RISC) architecture for processors, designed to be efficient and scalable.
  • Bluetooth 5 (LE) – The 5th generation of Bluetooth, with Low Energy (LE) mode, optimized for power-efficient wireless communication.

It is designed for IoT applications, offering low power consumption, rich peripheral interfaces (including GPIO, ADC, and UART), and is compatible with Arduino (C/C++) and MicroPython.

  • IoTInternet of Things, a concept where everyday devices are connected to the internet for automation, monitoring, and data collection.
  • GPIOGeneral-Purpose Input/Output, pins on a microcontroller that can be programmed to read inputs (like sensors) or control outputs (like LEDs).
  • ADCAnalog-to-Digital Converter, a hardware component that converts analog signals (like sensor readings) into digital data.
  • UARTUniversal Asynchronous Receiver-Transmitter, a serial communication protocol used to transfer data between devices.

xiaoReal.jpg

xiaoDiagram.jpg

xiaoDiagram2.jpg

ESP32-C3

DATASHEET: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf

  1. What is it?
    • A small but powerful computer chip (microcontroller) with built-in Wi-Fi and Bluetooth.
  2. Speed: 160 MHz
    • Can process 160 million instructions per second, much faster than ATmega328P.
  3. Memory:
    • 400 KB SRAM – Temporary memory (like RAM in a computer).
    • 4 MB Flash – Stores programs and data (like a hard drive).
  4. Power: 3.0V – 3.6V
    • Uses lower voltage, good for battery-powered devices.
  5. Pins (Connections):
    • 22 Digital Pins – Control LEDs, motors, etc.
    • 6 Analog Pins – Read sensors (like temperature or light).
  6. Timers & PWM:
    • Helps with timing, dimming lights, and controlling motors smoothly.
  7. Wi-Fi & Bluetooth (BLE):
    • Connects to the internet and other devices wirelessly.
  8. Communication:
    • UART (Serial Port) – Talks to a computer.
    • SPI & I²C – Connects to sensors and screens.
  9. Low Power Mode:
    • Can sleep to save battery, perfect for smart gadgets.

IDE

You can use several IDEs (Integrated Development Environments) to program the XIAO ESP32-C3, depending on the language you choose:

For C/C++ (Arduino)

  1. Arduino IDE – Easiest to use, with built-in ESP32 support.
  2. PlatformIO (VS Code Extension) – More powerful, better for larger projects.
  3. Espressif IDF (ESP-IDF in VS Code or Eclipse) – Official ESP32 development environment for advanced users.

For MicroPython & CircuitPython

  1. Thonny – Simple Python IDE, great for beginners.
  2. Mu Editor – Easy-to-use Python editor with ESP32 support.
  3. VS Code with PyMakr Plugin – More advanced Python development.

For Other Languages

  1. Rust with VS Code – If using Rust for embedded programming.
  2. Espruino Web IDE – For JavaScript programming on ESP32.

HELLO WORLD:

PHOTO IDE CODE VIDEO REAL

RASPBERRY PI PICO W:

https://www.raspberrypi.com/products/raspberry-pi-pico/

Raspberry Pi Pico W is a microcontroller board based on the RP2040 chip, developed by Raspberry Pi. The Pico W is an upgraded version of the Raspberry Pi Pico, featuring built-in Wi-Fi for wireless communication.

  • RP2040 – A dual-core ARM Cortex-M0+ microcontroller, designed for efficiency and performance.

It is designed for embedded systems, automation, and IoT applications, providing a range of interfaces and connectivity options.

picoReal.jpg

PicoDiagram.jpg

RP2040

DATASHEET: https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf

  1. What is it?
    • A dual-core microcontroller chip developed by Raspberry Pi, optimized for low power and high performance.
  2. Speed: 133 MHz
    • Can process 133 million instructions per second.
  3. Memory:
    • 264 KB SRAM – Temporary storage (like RAM in a computer).
    • 2 MB Flash – Stores programs and data.
  4. Power: 1.8V – 3.3V
    • Low power consumption, great for battery-powered projects.
  5. GPIO (General-Purpose Input/Output) Pins:
    • 26 digital pins – Can be programmed as input or output.
    • 3 analog pins – Reads sensor values (e.g., temperature, light intensity).
  6. PWM (Pulse Width Modulation):
    • Controls motor speed, LED brightness, etc.
  7. Timers:
    • Handles timing events, delays, and precise signal generation.
  8. Communication Protocols:
    • UART (Serial Communication) – Connects to computers and other devices.
    • SPI & I²C – Communicates with sensors, displays, and memory chips.
  9. Wi-Fi:
    • Integrated CYW43439 module for wireless connectivity in IoT projects.
  10. Low Power Modes:
    • Can enter sleep modes to extend battery life.

IDE

You can program the Raspberry Pi Pico W using various development environments and programming same as on XIAO.

HELLO WORLD:

PHOTO IDE CODE VIDEO REAL

SUMMARY:

Comparison Table:

Feature Arduino UNO Rev3 (ATmega328P) XIAO ESP32-C3 (ESP32-C3) Raspberry Pi Pico W (RP2040)
Processor 8-bit ATmega328P (16 MHz) 32-bit RISC-V (160 MHz) Dual-core ARM Cortex-M0+ (133 MHz)
Memory 2 KB SRAM, 32 KB Flash 400 KB SRAM, 4 MB Flash 264 KB SRAM, 2 MB Flash
GPIO Pins 14 digital, 6 analog 22 digital, 6 analog 26 multi-function
Wi-Fi ❌ No ✅ Yes (Wi-Fi 4, BLE) ✅ Yes (Wi-Fi 4)
Power Input 5V USB or DC Jack 3.0V - 3.6V 1.8V - 5.5V
Communication UART, SPI, I²C UART, SPI, I²C UART, SPI, I²C
PWM 6 channels Multiple channels Multiple channels
Best For Beginners, basic projects IoT, wireless applications Embedded, automation, IoT
Low Power Mode ❌ No ✅ Yes ✅ Yes

Suggestions for Use:

  • Arduino UNO Rev3 – Great for beginners and basic electronics projects.
  • XIAO ESP32-C3 – Ideal for IoT applications requiring Wi-Fi and Bluetooth.
  • Raspberry Pi Pico W – Best for embedded systems, automation, and wireless connectivity.

FINAL PROJECT

For FnessCat, I need a wireless, low-power, compact, and IoT-friendly microcontroller to handle multiple smart devices efficiently. Here’s why the XIAO ESP32-C3 is the best choice over Arduino UNO and Raspberry Pi Pico W:

  1. Built-in Wi-Fi & Bluetooth
    • Essential for wirelessly connecting multiple exercise machines and the food dispenser.
    • Arduino UNO lacks wireless connectivity, and while the Pico W has Wi-Fi, it doesn’t support Bluetooth (which could be useful for future expansions).
  2. Low Power Consumption
    • Since the devices will be running overnight, power efficiency is crucial.
    • The ESP32-C3 has deep sleep modes that save battery life, unlike the power-hungry Raspberry Pi Pico W or Arduino UNO.
  3. Small & Compact
    • XIAO’s tiny size makes it easy to integrate into different exercise machines without taking up too much space.
    • Arduino UNO is bulky, while the Pico W is larger than XIAO.
  4. Multiple I/O & Sensor Compatibility
    • Works well with sensors for detecting motion, distance, climbing, and button presses.
    • Supports I²C, SPI, UART, PWM, and ADC, making it easy to connect lights, sounds, and reward triggers.
  5. Expandable & Future-Proof
    • Supports IoT applications, making future upgrades easier (e.g., remote monitoring, app integration).
    • Has more computational power than Arduino UNO while being just as beginner-friendly.

Why Not Arduino UNO?

  • No wireless capability.
  • Larger size, making integration difficult.
  • Limited processing power and memory for handling multiple tasks.

Why Not Raspberry Pi Pico W?

  • No Bluetooth, which could limit expandability.
  • While it has Wi-Fi, it lacks deep sleep modes for ultra-low power consumption.


IDIVIDUAL ASSIGNMENTS

ARDUINO LED blinking & LED + button:

To start with circuit simulations I used https://www.tinkercad.com/dashboard. There’s a tab specific for electronics and circuits.

When you start a new project you can choose elements on the right side and simply place them on the worksheet. Everything is very intuitive with dragging and dropping or simply connecting elements by drawing wires. In the upper corner you can choose the edit mode for Arduino. I will used CODE.

On Thinkercad there’s already a code implemented making the build in led blink.

I’ll add an extra led for better visualisation

arduino.jpg

// C++ code
void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000); // Wait for 1000 millisecond(s)
}

I changed the code by coping and pasting what was in the LOOP to signalize the SOS in morse code

(3 short blinks, 3 longer and 3 short again)

arduino_sos.jpg

// CC+ code
void setup ()
{
pinMode (LED_BUILTIN, OUTPUT);
}

void loop()
{
digitalWrite(LED_BUILTIN, HIGH);
delay (750); // Wait for 750 millisecond(s)
digitalWrite(LED_BUILTIN, LOW);
delay (300); // Wait for 300 millisecond(s)

digitalWrite(LED_BUILTIN, HIGH);
delay (750);
digitalWrite(LED_BUILTIN, LOW);
delay(300);

digitalWrite(LED_BUILTIN, HIGH);
delay (750) ;
digitalWrite(LED_BUILTIN, LOW);
delay(300);

digitalWrite(LED_BUILTIN, HIGH);
delay(1500); // Wait for 1500 millisecond(s)
digitalWrite(LED_BUILTIN, LOW);
delay(300); // Wait for 300 millisecond (s)

digitalWrite(LED_BUILTIN, HIGH);
delay(1500);
digitalWrite(LED_BUILTIN, LOW);
delay (300) ;

digitalWrite(LED_BUILTIN, HIGH);
delay(1500);
digitalWrite(LED_BUILTIN, LOW);
delay (300);

digitalWrite(LED_BUILTIN, HIGH);
delay (750); // Wait for 750 millisecond(s)
digitalWrite(LED_BUILTIN, LOW);
delay (300); // Wait for 300 millisecond(s)

digitalWrite (LED_BUILTIN, HIGH);
delay(750);
digitalWrite(LED_BUILTIN, LOW);
delay(300);

digitalWrite(LED_BUILTIN, HIGH);
delay(750);
digitalWrite(LED_BUILTIN, LOW);
delay (1000); // Wait for 1000 millisecond(s)
}

VIDEO SIMULATION:

PUSH BUTTON & RESISTOR:

I connected the circuit to 5V that is way to much for the LED. I was already informed abut the maximum current for this led while doing the SOS light. This time my LED exploded :)

warning.jpg

VIDEO SIMULATION:

We have to add a resistor. To calculate the value I use Ohm's Law:

R = \frac{V_{supply} - V_{diode}}{I_{diode}}

For a regular LED:

  • Supply voltage
V_{supply} = 5V
  • Typical forward voltage
V_{diode} \approx 2V \text{ (for red, varies for other colors)}
  • Desired current
I_{diode} \approx 10-20mA \text{ (safe range for most LEDs)}
R = \frac{5V - 2V}{0.02A} = \frac{3V}{0.02A} = 150\Omega

resistor.jpg

READING A PUSH BUTTON:

I’ll explain int Variable in Arduino (A Global Declaration that was skipped in the previous examples)


In Arduino, int (short for integer) is a data type used to store whole numbers (positive or negative). It is one of the most commonly used variable types in Arduino programming.

Key Features of int in Arduino

  1. Stores whole numbers (e.g., 0, 1, -10, 255).
  2. Takes 2 bytes (16 bits) of memory.
  3. Value range: 32,768 to 32,767.
  4. Cannot store decimal numbers (use float or double for decimals).

Why Use int?

  • Easier to modify: Instead of using hardcoded numbers (pinMode(13, OUTPUT)), you can use variables (pinMode(ledPin, OUTPUT)), making the code more readable.
  • Efficient memory usage: int uses only 2 bytes, which is ideal for storing small numbers like pin numbers or button states.

When you plug a push button into an Arduino Uno, it acts as a simple input device. The button allows you to send a digital signal (HIGH or LOW) to the Arduino, which can be used to control outputs like LEDs, buzzers, or even motors.

I used tutorial from https://www.circuitbasics.com/how-to-connect-and-program-push-buttons-on-the-arduino/

tutorial.jpg

int buttonPin = 7;
int ledPin = 11;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int buttonState = digitalRead(buttonPin);
  digitalWrite(ledPin, buttonState);
}

Step-by-Step Explanation

1. Declaring Variables

int buttonPin = 7;
int ledPin = 11;
  • int buttonPin = 7; → Stores the pin number for the button (Pin 7).
  • int ledPin = 11; → Stores the pin number for the LED (Pin 11).

2. Setup Function (setup())

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
  • pinMode(buttonPin, INPUT);
    • Configures Pin 7 as an input (to read the button state).
  • pinMode(ledPin, OUTPUT);
    • Configures Pin 11 as an output (to control the LED).

3. Loop Function (loop())

void loop() {
  int buttonState = digitalRead(buttonPin);
  digitalWrite(ledPin, buttonState);
}

Step 1: Read the Button State

  • Reads the button's state (HIGH or LOW).
  • Stores the result in the integer variable buttonState.
  • If the button is pressed → buttonState = HIGH (1).
  • If the button is not pressed → buttonState = LOW (0).

Step 2: Control the LED

  • Writes the same value (buttonState) to the LED.
  • If buttonState is HIGH (1) → The LED turns ON.
  • If buttonState is LOW (0) → The LED turns OFF.

SUMMARY:

  1. Button is not pressed → Arduino reads LOW (0) → LED stays OFF.
  2. Button is pressed → Arduino reads HIGH (1) → LED turns ON.
  3. The loop repeats continuously, checking the button state and updating the LED.

PROBLEM OF FLOATING PINS:

If you build the project above and test it, you’ll notice that something weird is going on. The LED will probably flash on and off whenever you move your hand close to the button. What could be causing that?

The Arduino’s digital pins are extremely sensitive. Even weak electromagnetic fields created by your hand can be detected by the Arduino. And those are registered as high signals by the digitalRead() function.

When GPIO pins are allowed to pick up stray electromagnetic fields, they’re called floating pins. We need to fix this by making sure the buttonPin stays low when the button is not pressed.


PULL DOWN RESISTOR:

The easiest way is to connect a resistor from the left side of the push button to ground. When the button is not pressed, stray electromagnetic energy will flow to ground through the resistor. When the button is pressed, the resistor will restrict the current flow to ground and the current will flow to pin 7. This is called a pull down resistor because it connects a pin to ground to keep it in a low voltage state. The value of the pull down resistor can vary, but is usually higher than 10K Ohms.

PullDown.jpg

How Does a Pull-Down Resistor Work?

A pull-down resistor is used to ensure a stable LOW (0V) signal when the button is not pressed. Without it, the input pin could float, meaning it might randomly read HIGH or LOW due to electrical noise.

Circuit Setup

  • One side of the push button is connected to 5V.
  • The other side is connected to pin 7 and to GND through a pull-down resistor (10kΩ).

Two Scenarios: Pressed vs. Not Pressed:

1. When the Button is NOT Pressed (Open Circuit)

  • The button is not completing the circuit.
  • The pin only has a path to GND through the 10kΩ resistor.
  • The Arduino reads LOW (0V).

Why?

  • The pull-down resistor acts as a weak connection to GND, so the input pin is pulled to 0V.
  • Without the resistor, the pin would "float" and randomly pick up electrical noise (e.g., from your hand).

2. When the Button IS Pressed (Closed Circuit)

  • The button creates a direct path from 5V to pin 7.
  • Most of the current flows from 5V into the pin instead of through the resistor.
  • The pin reads HIGH (5V).

Why?

  • The current takes the "easiest" path. Since the pin is directly connected to 5V when the button is pressed, the Arduino reads HIGH.
  • Some small current still flows through the resistor to GND, but it's negligible.

PULL UP RESISTOR:

Pull up resistors are more common than pull down resistors. Pull up resistors are connected to a voltage source and keep the pin in a high voltage state. In this circuit, the pull up resistor is connected to 5 volts, and the right side of the button is connected to ground. Pressing the button will send a low signal to pin 7, turning the LED on. The pull up resistor is tied to 5 volts and keeps pin 7 high until the button is pressed.

PullUp.jpg

The code for using a pull up resistor looks like this:

int buttonPin = 7;
int ledPin = 11;

void setup() {
  pinMode(buttonPin, INPUT);  // Set buttonPin as input
  pinMode(ledPin, OUTPUT);    // Set ledPin as output
}

void loop() {
  int buttonState = digitalRead(buttonPin);  // Read the state of the button

  if (buttonState == LOW) {  // If button is pressed
    digitalWrite(ledPin, HIGH);  // Turn the LED ON
  }

  if (buttonState == HIGH) {  // If button is NOT pressed
    digitalWrite(ledPin, LOW);  // Turn the LED OFF
  }
}

Step-by-Step Explanation

  1. Variable Declarations:

    int buttonPin = 7;
    int ledPin = 11;
    
    • buttonPin is set to pin 7, where the button is connected.
    • ledPin is set to pin 11, where the LED is connected.
    • Setup Function:
    void setup() {
      pinMode(buttonPin, INPUT);
      pinMode(ledPin, OUTPUT);
    }
    
    • pinMode(buttonPin, INPUT); → Configures pin 7 as an input.
    • pinMode(ledPin, OUTPUT); → Configures pin 11 as an output.
    • Loop Function:
    void loop() {
      int buttonState = digitalRead(buttonPin);
    
    • digitalRead(buttonPin); → Reads the state of pin 7:
      • Returns HIGH (5V) if the button is not pressed.
      • Returns LOW (0V) if the button is pressed.
    • Turning the LED ON/OFF:
    if (buttonState == LOW) {
      digitalWrite(ledPin, HIGH);
    }
    
    if (buttonState == HIGH) {
      digitalWrite(ledPin, LOW);
    }
    
    • If buttonState == LOW (button is pressed), turn ON the LED.
    • If buttonState == HIGH (button is not pressed), turn OFF the LED.

How Does a Pull-Up Resistor Work?

A pull-up resistor is used to ensure a stable HIGH (5V) signal when the button is not pressed. Without it, the input pin could float, meaning it might randomly read HIGH or LOW due to electrical noise.

Circuit Setup

  • One side of the push button is connected to GND (0V).
  • The other side is connected to pin 7 and to 5V through a pull-up resistor (10kΩ).

Two Scenarios: Pressed vs. Not Pressed:

1. When the Button is NOT Pressed (Open Circuit)

  • The button is not completing the circuit.
  • The pin only has a path to 5V through the 10kΩ resistor.
  • The Arduino reads HIGH (5V).

Why?

  • The pull-up resistor acts as a weak connection to 5V, so the input pin is pulled to HIGH (5V).
  • Without the resistor, the pin would "float" and randomly pick up electrical noise.

2. When the Button IS Pressed (Closed Circuit)

  • The button creates a direct path from pin 7 to GND (0V).
  • Most of the current flows from the pin to GND instead of through the resistor.
  • The pin reads LOW (0V).

Why?

  • The current takes the "easiest" path. Since the pin is directly connected to GND when the button is pressed, the Arduino reads LOW.
  • Some small current still flows through the resistor to 5V, but it's negligible.

PULL-DOWN vs. PULL-UP:

Configuration Default State Pressed State
Pull-Down (Resistor to GND) LOW (0V) HIGH (5V)
Pull-Up (Resistor to 5V) HIGH (5V) LOW (0V)

ARDUINO’S INTERNAL PULL UP RESISTOR:

The previous code works with an external pull-up resistor, but the Arduino also has an internal pull up resistor that you can use for the same purpose.

Use INPUT_PULLUP in the setup() function:

pinMode(buttonPin, INPUT_PULLUP);
  • The button now connects the pin to GND when pressed, making the input LOW.
  • When the button is not pressed, the pin is pulled HIGH by the internal resistor.

internal.jpg

int buttonPin = 7;
int ledPin = 11;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);  // Enable internal pull-up resistor
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) {  // Button pressed
    digitalWrite(ledPin, HIGH);
  } else {  // Button not pressed
    digitalWrite(ledPin, LOW);
  }
}

How It Works:

Button State Pin Reads LED State
Not Pressed HIGH (5V) OFF
Pressed LOW (0V) ON

ARDUINO potentiometer + LED:

For this simulation I used WOKWI https://wokwi.com/ The aplication works very similar to Thinkercad- circuits. In the first place I wanted to use a light sensor, but couldn’t find one so I used a potentiometer that works with same idea as the photodetector.

wokwi.jpg

wokwi2.jpg

VIDEO SIMULATION:

diagram.json (for using in WOKWI)

{
  "version": 1,
  "author": "Daniel",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-breadboard", "id": "bb1", "top": -243, "left": -275.6, "attrs": {} },
    { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
    {
      "type": "wokwi-led",
      "id": "led1",
      "top": -94.4,
      "left": -63,
      "rotate": 180,
      "attrs": { "color": "red", "flip": "1" }
    },
    { "type": "wokwi-potentiometer", "id": "pot1", "top": -366.1, "left": -153.8, "attrs": {} },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": -81.6,
      "left": -221.35,
      "rotate": 90,
      "attrs": { "value": "10000" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r2",
      "top": -81.6,
      "left": -106.15,
      "rotate": 90,
      "attrs": { "value": "200" }
    }
  ],
  "connections": [
    [ "bb1:23b.g", "uno:12", "white", [ "v-201.6", "h9.6" ] ],
    [ "r2:1", "bb1:19b.h", "", [ "$bb" ] ],
    [ "r2:2", "bb1:bn.15", "", [ "$bb" ] ],
    [ "bb1:bn.1", "uno:GND.2", "green", [ "v277.1", "h402.4" ] ],
    [ "uno:5V", "bb1:16b.h", "blue", [ "v19.7", "h-246.4" ] ],
    [ "r1:1", "bb1:7b.h", "", [ "$bb" ] ],
    [ "r1:2", "bb1:bn.5", "", [ "$bb" ] ],
    [ "uno:A0", "bb1:11b.h", "#8f4814", [ "v58.1", "h-361.6" ] ],
    [ "bb1:11b.g", "bb1:7b.g", "green", [ "v0" ] ],
    [ "bb1:19b.g", "bb1:22b.g", "green", [ "v0" ] ],
    [ "bb1:16b.g", "pot1:VCC", "green", [ "v0" ] ],
    [ "pot1:SIG", "bb1:11b.f", "green", [ "v28.8", "h-38.8" ] ],
    [ "led1:A", "bb1:23b.j", "", [ "$bb" ] ],
    [ "led1:C", "bb1:22b.j", "", [ "$bb" ] ]
  ],
  "dependencies": {}
}

THE CODE:

#define ledPin 12

#define lightPin A0
float lightValue = 0;
float voltage = 0.00;

void setup() {

  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop() {

  lightValue = analogRead(lightPin);
  voltage = map_to_float(lightValue,0,1023,0,5);

  if (voltage < 1.60) {
    digitalWrite(ledPin,HIGH);
  }

  else {
    digitalWrite(ledPin, LOW);
  }

  Serial.println(voltage);
  delay(1); 

}

float map_to_float(float x, float a, float b, float c, float d)
{
 float f=x/(b-a)*(d-c)+c;

return f;
}

BREAKDOWN OF THE CODE:

  1. Define Constants & Variables

    #define ledPin 12
    #define lightPin A0
    float lightValue = 0;
    float voltage = 0.00;
    
    • ledPin → The LED is connected to pin 12.
    • lightPin → The light sensor is connected to A0 (analog pin 0).
    • lightValue → Stores the raw analog reading from the sensor.
    • voltage → Stores the converted voltage value.
  2. Setup Function (Runs Once)

    void setup() {
      Serial.begin(9600);  // Start Serial Monitor at 9600 baud
      pinMode(ledPin, OUTPUT);  // Set pin 12 as OUTPUT (for LED)
      digitalWrite(ledPin, LOW);  // Turn LED OFF initially
    }
    
    • Initializes Serial Monitor for debugging.
    • Sets ledPin as OUTPUT to control the LED.
    • Ensures LED is off at the start.
  3. Loop Function (Runs Repeatedly)

    void loop() {
      lightValue = analogRead(lightPin);  // Read sensor value (0-1023)
      voltage = map_to_float(lightValue, 0, 1023, 0, 5);  // Convert to voltage
    
      if (voltage < 1.60) {
        digitalWrite(ledPin, HIGH);  // Turn LED ON if voltage is low (dark)
      }
      else {
        digitalWrite(ledPin, LOW);  // Turn LED OFF if voltage is high (bright)
      }
    
      Serial.println(voltage);  // Print voltage to Serial Monitor
      delay(1);  // Short delay (1ms)
    }
    
    • Reads analog value (0–1023) from the light sensor.
    • Converts the reading to voltage (0–5V) using map_to_float().
    • If voltage is less than 1.6V (darker environment), the LED turns ON.
    • Otherwise, the LED turns OFF (brighter environment).
    • Prints the voltage value to Serial Monitor for debugging.
    • 1ms delay prevents overloading the processor with too many reads.
  4. Mapping Function

    float map_to_float(float x, float a, float b, float c, float d)
    {
        float f = x / (b - a) * (d - c) + c;
        return f;
    }
    
    • This function converts a sensor reading (0–1023) into voltage (0–5V).
    • It works similarly to Arduino’s built-in map() function, but for floating-point values.

    Formula Used:

f = \frac{x}{b - a} \times (d - c) + c

Where:

  • x → Input value (sensor reading: 0-1023)
  • a, b → Input range (0 to 1023)
  • c, d → Output range (0 to 5V)

Example:

If sensor reads 512, then:

\text{voltage} = \frac{512}{1023} \times 5 \approx 2.5

SUMMARY:

  1. Reads light sensor value (0–1023).
  2. Converts it to voltage (0–5V).
  3. If voltage < 1.6V (dark environment), the LED turns ON.
  4. If voltage ≥ 1.6V (bright environment), the LED turns OFF.
  5. Prints the voltage to the Serial Monitor.

XIAO-ESP32-C3 potentiometer + LED:

VIDEO SIMULATION

diagram.json (for using in WOKWI)

{
  "version": 1,
  "author": "Uri Shaked",
  "editor": "wokwi",
  "parts": [
    { "type": "board-xiao-esp32-c3", "id": "esp", "top": 38.97, "left": 13.78, "attrs": {} },
    { "type": "wokwi-led", "id": "led1", "top": 6, "left": -73, "attrs": { "color": "red" } },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": 147.95,
      "left": -57.6,
      "attrs": { "value": "1000" }
    },
    { "type": "wokwi-junction", "id": "j1", "top": 148.8, "left": 24, "attrs": {} },
    { "type": "wokwi-potentiometer", "id": "pot1", "top": -135.7, "left": -0.2, "attrs": {} },
    {
      "type": "wokwi-resistor",
      "id": "r2",
      "top": 3.95,
      "left": 115.2,
      "attrs": { "value": "10000" }
    }
  ],
  "connections": [
    [ "led1:C", "r1:1", "black", [ "v0" ] ],
    [ "j1:J", "r1:2", "black", [ "v0" ] ],
    [ "esp:GND", "j1:J", "black", [ "h19.82", "v86.4" ] ],
    [ "esp:D4", "led1:A", "green", [ "h-67.2" ] ],
    [ "esp:GND", "r2:2", "black", [ "h0" ] ],
    [ "r2:1", "pot1:GND", "black", [ "v0", "h-76.8" ] ],
    [ "pot1:SIG", "esp:D0", "green", [ "v38.4", "h-58", "v86.4" ] ]
  ],
  "dependencies": {}
}

THE CODE:

#define ledPin D4
#define lightPin A0

int lightValue = 0;

void setup() {

  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop() {

  lightValue = analogRead(lightPin); 

  if (lightValue < 500) {
    digitalWrite(ledPin,HIGH);
  }

  else {
    digitalWrite(ledPin, LOW);
  }

  Serial.println(lightValue);
  delay(1); 

}

BREAKDOWN OF THE CODE:

This code reads a light sensor (on A0), checks its value, and turns on an LED (on D4) if it's dark. Let's break it down step by step.

  1. Defining Constants and Variables

    #define ledPin D4
    #define lightPin A0
    
    int lightValue = 0;
    
    • ledPinDefines pin D4 as the LED pin.
    • lightPinDefines pin A0 as the light sensor input.
    • lightValue → Stores the raw analog sensor value (0 to 1023).
  2. Setup Function (Runs Once at Startup)

    void setup() {
      Serial.begin(9600);
      pinMode(ledPin, OUTPUT);
      digitalWrite(ledPin, LOW);
    }
    
    • Serial.begin(9600);Starts serial communication at 9600 baud (for debugging).
    • pinMode(ledPin, OUTPUT);Configures D4 as an output pin (for the LED).
    • digitalWrite(ledPin, LOW);Ensures the LED starts off.
  3. Loop Function (Runs Continuously)

    void loop() {
      lightValue = analogRead(lightPin);
    
    • Reads light sensor value (0–1023) and stores it in lightValue.
      • Higher values (~1023)Brighter light.
      • Lower values (~0)Darker light.
  4. Light Threshold Logic

      if (lightValue < 500) {
        digitalWrite(ledPin, HIGH);
      }
      else {
        digitalWrite(ledPin, LOW);
      }
    
    • If lightValue is below 500 (dark environment), the LED turns ON.
    • If lightValue is 500 or more (bright environment), the LED turns OFF.

    Why 500?

    • 500 is an arbitrary threshold (you can adjust it based on testing).
  5. Debugging Output & Delay

      Serial.println(lightValue);
      delay(1);
    }
    
    • Serial.println(lightValue);Prints the sensor reading in the Serial Monitor (for debugging).
    • delay(1);Adds a short 1ms delay to stabilize the readings.

SUMMARY:

Reads light sensor value (0–1023).

Turns ON the LED if the value is below 500 (darker).

Turns OFF the LED if the value is 500 or more (brighter).

Prints sensor values for debugging.

Let’s make it a little bit better by adding PWM dimming instead of just turning the LED ON/OFF. Now, the LED will gradually change brightness depending on the light sensor value.

#define ledPin D4
#define lightPin A0

int lightValue = 0;
float voltage = 0.0;

void setup() {
  Serial.begin(9600);        // Start Serial Monitor
  pinMode(ledPin, OUTPUT);   // Set LED pin as OUTPUT
  digitalWrite(ledPin, LOW); // Start with LED OFF
}

void loop() {
  lightValue = analogRead(lightPin);  // Read light sensor (0-1023)
  voltage = lightValue * (5.0 / 1023.0);  // Convert sensor value to voltage (0-5V)

  int brightness = map(lightValue, 0, 1023, 255, 0);  // Map lightValue to PWM range (inverted)
  analogWrite(ledPin, brightness);  // Adjust LED brightness

  Serial.print("Light Value: ");
  Serial.print(lightValue);
  Serial.print(" | Voltage: ");
  Serial.println(voltage);  // Print voltage value for debugging

  delay(10);  // Small delay to stabilize readings
}

  • LED brightness is now controlled smoothly (instead of just ON/OFF).
  • analogWrite() is used for PWM dimming (values range from 0-255).
  • Light sensor value is mapped so that:
    • Dark → LED is Bright
    • Bright → LED is Dim.

Serial Monitor now displays both raw sensor values & voltage.

VIDEO SIMULATION

XIAO-ESP32-C3 button + LED:

VIDEO SYMULATION

diagram.json (for using in WOKWI)

{
  "version": 1,
  "author": "Uri Shaked",
  "editor": "wokwi",
  "parts": [
    { "type": "board-xiao-esp32-c3", "id": "esp", "top": 38.97, "left": 13.78, "attrs": {} },
    { "type": "wokwi-led", "id": "led1", "top": 6, "left": -73, "attrs": { "color": "red" } },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": 147.95,
      "left": -57.6,
      "attrs": { "value": "1000" }
    },
    { "type": "wokwi-junction", "id": "j1", "top": 148.8, "left": 24, "attrs": {} },
    {
      "type": "wokwi-pushbutton",
      "id": "btn3",
      "top": -41.8,
      "left": 307.2,
      "attrs": { "color": "red", "xray": "1" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r6",
      "top": 51.95,
      "left": 182.4,
      "attrs": { "value": "1000" }
    }
  ],
  "connections": [
    [ "esp:D2", "led1:A", "green", [ "h0" ] ],
    [ "led1:C", "r1:1", "black", [ "v0" ] ],
    [ "j1:J", "r1:2", "black", [ "v0" ] ],
    [ "esp:GND", "j1:J", "black", [ "h19.82", "v86.4" ] ],
    [ "esp:5V", "r6:1", "red", [ "h0" ] ],
    [ "r6:2", "esp:D9", "blue", [ "v0" ] ],
    [ "r6:2", "btn3:1.l", "blue", [ "v0" ] ],
    [ "btn3:2.r", "esp:GND", "black", [ "h29", "v77" ] ]
  ],
  "dependencies": {}
}

THE CODE:

const int buttonRed = D9;
const int ledRed = D2;

void setup() {
Serial.begin(115200); //Starts serial communication at 115200 baud rate
Serial.println("Ready"); //Prints Ready when the program has started successfully

pinMode(buttonRed, INPUT);  // When the button is not pressed, the pin reads HIGH (due to the pull-up resistor)

pinMode(ledRed, OUTPUT); //This allows the microcontroller to control the LEDs by setting them HIGH (turning them on) or LOW (turning them off)

digitalWrite(ledRed, LOW); //ensures that all LEDs are off at the start of the program

}

void loop() {
bool redState = digitalRead(buttonRed); //reads the current state (HIGH or LOW) of each button

digitalWrite(ledRed, !redState); //controls each LED by setting it to HIGH (on) or LOW (off)

Serial.print("Red: "); Serial.print(!redState); //Prints the LED states (1 for on, 0 for off) to the Serial Monitor

delay(100);
}

BREAKDOWN OF THE CODE:

This code reads a button press (on D9) and controls an LED (on D2) accordingly. If the button is pressed, the LED turns on; otherwise, it stays off.

  1. Defining Constants

    const int buttonRed = D9;
    const int ledRed = D2;
    
    • buttonRedDefines pin D9 as the button input.
    • ledRedDefines pin D2 as the LED output.

2. Setup Function (Runs Once at Startup)

void setup() {
  Serial.begin(115200);
  Serial.println("Ready");

  pinMode(buttonRed, INPUT);
  pinMode(ledRed, OUTPUT);
  digitalWrite(ledRed, LOW);
}
  • Serial.begin(115200);Starts serial communication at 115200 baud (for debugging).
  • Serial.println("Ready");Prints "Ready" to confirm program start.
  • pinMode(buttonRed, INPUT);Configures D9 as an input for the button.
  • pinMode(ledRed, OUTPUT);Configures D2 as an output for the LED.
  • digitalWrite(ledRed, LOW);Ensures the LED starts off.

  • Loop Function (Runs Continuously)

    void loop() {
      bool redState = digitalRead(buttonRed);
    
    • Reads the button state (HIGH or LOW).
      • HIGH → Button is not pressed.
      • LOW → Button is pressed.
  • LED Control Logic

      digitalWrite(ledRed, !redState);
    
    • The LED turns ON when the button is pressed (redState == LOW).
    • The LED turns OFF when the button is released (redState == HIGH).
    • This works because !redState inverts the logic:
      • If redState is LOW (pressed), !redState is HIGH, turning the LED ON.
      • If redState is HIGH (not pressed), !redState is LOW, turning the LED OFF.
  • Debugging Output & Delay

      Serial.print("Red: ");
      Serial.println(!redState);
      delay(100);
    }
    
    • Serial.print("Red: "); Serial.println(!redState);Prints the LED state (1 = ON, 0 = OFF) for debugging.
    • delay(100);Adds a short 100ms delay to debounce the button.

SUMMARY:

  1. Reads the button state (HIGH when not pressed, LOW when pressed).
  2. Turns ON the LED when the button is pressed.
  3. Turns OFF the LED when the button is released.
  4. Prints the LED state for debugging.

CHECKLIST:

Group assignment:

  • Demonstrate and compare the toolchains and development workflows for available embedded architectures
  • Document your work to the group work page and reflect on your individual page what you learned

Individual assignment:

  • Browse through the datasheet 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 connection)

Learning outcomes

  • Implement programming protocols.

Have you answered these questions?

  • Linked to the group assignment page
  • Browsed and documented some information from your microcontroller's datasheet
  • Programmed your simulated board to interact and communicate
  • Described the programming process(es) you used
  • Included your source code
  • Included ‘hero shot(s)’

////////////////////////////////////////////////////////////////////////////////////////////////////////// ———————————————————————————————————————————

WEEK PLAN:

DAY WED TH FR SA SU MON TU
PLAN -12:00 LAB with Andre
-14:00 Global evaluation
-15:45 Neil’s class -10:30 Andre online class -10:30 LAB with Andre -15:00 Global time
-10:00 LAB alone -10:00 LAB alone
INFO Plan the strategy for the week