Contador de piezas

Buenas trades

Estoy realizando un proyecto de un contador de piezas con arduino, estoy usando un tecldo matricial par ingresar la cantidad a contar una pantalla lcd 16x2 con interfaz i2c y un sensor infrarojo coar contar las piezas y quiero agregarle un motor paso a paso que gire una banda cuando inicie el contador y se detenga cuando el sensor temine de contar las piezas ingrsadas con el teclado.

la cuestion es que no logro que el motor gire y el sensor cuente a la vez

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Stepper.h>

// Inicializar el LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Definir el teclado matricial
const byte ROWS = 4;
const byte COLS = 3;
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; 
byte colPins[COLS] = {5, 4, 3};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// Definir el pin del sensor infrarrojo
const int sensorPin = 2;

// Definir los pines del motor paso a pas 
#define STEPS 2038 // Número de pasos para una vuelta completa (28BYJ-48)
#define IN1 10
#define IN2 11
#define IN3 12
#define IN4 13 

// Crear un objeto de la clase Stepper
Stepper stepper(STEPS, IN1, IN3, IN2, IN4);

int cantidadPiezas = 0;
int piezasContadas = 0;
bool nuevoConteo = false;

void setup() {
  // Inicializar el LCD
  lcd.init();
  lcd.backlight();

  // Inicializar el motor paso a paso
  stepper.setSpeed(15); // Velocidad baja para 28BYJ-48

  // Mostrar instrucciones iniciales en el LCD
  lcd.setCursor(0, 0);
  lcd.print("Ingrese cantidad");
  lcd.setCursor(0, 1);
  lcd.print("de piezas:");
}

void loop() {
  // Leer la entrada del teclado
  char key = keypad.getKey();
  
  // Si se presiona un número, actualizar la cantidad de piezas
  if (key >= '0' && key <= '9') {
    // Convertir el carácter numérico a un entero y sumarlo a la cantidad actual
    int numero = key - '0';
    cantidadPiezas = cantidadPiezas * 10 + numero;
    
    // Actualizar el LCD con la cantidad ingresada
    lcd.setCursor(0, 1);
    lcd.print("              "); // Limpiar la línea anterior
    lcd.setCursor(0, 1);
    lcd.print("Ingresada: ");
    lcd.print(cantidadPiezas);
    
    delay(200); // Pequeño retardo para evitar rebotes del botón
  } else if (key == '#') { // Si se presiona '#', comenzar a contar con el sensor infrarrojo
    // Limpiar el LCD
    lcd.clear();
    
// 

    // Mostrar mensaje de inicio de conteo en el LCD
    lcd.setCursor(0, 0);
    lcd.print("Ingresada: ");
    lcd.print(cantidadPiezas);
    lcd.setCursor(0, 1);
    lcd.print("Contando...");
    
    //Iniciar el motor paso a paso
    stepper.step(STEPS * cantidadPiezas);

    // Establecer la cantidad contada como cero
    piezasContadas = 0;
    // Iniciar el conteo de piezas
    while (piezasContadas < cantidadPiezas) {
      if (digitalRead(sensorPin) == HIGH) {
        // Si se detecta una pieza, incrementar el contador de piezas contadas
        piezasContadas++;
        // Actualizar el LCD con la cantidad contada
        lcd.setCursor(0, 1);
        lcd.print("Contando: ");
        lcd.print(piezasContadas);
        delay(100); // Retardo para evitar contar varias veces la misma pieza
      }
      // Verificar si se ha solicitado un nuevo conteo
      if (nuevoConteo) {
        nuevoConteo = false;
        break;
      }
    }
    
    // Detener el motor paso a paso
    stepper.step(0);

    // Mostrar mensaje de finalización en el LCD
    lcd.clear();
    lcd.print("Conteo completo!");
    
    // Esperar un momento antes de mostrar la cantidad contada
    delay(2000);
    
    // Mostrar la cantidad contada en el LCD
    lcd.clear();
    lcd.print("Contadas: ");
    lcd.print(piezasContadas);
    // Esperar hasta que se presione una tecla para volver a ingresar la cantidad
    while (keypad.getKey() != '#');
    // Limpiar el LCD y reiniciar la cantidad de piezas
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Ingrese cantidad");
    lcd.setCursor(0, 1);
    lcd.print("de piezas:");
    cantidadPiezas = 0;
  } else if (key == '*') { // Si se presiona '*', solicitar nuevo conteo
    nuevoConteo = true;
  }
}

