Problemas Nema 17 + Pololu 8825 + Display TM1637

Buen día,

Estoy armando algo simple con un paso a paso Nema 17, lo tenía casi listo pero se me ocurrio agregarle un TM1637 para que me muestre la cantidad de vueltas que ingreso con el encoder rotativo y que una vez que doy start me diga cuentas vueltas restan a medida que el motor gira.

Tengo básicamente dos problemas:

1- El motor, al variar su velocidad resulta que no en todos los puntos es sereno (en muchos puntos tiembla o bibra). Como se soluciona esto? estoy usando la AccelStepper justamente porque dicen que es la mejorcita.

2- El problema que surgió al colocar el TM1637: con solo conectarlo al arduino y encenderlo hace que el motor empiece a girar. Acaso hay un problema de compatibilidad?.

Este es el código hasta el momento:

#include <AccelStepper.h>
#include <GFButton.h>
#include <TM1637Display.h>

const int pinBoton = 4;
int id_dato = 0;
GFButton boton(pinBoton);

// Pote display
int change = 0;
int encoderVal = 0;
const int clkPin = 2;
const int dtPin = 3;
long count_rest = 0;

//Inicializa display
const int CLK = 10;
const int DIO = 11;
TM1637Display display(CLK, DIO);

int cant_vueltas = 0;
long valor_pote = 0;
int vel = 0;

const int dirPin = 5;
const int stepPin = 6;
const int motorInterfaceType = 1;
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
 
void setup()
{ 
  stepper.setMaxSpeed(2000);
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);

  pinMode(CLK, OUTPUT);
  pinMode(DIO, OUTPUT);
  display.setBrightness(3);
}

void loop()
{ 
  change = getEncoderTurn();
  encoderVal = encoderVal + (change);
  
  cant_vueltas = encoderVal * 10;
  display.showNumberDec(cant_vueltas, false);

  if(not boton.isPressed()){
    delay(50);
    if(not boton.isPressed()){
      id_dato = id_dato + 1;
      cant_vueltas = cant_vueltas * 200;
      Motores();
    }
  } 
}

void Motores() {
    stepper.setCurrentPosition(0);
    // 200 pasos = 1 vuelta

    while(stepper.currentPosition() < cant_vueltas)
    {
      valor_pote = analogRead(A0);
      if(valor_pote == 0){ valor_pote = 50;}
      if((valor_pote > 125) & (valor_pote <= 224)){ valor_pote = 150;}
      if((valor_pote > 225) & (valor_pote <= 324)){ valor_pote = 250;}
      if((valor_pote > 325) & (valor_pote <= 424)){ valor_pote = 350;}
      if((valor_pote > 425) & (valor_pote <= 524)){ valor_pote = 450;}
      if((valor_pote > 525) & (valor_pote <= 624)){ valor_pote = 550;}
      if((valor_pote > 625) & (valor_pote <= 724)){ valor_pote = 650;}
      if((valor_pote > 725) & (valor_pote <= 824)){ valor_pote = 750;}
      if((valor_pote > 825) & (valor_pote <= 924)){ valor_pote = 850;}
      if(valor_pote > 920){ valor_pote = 950;}

      vel = valor_pote;
      stepper.setSpeed(vel);
      stepper.runSpeed();
      count_rest = ((cant_vueltas - stepper.currentPosition())/200);
      display.showNumberDec(count_rest, false);
    }
}

int getEncoderTurn(void)
{
  static int oldA = HIGH; 
  static int oldB = HIGH;
  int result = 0;
  int newA = digitalRead(dtPin);
  int newB = digitalRead(clkPin);
  if (newA != oldA || newB != oldB)
  {
    if (oldA == HIGH && newA == LOW)
    {
      result = (oldB * 2 - 1);
    }
  }
  oldA = newA;
  oldB = newB;
  return result;
}

Motor paso a paso, tiene X pasos por vuelta, para que quieres un enconder para contarlas si cada vez que se mueve lo hace en un angulo conocido?

