9. Input Devices




💧 Sensing everything

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."

Imagen

Learning Plan:

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.


💧 Research Objectives & Workflow

Two small circuits will be built, and their signals will be read to note and understand the differences

Imagen

💧 Learning to use the equipment (Group Asignment)

1. The first circuit will be a PWM output signal sent to a servomotor

Imagen

Oscilloscope SIGLENT SDS1102

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.

Imagen
            
    #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.

Imagen
            
    #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
  }
}
            
            

💧 Feeling Things (Personal Asingment)

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.

Imagen

💧 Two little games (Personal Asignment)

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.

Imagen

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.

Imagen

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.

Imagen
Imagen

💧 Downloadable Files

Arduino Code of Limit Switch Project

Arduino Code of Buttons' Game