The objective of this week is to understand the behavior of digital signals and analog levels of various electronic components using the oscilloscope and, based on that learning, to design input systems for our board."
To understand the energy flow in a circuit, we will use and learn about the oscilloscope; in this case, we will use the SIGLENT SDS1102 model.
An oscilloscope is an electronic test instrument that displays varying voltage signals as a two-dimensional graph, with voltage on the vertical axis and time on the horizontal axis. It is used to analyze electrical signals' amplitude, frequency, and waveform in fields like engineering, telecommunications, and electronics.
Two small circuits will be built, and their signals will be read to note and understand the differences
1. The first circuit will be a PWM output signal sent to a servomotor
The Siglent SDS1102 is a 2-channel digital oscilloscope with 200 MHz bandwidth and 1 GSa/s sampling rate. Using SPO technology, it offers low noise, 14 Mpts memory, and up to 400,000 wfms/s capture rate. Features include advanced triggers, free serial bus decoding (IIC, SPI, UART, CAN, LIN), 1 Mpt FFT, and a 7-inch display with 256-level intensity grading.
2. The servomotor circuit is analyzed and allows explaining how PWM signals can be interpreted as angles for the servo.
#include Servo miServo; // Crear objeto Servo int pinServo = 9; // Pin donde está conectado el servo float tiempoCiclo = 5000.0; // Duración total del ciclo (5 segundos en ms) float medioCiclo = 2500.0; // Mitad del ciclo (2.5 segundos en ms) unsigned long tiempoInicio = 0; // Tiempo de inicio del ciclo bool mensajeEnviado0 = false; // Control para mensaje en 0 grados bool mensajeEnviado180 = false; // Control para mensaje en 180 grados void setup() { Serial.begin(9600); // Iniciar comunicación serie miServo.attach(pinServo); // Asignar el pin al servo miServo.write(0); // Iniciar en 0 grados Serial.println("Servo en 0 grados"); // Mensaje inicial tiempoInicio = millis(); // Registrar tiempo inicial } void loop() { unsigned long tiempoActual = millis(); // Tiempo actual float tiempoRelativo = (tiempoActual - tiempoInicio) % (unsigned long)tiempoCiclo; // Tiempo dentro del ciclo // Calcular ángulo con suavizado sinusoidal float angulo; if (tiempoRelativo <= medioCiclo) { // Ida: 0 a 180 grados (0 a 2.5 segundos) float fraccion = tiempoRelativo / medioCiclo; // Progreso de 0 a 1 angulo = 90.0 * (1.0 - cos(fraccion * PI)); // Suavizado sinusoidal } else { // Vuelta: 180 a 0 grados (2.5 a 5 segundos) float fraccion = (tiempoRelativo - medioCiclo) / medioCiclo; // Progreso de 0 a 1 angulo = 180.0 - 90.0 * (1.0 - cos(fraccion * PI)); // Suavizado sinusoidal } // Escribir ángulo en el servo miServo.write(round(angulo)); // Mostrar mensajes en los extremos if (angulo >= 179.5 && !mensajeEnviado180) { Serial.println("Servo en 180 grados"); mensajeEnviado180 = true; mensajeEnviado0 = false; // Reiniciar para próximo mensaje en 0 } else if (angulo <= 0.5 && !mensajeEnviado0) { Serial.println("Servo en 0 grados"); mensajeEnviado0 = true; mensajeEnviado180 = false; // Reiniciar para próximo mensaje en 180 } }
3. "The next exercise consists of understanding how a potentiometer works as a resistor that we can manage in an analog way and how the oscilloscope's curve changes.
This week's assignment is to test different inputs with the PCB I fabricated. I will try a limit switch module and an two buttons, so I will create small interfaces in the serial monitor to visualize the data.
1. A second exercise was developed to validate the use of Bluetooth. In this case, the goal was to create a remote camera trigger using Bluetooth Low Energy between the Seeed board and my cellphone.
2. The first part of the code block defines the interaction pins between the PCB and the limit switch, and also sets the initial state of the switch.
#define switchPin D1 // Limit switch on D1 (GPIO 1) int lastSwitchState = HIGH; // Pull-up, switch press is LOW int counter = 0; // Counter variable void setup() { // Empty setup to satisfy Arduino framework }
3. The second section defines the use of the serial monitor as an information exchange tool, allowing us to read the number of times the switch has been triggered.
void loop() { // One-time initialization static bool initialized = false; if (!initialized) { Serial.begin(115200); // Initialize Serial at 115200 baud pinMode(switchPin, INPUT_PULLUP); // D1 as input with pull-up Serial.println("Counter Started"); initialized = true; }
4. The final part is the function that progressively adds +1 to the previously recorded count each time the switch is clicked.
// Read the limit switch state int switchState = digitalRead(switchPin); // Detect a press (falling edge: HIGH to LOW) if (switchState == LOW && lastSwitchState == HIGH) { counter++; // Increment counter Serial.print("Click detected! Counter: "); Serial.println(counter); // Display counter value delay(50); // Simple debounce } lastSwitchState = switchState; }
5. The final result is evaluated by clicking the switch and observing how the monitor updates in real time.
6. The second exercise consists of a button-pressing competition, where two buttons and a protoboard become the game board.
7. First, the code starts by defining which pins the two buttons are connected to and sets up some variables to count how many times each button is pressed. It assumes the buttons are using a pull-up configuration, meaning they normally read as HIGH and drop to LOW when pressed.
#define button1Pin D3 // Button 1 on D3 (GPIO 3) #define button2Pin D1 // Button 2 on D2 (GPIO 2) int lastButton1State = HIGH; // Pull-up, button press is LOW int lastButton2State = HIGH; int button1Count = 0; // Counter for Button 1 int button2Count = 0; // Counter for Button 2
8. Next, inside the loop(), there's a one-time setup that runs the first time the code loops. It starts the Serial connection, defines the pins as inputs with pull-up resistors, and gives a little 5-second countdown before the button competition begins.
if (!initialized) { Serial.begin(115200); pinMode(button1Pin, INPUT_PULLUP); pinMode(button2Pin, INPUT_PULLUP); Serial.println("Counting will start in 5 seconds..."); delay(5000); Serial.println("Start!"); initialized = true; }
9. Then, the actual game begins. For 10 seconds, the code checks the state of each button to see if it's being pressed. Every time a button is clicked (from HIGH to LOW), it increases that button’s counter. It also prints out the state of each pin every 100 milliseconds so you can see it live. A short delay helps avoid counting the same press multiple times.
unsigned long startTime = millis(); while (millis() - startTime < 10000) { int button1State = digitalRead(button1Pin); int button2State = digitalRead(button2Pin); if (millis() - lastDebugTime >= 100) { Serial.print("D3 State: "); Serial.print(button1State); Serial.print(" | D2 State: "); Serial.println(button2State); lastDebugTime = millis(); } if (button1State == LOW && lastButton1State == HIGH) { button1Count++; Serial.println("D3 Press Detected"); delay(50); // Debounce } lastButton1State = button1State; if (button2State == LOW && lastButton2State == HIGH) { button2Count++; Serial.println("D2 Press Detected"); delay(50); // Debounce } lastButton2State = button2State; }
10. Finally, after the 10-second timer ends, the program checks which button was pressed the most. It then announces the winner—or a tie if the scores are the same. It prints out the total number of presses for each button.
Serial.println("Time's up!"); if (button1Count > button2Count) { Serial.println("Button D3 Winner"); } else if (button2Count > button1Count) { Serial.println("Button D2 Winner"); } else { Serial.println("Tie"); } Serial.print("D3 Presses: "); Serial.println(button1Count); Serial.print("D2 Presses: "); Serial.println(button2Count);
11. The final result is tested using the two buttons installed on the protoboard.
Arduino Code of Limit Switch Project Arduino Code of Buttons' Game