Controllo velocità motori passo passo con potenziometri

Buonasera,
Sto iniziando a toccare con mano le funzionalità di arduino ed eccomi che da subito mi sono trovato di fronte al mio primo problema.
Io dovrei gestire la velocità di due motori passo passo con i rispettivi potenziometri. Alcuni dati:

Ardino uno rev3
2 Motori nema 23 3a
2 Driver della microstep M542
2 Potenziometri da 50K ohm

all'inizio ho gestito un solo motore senza problemi, anzi va che è una favola! di seguito il codice:

/*
Driver microstep ST-M542
Pul+ -> +5V
Pul- -> Pin 9
Dir+ -> +5V
Dir- -> Pin 8
Enable+ non connesso
Enable- non connesso
*/

int PotPin1 = A3; // pin analogico usato per connetter il potenziometro1
int PotVal = 0; // variabile letta dal PotPin1 

void setup() {                
  pinMode(8, OUTPUT); //Pin direzione
  pinMode(9, OUTPUT); //Pin step 
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
}

void loop() {
  PotVal = analogRead(PotPin1); // legge il valore del potenziometro1 (valore tra 0-1023)
  PotVal = map(PotVal,0,1023,0,1600); // map(valore,valmin,valmax,outputvalmin,outputvalmax)
  digitalWrite(9, HIGH);
  delayMicroseconds(PotVal);          
  digitalWrite(9, LOW); 
  delayMicroseconds(PotVal);
 }

Nel momento in cui duplico il listato noto che i motori non seguono i due potenziometri in modo distinto ma al contrario sembrano che vadano all unisono, o comunque il secondo potenziometro non sembra funzionare. Di seguito il codice:

/*
Driver microstep ST-M542
Pul+ -> +5V
Pul- -> Pin 9
Dir+ -> +5V
Dir- -> Pin 8
----
Pul+ -> +5V
Pul- -> Pin 7
Dir+ -> +5V
Dir- -> Pin 6
----
Enable+ non connesso
Enable- non connesso
*/

int PotPin1 = A3; // pin analogico usato per connetter il potenziometro1
int PotPin2 = A2; // pin analogico usato per connetter il potenziometro2
int PotVal1 = 0; // variabile letta dal PotPin1 
int PotVal2 = 0; // variabile letta dal PotPin2

void setup() {                
  pinMode(8, OUTPUT); //Pin direzione1
  pinMode(9, OUTPUT); //Pin step1 
  pinMode(6, OUTPUT); //Pin direzione2
  pinMode(7, OUTPUT); //Pin step2 
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
}

void loop() {
  PotVal1 = analogRead(PotPin1); // legge il valore del potenziometro1 (valore tra 0-1023)
  PotVal1 = map(PotVal1,0,1023,0,1600); // map(valore,valmin,valmax,outputvalmin,outputvalmax)
  PotVal2 = analogRead(PotPin2); // legge il valore del potenziometro2 (valore tra 0-1023)
  PotVal2 = map(PotVal2,0,1023,0,1600); // map(valore,valmin,valmax,outputvalmin,outputvalmax)
  digitalWrite(9, HIGH);
  delayMicroseconds(PotVal1);          
  digitalWrite(9, LOW); 
  delayMicroseconds(PotVal1);
  digitalWrite(7, HIGH);
  delayMicroseconds(PotVal2);          
  digitalWrite(7, LOW); 
  delayMicroseconds(PotVal2);
  delay(15); //ritardo per completare il ciclo
 }

Ora io è da un pò che sto guardando in rete qualche soluzione ma penso seriamente che sia una cavolata tale che nessuno si è mai preso la briga di scrivere, chiedo aiuto in tal senso grazie mille!

  1. prova ad inserire un tempo di 10 ms tra una lettura e l'altra.
    il tempo che ti ho suggerito è esagerato , ma è solo una prova di DEBUG

il_dek:
..sembrano che vadano all unisono...

  1. ovvero i valori letti dai potenziometri sono uguali ?

il_dek:
, o comunque il secondo potenziometro non sembra funzionare

3)Hai provato a scollegare completamente il pot1 dal circuito e provare il pot2 con il secondo sketch ?
Sul pot1 leggerai valori casuale , sul pot2 il valore dal potenziometro 2
ciao

Non mi sembra di vedere errori nel codice..forse è un problema HW.. prova a inviare su seriale i valori letti dagli analogici.. oppure, se hai un tester, misura cosa arriva al pin analogico..

ciao

la lettura degli ingressi analogici avviene in multiplex ovvero c'è un solo convertitore AD che legge i vari ingressi " a turno".
Se non lasci un pò di tempo tra una lettura e l'altra (molto probabilmente) otterrai lo stesso valore per tutti gli ingressi.

