Saltar a contenido

EMBEDDED PROGRAMMING

TOOLS

Arduino
Arduino IDE
Embedded development environment

Architecture

ESP32

The ESP32 is a System-on-Chip (SoC) microcontroller developed by Espressif Systems. It integrates processing units, memory, wireless connectivity, and peripherals on a single chip. It supports the execution of a real-time operating system such as FreeRTOS. Although an RTOS is not mandatory, it can also be programmed in bare-metal mode or through higher-level environments such as the Arduino framework.

Internal vs. External: The ESP32 integrates internal ROM and SRAM memory, along with external Flash memory connected through a QSPI interface. It supports up to 16 MB of external Flash mapped into the program address space.

Real-Time vs. Asynchronous: The ESP-IDF framework runs on top of FreeRTOS, enabling preemptive multitasking. Even when programmed using the Arduino IDE, the ESP32 still operates over FreeRTOS internally, although task management is abstracted from the developer.

The ESP32 features two 32-bit Xtensa LX6 cores based on a Harvard RISC architecture with a 7-stage pipeline and variable-length instructions (commonly 16 and 24 bits). It includes a floating-point unit (FPU) and supports 32/40-bit multiplication and DSP operations.

  • Registers: 16 general-purpose 32-bit registers.
  • SRAM: 520 KB of internal SRAM (shared between instruction and data memory), plus 16 KB of RTC fast memory.
  • ROM: 448 KB internal ROM containing bootloader and system libraries.
  • Flash: External QSPI Flash (typically 4 MB in WROOM modules).
  • EEPROM: No dedicated EEPROM; Flash memory can emulate EEPROM functionality.
  • eFuse: 1 Kbit of non-volatile eFuse memory for configuration and security.

ARDUINO UNO

The Arduino UNO R3 is based on the ATmega328P, an 8-bit AVR microcontroller designed for general-purpose embedded applications, education, and prototyping. The program executes sequentially inside the loop() function, while interrupt service routines handle asynchronous events.

Internal vs. External: The ATmega328P includes on-chip Flash memory (program storage), SRAM (data memory), and EEPROM (non-volatile storage). No external memory is required for standard operation.

Real-Time vs. Asynchronous: The Arduino UNO does not natively support a real-time operating system (RTOS) or preemptive task scheduling. Execution is cooperative, based on the main loop() and interrupt routines.

The ATmega328P uses a Harvard architecture with separate program and data memories. It is an 8-bit, single-core RISC processor based on the AVR architecture, featuring 131 optimized instructions and 32 general-purpose 8-bit registers.

  • Flash: 32 KB (0.5 KB used by bootloader).
  • SRAM: 2 KB.
  • EEPROM: 1 KB.
  • Clock Speed: 16 MHz.

ESP32 VS ARDUINO UNO

The Arduino UNO R3 integrates an 8-bit ATmega328P microcontroller operating at 16 MHz, whereas the ESP32 employs a dual-core, 32-bit Tensilica Xtensa LX6 processor running at up to 240 MHz. Both microcontrollers exhibited mechanical bounce due to the inherent physical characteristics of the pushbutton. However ESP32 demonstrated a shorter signal stabilization time than the Arduino UNO.

Both microcontrollers exhibited mechanical bounce due to the inherent physical characteristics of the pushbutton. However ESP32 demonstrated a shorter signal stabilization time than the Arduino UNO.

Assembly

The simulation was carried out using the Wokwi virtual platform, which allows testing embedded systems before implementing them in physical hardware. This helps validate connections, pin configuration, and program logic.


Button and LED Control

In the first simulation a push button, and an LED were used to verify digital input and output behavior.

  • A digital input was configured with internal pull-up resistor.
  • The push button changes the logic level when pressed.
  • When the button is pressed, the LED turns ON.
  • When the button is released, the LED turns OFF.
  • GPIO pin configuration.
  • Digital read functionality.
  • Digital write control.
  • Input/output interaction.

OLED Display with Button

The OLED display was connected through I2C and added to the ESP32 along with a push button.

  • The OLED display communicates via I2C protocol.
  • The display starts with a cleared screen.
  • When the button is pressed, a message is shown on the display.
  • When the button is released, the display is cleared.
  • Proper communication between the ESP32 and the display was verified.
  • I2C communication.
  • Library integration.
  • Display buffer control.
  • Event-based interaction.

Tests were also carried out with the LED matrix and the OLED display (U8G2 library) to validate the operation of the circuit and verify the preliminary stage of the system that will be used in the final project.

In the LED matrix, Braille display patterns were tested to represent the word “HOLA”. The assigned representation was correct but the displayed output appeared mirrored compared to the initial input configuration. This behavior was documented for later adjustment in the final implementation.

The OLED display simulation was performed to verify proper operation and visual output of the word “HOLA”, confirming correct functionality for its integration into the final project.

Arduino IDE version 2.3.7 was installed and will be used as the development environment for ESP32 programming.

The libraries required to control the ESP32 (Espressif Systems) and the OLED display (U8G2) were installed to enable program development and execution within the Arduino IDE.

With the ESP32 libraries installed, different board models become available in the Boards menu. The ESP32 Dev Module will be used. Your board model may be different, so make sure to select the correct one.