Motor paso a paso, tiene X pasos por vuelta, para que quieres un enconder para contarlas si cada vez que se mueve lo hace en un angulo conocido?

Con el encoder selecciono la cantidad de vueltas que va a dar en total. Preciso dar x cantidad de vueltas de forma exacta y las debo poder setear a gusto o necesidad.

Ahora quite el display ese para probar, le conecte uno LCD de 16x2. Ya no tiene la falla que me hacía con el otro display pero no logro sacar el zumbido del Nema al funcionar (por más que ajuste el preset en el pololu sigue zumbando).

Notar que le paso cantidad de vueltas que debe dar, y velocidad y que durante el proceso puedo variar la velocidad desde un potenciómetro:

#include <AccelStepper.h>
#include <GFButton.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

const int pinBoton = 4;
int id_dato = 0;
GFButton boton(pinBoton);

// Pote display
int change = 0;
int encoderVal = 0;
const int clkPin = 2;
const int dtPin = 3;
long count_rest = 0;

long cant_vueltas = 0;
long valor_pote = 0;
long vel = 0;

const int dirPin = 5;
const int stepPin = 6;
const int motorInterfaceType = 1;
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
 
void setup()
{ 
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Iniciando");
  lcd.setCursor(0,1);
  lcd.print("Bobinadora...");
  stepper.setMaxSpeed(2000);
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);
}

void loop()
{ 
  change = getEncoderTurn();
  encoderVal = encoderVal + (change);
  cant_vueltas = encoderVal * 10;

  lcd.setCursor(0,0);
  lcd.print("C.Vuelt: "+String(cant_vueltas)+"      ");
  valor_pote = analogRead(A0);
  if((valor_pote >= 0) & (valor_pote <= 255)){ vel = 600;}
  if((valor_pote >= 256) & (valor_pote <= 511)){ vel = 800;}
  if((valor_pote >= 512) & (valor_pote <= 667)){ vel = 1100;}
  if((valor_pote >= 668) & (valor_pote <= 1023)){ vel = 1300;}
  lcd.setCursor(0,1);
  lcd.print("Vel: "+String(vel)+" rpm  ");

  if(not boton.isPressed()){
    delay(50);
    if(not boton.isPressed()){
      cant_vueltas = cant_vueltas * 200; // 200 pasos una vuelta
      Motores();
    }
  } 
}

void Motores() {
    stepper.setCurrentPosition(0);
    while(stepper.currentPosition() < cant_vueltas)
    {
      valor_pote = analogRead(A0);
      if((valor_pote >= 0) & (valor_pote <= 255)){ vel = 600;}
      if((valor_pote >= 256) & (valor_pote <= 511)){ vel = 800;}
      if((valor_pote >= 512) & (valor_pote <= 667)){ vel = 1100;}
      if((valor_pote >= 668) & (valor_pote <= 1023)){ vel = 1300;}
      stepper.setSpeed(vel);
      stepper.runSpeed();
    }
}

int getEncoderTurn(void)
{
  static int oldA = HIGH; 
  static int oldB = HIGH;
  int result = 0;
  int newA = digitalRead(dtPin);
  int newB = digitalRead(clkPin);
  if (newA != oldA || newB != oldB)
  {
    if (oldA == HIGH && newA == LOW)
    {
      result = (oldB * 2 - 1);
    }
  }
  oldA = newA;
  oldB = newB;
  return result;
}

Si logro sacar ese zumbido ya estaría listo.... pero no lo puedo lograr!!.

Seguramente no has investigado la librería que usas. No estoy respondiendo tus ultimos post sino me quedé en el tema Uso de enconder.
https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html#a96685e0945b7cf75d5959da679cd911e
Si ves ahi, la rutina

targetPosition()

targetPosition()
La mas reciente posicion objetivo en pasos, positivos de acuerdo a las agujas del reloj desde la posicion 0 inicial.