Puoi provare a "buttare" la prima lettura semplicemente aggiungendo un analogread:

  PotVal1 = analogRead(PotPin1); // legge il valore del potenziometro1 (valore tra 0-1023)
  PotVal1 = analogRead(PotPin1);
  PotVal1 = map(PotVal1,0,1023,0,1600); // map(valore,valmin,valmax,outputvalmin,outputvalmax)
  PotVal2 = analogRead(PotPin2);
  PotVal2 = analogRead(PotPin2); // legge il valore del potenziometro2 (valore tra 0-1023)
  PotVal2 = map(PotVal2,0,1023,0,1600); // map(valore,valmin,valmax,outputvalmin,outputvalmax)

Il valore dei potenziometri (50K) credo sia troppo elevato: se non sbaglio consigliano un valore tra i 10 e i 20k

ciao
pippo72

quel sistema li va bene per imparare a capire cosa sono e come sono fatti i motori passo passo..
meglio se adotti hardware specifico che li controlla in corrente.

pippo72:
Il valore dei potenziometri (50K) credo sia troppo elevato: se non sbaglio consigliano un valore tra i 10 e i

Si è troppo alto, deve usare un potenziometro da 10k altrimenti l'ADC ha grossi problemi quando si cambia canale per leggere alternativamente i due potenziometri.

elpapais:
meglio se adotti hardware specifico che li controlla in corrente.

Sta usando questo driver, l'ha scritto nel primo post, semmai è il codice che è totalmente da rivedere visto che fa largo uso della delay().
Esistono librerie specifiche per gli stepper, che indirizzano direttamente l'hardware e usano i timer per generare le temporizzazioni, p.e. la accelstepper.

astrobeed:
Sta usando questo driver, l'ha scritto nel primo post, semmai è il codice che è totalmente da rivedere visto che fa largo uso della delay().
Esistono librerie specifiche per gli stepper, che indirizzano direttamente l'hardware e usano i timer per generare le temporizzazioni, p.e. la accelstepper.

Non avevo letto del driver... si in effetti meglio accelstepper in quel caso.

In ogni loop, fai fare un passo al primo motore ed attendi x microsecondi, poi fai fare un passo al secondo motore ed attendi y microsecondi.
Quindi ad ogni loop attendi x + y microsecondi (oltre a quelli fra hi e low, ma l’importante è ora capire).
Il primo motore farà un passo ogni x+y microsecondi.
Il secondo motore, invece… pure.
Ecco come mai ti sembrano “sincronizzati”.

Ragazzi siete troppo generosi. Ok ho capito tutto e adesso mi studio le vostre riposte. A breve vi faccio sapere i risultati.

Ps: per i miei test dovrò aggiungere anche un terzo motore sempre pilotato da un potenziometro, quindi suppongo che il problema deve esser risolto alla radice ovvero usare la libreria accelstepper.

Questa soluzione sarà temporanea e quindi non vorrei spendere troppo tempo e denaro però devo controllare questa velocità in qualche modo, quindi devo arrivare a un compromesso.

Vi ringrazio per l'attenzione e per l'aiuto

N

Buongiorno,
Niente mi sto arrendendo al fatto che non si possa utilizzare il potenziometro con i motori passo passo.
Vi elenco le prove eseguite, nella speranza di trovare l errore:

Cambiato il potenziometro da 50k a 10k come consigliato, ma nulla di fatto

Mi sono “studiato” la libreria AccelStepper ed ho eseguito questi test:
Pilotaggio Motore1 senza potenziometro -->OK
Pilotaggio Motore2 senza potenziometro -->OK
Pilotaggio Motore1 e Motore2 senza potenziometro -->OK

Esempio codice

/*
Driver microstep ST-M542
Pul+ 5V
Pul- 9, 7, 5
Dir+ 5V
Dir- 8, 6, 4 
Enable+ no
Enable-  no
----------
----------
Test ok con i motori
Fallito con aggiunta del potenziometro fallito (interrupt?)
*/

#include <AccelStepper.h>
AccelStepper MotBiella(1, 9, 8); // pin 9= step, pin 8 = direction
AccelStepper MotRullo(1, 7, 6); // pin 7= step, pin 6 = direction

void setup() {

  MotBiella.setMaxSpeed(3000);
  MotBiella.setSpeed(500);
  MotRullo.setMaxSpeed(3000);
  MotRullo.setSpeed(250);
}

void loop() {           
  MotBiella.runSpeed();
  MotRullo.runSpeed();
}

Pilotaggio Motore1 con potenziometro -->OK
Pilotaggio Motore2 con potenziometro -->OK

(quindi cablaggi e software sono corretti)