El motor solo funciona?

Buenas noches
si primero funciona el motor luego se detiene y enpieza a funcinar el sensor

Tu problema es que el pin 2 del sensor no esta definido en el setup.
agrega esto en el setup.

void setup() {
  // Inicializar el LCD
  pinMode(sensorPin, INPUT);

Buenas noches
muchas gracias por la respuesta , ya realice el cambio que me dices sin embargo sigue haciendo lo mismo

No estoy muy ducho con la librería Stepper pero entiendo que tu código primero mueve la cinta lo necesario para que pasen todas las piezas (con la función step(), que es bloqueante y solo termina cuando se han dado los pasos indicados) y después entra en un lazo while() en el que, se supone, cuenta las piezas.

El problema es que las piezas ya pasaron y no hay nada por contar, entonces el código queda "encerrado" en el lazo.

Correcto eso es lo que secede

Yo simulé todo tu código.
Le puse el pulsador a modo de sensor y funcionó perfectamente.

No pretendo discutir pero el código de #1 hace lo que explico en #6 no lo que el PO pretende que haga.

La razón es sencilla, la función step() es bloqueante (y está aclarado en el código de la librería), entonces hasta que no avanza los pasos que se le han pasado como parámetro no termina.
Como resultado (y porque es lo que está en el código) la cinta avanza arrastrando todas las piezas y cuando se detiene recién intenta contar las piezas que, obviamente, ya pasaron por el sensor. O sea, ya no hay nada que contar y allí se queda esperando que algo pase por delante.

Lo que se debe hacer es avanzar la cinta desde dentro del lazo que cuenta las piezas hasta llegar a la cantidad de piezas solicitadas.

Buenas noches
No te entiendo cuando te refieres al pulsador ?

Lo simulé en Wokwi y como no puedo simular el sensor optico le puse un pulsador.

Vale
Despues de analizar el codigo me he dado cuenta que tendre que usar la funcion millis para que me realice las dos opreaciones a la vez.

Decidi cambiar algunas piezas en el montaje usar un encoder en vez del teclado y una pantalla oled 128x64 0.96 y un servo en vez del motor paso a paso.

sin embargo no logro que me funcione el codigo lo cargo y la pantalla entra a los menus sola y parpadea y el servo se mueve adelante y atras.

#include "U8glib.h"
#include <Servo.h> 

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); 

#define tamano_menu 2
int posicion_menu = 0; //Variable de la posicion del marco en el menu principal
int numero = 0; //Variable del menu Separar1
int cuenta=0; //Variable del menu contar
int tracker=0; //Variable auxiliar para saber en que menu estoy
int valor_boton=0; //Variable para leer el valor del boton
Servo servo;
long int temporizador= 0;

#define encoder0PinA  2 //Variables del encoder pin A
#define encoder0PinB  4 //Variables del encoder pin B 
#define boton 7        //Variables del encoder boton
#define sensor 3

volatile unsigned int valor_sensor = 0;

void drawMenu(void) {

  char *menu[tamano_menu] = {"Contar tuercas", "Separar tuercas"  };
  int i=0;

  tracker=1;

  for (i=0; i<tamano_menu; i++) {  

    u8g.setFontPosTop();
    int ancho = u8g.getStrWidth(menu[i]);
    int margen_ancho = (128-ancho)/2;
    int altura = u8g.getFontAscent()-u8g.getFontDescent();
    int margen_alto = (48-(altura*tamano_menu))/tamano_menu+1;

    u8g.setFont(u8g_font_unifont);
    u8g.drawStr( margen_ancho, margen_alto*(i+1)+altura*i, menu[i]);

    if ( i == posicion_menu ) {
      u8g.drawFrame(margen_ancho-3, (margen_alto*(i+1)+altura*i)-1 , ancho+6, altura+4);
    }
  }

}



