Control velocidad Nema-17 con encoder

Buenas tardes amigos, no consigo controlar la velocidad del motor a pasos, con el encoder, ahora estoy usando un potenciómetro de precisión, vía analógico, funciona bien pero el encoder me dará mas seguridad, ya que se trata de una bomba peristáltica para dosificación de químicos, y se requiere de exactitud para conseguir una mezcla perfecta, estos son los códigos que tengo.

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

int CLK = 2;
int DT = 3;
int SW = 4;
int Bomba = 5;
int paro = 6;

int anteriorCLK;
int valorCLK;
int valorDT;
int valorSW;
int anteriorSW;
int cont;

void setup() {

Wire.begin();
lcd.begin(16, 2);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
Serial.begin(9600);

pinMode(Bomba, OUTPUT);
pinMode(paro, OUTPUT);
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT);
digitalWrite(Bomba, LOW);
digitalWrite(paro, LOW);
anteriorCLK = digitalRead(CLK);
cont = 0;
}

void loop() {
valorCLK = digitalRead(CLK);
if (valorCLK != anteriorCLK) {
  valorDT = digitalRead(DT);
  if (valorDT == valorCLK) { //derecha
    cont++;
    if (cont > 255) {
      cont = 0;
    }
  } else { //izquierda
    cont--;
    if (cont < 0) {
      cont = 255;
    }
  }
  analogWrite(Bomba, cont);
  anteriorCLK = valorCLK;
  Serial.print("velocidad ");
  Serial.println(valorDT);
  lcd.setCursor(0, 0);
  lcd.print("velocidad   ");
  lcd.print(valorDT);
}
valorSW = digitalRead(SW);
if (valorSW != anteriorSW) {
  valorSW = digitalRead(SW);
  digitalWrite(paro, HIGH);
  Serial.print("stop ");
  Serial.println(valorSW);
  lcd.setCursor(1, 0);
  lcd.print("stop   ");
  lcd.print(valorSW);

}
}

Este es el que quiero que funcione


 
int steps = 5;       // pin step 9
int direccion = 2;   // pin dirección 3
int potenciometro;   // lectura del potenciómetro
//int boton = 7;       // pin pulsador
 
void setup() {                
  
  // inicializamos pin como salidas.
  
  pinMode(steps, OUTPUT); 
  pinMode(direccion, OUTPUT); 
//  pinMode(boton, INPUT);
}
 
void loop() {
 
   // int sentido = digitalRead(boton);    // leemos el botón de dirección
  //  digitalWrite(direccion, sentido);    // cambiamos de dirección según pulsador
    potenciometro = analogRead(A0);     // leemos el potenciómetro
    potenciometro = map(potenciometro,0,1024,25,300);  // adaptamos el valor leído a un retardo
    digitalWrite(steps, HIGH);         // Aquí generamos un flanco de bajada HIGH - LOW
    delayMicroseconds(15);              // Pequeño retardo para formar el pulso en STEP
    digitalWrite(steps, LOW);         // y el A4988 de avanzara un paso el motor
    delayMicroseconds(potenciometro); // generamos un retardo con el valor leído del potenciometro
  }

Este es el que estoy usando ahora de forma rudimentaria, ni siquiera le he incluido la LCD
Buena tarde.

Buenas noches, amigos yo se que esta es la forma correcta de hacer un código, pero no tengo la labilidad suficiente para hacerlo, si alguno de ustedes desea ayudarme a terminar este código, que esta construido con pedacearía de por aquí y google, creo que quedaría un bonito trabajo.
Gracias.