Nel momento in cui faccio eseguire le due cose assieme allora si crea il casino più totale.
Se faccio andare in contemporanea motore a velocità fissa e motore con pot noto che la logica da la precedenza o al potenziometro o al motore!
a voi è mai successo una cosa simile?
io non vorrei azzardare conclusioni affrettate pero non vorrei che sia un problema di interrupt, cioè che Arduino scelga o di pilotare il primo motore oppure il secondo!!!
ho notato che se io insisto nel azionare il potenziometro il driver mi va in protezione (vedi foto allegata)

allego esempio del codice

Driver microstep ST-M542
Pul+ -> +5V
Pul- -> Pin 9
Dir+ -> +5V
Dir- -> Pin 8
Enable+ non connesso
Enable- non connesso
*/

#include <AccelStepper.h> 
AccelStepper MotBiella(1, 9, 8); // pin 9= step, pin 8= direction regolazione velocità tramite potenzimetro
AccelStepper MotRullo(1, 7, 6); // pin 7= step, pin 6= direction


int val = 0; //variabile potenziometro
int previous = 0;
int long newval = 0;    

void setup() {
  MotBiella.setMaxSpeed(3000);  // massima velocità impostata sulla rotazione
  MotBiella.setAcceleration(2500);  // massima velocità impostata sulla rotazione 
  MotRullo.setMaxSpeed(3000); 
  MotRullo.setSpeed(250); //velocità fissa
}

void loop() {
  val = analogRead(A2);  // lettura valore istantaneo Pot
  if ((val > previous+6) || (val < previous-6)) {  // controllo lettura Pot
    newval = map(val, 0, 1023, 0, 1600);  // mappatura valori (1600 = 1 rotazione completa)
    MotBiella.runToNewPosition(newval);  // muovi verso la nuova posizione
    previous = val;  // salvataggio del valore corrente variabile previous
  }
    MotRullo.runSpeed(); //start del motore a velocità fissa
}

Ho fatto anche un breve video in cui è presente il movimento con l 'ultimo codice al seguente link
https://drive.google.com/file/d/0BwLQuEK2hlQTZnBobnpVUWZhY1U/view?usp=sharing

Vi risparmio il cablaggio perché sono semplici pin collegati al driver e un 5v in comune fra loro.

Le mie considerazioni:
Arduino gestisce una sola istanza alla volta e non tutt e due (spero di sbagliarmi)
Io purtroppo ho necessità di proseguire con lo studio e non so più dove sbattere la testa, a saperlo che c erano questi problemi e prendevo sicuramente un altra strada. Quello che più mi da sconforto è il fatto che dovrebbero essere cose molto semplici da gestire… ma parlo da meccanico quindi suona piu come uno sfogo…

se avete qualche idea io sono qui che vi aspetto, e non parlo solo di Arduino ma di qualsiasi altra soluzione, sono disposto anche pagare, se necessario.

Altrimenti prenderò un altro Arduino che mi gestisca solo il potenziometro ma non la vedo la strada più corretta.

Grazie per l’attenzione
N

Arduino gestisce una sola istanza alla volta e non tutt e due (spero di sbagliarmi)

Non è Arduino che gestisce un motore alla volta, ma il comando **xxx.runToNewPosition(x); ** che è bloccante

Moves the motor (with acceleration/deceleration) to the new target position and blocks until it is at position. Dont use this in event loops, since it blocks.

This function does not return until the motor is stopped, so it is only useful if no other motors are moving.

Brunello:
Non è Arduino che gestisce un motore alla volta, ma il comando xxx.runToNewPosition(x); che è bloccante

Si hai perfettamente ragione. Ho preso visione e non appena mi arriva il nuovo potenziometro ti faccio sapere.

Questo fine settimana ho effettuato un altro test, senza potenziometro ma niente, non funziona. ho collegato un elettrovalvola al pin 12 e l’ho fatta azionare in contemporanea.
non capisco perche si blocchi il motore e vada in protezione il driver.

#include <AccelStepper.h>

AccelStepper MotRullo(1, 7, 6); // pin 7= step, pin 6 = direction


void setup() {
  pinMode(12, OUTPUT);
  MotRullo.setMaxSpeed(3000);
  MotRullo.setSpeed(-250);
}

void loop() {
  digitalWrite(12, HIGH); 
  delay(1000);              
  digitalWrite(12, LOW);   
  delay(1000);             
  MotRullo.runSpeed();
}

se leggi la spiegazione del comando runspeed

Poll the motor and step it if a step is due, implementing a constant speed as set by the most recent call to setSpeed(). You must call this as frequently as possible, but at least once per step interval,

Guarda anche la spiegazione di setspeed, nel punto in cui fa riferimento alle chiamate a runspeed

A parte il fatto che dovresti dirgli "dove deve andare", concentrati su quel

You must call this as frequently as possible, but at least once per step interval

e su quei due delay mille che hai messo