void drawContar (void) {
  int l=0, m=0;
  char *texto_contar[2] = {"Pulsa el encoder", "para salir"};
  
  tracker=2;
  
  u8g.setFontPosTop();
  u8g.setFont(u8g_font_unifont);
  
  for (l=0;l<2;l++){ 
  u8g.drawStr(0,44+16*l,texto_contar[l]);}
  
  u8g.setFontPosTop();
  u8g.setFont(u8g_font_ncenR18);
  int ancho_fuente2 = 10;
  int margen_ancho3 = (128-4*ancho_fuente2)/2;
  int altura3 = u8g.getFontAscent()-u8g.getFontDescent();
  int margen_alto3 = 24;
  
  if (cuenta<10) {m=3;}
   else if (cuenta>=10&&cuenta<100) {m=2;}
    else if (cuenta>=100&&cuenta<1000) {m=1;}
     else {m=0;}
     
  u8g.setPrintPos(margen_ancho3+ancho_fuente2*m, margen_alto3);
  u8g.print(cuenta);

}



void drawSeparar1(void) {

  int j=0, k=0;  
  char *texto_separar[3] = {"Seleccione el numero", "de tuercas que desea", "separar"  }; 

  tracker=3;

  u8g.setFontPosTop();
  u8g.setFont(u8g_font_6x13);
  for(k=0;k<3;k++){
    u8g.drawStr(3, 13*(k+1), texto_separar[k]);
  }

  u8g.setFontPosTop();
  u8g.setFont(u8g_font_gdr14);
  int ancho_fuente = 10;
  int margen_ancho2 = (128-4*ancho_fuente)/2;
  int altura2 = u8g.getFontAscent()-u8g.getFontDescent();
  int margen_alto2 = 60;

  if (numero<10) {j=3;}
   else if (numero>=10&&numero<100) {j=2;}
    else if (numero>=100&&numero<1000) {j=1;}
     else {j=0;}

  u8g.setPrintPos(margen_ancho2+ancho_fuente*j, margen_alto2);
  u8g.print(numero);

}



void doEncoder() {
  
  /* If pinA and pinB are both high or both low, it is spinning
   * forward. If they're different, it's going backward.
   */
  
  if (tracker==1) {
     
    if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
     posicion_menu++;
     if(posicion_menu>1) {posicion_menu=1;}
    }
    else {
     posicion_menu--;
     if (posicion_menu<0) {posicion_menu=0;}  
    }
  }
  
  
  else if (tracker==3) {
  
    if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
     numero++;
     if(numero>9999) {numero=9999;}
    }
    else {
     numero--;
     if (numero<0) {numero=0;}  
    }
  }
  
}


void sensor_IR (){
  valor_sensor = digitalRead(sensor);
  if (valor_sensor=HIGH&&millis()-temporizador>=50)
  {cuenta++;
  temporizador=millis();
  }
}



void setup(void) {

 pinMode(encoder0PinA, INPUT_PULLUP);
 pinMode(encoder0PinB, INPUT_PULLUP);
 pinMode(sensor, INPUT); 
 pinMode(boton, INPUT_PULLUP); 
 
 servo.attach(9);
   
 attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
 attachInterrupt(1, sensor_IR, FALLING); //encoder boton on interrupt 1 - pin 3
 Serial.begin (9600); 
 
 
 
}



void loop(void) {
  
  u8g.firstPage();  
  do {
  drawMenu();
  } 
  while( u8g.nextPage() );
  
  int valor_boton = digitalRead(boton);
  delay(10);
  
  if (posicion_menu==0 && valor_boton) {
   cuenta=0;
   servo.write(100);
   delay(500);
   
    do{
     valor_boton = digitalRead(boton);
     
     u8g.firstPage();  
      do {
      drawContar();
      } 
     while( u8g.nextPage());
    } 
   while(valor_boton==0);
  
  servo.write(90);
  }
  
  if (posicion_menu==1&&valor_boton) {
   delay(500);
   
   do{
    valor_boton = digitalRead(boton);
    u8g.firstPage();  
    do {
    drawSeparar1();
    } 
    while( u8g.nextPage() );
   } while(valor_boton==0);
   numero=0;
  }

}

Trabajar con millis() no se asemeja en nada a lo que se programa usando delay()
Con delay() tu programa va paso a paso, o sea, es secuencial y en general no tienes problemas porque es como la manera mas usual de programar.

Cuando usas millis() el código sigue ejecutándose y no se detiene salvo para comprobar el condicional. Cuando dicho condicional se cumple realizas algo. Ahi radica la gran diferencia.
Entonces. millis() requiere que separes las acciones por estados lógicos. A es se lo llama máquina de estados y es un concepto que no conoces seguramente.
Luego miro tu código a ver donde puede estar el problema.
Seguro edito este mismo post si nadie mas lo hace.

