Estimados, buenos días! Es mi primer posteo, espero no estar cometiendo muchos errores.
Tengo un código que es de un proyecto en desarrollo, para una bomba de infusión a jeringa con un Arduino UNO, una pantalla OLED 0,96", y un driver para motor stepper A4988. Por ahora estoy haciendo el menú, el cual imprimo en el panel OLED, y tengo 4 pulsadores para moverme (arriba, abajo, atrás, adelante), un pulsador para OK, y otro para Cancelar. En este menú quiero modificar la cantidad de ml/h a infundir, y para ello quiero imprimir un número en pantalla como "000,00" en el que pueda desplazarme por dígito de adelante a atrás, y poder cambiar cada dígito por separado, del 0 al 9.
Cada submenú tiene un "case", y cada botón tiene un switch case con acciones para ese menú.
Tengo dos problemas:
Para mostrar el número "000,00" intento imprimir cada dígito con un vector "dosis[editPosición]", pero cuando intento imprimir en la pantalla OLED todos los valores en un bucle for() y cargo el código, el arduino se bloquea.
for (int j=0 ; j<5; j++){
oled.print(dosis[j]);
}
Carga el código sin errores de compilación, pero la pantalla se congela. Arduino no se resetea y no reacciona.
Si en lugar de esto, hago lo siguiente, Arduino UNO carga el código y funciona perfecto.
for (int j = 0; j < editPos + 1; j++) {
char dosisStr[2];
snprintf(dosisStr, sizeof(dosisStr), "%02d", dosis[j]);
oled.print(dosisStr);
}
Alguien podría explicarme por qué?
Además, quise iniciar "Serial.begin(9600)" para poder imprimir en serial algunas variables que me ayuden a entender qué sucede, pero en este caso también Arduino se bloquea luego de cargar el código, y tampoco entiendo por qué.
Dejo el código para ver si me pueden ayudar a entender qué sucede. Muchas gracias por sus aportes!
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Button.h>
// Define pantalla OLED
#define ANCHO 128
#define ALTO 64
#define OLED_RESET 4
Adafruit_SSD1306 oled(ANCHO, ALTO, &Wire, OLED_RESET);
//// Define pulsadores
#define BTN_ATRAS_PIN 7
#define BTN_ADELANTE_PIN 6
#define BTN_ARRIBA_PIN 9
#define BTN_ABAJO_PIN 8
#define BTN_OK_PIN 10 // Nuevo pulsador "OK"
#define BTN_CANCEL_PIN 11 // Nuevo pulsador "Cancel"
//
//// Define botones para librería Button, para hacer debouncing
Button btnAtras(BTN_ATRAS_PIN);
Button btnAdelante(BTN_ADELANTE_PIN);
Button btnArriba(BTN_ARRIBA_PIN);
Button btnAbajo(BTN_ABAJO_PIN);
Button btnOk(BTN_OK_PIN); // Nuevo botón "OK"
Button btnCancel(BTN_CANCEL_PIN); // Nuevo botón "Cancel"
//
#define MAX_JERINGAS 7 // Define el tamaño máximo de la matriz
struct Jeringas {
int numero;
char nombre[20];
float diametro;
float largo;
};
Jeringas matriz[MAX_JERINGAS];
int numJeringas = 0; // Variable para llevar el control del número de elementos en la matriz
int cuentaFilas = 0; // Variable para contar filas llenas de la matriz
int indiceMatriz = 0; // Indice para selección de jeringa
int dosis[5]= {1,2,3,4,5};// Valor inicial de la dosis
int editPos = 0; // Posición de edición: 0 para el primer dígito, 1 para el segundo, 2 para el tercero, 3 para el primer decimal y 4 para el segundo
//char dosisStr[8]; // Muestra el valor de la dosis formateado en la pantalla
enum MenuState { // Enumera opciones de menú
MENU_PRINCIPAL,
CONTINUAR_DOSIS,
CONFIRM_DOSIS,
NUEVA_DOSIS, // Empieza mostrando "Seleccionar jeringa"
SET_DOSIS,
OPTION_1,
OPTION_2,
NUEVA_JERINGA,
SET_JERINGA
};
MenuState currentMenuState = MENU_PRINCIPAL;
int opMenuPpal = 1; // Opción seleccionada en el menú principal
int opMenuJeringas = 1; // Opción seleccionada en menú jeringas
void setup() {
//Serial.begin(9600);
matriz[0].numero = 1;
strcpy(matriz[0].nombre, "B-D 5ml");
matriz[0].diametro = 11.99;
matriz[0].largo = 46.5;
matriz[1].numero = 2;
strcpy(matriz[1].nombre, "B-D 10ml");
matriz[1].diametro = 14.43;
matriz[1].largo = 69;
matriz[2].numero = 3;
strcpy(matriz[2].nombre, "B-D 20ml");
matriz[2].diametro = 19.05;
matriz[2].largo = 76;
matriz[3].numero = 4;
strcpy(matriz[3].nombre, "B-D 30ml");
matriz[3].diametro = 21.59;
matriz[3].largo = 87;
matriz[4].numero = 5;
strcpy(matriz[4].nombre, "B-D 60ml");
matriz[4].diametro = 26.59;
matriz[4].largo = 98;
for (int cuentaFilas = 0; cuentaFilas < MAX_JERINGAS; cuentaFilas++) {
// Verificar si la primera columna de la fila tiene datos válidos (por ejemplo, no es cero)
if (matriz[cuentaFilas].numero != 0) {
numJeringas++;
}
}
int nuevaFila = numJeringas; //Guarda el número de la última fila de matriz ocupada
matriz[nuevaFila].numero = numJeringas + 1; // Número único para "Nueva jeringa"
strcpy(matriz[nuevaFila].nombre, "Nueva jeringa");
matriz[nuevaFila].diametro = 0.0;
matriz[nuevaFila].largo = 0.0;
// Llamar a la función agregarJeringa() para añadir un nuevo elemento
//agregarJeringa(4, "Nombre4", 3.2, 12.1);
pinMode(BTN_ATRAS_PIN, INPUT_PULLUP);
pinMode(BTN_ADELANTE_PIN, INPUT_PULLUP);
pinMode(BTN_ARRIBA_PIN, INPUT_PULLUP);
pinMode(BTN_ABAJO_PIN, INPUT_PULLUP);
pinMode(BTN_OK_PIN, INPUT_PULLUP);
pinMode(BTN_CANCEL_PIN, INPUT_PULLUP);
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 0);
oled.println("Menu Principal");
oled.display();
//delay(2000);
}
void showMenu(MenuState state) {
oled.clearDisplay();
oled.setCursor(0, 0);
oled.setTextSize(1);
switch (state) {
case MENU_PRINCIPAL:
oled.print(opMenuPpal == 1 ? "> " : " ");
oled.println("1 Continuar dosis");
oled.print(opMenuPpal == 2 ? "> " : " ");
oled.println("2 Nueva dosis");
break;
case CONTINUAR_DOSIS:
oled.println("1.1 Confirmar?");
break;
case CONFIRM_DOSIS:
oled.println("Confirmada!");
break;
case NUEVA_DOSIS:
oled.println("Seleccionar jeringa");
for (int i = 0; i <= numJeringas; i++) {
oled.print(opMenuJeringas == (i + 1) ? "> " : " ");
oled.println(matriz[i].nombre);
}
break;
case SET_DOSIS:
oled.setCursor(0, 0);
oled.setTextSize(1);
oled.print(matriz[indiceMatriz].nombre);
oled.println(" seleccionada");
oled.println("Set dosis: ");
oled.setTextSize(2);
oled.setTextColor(WHITE);
oled.setCursor(10, 25);
for (int j = 0; j < editPos + 1; j++) {
//for (int j=0 ; j<5; j++){
//oled.print(dosis[j]);
char dosisStr[2];
snprintf(dosisStr, sizeof(dosisStr), "%02d", dosis[j]);
oled.print(dosisStr);
}
oled.println();
//oled.display();
break;
case NUEVA_JERINGA:
oled.println("Ingrese nueva jeringa");
break;
case SET_JERINGA:
oled.println("Diametro interno: ");
break;
}
oled.display();
}
void handleInput() {
if (btnArriba.pressed()) {
switch (currentMenuState) {
case MENU_PRINCIPAL:
opMenuPpal = opMenuPpal == 1 ? 2 : 1;
break;
case CONTINUAR_DOSIS:
break; // No action
case CONFIRM_DOSIS:
break; // No action
case NUEVA_DOSIS:
if(opMenuJeringas > 1){
opMenuJeringas --;
} else { opMenuJeringas = numJeringas+1;
};
break;
case SET_DOSIS:
dosis[editPos] = (dosis[editPos] + 1) % 10;
break;
}
}
if (btnAbajo.pressed()) {
switch (currentMenuState) {
case MENU_PRINCIPAL:
opMenuPpal = opMenuPpal == 2 ? 1 : 2;
break;
case CONTINUAR_DOSIS:
break; // No action
case NUEVA_DOSIS:
if(opMenuJeringas < numJeringas+1){
opMenuJeringas ++;
} else {
opMenuJeringas = 1;
}
break;
case SET_DOSIS:
dosis[editPos] = (dosis[editPos] - 1 + 10) % 10;
break; // No action
}
}
if (btnOk.pressed()) { // Nuevo botón "OK"
switch (currentMenuState) {
case MENU_PRINCIPAL:
if (opMenuPpal == 1)
currentMenuState = CONTINUAR_DOSIS;
else if (opMenuPpal == 2)
currentMenuState = NUEVA_DOSIS;
break;
// ...
case CONTINUAR_DOSIS:
currentMenuState = CONFIRM_DOSIS;
break;
case CONFIRM_DOSIS:
currentMenuState = MENU_PRINCIPAL;
break;
case NUEVA_DOSIS:
if (opMenuJeringas < numJeringas+1) {
indiceMatriz = opMenuJeringas-1;
currentMenuState = SET_DOSIS;
} else {
currentMenuState = SET_JERINGA;
}
break;
case SET_DOSIS:
break; // No action
case SET_JERINGA:
break; // No action
}
}
if (btnCancel.pressed()) { // Nuevo botón "Cancel"
switch (currentMenuState) {
case CONTINUAR_DOSIS:
currentMenuState = MENU_PRINCIPAL;
break;
case CONFIRM_DOSIS:
currentMenuState = CONTINUAR_DOSIS;
break;
case NUEVA_DOSIS:
currentMenuState = MENU_PRINCIPAL;
break;
case SET_DOSIS:
currentMenuState = NUEVA_DOSIS;
// Serial.println(dosisStr);
break;
case OPTION_1:
currentMenuState = NUEVA_DOSIS;
break;
case OPTION_2:
currentMenuState = NUEVA_DOSIS;
break;
case SET_JERINGA:
currentMenuState = NUEVA_DOSIS;
break;
}
}
if (btnAdelante.pressed()) {
switch (currentMenuState) {
case SET_DOSIS:
// Cambiar la posición de edición entre dígitos y decimales
editPos = (editPos + 1) % 5;
break;
}
}
if (btnAtras.pressed()) {
switch (currentMenuState) {
case SET_DOSIS:
// Cambiar la posición de edición entre dígitos y decimales
editPos = (editPos + 4) % 5;
break;
}
}
}
void loop() {
handleInput();
showMenu(currentMenuState);
//Serial.println(dosisStr);
}