currentPosition()
La posicion actual. Lo mismo medida positiva desde la inicial en el sentido de las agujas del reloj.

runToPosition()
Mueve el motor (con aceleración/desaceleración) a la posición deseada y lo bloquea en esa posición. No usarlo en loops ya que lo va a bloquear.

Es la librería de steppers mas potente

Entonces repito, no necesitas enconder.
Tu motor tiene 200 pasos por vuelta, le dices 200 para 1 vuelta
300 para vuelta y media y asi sucesivamente.

Nota: tienes un pequeño error en la selección de la velocidad
pones

if ((valor_pote >= 512) & (valor_pote <= 667)){ 

deberia ser

if ((valor_pote >= 512) & (valor_pote <= 767)){ 

Finalmente estaba modificando tu código pero sin los elementos me arriesgo a que no funcione.

Esto podria funcionar y es mas simple, aunque tu serie de if funciona.

          valor_pote = analogRead(A0);
          switch(valor_pot % 256) {
              case 0: vel= 600;
                      break;
              case 1: vel = 800;
                      break;
              case 1: vel = 1100;
                      break;
              case 1: vel = 1300;
                      break;

          }

Mi sugerencia seria esta pero no tengo ni el driver ni el stepper

void Motores() {
    stepper.setCurrentPosition(0);
    stepperMotor.moveTo(cant_vueltas);  // lo mismo sin enconder
    while (stepperMotor.distanceToGo > 0) {
          valor_pote = analogRead(A0);
          switch(valor_pot % 256) {
              case 0: vel= 600;
                      break;
              case 1: vel = 800;
                      break;
              case 1: vel = 1100;
                      break;
              case 1: vel = 1300;
                      break;

          }
          stepper.setSpeed(vel);
          stepper.runSpeed();
    }
}

¿No debería ser

if ((valor_pote >= 512) && (valor_pote <= 767)){

?

Con la siguiente función, funciona. Pero sigo teniendo el zumbido o bibración (alta o baja dependiendo de la vibración del motor):

void Motores() {
    stepper.setCurrentPosition(0);
    stepper.moveTo(cant_vueltas);
    while(stepper.distanceToGo() > 0){
          valor_pote = analogRead(A0);
          switch(valor_pote / 256) {
              case 0: vel= 600;
                      break;
              case 1: vel = 800;
                      break;
              case 2: vel = 1100;
                      break;
              case 3: vel = 1300;
                      break;
          }
          stepper.setSpeed(vel);
          stepper.runSpeed();
    }
}

Si, claro ya te dije que no prestaba atención a los post en los que mencionabas el problema de hardware (zumbido).
El zumbido cuando lo hace?
Puedes grabar un video en el que se aprecie el problema.

El zumbido es solo cuando gira, dependiendo de la velocidad el zumbido es mas agudo o más como vibración. Estuve leyendo y el Nema 17 parece que es así incluso se venden unos soportes con goma en medio justamente para absorver eso.

Ahora, pregunta: puede ser que la velocidad máxima del Nema 17 sea de 2000rmp nada más?.

Sinceramente no se cual sería la velocidad máxima de tus steppers.
Lo que si es cierto que a baja velocidad es que la vibración es máxima y va desapareciendo conforme la velocidad aumenta.

Mira este link Tips to Minimize Stepper Motor Vibration
No es por nada pero observa una de las primeras reflexiones
A stepper motor provides accurate position control, without the aid of an encoder,

Justamente mi idea era dajar de lado el encoder y usar el TM1637, colocar ahí el valor con un teclado numérico y tomar ese valor para pasarlo como cantidad de vueltas. Pero no logré hacer funcionar el display ese junto con el pololu y que no meta interferencia. Pero bueno, todo no se puede.

Corregiste los if()...

Eliminado por quedar fuera de contexto.

Gracias @Surbyte

Ya no usa mas los if, esta con el switch case y en cada case hace la consulta tipo AND con el if.