El servo de mueve de 0° a 180°? Cómo se controla el avance de la banda?

Si estas en lo correcto el servo no funciona comparto el nuevo codigo con el motor paso a paso.

#include "U8glib.h"
#include <AccelStepper.h>

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); 

#define tamano_menu 2
int posicion_menu = 0;
int numero = 0;
int cuenta = 0;
int tracker = 0;
int valor_boton = 0;
long int temporizador = 0;

#define encoder0PinA  2
#define encoder0PinB  4
#define boton 7
#define sensor 3

volatile unsigned int valor_sensor = 0;

// Definición de pines para el motor paso a paso
#define motorPasoPasoPin1 8
#define motorPasoPasoPin2 9
#define motorPasoPasoPin3 10
#define motorPasoPasoPin4 11

// Inicialización del motor paso a paso
AccelStepper stepper(1, motorPasoPasoPin1, motorPasoPasoPin3, motorPasoPasoPin2, motorPasoPasoPin4);

void drawMenu(void) {
    char *menu[tamano_menu] = {"Contar tuercas", "Separar tuercas"  };

    tracker = 1;

    for (int i = 0; i < tamano_menu; i++) {  
        u8g.setFontPosTop();
        int ancho = u8g.getStrWidth(menu[i]);
        int margen_ancho = (128 - ancho) / 2;
        int altura = u8g.getFontAscent() - u8g.getFontDescent();
        int margen_alto = (48 - (altura * tamano_menu)) / tamano_menu + 1;

        u8g.setFont(u8g_font_unifont);
        u8g.drawStr(margen_ancho, margen_alto * (i + 1) + altura * i, menu[i]);

        if (i == posicion_menu) {
            u8g.drawFrame(margen_ancho - 3, (margen_alto * (i + 1) + altura * i) - 1 , ancho + 6, altura + 4);
        }
    }
}

void drawContar(void) {
    char *texto_contar[2] = {"Pulsa el encoder", "para salir"};

    tracker = 2;

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_unifont);

    for (int l = 0; l < 2; l++) { 
        u8g.drawStr(0, 44 + 16 * l, texto_contar[l]);
    }

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_ncenR18);
    int ancho_fuente2 = 10;
    int margen_ancho3 = (128 - 4 * ancho_fuente2) / 2;
    int altura3 = u8g.getFontAscent() - u8g.getFontDescent();
    int margen_alto3 = 24;

    int m = cuenta < 10 ? 3 : (cuenta >= 10 && cuenta < 100) ? 2 : (cuenta >= 100 && cuenta < 1000) ? 1 : 0;

    u8g.setPrintPos(margen_ancho3 + ancho_fuente2 * m, margen_alto3);
    u8g.print(cuenta);
}

void drawSeparar1(void) {
    char *texto_separar[3] = {"Seleccione el numero", "de tuercas que desea", "separar"};

    tracker = 3;

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_6x13);
    
    for (int k = 0; k < 3; k++) {
        u8g.drawStr(3, 13 * (k + 1), texto_separar[k]);
    }

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_gdr14);
    int ancho_fuente = 10;
    int margen_ancho2 = (128 - 4 * ancho_fuente) / 2;
    int altura2 = u8g.getFontAscent() - u8g.getFontDescent();
    int margen_alto2 = 60;

    int j = numero < 10 ? 3 : (numero >= 10 && numero < 100) ? 2 : (numero >= 100 && numero < 1000) ? 1 : 0;

    u8g.setPrintPos(margen_ancho2 + ancho_fuente * j, margen_alto2);
    u8g.print(numero);
}

void doEncoder() {
    if (tracker == 1) {
        if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
            posicion_menu++;
            if (posicion_menu > 1) {
                posicion_menu = 1;
            }
        } else {
            posicion_menu--;
            if (posicion_menu < 0) {
                posicion_menu = 0;
            }  
        }
    } else if (tracker == 3) {
        if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
            numero++;
            if (numero > 9999) {
                numero = 9999;
            }
        } else {
            numero--;
            if (numero < 0) {
                numero = 0;
            }  
        }
    }
}

void sensor_IR() {
    valor_sensor = digitalRead(sensor);
    if (valor_sensor == HIGH && millis() - temporizador >= 50) {
        cuenta++;
        temporizador = millis();
    }
}