#include <encoder.h>
#include <pulsador.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20 , 4);
int encoder_maximo = 0;
int encoder_minimo = 0;
int estado;
int cont;
int PUL = 5;
int DIR = 6;
int EN  = 7;
enum estado_pulsador {
  ESTADO_PULSADOR_OFF,
  ESTADO_PULSADOR_ON
};
estado_pulsador;
enum estado_encoder {
  ESTADO_ENCODER_MAXIMO,
  ESTADO_ENCODER_MINIMO
};
estado_encoder;
const byte PIN_ENCODER_CLK = A1;
const byte PIN_ENCODER_DT  = A2;
const byte PIN_PULSADOR    = A3;
Pulsador pulsador(PIN_PULSADOR);
Encoder encoder(PIN_ENCODER_CLK, PIN_ENCODER_DT, 0, 0, 0);
const unsigned long INTERVALO_ENTRE_LECTURAS = 50UL;

void setup() {
  Wire.begin();
  lcd.begin(20, 4);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  Serial.begin(9600);

  pinMode(PUL, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(EN, OUTPUT);

  digitalWrite(PUL, LOW);
  digitalWrite(DIR, LOW);
  digitalWrite(EN,  LOW);



}

void loop() {
  unsigned long instanteActual = millis();
  switch (estado) {
    case ESTADO_PULSADOR_ON :
    case ESTADO_PULSADOR_OFF :
      break;
    default:
      pulsador.loop();
      if (pulsador.inicioPulsadoLargo()) {
        digitalWrite (EN, HIGH);         //Arranque de motor
      }
      if (pulsador.inicioPulsadoLargo()) {
        digitalWrite (EN, LOW);         //paro de motor
      }
  }
  switch (estado) {
    case ESTADO_ENCODER_MAXIMO :
    case ESTADO_ENCODER_MINIMO :
      break;
    default:
      encoder.loop();
//      if (encoder_maximo()) { //"En este renglon me da error, no encuantro la solución 
        cont++;
        if (cont > 255) {  // 255 pasos derecha del encoder maxima velocidad LCD 255
          cont = 0;
        }
      }
  }
 // if (encoder.minimo()) {
    cont--;
    if (cont < 0) {
      cont = 255;        //255 pasos izquierda del encoder minima velocidad LCD 0
    }

  }
}

...

Moderador:
He cerrado una publicación similar en esta sección
El doble posteo va en contra de las reglas del foro de Arduino.
La razón es que las publicaciones duplicadas hacen perder el tiempo a las personas que intentan ayudar.
Alguien podría pasar mucho tiempo investigando y escribiendo una respuesta detallada sobre un tema, sin saber que alguien más ya hizo lo mismo en el otro tema.
La publicación cruzada repetida puede resultar en una suspensión del foro, comenzando por una baneo de 7 dias e incluso si repites el comportamiento hasta cerrar tu cuenta.
En el futuro, crea solo un tema para cada tema distinto.
Lee nuevamente si es que no lo has hecho, las Normas del foro.
Gracias de antemano por tu cooperacion.

Buenos días, una disculpa, en cuanto me di cuenta intente corregirlo, no pude eliminarla y pedí ayuda, le agradezco su comprensión no se repetirá otra vez. Gracias.

Cual código miramos? Indica con el post#

Post # 2

Primer inconveniente:
¿De dónde has descargado la librería "Pulsador"?
Porque no la encuentro.

Sugerencia:
Si defines

byte cont;

en lugar de

int cont;

no es necesario

        if (cont > 255) {  // 255 pasos derecha del encoder maxima velocidad LCD 255
          cont = 0;
        }

ni

    if (cont < 0) {
      cont = 255;        //255 pasos izquierda del encoder minima velocidad LCD 0
    }

Porque un byte con valor 255 al incrementarlo pasa a contener 0.
Y un byte con valor 0 al decrementarlo pasa a contener 255.

Buenas tardes Maximo Esfuerzo, las librerias las saque del foro Solucionado Ajustar temperatura sin conectar Arduino a PC - #27 by victorjam post#45

Recuerda siempre agregar el link a las librerías que no sean nativas de arduino.

La librería de encoder se actualizo con una en post#49 .
ya cambie int, por byte cont.

