Go Down

Topic: Problema movimento motore (Read 285 times) previous topic - next topic

SCIPIO___

Salve a tutti
ho un problema abbastanza strano con il mio arduino mega

devo muovere un motore, e tra un movimento e l'altro fare alcune operazioni.
Il comportamento strano è il seguente. Se commento //Serial.println("delay"); funziona, altrimenti non si muove.

Test fatti:
Ho pensato fosse un problema di frequenza del treno di impulsi, ho provato a inserire vari delay ma nulla. ho provato a cambiare la velocita di scrittura (9600)
ho provato a definire la porta seriale (serial1.print)

si accettano suggerimenti

questo è il mio codice

#include <stdio.h>
int att = 4;
int phase = 6;
int dir = 8;

void setup() {               

  pinMode(phase, OUTPUT);   
  pinMode(dir, OUTPUT);
  pinMode(att, OUTPUT);
  Serial.begin(9600);

  digitalWrite(dir, HIGH);      //Direzione
  digitalWrite(att, LOW);      //LOW attivo, high no
}
 
void loop() {
 
 //Serial.println("delay");
 Muovi();
}

void Muovi()
{
   digitalWrite(phase, HIGH);   //muove il motore
  delayMicroseconds(1);    //  ~3Hz /10     
  digitalWrite(phase, LOW);
  delayMicroseconds(2);
 
}

Maurotec

Ma si tratta di un motore passo passo bipolare?

Comunque il codice nella funzione Muovi può funzionare se il programma non altro da fare e quindi ha solo
valenza di didattica. La serial.println() non lentissima nel scrive nel serial monitor, ma comunque richiede del tempo per essere completata, ciò comporta il  mancato rispetto delle tempistiche richieste dalla funzione Muovi.

Per cui o usi una libreria già pronta per movimentare il motore o trovi un modo alternativo simile a quello impiegato nelle librerie.

Ciao.

SCIPIO___

il motore è questo
https://m.es.aliexpress.com/item/32918224924.html?pid=808_0000_0131&spm=a2g0n.search-amp.list.32918224924

credo che si, sia passo passo bipolare.

Code: [Select]
ciò comporta il  mancato rispetto delle tempistiche richieste dalla funzione Muovi.


questo in realtà non mi torna, se pongo un delay non dovrei dargli tempo per farlo?
una cosa come print,delay,muovi,delay

cmq grazie per l'aiuto, sto cercando di vedere come fare con le librerie

Maurotec

Suppongo che il motore sia connesso ad una scheda con funzione di Driver, a te quindi serve generare un treno di impulsi a frequenza variabile così da potere aumentare/diminuire la velocità di rotazione dell'asse ridotto.

In effetti è quello che fa la funzione Muovi().

Quote
questo in realtà non mi torna, se pongo un delay non dovrei dargli tempo per farlo?
una cosa come print,delay,muovi,delay
La sequenza non è errata ma non funge perché ogni istruzione presente nello scketch è in realtà composta da più istruzioni elementari dette Istruction Set, di queste trovi un sommario nel datasheet della MCU (Micro Controller Unit).

Ogni istruzione elementare richiede 1/fclock tempo per essere eseguita, stessa sorte tocca alla istruzioni composte (dette funzioni) come delayMicrosenconds(time) che richiede time tempo, trascorso il tempo time viene caricata la successiva istruzione ed infine eseguita.

Per la serial.println() impegna la cpu in modo esclusivo per il tempo necessario a trasferire la stringa nel buffer dati a servizio della seriale + il tempo per la chiamata a funzione (prologo ed epilogo) ecc.

Quindi per riassumere, tecnicamente parlando hai un solo thread, un solo task ed un solo ciclo infinito che per essere completato richiede un tempo t che aumenta tanto più codice c'è inserito nella funzione loop().

PS: Quando fclock=16 000 0000 Hz, un ciclo di clock dura tclock=62.5ns

SCIPIO___

ok, scusa se approfitto, ma non riesco a venirne fuori

si mi sono dimenticato di dire che ho un driver che mi connette motore e arduino
il driver ha 6 uscite (ena+/-, pull +/-, dir +/-)
di queste tre le ho messe a terra ( i tre -) e le altre tre connesse ad arduino

Ora ho capito che la mia funzione era troppo "naive" per funzionare e devo passare alle librerie
Sto cercando di usare la libreria stepper, che mi sembra sia quello di cui ho bisogno

ora mi dice
Stepper(steps, pin1, pin2)
pin1, pin2: two pins that are attached to the motor (int)

nel mio caso sarebbero il pull e la dir? (enable lo uso per accendere il motore)