void setup(void) {
    pinMode(encoder0PinA, INPUT_PULLUP);
    pinMode(encoder0PinB, INPUT_PULLUP);
    pinMode(sensor, INPUT); 
    pinMode(boton, INPUT_PULLUP);

    // Configuración del motor paso a paso
    stepper.setMaxSpeed(1000);
    stepper.setAcceleration(100);

    attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
    attachInterrupt(1, sensor_IR, FALLING); // encoder boton on interrupt 1 - pin 3

    Serial.begin(9600); 
}

void loop(void) {
    u8g.firstPage();  
    do {
        drawMenu();
    } while (u8g.nextPage());

Parece que no subió completo...

y con este no me compila me supera el maximo de bytes

#include "U8glib.h"
#include <AccelStepper.h>

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); 

#define TAMANO_MENU 2

#define ENCODER_PIN_A  2
#define ENCODER_PIN_B  4
#define BOTON_PIN 7
#define SENSOR_PIN 3

// Definición de pines para el motor paso a paso
#define MOTOR_PIN_1 8
#define MOTOR_PIN_2 9
#define MOTOR_PIN_3 10
#define MOTOR_PIN_4 11

AccelStepper stepper(1, MOTOR_PIN_1, MOTOR_PIN_3, MOTOR_PIN_2, MOTOR_PIN_4);

int posicion_menu = 0;
int numero = 0;
int cuenta = 0;
int tracker = 0;
unsigned long temporizador = 0;

volatile unsigned int valor_sensor = 0;

void drawMenu(void) {
    char *menu[TAMANO_MENU] = {"Contar tuercas", "Separar tuercas"  };

    tracker = 1;

    for (int i = 0; i < TAMANO_MENU; i++) {  
        u8g.setFontPosTop();
        int ancho = u8g.getStrWidth(menu[i]);
        int margen_ancho = (128 - ancho) / 2;
        int altura = u8g.getFontAscent() - u8g.getFontDescent();
        int margen_alto = (48 - (altura * TAMANO_MENU)) / TAMANO_MENU + 1;

        u8g.setFont(u8g_font_unifont);
        u8g.drawStr(margen_ancho, margen_alto * (i + 1) + altura * i, menu[i]);

        if (i == posicion_menu) {
            u8g.drawFrame(margen_ancho - 3, (margen_alto * (i + 1) + altura * i) - 1 , ancho + 6, altura + 4);
        }
    }
}

void drawContar(void) {
    char *texto_contar[2] = {"Pulsa el encoder", "para salir"};

    tracker = 2;

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_unifont);

    for (int l = 0; l < 2; l++) { 
        u8g.drawStr(0, 44 + 16 * l, texto_contar[l]);
    }

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_ncenR18);
    int ancho_fuente2 = 10;
    int margen_ancho3 = (128 - 4 * ancho_fuente2) / 2;
    int altura3 = u8g.getFontAscent() - u8g.getFontDescent();
    int margen_alto3 = 24;

    int m = cuenta < 10 ? 3 : (cuenta < 100) ? 2 : (cuenta < 1000) ? 1 : 0;

    u8g.setPrintPos(margen_ancho3 + ancho_fuente2 * m, margen_alto3);
    u8g.print(cuenta);
}

void drawSeparar1(void) {
    char *texto_separar[3] = {"Seleccione el numero", "de tuercas que desea", "separar"};

    tracker = 3;

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_6x13);
    
    for (int k = 0; k < 3; k++) {
        u8g.drawStr(3, 13 * (k + 1), texto_separar[k]);
    }

    u8g.setFontPosTop();
    u8g.setFont(u8g_font_gdr14);
    int ancho_fuente = 10;
    int margen_ancho2 = (128 - 4 * ancho_fuente) / 2;
    int altura2 = u8g.getFontAscent() - u8g.getFontDescent();
    int margen_alto2 = 60;

    int j = numero < 10 ? 3 : (numero < 100) ? 2 : (numero < 1000) ? 1 : 0;

    u8g.setPrintPos(margen_ancho2 + ancho_fuente * j, margen_alto2);
    u8g.print(numero);
}