if (cont > 255) {  // 255 pasos derecha del encoder maxima velocidad LCD 255
          cont = 0;
        }

Respecto al renglón 74 no puedo procesar dónde está mi error y como debo corregir lo. Si entendí el código hace lo contrario de lo que comento. No es necesario que sean 255 byte puede ser de 0 a 100 o 0 a 1024, mi idea original: 0 apagado 1 paso del encoder una rotación, 100 pasos del encoder 100 cien rotaciones del motor, a 200 pasos por rotación, si configuro el TB6560 a 400 pasos por rotación obtendría la mitad del volumen . Si es 0 a 255 pasos del encoder debe dar un buenos resultados, ejemplo: si hoy dosifico a 50 bits y mañana a 230 bits y pasado mañana otra vez 50 bits voy a obtener lo mismo que el primer día, y el potenciómetro es imposible ajustarlo para que de él mismo volumen, puede variar 3 o 8 mililitros o más por eso la idea de que el control sea digital.

Si lo haré, he visto que muchos en el foro agregan el link al código, cuando se soluciono el tema.
Gracias por el tip.

No dije que fuese un error, solo te expliqué como puedes ahorrar pasos cambiando el tipo de la variable. Porque un byte nunca puede contener un valor mayor a 255 ni menor a 0.
Sin embargo, si hablas de poder ajustar el valor a 400, déjalo como estaba porque 400 ya excede lo que puede almacenar un byte.

En el link post#49 solo aparece encoder.cpp, cuando es asi poco te cuesta subir los archivos para que esten disponibles a quienes pretendemos ayudarte.

Están ambas.

Actualización de Encoder

Igual, coincido con lo de que es mejor subir o linkear directamente los archivos

encoder.h (863 Bytes)
pulsador.cpp (4,9 KB)
pulsador.h (1,3 KB)
encoder.cpp (1,9 KB)

Aqui esta las librerias.

Esta es la bomba dosificadora. En el dip switch rojo del driver, es donde se configuran los pulsos por cada rotación, 200 o 400 o 800 1600 en este caso hay otros drivers que permiten hasta 3200 pulsos por rotación, solo que son muy caros.
Buenas noches

#include <encoder.h>
#include <pulsador.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20 , 4);
int encoder_maximo = 0;
int encoder_minimo = 0;
int anteriorCLK;
int valorCLK;
int valorDT;
int valorSW;
int anteriorSW;
unsigned long instanteAnterior;
int estado;
int cont;
int PUL = 5;
int DIR = 6;
int EN  = 7;
enum estado_pulsador {
  ESTADO_PULSADOR_OFF,
  ESTADO_PULSADOR_ON
};
estado_pulsador;
enum estado_encoder {
  ESTADO_ENCODER_MAXIMO,
  ESTADO_ENCODER_MINIMO
};
estado_encoder;
const byte PIN_ENCODER_CLK = A1;
const byte PIN_ENCODER_DT  = A2;
const byte PIN_PULSADOR    = A3;
Pulsador pulsador(PIN_PULSADOR);
Encoder encoder(PIN_ENCODER_CLK, PIN_ENCODER_DT, 0, 0, 0);
const unsigned long INTERVALO_ENTRE_LECTURAS = 50UL;

