#include <stdio.h> // Para imprimir mensajes en consola
#include "pico/stdlib.h" // Funciones básicas para la Raspberry Pi Pico
#include "hardware/gpio.h" // Para controlar los pines GPIO
#include "hardware/adc.h" // Para usar el ADC (lectura analógica)
#include "hardware/timer.h" // Para usar temporizadores
// Asignación de pines a los segmentos del display de 7 segmentos
#define segmA 7
#define segmB 11
#define segmC 2
#define segmd 4
#define segmE 5
#define segmf 8
#define segmG 1
#define segmdP 3 // Punto decimal
// Pines que activan cada uno de los 4 dígitos del display
#define dig1 6
#define dig2 9
#define dig3 10
#define dig4 0
#define button 26 // Pin del botón para cambiar entre voltaje y corriente
// Pines para medir voltaje y corriente con el ADC
#define ADC_VOLTAGE 28 // GPIO28 (canal 2)
#define ADC_CURRENT 27 // GPIO27 (canal 1)
// Tabla con los valores binarios que indican qué segmentos encender para mostrar del 0 al 9
const uint8_t segment_map[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111 // 9
};
// Variables globales
char display_buffer[5]; // Arreglo donde se guardan los dígitos a mostrar
int current_digit = 0; // Índice del dígito que se está mostrando
bool measure_current = false; // false = medir voltaje, true = medir corriente
// Función que configura los pines del display y el botón
void initialize_gpio() {
uint8_t segment_pins[] = {segmA, segmB, segmC, segmd, segmE, segmf, segmG, segmdP};
uint8_t digit_pins[] = {dig1, dig2, dig3, dig4};
// Configura cada pin de segmento como salida y lo apaga
for (int i = 0; i < sizeof(segment_pins) / sizeof(segment_pins[0]); i++) {
gpio_init(segment_pins[i]);
gpio_set_dir(segment_pins[i], GPIO_OUT);
gpio_put(segment_pins[i], 0);
}
// Configura cada pin de dígito como salida y lo apaga (1 en cátodo común)
for (int i = 0; i < sizeof(digit_pins) / sizeof(digit_pins[0]); i++) {
gpio_init(digit_pins[i]);
gpio_set_dir(digit_pins[i], GPIO_OUT);
gpio_put(digit_pins[i], 1);
}
// Configura el botón como entrada con resistencia pull-up interna
gpio_init(button);
gpio_set_dir(button, GPIO_IN);
gpio_pull_up(button);
}
// Muestra un dígito específico en el display
void display_digit(int index) {
uint8_t segment_pins[] = {segmA, segmB, segmC, segmd, segmE, segmf, segmG, segmdP};
uint8_t digit_pins[] = {dig1, dig2, dig3, dig4};
uint8_t segments = segment_map[display_buffer[index] - '0'];
// Si es el primer dígito, encender el punto decimal
if (index == 0) {
segments |= (1 << 7);
}
// Apagar todos los dígitos
for (int i = 0; i < sizeof(digit_pins) / sizeof(digit_pins[0]); i++) {
gpio_put(digit_pins[i], 1);
}
// Configurar los segmentos a encender
for (int i = 0; i < sizeof(segment_pins) / sizeof(segment_pins[0]); i++) {
gpio_put(segment_pins[i], (segments & (1 << i)) ? 1 : 0);
}
// Encender el dígito correspondiente
gpio_put(digit_pins[index], 0);
}
// Prepara el número (ej. 2.345) para mostrar en el display
void prepare_display(float value) {
int int_part = (int)value;
float frac_part = value - int_part;
display_buffer[0] = int_part + '0';
display_buffer[1] = (int)(frac_part * 10) % 10 + '0';
display_buffer[2] = (int)(frac_part * 100) % 10 + '0';
display_buffer[3] = (int)(frac_part * 1000) % 10 + '0';
display_buffer[4] = '\0';
printf("Mostrando: %s\n", display_buffer);
}
// Leer el voltaje del pin GPIO28 (canal 2)
float read_voltage() {
adc_select_input(2);
uint16_t raw_value = adc_read();
return raw_value * (3.3f / 4095.0f);
}
// Leer la corriente del pin GPIO27 (canal 1)
float read_current() {
adc_select_input(1);
uint16_t raw_value = adc_read();
return raw_value * (3.3f / 4095.0f) / 3.3f;
}
// Interrupción cuando se presiona el botón
void button_interrupt(uint gpio, uint32_t events) {
measure_current = !measure_current; // Cambia el modo
printf("Modo cambiado: %s\n", measure_current ? "Corriente" : "Voltaje");
}
// Refresca el dígito del display en cada ciclo
bool refresh_display(repeating_timer_t *t) {
display_digit(current_digit);
current_digit = (current_digit + 1) % 4;
return true;
}
// Función principal
int main() {
stdio_init_all(); // Inicializa entrada/salida (USB)
// Inicializa ADC y pines del ADC
adc_init();
adc_gpio_init(ADC_VOLTAGE);
adc_gpio_init(ADC_CURRENT);
// Inicializa GPIOs del display y botón
initialize_gpio();
// Configura la interrupción del botón
gpio_set_irq_enabled_with_callback(button, GPIO_IRQ_EDGE_RISE, true, &button_interrupt);
// Configura temporizador para refrescar el display cada 20 ms
repeating_timer_t timer;
add_repeating_timer_ms(20, refresh_display, NULL, &timer);
// Bucle principal
while (1) {
float measurement;
// Medir corriente o voltaje dependiendo del modo
if (measure_current) {
measurement = read_current();
printf("Corriente: %.3f A\n", measurement);
} else {
measurement = read_voltage();
printf("Voltaje: %.3f V\n", measurement);
}
// Preparar el valor para mostrar en el display
prepare_display(measurement);
sleep_ms(500); // Espera antes de la siguiente lectura
}
return 0;
}