void doEncoder() {
    if (tracker == 1) {
        if (digitalRead(ENCODER_PIN_A) == digitalRead(ENCODER_PIN_B)) {
            posicion_menu = constrain(posicion_menu + 1, 0, TAMANO_MENU - 1);
        } else {
            posicion_menu = constrain(posicion_menu - 1, 0, TAMANO_MENU - 1);
        }
    } else if (tracker == 3) {
        if (digitalRead(ENCODER_PIN_A) == digitalRead(ENCODER_PIN_B)) {
            numero = min(numero + 1, 9999);
        } else {
            numero = max(numero - 1, 0);
        }
    }
}

void sensor_IR() {
    valor_sensor = digitalRead(SENSOR_PIN);
    if (valor_sensor == HIGH && millis() - temporizador >= 50) {
        cuenta++;
        temporizador = millis();
    }
}

void setup(void) {
    pinMode(ENCODER_PIN_A, INPUT_PULLUP);
    pinMode(ENCODER_PIN_B, INPUT_PULLUP);
    pinMode(SENSOR_PIN, INPUT); 
    pinMode(BOTON_PIN, INPUT_PULLUP);

    // Configuración del motor paso a paso
    stepper.setMaxSpeed(1000);
    stepper.setAcceleration(100);

    attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
    attachInterrupt(1, sensor_IR, FALLING); // encoder boton on interrupt 1 - pin 3

    Serial.begin(9600); 
}

void loop(void) {
    u8g.firstPage();  
    do {
        drawMenu();
    } while (u8g.nextPage());
    
    int valor_boton = digitalRead(BOTON_PIN);
    delay(10);

    if (posicion_menu == 0 && valor_boton) {
        cuenta = 0;
        stepper.moveTo(100); // Mover el motor paso a paso a una posición específica
        stepper.runToPosition(); // Ejecutar el movimiento
        delay(500);
        
        do {
            valor_boton = digitalRead(BOTON_PIN);
            u8g.firstPage();  
            do {
                drawContar();
            } while (u8g.nextPage());
        } while (valor_boton == 0);

        stepper.moveTo(0); // Mover el motor paso a paso a la posición inicial
        stepper.runToPosition(); // Ejecutar el movimiento
    }

    if (posicion_menu == 1 && valor_boton) {
        delay(500);
        
        do {
            valor_boton = digitalRead(BOTON_PIN);
            u8g.firstPage();  
            do {
                drawSeparar1();
            } while (u8g.nextPage());
        } while (valor_boton == 0);
        
        numero = 0;
    }
}

Buena tardes ya logre que funcionara sin embargo use un encoder y hay veces cuando lo giro muy rapido no estn presiso y quisiera cambiarlo por un tecldo matrcial 4x3 algien me puede orientar

#include "U8glib.h"
#include <Servo.h>

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);

#define encoder0PinA  2
#define encoder0PinB  4
#define boton 7
#define sensor 3

volatile unsigned long lastEncoded = 0;
volatile long encoderValor = 0;
int numeroFijo = 10;
int key2 = 0;
int cuenta = 0;
int aux1 = 0;
int aux2 = 0;
int tracker = 0;
Servo servo;
const int pinServo = 11;

void setup() {
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);
  pinMode(boton, INPUT_PULLUP);
  pinMode(sensor, INPUT);

  servo.attach(9);
  pinMode(pinServo, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(encoder0PinA), doEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoder0PinB), doEncoder, CHANGE);
  attachInterrupt(1, sensor_IR, FALLING);
  Serial.begin(9600);

  u8g.setFont(u8g_font_6x10);
}

void sensor_IR() {
  unsigned int valor_sensor = digitalRead(sensor);
  static unsigned long temporizador = 0;

  if (valor_sensor = HIGH && millis() - temporizador >= 50) {
    cuenta++;
    temporizador = millis();
  }
}

void drawMenu() {
  u8g.firstPage();
  do {
    u8g.setFont(u8g_font_7x13B);
    u8g.drawStr(0, 30, tracker == 0 ? "> CONTAR TUERCAS" : "  Contar Tuercas");
    u8g.drawStr(0, 50, tracker == 1 ? "> SEPARAR TUERCAS" : "  Separar Tuercas");
  } while (u8g.nextPage());
}