void setup() {
  Wire.begin();
  lcd.begin(20, 4);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  Serial.begin(9600);

  pinMode(PUL, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(EN, OUTPUT);

  digitalWrite(PUL, LOW);
  digitalWrite(DIR, LOW);
  digitalWrite(EN,  LOW);



}

void loop() {
  unsigned long instanteActual = millis();
  switch (estado) {
    case ESTADO_PULSADOR_ON :
    case ESTADO_PULSADOR_OFF :
      break;
    default:
      pulsador.loop();
      if (pulsador.inicioPulsadoLargo()) {
        digitalWrite (EN, HIGH);
      }
      if (pulsador.inicioPulsadoLargo()) {
        digitalWrite (EN, LOW);
      }
  }
  switch (estado) {
    case ESTADO_ENCODER_MAXIMO :

      if (encoder_maximo) {
        cont++;
        if (cont > 250) {
          cont = 0;
        }
        break;

      }

    case ESTADO_ENCODER_MINIMO :

      if (encoder_minimo) {
        cont--;
        if (cont < 1) {
          cont = 250;
        }
        break;

      }
  }
}

Buenas tardes, este código ya copila, pero estoy trabajando fuera de mi ciudad no lo he podido probar.
buenas tardes amigos.

#include <encoder.h>
#include <pulsador.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20 , 4);
int encoder_maximo = 0;
int encoder_minimo = 0;
int anteriorCLK;
int valorCLK;
int valorDT;
int valorSW;
int anteriorSW;
unsigned long instanteAnteriorpulsador;
unsigned instanteAnteriorencoder;
int estado;
int cont;
int PUL = 5;
int DIR = 6;
int EN  = 7;
enum estado_pulsador {
  ESTADO_PULSADOR_OFF,
  ESTADO_PULSADOR_ON
};
estado_pulsador;
enum estado_encoder {
  ESTADO_ENCODER_MAXIMO,
  ESTADO_ENCODER_MINIMO
};
estado_encoder;
const byte PIN_ENCODER_CLK = A1;
const byte PIN_ENCODER_DT  = A2;
const byte PIN_PULSADOR    = A3;

Pulsador pulsador(PIN_PULSADOR);
Encoder encoder(PIN_ENCODER_CLK, PIN_ENCODER_DT, 0, 0, 0);
const unsigned long INTERVALO_ENTRE_LECTURAS = 50UL;

void setup() {
  Wire.begin();
  lcd.begin(20, 4);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  Serial.begin(9600);

  pinMode(PUL, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(EN, OUTPUT);

  digitalWrite(PUL, LOW);
  digitalWrite(DIR, LOW);
  digitalWrite(EN,  LOW);



}

void loop() {
  unsigned long instanteAnterior = millis();
  unsigned long instanteActual = millis();
  instanteAnteriorpulsador = instanteActual;
  switch (estado) {
    case ESTADO_PULSADOR_ON :
    case ESTADO_PULSADOR_OFF :
      break;
    default:
      pulsador.loop();
      if (pulsador.inicioPulsadoLargo()) {
        digitalWrite (EN, HIGH);
        Serial.print(EN);
        lcd.setCursor(0, 0);
        lcd.print(EN);
      }
      if (pulsador.inicioPulsadoLargo()) {
        digitalWrite (EN, LOW);
        Serial.print(EN);
        lcd.setCursor(0, 0);
        lcd.print(EN);
      }
  }
  instanteAnteriorencoder = millis();
  instanteAnteriorencoder = instanteActual;
  switch (estado) {
      unsigned long instanteAnterior = millis();

    case ESTADO_ENCODER_MAXIMO :

      if (encoder_maximo) {
        cont++;
        if (cont > 250) {
          cont = 0;
          Serial.print(cont);
          lcd.setCursor(0, 2);
          lcd.print(cont);
        }
        break;

      }

    case ESTADO_ENCODER_MINIMO :

      if (encoder_minimo) {
        cont--;
        if (cont < 1) {
          cont = 250;
          Serial.println(cont);
          lcd.setCursor(0, 2);
          lcd.print(cont);
        }
        break;

      }

      instanteActual = millis();
  }
}

Buenos días, amigos ya lo mejore, ya estoy de regreso en mi ciudad, lo cargo por la tarde y les digo como funciona.
Buenos días amigos

Buenos días, no funciona a un alguna idea dé porque.

Buenas tardes, de momento ya la tengo operando sin Arduino, por desgracia, toda vía no obtengo la precisión requerida en micro dosificación, de medio mililitro por minuto en adelante ya cumple con mis necesidades, lo seguiré intentando con el código de Arduino.
Buen fin de semana amigos.