Actuador lineal

Buenos días amigos, estoy construyendo un actuador lineal, lo único fijo del diseño es que va controlado por un arduino nano y que los sensores que indican el final del movimiento son sensores inductivos NA npn LJ12A3-4-z/BX cuya salida ya he adaptado para que no sobrepase los 4.7v y queme arduino ya que van alimentados a 12v, estos mantienen la salida a 4,7v y cuando detectan metal bajan a 0V hasta que dejan de detectar.

Por otro lado el motor es un paso a paso que acabará siendo un nema23 en vez del 17 con el que estaba probando que tenía poca fuerza.
el carro del actuador se mueve mediante una correa GT2 y la polea del motor tiene un perímetro de 38,3mm y la idea es que recorra un metro en un segundo por lo que el motor debería girar a 26 rps o 1550 rpm mas o menos.

La idea es que al encenderse se ponga a girar en dirección al sensor superior(aún no está implementado) y que cada vez que detecte un sensor, gire en el sentido contrario en un ciclo infinito hasta que se apague.

El código mas efectivo que he tenido es uno que controlaba el motor paso a paso ( he terminado probando con motores DC pero no tengo ninguno que me permita trabajar a las revoluciones que quiero con el par que necesito), el código cambiaba el sentido de giro correctamente pero la velocidad de giro era exageradamente lenta y encima en uno de los sentidos de giro temblaba mucho, giraba mucho y sin fuerza.

Tristemente tras mucha pelea con el código y quemar dos arduinos sin querer al conectar a mano los pines de los sensores a 12v en vez de 5V he decidido recurrir a la sabiduría del foro, pongo el código que me funcionaba por último con el motor paso a paso pero que no giraba a la velocidad necesaria y en el sentido contrario giraba lento temblando.

Para aclarar, en el Driver del stepper no tengo activado el microstepping.

Código:
int SensorSuperior = 4;
int SensorInferior = 3;
int goingup = 1;
int goingdown = 0;
int Delay = 500;//in microseconds
const int DIR = 8;//define Direction pin
const int PUL = 9;//define Pulse
void setup() {
 
  Serial.begin(9600);

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

void loop() {

  digitalRead(SensorSuperior);
  digitalRead(SensorInferior);


if (digitalRead(SensorInferior) == 0)
  {
    goingdown = 0;
    goingup = 1;
  }
 if (digitalRead(SensorSuperior) == 0)
  {
    goingup = 0;
    goingdown = 1;
  }



  if (goingup == 1)
  {


    Serial.println("UP");

    digitalWrite(DIR, LOW);
    digitalWrite(PUL, HIGH);
    digitalWrite(PUL, LOW);
    delayMicroseconds(Delay);

  }
  if (goingdown = 1)
  {
    Serial.println("DOWN");
    
    digitalWrite(DIR, HIGH);
    digitalWrite(PUL, LOW);
    digitalWrite(PUL, HIGH);
    delayMicroseconds(Delay);
  }

 
}

Muchas gracias de antemano.
 
He seguido experimentando y he concluido que la diferencia en la velocidad de giro es a causa del tiempo que tarda en ejecutar el código ya que el mismo código en bucle en un sketch separado que se dedica solo a girar el motor en ese sentido hace que gire correctamente, posteo el código con el que estoy trabajando ahora mismo:

Código:
int SensorSuperior = 2;
int SensorInferior = 3;
int goingup = 0;
int goingdown = 1;
const int DIR = 7;//define Direction pin
const int STEP = 6;//define Pulse

int pulseWidthMicros = 500;  // microseconds
int millisbetweenSteps = 1; // milliseconds




void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
  pinMode(SensorSuperior, INPUT_PULLUP);
  pinMode(SensorInferior, INPUT_PULLUP);
}