The code was developed based on the fundamental logic of the Braille system:

Pin and Variable Definitions in the Program

  • CLK (17): Clock pin used for communication with the LED matrix controller. It synchronizes the bit transmission.
  • DIN (4): Data input pin that sends the bit patterns to the LED matrix module.
  • CS (16): Chip Select pin that enables or disables communication with the matrix controller.
  • BTN_MODE1 (32): Digital input pin assigned to select operation Mode 1.
  • BTN_MODE2 (33): Digital input pin assigned to select operation Mode 2.
  • mode (int): Stores the current active operating mode of the system.
  • currentNumber (int): Holds the current selected or displayed number inside the system logic.
  • freePattern (byte): Stores an 8-bit pattern used for custom LED matrix configurations (for example Braille patterns).
  • SDA (21): I2C data line used for communication with the OLED display.
  • SCL (22): I2C clock line that synchronizes I2C data transmission.
  • Wire (I2C): I2C communication interface used to manage serial communication with external devices through Wire.begin(21,22).

#include <Wire.h>
#include <U8g2lib.h>

// ================= PINS =================
#define CLK 17
#define DIN 4
#define CS 16

#define BTN_MODE1 32
#define BTN_MODE2 33
#define B3 25
#define B4 26
#define B5 27
#define B6 14

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

int mode = 0;
int currentNumber = 0;
byte freePattern = 0;

int exitCounter = 0;
bool previousBTN2State = HIGH;
unsigned long lastBTN2Time = 0;

// ================= BRAILLE NUMBERS =================
byte brailleNumbers[10] = {
B00011010,B00000001,B00000011,B00001001,B00011001,
B00010001,B00001011,B00011011,B00010011,B00001010
};

// ================= MAX7219 =================
void sendCommandAll(byte address, byte data){
digitalWrite(CS, LOW);
shiftOut(DIN, CLK, MSBFIRST, address);
shiftOut(DIN, CLK, MSBFIRST, data);
digitalWrite(CS, HIGH);
}

void clearMatrix(){
for(int i=1;i<=8;i++)
sendCommandAll(i,0x00);
}

// ================= BRAILLE OLED =================
void drawBrailleOLED(int X, int Y, byte pattern) {

int r = 2;
int spaceY = 8;
int spaceX = 8;

for (int i = 0; i < 6; i++) {

int col = i / 3;
int row = i % 3;

int dx = X + col * spaceX;
int dy = Y + row * spaceY;

if (pattern & (1 << i))
u8g2.drawDisc(dx, dy, r);
else
u8g2.drawCircle(dx, dy, r);
}
}

void showMenu(){
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_6x12_tr);
u8g2.drawStr(20,20,"BTN1: Numbers");
u8g2.drawStr(20,40,"BTN2: Free");
u8g2.sendBuffer();
}

// ================= SETUP =================
void setup(){

pinMode(CLK,OUTPUT);
pinMode(DIN,OUTPUT);
pinMode(CS,OUTPUT);

pinMode(BTN_MODE1,INPUT_PULLUP);
pinMode(BTN_MODE2,INPUT_PULLUP);
pinMode(B3,INPUT_PULLUP);
pinMode(B4,INPUT_PULLUP);
pinMode(B5,INPUT_PULLUP);
pinMode(B6,INPUT_PULLUP);

Wire.begin(21,22);
u8g2.begin();

showMenu();
mode = 0;
}

// ================= LOOP =================
void loop(){

if(mode==0){

if(digitalRead(BTN_MODE1)==LOW){
mode=1;
clearMatrix();
delay(300);
}

if(digitalRead(BTN_MODE2)==LOW){
mode=2;
freePattern=0;
delay(300);
}
}

else if(mode==2){

freePattern = 0;

if(digitalRead(BTN_MODE1)==LOW) freePattern |= (1<<0);
if(digitalRead(B3)==LOW) freePattern |= (1<<1);
if(digitalRead(BTN_MODE2)==LOW) freePattern |= (1<<2);
if(digitalRead(B4)==LOW) freePattern |= (1<<3);
if(digitalRead(B6)==LOW) freePattern |= (1<<4);
if(digitalRead(B5)==LOW) freePattern |= (1<<5);

u8g2.clearBuffer();
drawBrailleOLED(60,30,freePattern);
u8g2.sendBuffer();
}
}

In the deployment of my OLED display, I used an image converted into a byte array format, allowing the microcontroller to send pixel data that the screen can properly interpret.


The system is composed of two operating modes controlled through six push buttons, which together form a six-dot braille keyboard. Depending on the mode, some of these push buttons are also used to select a mode or exit the current one. This keyboard is mainly used in Mode 2, where it allows real-time visualization of which dots are active within the braille cell.

Mode 1:This mode allows the visualization of numbers together with their braille representation. The braille output is displayed using a 2×3 braille cell format, which corresponds to the standard braille writing structure. In later stages of the final project, this representation will be implemented with a solenoid array, where each solenoid corresponds to one dot of the braille cell.

Mode 2:In this mode, the user can manually activate the six dots using the buttons to create custom braille patterns. The system immediately shows which keys are being pressed and how the generated pattern is translated. It works both as a braille visualizer and as an interactive braille construction tool.