void drawContar() {
  u8g.firstPage();
  int m = 0;
  servo.write(120);

  do {
    //u8g.setFont(u8g_font_6x10);
    //u8g.drawStr(0, 10, "Contar Tuercas:");
    u8g.setFont(u8g_font_9x18B);
    u8g.setPrintPos(0, 30);
    u8g.print("CONTADOR: ");
    u8g.print(cuenta);
    u8g.setFont(u8g_font_6x10);
    u8g.drawStr(0, 60, "Push botton exit");

    if (cuenta < 10) {
      m = 3;
    } else if (cuenta >= 10 && cuenta < 100) {
      m = 2;
    } else if (cuenta >= 100 && cuenta < 1000) {
      m = 1;
    } else {
      m = 0;
    }
  }
  while (u8g.nextPage());
}

void drawSeparar1() {
  int k = 0;
  u8g.firstPage();
  do {
    u8g.setFont(u8g_font_9x18B);
    u8g.setPrintPos(0, 10);
    u8g.print("SEPARAR:  ");
    u8g.print(aux1);
    u8g.setFont(u8g_font_9x18B);
    u8g.setPrintPos(0, 40);
    u8g.print("CONTEO:  ");
    u8g.print(aux2);

    if (encoderValor < 10) {
      k = 3;
    } else if (encoderValor >= 10 && encoderValor < 100) {
      k = 2;
    } else if (encoderValor >= 100 && encoderValor < 1000) {
      k = 1;
    } else {
      k = 0;
    }
  } while (u8g.nextPage());
}

void doEncoder() {
  unsigned long now = micros();
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = now;

  if (interruptTime - lastInterruptTime > 1000) {
    int MSB = digitalRead(encoder0PinA);
    int LSB = digitalRead(encoder0PinB);
    int encoded = (MSB << 1) | LSB;
    int sum = (lastEncoded << 2) | encoded;

    if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
      if (tracker < 1) {
        tracker++;
      }
    } else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
      if (tracker > 0) {
        tracker--;
      }
    }

    lastEncoded = encoded;
    lastInterruptTime = interruptTime;
  }
}

void doEncoderSeparar() {
  unsigned long now = micros();
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = now;

  if (interruptTime - lastInterruptTime > 100) { // Reducir el tiempo de espera a 100 microsegundos
    int MSB = digitalRead(encoder0PinA);
    int LSB = digitalRead(encoder0PinB);
    int encoded = (MSB << 1) | LSB;
    int sum = (lastEncoded << 2) | encoded;

    if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
      cuenta++;
    } else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
      cuenta--;
    }

    lastEncoded = encoded;

    if (encoderValor < 1) {
      encoderValor = 1;
    } else if (encoderValor > 100) {
      encoderValor = 100;
    }

    if (aux1 == aux2 && key2 == 1) {
      
      numeroFijo = 0;
      
    }

    aux2 = cuenta - 2;

    if (digitalRead(boton) == LOW) {
      delay(50); //filtro rebotes
      if (digitalRead(boton) == LOW) { 
        aux1 = aux2;
        cuenta = 2;
        key2 = 1;
        digitalWrite(pinServo, HIGH);
        servo.write(120);
      }
    }

    lastInterruptTime = interruptTime;
  }
}


void loop() {
  if (tracker == 0) {
    digitalWrite(pinServo, LOW);
    drawMenu();
    if (digitalRead(boton) == LOW) {
      while (digitalRead(boton) == LOW);
      tracker = 2;
      encoderValor = 0;
      cuenta = 0;
    }
  } 
  
  else if (tracker == 1) {
    digitalWrite(pinServo, LOW);
    drawMenu();
    if (digitalRead(boton) == LOW) {
      while (digitalRead(boton) == LOW);
      tracker = 3;
      encoderValor = 0;
      cuenta = 0;
    }
    sensor_IR();
  } 
  
  else if (tracker == 2) {
    digitalWrite(pinServo, HIGH);
    servo.write(120);
    drawContar();
    if (digitalRead(boton) == LOW) {
      while (digitalRead(boton) == LOW);
      tracker = 0;
      cuenta = 0;
    }
  } 
  
  else if (tracker == 3) {

    drawSeparar1();
    doEncoderSeparar();
  
    if (numeroFijo == 0 && aux2 == aux1) {
      digitalWrite(pinServo, LOW);

      drawSeparar1();
      delay(5000);
      
      cuenta = 0;
      aux1 = 0;
      numeroFijo = 1;
      tracker = 0;
      key2 = 0;
    }
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.