void loop() {

  attachInterrupt(digitalPinToInterrupt(SensorInferior), goingUp, LOW);
  attachInterrupt(digitalPinToInterrupt(SensorSuperior), goingDown, LOW);

 
    while (goingup==1) {
      Serial.println("UP");
      digitalWrite(DIR, LOW);

      digitalWrite(STEP, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(STEP, LOW);
      delay(millisbetweenSteps);
    }
 

    while (goingdown==1){
      Serial.println("DOWN");
      digitalWrite(DIR, HIGH);

      digitalWrite(STEP, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(STEP, LOW);
      delay(millisbetweenSteps);
    }
 


}



void goingUp() {

goingdown=0;
goingup=1;
for (int i = 0; i <= 200; i++) {
    //Da una vuelta para salir del campo del detector
    Serial.println("UP");
      digitalWrite(DIR, LOW);

      digitalWrite(STEP, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(STEP, LOW);
      delay(millisbetweenSteps);
  }

}

void goingDown() {

goingdown=1;
goingup=0;
for (int i = 0; i <= 200; i++) {
    //Da una vuelta para salir del campo del detector
    Serial.println("DOWN");
      digitalWrite(DIR, HIGH);

      digitalWrite(STEP, HIGH);
      delayMicroseconds(pulseWidthMicros);
      digitalWrite(STEP, LOW);
      delay(millisbetweenSteps);
  }

}

En cada interrupción he tenido que poner que el motor gire una vuelta completa(200)pasos para que el metal que detecten los sensores salga del campo de detección, si no la interrupción se quedaba activada permanentemente.

Lo que no entiendo es por que si tengo un bucle while con una condición cierta, el interior del bucle se ejecuta de manera permanente hasta que el sensor que cambia el estado de la condición se active, sin embargo el código de dentro se ejecuta sufriendo retrasos y causando que el motor gire mas lento.
NO entiendo a que se puede deber por eso recurro a vosotros, si a alguno se le ocurre una manera distinta de escribir el código, será bienvenida.
 
Sin entrar en detalles. Usando una placa SilentStepSticks TMC 2208 o 09 puedes controlar un motor de paso de forma efectiva Estas plaquitas se consiguen muy económicas por ser ampliamente usados en impresoras 3D. En el tutorial avanzado que he publicado aquí en el foro doy alguna información sobre como seleccionar un motor de paso apropiado. Como tu solo hablas de pasar de motor NEMA 17 a NEMA 23 por hacerle falta torque, me parece que tal información te falta. La placa Arduino iniciaría la placa SilentStepSticks y luego solo daría los impulsos y la dirección de giro. En ebay.com esas placas se pueden comprar por 4.67 USD
 
Hablo de memoria pero la librería de stepper de Arduino era bastante/muy mala.
Si no recuerdo mal mataba todos los procesos hasta que acababa. Puede que sea eso lo que te está pasando.
Aunque mirando a tu código parece que no la estás usando.
 
Sin entrar en detalles. Usando una placa SilentStepSticks TMC 2208 o 09 puedes controlar un motor de paso de forma efectiva Estas plaquitas se consiguen muy económicas por ser ampliamente usados en impresoras 3D. En el tutorial avanzado que he publicado aquí en el foro doy alguna información sobre como seleccionar un motor de paso apropiado. Como tu solo hablas de pasar de motor NEMA 17 a NEMA 23 por hacerle falta torque, me parece que tal información te falta. La placa Arduino iniciaría la placa SilentStepSticks y luego solo daría los impulsos y la dirección de giro. En ebay.com esas placas se pueden comprar por 4.67 USD

A que te refieres con que tal información me falta? he llegado a la conclusión de que le falta par al motor ya que con la mano y sin ningún esfuerzo podía evitar que girase y con su corriente máxima se calentaba MUCHO (motor de chinesio puro, que se le va a hacer), el nema 23 me mueve una polea de 60 dientes con muchísimo mas par en su diámetro de trabajo que el nema17 con una polea de 20 dientes creo que eran.

El Driver que uso ahora mismo es un TB6600 a 2A y pico aunque si he de ser sincero cada vez me inspira menos confianza, el que me indicas no me cubre tal capacidad de corriente, además de que los comandos tanto para el driver que uso como para el TMC que me indicas son los mismos igualmente, dirección y paso.

Respecto a lo que me indica Scooter, correcto, no uso la librería stepper ya que por lo que pude ver está destinada a drivers que toman la señal de cada hilo y la amplifican directamente en vez de usar la señal de Step y Dir que es lo que usa el drivel del que dispongo ( y que aunque cambie de driver pretendo usar ese mismo sistema).
 
Ves jjjasesino, a eso me refiero. Extensamente y mostrando videos que subí a YouTube en el curso avanzado para motores de paso doy las informaciones. Cuando yo empecé a experimentar con motores de paso hace unos 8 anos usé un controlador para motores de paso basado en las componentes L297 y L298 y alimenté mi motor de paso con 12 VDC. Fui incapaz de hacerlo girar y hasta llegue a dudar de mi capacidad de entender el porque demonios no era capaz de hacer al motor de paso dar pasos.
Algunos meses mas tarde la empresa Trinamic me regaló una placa llamada stepRocker que aún se puede comprar y usar su excelentísima IDE para experimentar y entender las diversas funciones de la componente de Trinamic. Uno de los resultados fue que mi motor de paso recién empezaba a dar pasos cuando lo activaba con 16 micropasos por paso completo. Evidentemente era imposible usar ese motor de paso con las componentes L297 y L298 pues esas solo permitían 2 micropasos por paso completo.

Las placas SilentStepSticks TMC2209 o 2208 las puedes controlar con un Arduino UNO y como te mostré con el enlace baratísimos.

La otra cosa que describes, que el motor se calienta muchísimo es otra prueba de la solución inadecuada o ineficiente que usas. Las componentes de Trinamic son capaces de regular la cantidad de corriente suministrada a las bobinas del motor de paso de 2 fases para crear el torque requerido. Hasta son capaces de suministrar hasta un 20% mas de corriente por un tiempo limitado por si requieres un pico de torque. La otra cosa que es tan importante que la quiero mencionar aquí otra vez. Motores de paso según el sitio de Trinamic se operan con hasta 20 veces el valor de la tensión nominal. Tensión y nominal nominal son aquellas especificadas en la hoja de datos del motor o en la placa en el motor.

El torque de un motor de paso es directamente proporcional a la cantidad de corriente que fluye atraves de el. Si el motor de paso solo requiere en algún momento un torque menor al que resulta por las especificaciones del motor, entonces el chip de Trinamic usa su función de PWM para reducir la cantidad de corriente. Eso tiene como efecto colateral, que el motor de paso no se calienta tanto. Yo la usé como winche en un modelo de un velero y allí es un pack de baterías que proporciona tensión y corriente. El ahorro de energía alarga el tiempo que el pack de baterías es capaz de suministrar energía.

Repito, en el curso avanzado sobre motores de paso en este foro, presento mucha información.
 
Hellmut, entiendo lo que me quieres decir, el nema14 se me calentaba en exceso ya que al ser de lazo abierto, para mantener a posición está constantemente pasando corriente, mi idea es no cambiar nada de lo que tengo ahora mismo, el nema23 junto al driver chino y el control por Arduino, se controlar el motor sin problemas, lo que me falla es el software ya que el código de giro del motor funciona perfectamente por separado tanto el giro horario como el antihorario.

El problema llega cuando junto el código de giro con el código de los sensores y estoy casi seguro de la causa es el tiempo de ejecución del código, no consigo que al leer un sensor el código se quede en un loop de giro hasta que detecte un sensor de final de recorrido, parece que lo que ocurre es que comprueba el último sensor que se ha activado y ejecuta todo el código de nuevo saltándose el código que no se ejecute por no estar activo el sensor correspondiente.
 
He estado trasteando simplemente para conseguir lo que a mi parecer es la mejor mezcla de velocidad-par-sonido silencioso, eso ya está perfectamente solucionado, he optado por usar el comando break para salir de bucles while pero no me está funcionando, puesto que soy mayormente autodidacta en arduino supongo que estoy haciendo algo muy simple de manera equivocada pero no logro ver el qué, el código se queda en el bucle while(goingDown==1) , Declaro esa variable como 1 al principio pero debería de cambiar cuando detecte el sensor inferior, lo cual no ocurre, alguna idea para un alma perdida?

Código:
int SensorSuperior = 2;
int SensorInferior = 3;
int goingup = 0;
int goingdown = 1;
const int DIR = 7;//define Direction pin
const int STEP = 6;//define Pulse

int pulseWidthMicros = 500;  // microseconds
int millisbetweenSteps = 1; // milliseconds




void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
  pinMode(SensorSuperior, INPUT_PULLUP);
  pinMode(SensorInferior, INPUT_PULLUP);
}

void loop() {
 
  while (goingup == 1) {

    digitalWrite(STEP, HIGH);
    delayMicroseconds(50);
    digitalWrite(STEP, LOW);
    delayMicroseconds(50);
    if (SensorSuperior == LOW) {   // bail out on sensor detect
    break;}
  }


  while (goingdown == 1) {

    digitalWrite(STEP, HIGH);
    delayMicroseconds(50);
    digitalWrite(STEP, LOW);
    delayMicroseconds(50);
    if (SensorInferior == LOW) {   // bail out on sensor detect
    break;}
  }



}



void goingUp() {

  goingdown = 0;
  goingup = 1;

  Serial.println("UP");
  digitalWrite(DIR, LOW);
  for (int i = 0; i <= 200; i++) {
    //Da una vuelta para salir del campo del detector
    digitalWrite(STEP, HIGH);
    delayMicroseconds(50);
    digitalWrite(STEP, LOW);
    delayMicroseconds(50);
  }


}

void goingDown() {

  goingdown = 1;
  goingup = 0;
  Serial.println("DOWN");
  digitalWrite(DIR, HIGH);
  for (int i = 0; i <= 200; i++) {
    //Da una vuelta para salir del campo del detector
    digitalWrite(STEP, HIGH);
    delayMicroseconds(50);
    digitalWrite(STEP, LOW);
    delayMicroseconds(50);
  }

}

Pd: Hellmut, ojalá algún día tenga algún proyecto para meter los controladores de trinamic, me gustaría hacer un actuador con una reductora cicloidal con un motor brushless pero no tengo ni una cnc ni todo el dinero que cuesta un motor interesante para ese propósito aún jaja

Edit: me olvidé del código.
 
Al final conseguí que funcionase, al fin y al cabo, a mi me encanta escribir código pero yo no le gusto al código jajaj, El movimiento es muy brusco así que escribiré un par de bucles for de aceleración y deceleración para que no sufra estrés mecánico y listo pero ya funciona, era una tontería pero no me salía:

Código:
int SensorSuperior = 2;
int SensorInferior = 3;
int goingup = 1;
int goingdown = 0;
int sensorValue = 0;
const int DIR = 7;//define Direction pin
const int STEP = 6;//define Pulse





void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
  pinMode(SensorSuperior, INPUT_PULLUP);
  pinMode(SensorInferior, INPUT_PULLUP);
}

void loop() {

  while (goingup == 1) {
    sensorValue = digitalRead(2);
    digitalWrite(DIR, HIGH);
    digitalWrite(STEP, HIGH);
    delayMicroseconds(50);
    //Serial.println(sensorValue);
    digitalWrite(STEP, LOW);
    delayMicroseconds(50);
    if (sensorValue == 0) {   // bail out on sensor detect
      goingup=0;
      goingdown=1;
      break;
    }
  }


  while (goingdown == 1) {
    sensorValue = digitalRead(3);
    digitalWrite(DIR, LOW);
    digitalWrite(STEP, HIGH);
    delayMicroseconds(50);
    //Serial.println(sensorValue);
    digitalWrite(STEP, LOW);
    delayMicroseconds(50);
    if (sensorValue == 0) {   // bail out on sensor detect
      goingup=1;
      goingdown=0;
      break;
    }
  }
}
 
Arriba