questo è il codice (l'esempio di arduino leggermente modificato) e non va


#include <Stepper.h>

const int stepsPerRevolution = 64000;  // change this to fit the number of steps per revolution
                                     // for your motor

int ena_p=32;
Stepper myStepper(stepsPerRevolution, 24,28);           

int stepCount = 0;         // number of steps the motor has taken

void setup() {
  // initialize the serial port:
  Serial.begin(9600);
  pinMode(ena_p, OUTPUT);
  digitalWrite(ena_p, LOW);
}

void loop() {
  // step one step:
  myStepper.step(1);
  Serial.print("steps:" );
  Serial.println(stepCount);
  stepCount++;
  delay(1);
}



Maurotec

Credo sia meglio usare una libreria dedicata al tuo driver, quelli di arduino è generica ed è principalmente pensata per uso didattico in quanto permette di controllare 4 mosfet (o bjt) configurati a ponte o ancora l'integrato L293.

Visto che di programmazione non sei a digiuno ti consiglio di aprire i file di libreria e sbirciarci dentro. Le librerie sono sorgenti .h e .cpp in formato ascii e contengono commenti che possono permetterti di comprendere come usarla e come modificarla a tuo piacimento.

Quote
Ora ho capito che la mia funzione era troppo "naive" per funzionare e devo passare alle librerie
Sto cercando di usare la libreria stepper, che mi sembra sia quello di cui ho bisogno
Era rustica e avrebbe anche funzionato se l'avessi fatta chiamare da un evento scatenato da un timer hardware.
Comunque la libreria aiuta ma deve rimanere chiaro che il ciclo di loop() viene eseguito una istruzione dopo l'altra ed è interrompibile solo da eventi agganciati alle routine di interrupt (ISR).

Ciao.

SCIPIO___

Quote
Credo sia meglio usare una libreria dedicata al tuo driver
Una libreria dedicata al mio driver non l'ho incontrata
sto quindi usando questa (AccelStepper)

http://www.airspayce.com/mikem/arduino/AccelStepper/

e ovviamente il motore non si muove.
in realtà stepper.isRunning() cambia di valore durante il run, passa dopo un po di tempo da 1 a 0
questo mi fa pensare che il treno di impulsi viene inviato, pero non ha la "forza" per muovere il motore.
diciamo una mancanza di corrente(?) pero mi suona strano perché nella versione primitiva del codice il motore si muove.

Code: [Select]


#include <AccelStepper.h>

int ena_p=32;
     
AccelStepper stepper(AccelStepper::DRIVER,28,24); //28 pull 24 dir

int stepCount = 0;         // number of steps the motor has taken

void setup() {
  // initialize the serial port:
  Serial.begin(9600);
  pinMode(ena_p, OUTPUT);
  digitalWrite(ena_p, LOW);

  stepper.setMinPulseWidth(20); //i valori li ho messi a caso, ho provato a cambiarli di fattori 10, ma nulla
  stepper.moveTo(10000);
  stepper.setMaxSpeed(10000);
  stepper.setAcceleration(1000);
  stepper.setSpeed(100);
}

void loop() {

 stepper.run();
 Serial.println(stepper.isRunning());
 if(!stepper.isRunning()){Serial.println("????");}
 
}

Maurotec

#7
Apr 12, 2019, 09:34 pm Last Edit: Apr 12, 2019, 09:35 pm by Maurotec
Ho dato uno sguardo veloce ad AccelStepper on  line su https://github.com e anche questa libreria è valida per controllare ponti discreti.

Mentre sempre su github c'è questa : stepper driver
che come vedi consultandola online sembra fare al caso tuo, se posti un link al tuo driver ti posso seguire meglio.

Se il tuo driver ha pin dedicati per la configurazione microstepping per fare i test li colleghi manualmente, poi eventualmente poco per volta ti modifichi la libreria se necessario.

Ciao.

SCIPIO___

ok grazie infinite, ora studio i documenti

il mio driver è DM860H
driver_manual

Maurotec

L'esempio qui riportato dovrebbe funzionare con il tuo driver, example

Devi solo commentare questa:
Code: [Select]
BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP);
e de-commentare questa:
Code: [Select]
#define SLEEP 13
e questa:
Code: [Select]
BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP, SLEEP);


Se hai collegato la mega al driver come consigliato nel datasheet del driver
devi de-commentare anche:
Code: [Select]
stepper.setEnableActiveState(LOW);

SLEEP equivale a ENABLE.

Ciao.

SCIPIO___

Ciao

allora ho provato la libreria che mi avevi passato
in realtà non compilava quindi ho dovuto cambiare un po la classe ciononostante non funzionava

sono quindi ripartito dalle basi, cambiando il passo del motore a quel punto funzionava anche con la versione base

pensavo quindi fosse un problema di passo troppo piccolo,
e partendo dallo step piu grande (400) sono andato crescendo
con mia sorpresa ha funzionato fino  64000, la configurazione in cui al principio non funzionava nulla

fatte varie prove, e funzionava a meraviglia, finche da un punto all'altro si è piantato di nuovo
a questo punto penso sia un problema hardware, forse un cavo manda interferenze non adeguatamente schermate

Comunque volevo ringraziarti per la disponibilità e la gentilizza :)

grazie mille

Go Up