Go Down

Topic: accelerazione e posizione (Read 260 times) previous topic - next topic

1oniudra2

Salve

Non avendo molta esperienza con queste problematiche chiederei un aiuto per risolvere due problemi.
Sto utilizzando uno stepper nema che lo "guido" con questo sketch.

Code: [Select]


digitalWrite(dirPin1,HIGH);
 
  if(prova==0)
   {
  for (int x = 0; x < 3800; x++)
  {
    digitalWrite(stepPin1,HIGH);
    delayMicroseconds(200);
    digitalWrite(stepPin1,LOW);
    delayMicroseconds(200);
    prova=1;
    }
    delay(1000);
 }
 
   if(prova==1)
   {
    digitalWrite(dirPin1,LOW);
     for (int x = 0; x < 3800; x++)
  {
    digitalWrite(stepPin1,HIGH);
    delayMicroseconds(200);
    digitalWrite(stepPin1,LOW);
    delayMicroseconds(200);
    prova=2;



Vorrei creare un' accelerazione e decellerazione senza ricorrere a librerie tipo accelestepper ecc.
Avevo pensato di introdurre un altro ciclo for all'interno con variabile y e delaymicroseconds(y)
ma non mi riesce.

Altro controllo che non riesco a fare e' l'introduzione di un if che mi permetta quando il motore
raggiunge una determinata posizione es x=2000 di compiere un'azione es accendere un led ecc.

Ringrazio dei suggerimenti.

torn24

Ciao! Ci sarebbero molte cose da dire anche sul codice che hai postato, esempio per ruotare il motore in un senso e poi nell'altro usi lo stesso codice ripetuto due volte, potresti crearti una funzione che da gli impulsi al motore e tu devi agire solo sul pin direzione.

Se vuoi accelerare devi diminuire di volta in volta il delay nel ciclo for, in questo modo impiegherà meno tempo per fare uno step e la rotazione accelererà. Poi aumenti il delay e il motore decellererà. potresti usare un if(variabile>=10) variabile--;a inizio del corpo del for, e poi metterai delay(variabile);


Per fare qualcosa dopo un numero di passi, metti un if all'interno del for che valuta il valore di x.


Non ho mai usato librerie che permettessero di accelerare uno stepper, ma di solito usando librerie si riesce a fare una cosa molto meglio che senza.

gpb01

#2
May 19, 2019, 10:22 am Last Edit: May 19, 2019, 10:22 am by gpb01
Non ho mai usato librerie che permettessero di accelerare uno stepper, ma di solito usando librerie si riesce a fare una cosa molto meglio che senza.
... aggiungo ... anche non volendole usare, comunque studiandole (sono di files sorgenti totalmente leggibili), si impara molto e si capisce come potre fare in modo efficiente una cosa.

Guglielmo
Search is Your friend ... or I am Your enemy !

1oniudra2

Per God Member

Grazie della risposta.

Potresti intervenire sul codice che ho postato in modo tale che possa studiare per bene le debite variazioni.


Per Global Moderator

Hai ragione ,ho provato anche quelle ma se quello che voglio fare e' abbastaza semplice non ci sono problemi
se poi le cose si complicano un po' es utilizzando piu' motor ho trovato difficolta'.

Silente

Utilizzando più motori devi cambiare tutti i delay() con usi della funzione millis(), una bella gatta da pelare se vuoi modificare il codice senza riscriverlo. Quanto a conoscere la posizione non é possibile, puou soltanto sapere quanti passi hai fatto fare al motore, mettendo l'if dentro nelle graffe di for e testando il valore della variabile. Infine per accellerare e decelerare devi creare una variabile che contenga il valore del delay(1000) e abbassarla/alzarla della quantità desiderata ad ogni ciclo di for, e chiaramente sostituire quel 1000 con il nome della variabile
Dove va un numero va una variabile o una funzione. E dove va una boolean va un insieme di test.

Se vuoi ottenere devi saper spiegare

In pochi capiscono l'importanza di formattare, sii tra di essi

torn24

Da quello che ti ho indicato saresti dovuto riuscire tu stesso a modificare il tuo codice, ti posto un esempio
almeno cerca di capirlo bene, altrimenti non avrai imparato assolutamente nulla :)



Code: [Select]


/* Siccome lo stesso codice "il for" viene ripetuto
    identico due volte, ci creiamo una funzione con parametri.
    Di solito se un codice è ripetuto più volte nel programma,
    ci si crea un sottoprogramma e lo si richiama le volte necessarie.
*/

void loop(){

    

    digitalWrite(dirPin1,HIGH);
  
    if(prova==0){
       rotazioneMotore(1);
       prova=1;
       delay(1000);
    }
 
   if(prova==1){
       digitalWrite(dirPin1,LOW);
       rotazioneMotore(0);
       prova=2;
   }
}// end loop()


void rotazioneMotore(int incremetoDecremento){

     int tempo=800;
     for (int x = 0; x < 3800; x++){
    
        digitalWrite(stepPin1,HIGH);
        delayMicroseconds(tempo);
        digitalWrite(stepPin1,LOW);
        delayMicroseconds(tempo);
        
        if(incrementoDecremento==1 && tempo>10){// diminuisco il delay fino a valore 10
             tempo-=2;
        }else if(incrementoDecremento==0 && tempo <=1000){//aumento fino a valore 1000
        
             tempo+=2;

        }
        
     }// end for



}


1oniudra2

Io sto cercando di capirlo bene ma mi sono accorto che non funziona un motivo l'ho trovato:Hai scritto
incremetoDecremento al posto di incrementoDecremento va be' una svista,il problema pero' e' che anche dopo
averlo corretto arduino mi restituisce "Errore durante la compilazione........"Francamente non so se e' la mia scheda arduino che ha dei problemi o il codice che hai scritto.
Grazie dell'attenzione.

torn24

Sicuramente è il codice :) Non è un programma completo ma un esempio, nel codice manca ad esempio la funzione void setup(){}, che è obbligatoria, se usi delle variabili queste vanno dichiarate, se usi pin questi devono essere predisposti con la funzione pinMode() ecc..


Il codice che hai postato non era un programma completo, non so dove hai dichiarato le varie variabili, e i pin che utilizzi.

1oniudra2

O.K.

Ti metto una parte completa del codice cosi' se vuoi puoi intervenire in maniera esauriente.
 
E cosi' me lo posso studiare per benino.Ho indicato solo un motore dei tre ma penso che la correzione che apporterai come semplificazione e come accelerazione la possa trasferire anche agli altri.
Ti ringrazio ancora.

Code: [Select]

const int stepPin1 = 2;//primo motore
const int dirPin1 = 3;//primo motore
const int stepPin2 = 6;//secondo motore
const int dirPin2 = 7; //secondo motore
const int stepPin3 = 10;//terzo motore
const int dirPin3 = 9;//terzo motore

int prova=0;

 void setup()
 {
 
  // Sets the two pins as Outputs
  pinMode(stepPin1,OUTPUT);
  pinMode(dirPin1,OUTPUT);
  pinMode(stepPin2,OUTPUT);
  pinMode(dirPin2,OUTPUT);
   pinMode(stepPin3,OUTPUT);
  pinMode(dirPin3,OUTPUT);
   
  digitalWrite(13,OUTPUT);
 
}
void loop()
{
 
  digitalWrite(dirPin1,HIGH); 
   
  if(prova==0)
   {
  for (int x = 0; x < 3800; x++)
  {
    digitalWrite(stepPin1,HIGH);
    delayMicroseconds(200);
    digitalWrite(stepPin1,LOW);
    delayMicroseconds(200);
    prova=1;
    }
    delay(1000);
 }
 
   if(prova==1)
   {
    digitalWrite(dirPin1,LOW);
     for (int x = 0; x < 3800; x++)
  {
    digitalWrite(stepPin1,HIGH);
    delayMicroseconds(200);
    digitalWrite(stepPin1,LOW);
    delayMicroseconds(200);
    prova=2;
     
 }
   delay(1000);
    }
     
...................


torn24

Intanto avendo come esempio la funzione devi sapere andare avanti da solo, altrimenti non sei ancora in grado di fare quello che vorresti, ossia il progetto non è adatto alle tue attuali conoscenze.Poi nessuno ti ruba idee, forse dovresti spiegare cosa voi fare con tre motori, cosa devi ottenere come risultato globale e finale, la tua domanda era come accelerare un motore, è un problema semplice, ma se tu con tre motori devi ottenere qualcosa, la cosa è diversa e potrebbe essere complessa. Parti dall' inizio spiega il tuo progetto e cerca suggerimenti per tutto il progetto, non si può parlare di uova se devi fare lasagne, non ti serve parlare di come accelerare il motori che forse i problemi sono altri, e richiedono soluzioni più complesse, nessuno ti ruba il progetto, ci sono librerie molto complesse date a tutti, figurati se rubano il tuo progetto.

1oniudra2

No.......

Figurati se mi pongo questo problema......Credimi c'e' poco da rubare.

Comunque il progettino e' semplice si tratta di un braccio robotizzato che voglio rendere autonomo senza ricorrere a cnc.
Gia' con le mie poche conoscenze riesco a fargli fare quello che ho in mente, se osservi le poche righe di codice scritte e' facile intuire che tutto cio' e' fattibile.
Volevo solo rendere il progettino un po' piu' articolato facendo utilizzo delle accelerazioni dei bracci anche se non e' fondamentale dato che gli stessi si muovono gia' lentamente.
Era solo uno sfizio progettuale.
Per il momento un piccolo passo in avanti l'ho fatto e cioe' fare qualche cosa quando la x si trova in una certa posizione.Lo so che non e' la strada piu' breve ma funziona.
Per le accelerazioni ho provato seguendo il tuo schema ma non mi torna.

 
Code: [Select]

const int stepPin1 = 2;//primo motore
const int dirPin1 = 3;//primo motore
 

int prova=0;

 void setup()
 {
 
   
  pinMode(stepPin1,OUTPUT);
  pinMode(dirPin1,OUTPUT);
 
   
  pinMode(13,OUTPUT);
 
}
void loop()
{
 
  digitalWrite(dirPin1,HIGH); 
   
  if(prova==0)
   {
  for (int x = 0; x < 5000; x++)
  {
    digitalWrite(stepPin1,HIGH);
    delayMicroseconds(200);
    digitalWrite(stepPin1,LOW);
    delayMicroseconds(200);
   if(x==3000)
{
digitalWrite(13,HIGH);
prova=1;
}
   
    }//chiusura for
   }//chiusura if
 
 }//chiusura loop 




Comunque se vuoi scrivo quello che mi sembrava funzionasse come accelerazione ma non e' cosi'
e magari mi puoi dire dove sbaglio.

torn24

Sapendo lo scopo sarebbe meglio cercare librerie, che per posizionarsi accellerano e decellerano che calcolino la giusta accellerazione. Poi se ti accontenti di qualcosa che si muove, altrimenti per movimenti complessi sono nessari software molto complessi e non Arduino.

Maurotec

Quote
Volevo solo rendere il progettino un po' piu' articolato facendo utilizzo delle accelerazioni dei bracci anche se non e' fondamentale dato che gli stessi si muovono gia' lentamente.
Era solo uno sfizio progettuale.
Qualche mese fa ho sperimentato con un passo passo controllato con un driver generico L298 montato su un schedina sparkfun. Devo dire che è stato istruttivo sperimentare il passo intero e il mezzo passo via software in quanto L298 non permette il micro step via hardware.

Sperimentando mi sono accorto di quanto è importante avviare e fermare il motore attraverso curve di accelerazione decellerazione.

Per semplificare non ho usato curve ma un trapezio, cioè immaginiamo di disegnare un trapezio sugli assi cartesiani dove x è il tempo che scorre, y è la velocità istantanea. Il valore di y cresce si stabilizza e poi decresce fino a 0. L'andamento di y traccia appunto un trapezio, pertanto è più corretto parlare di rampe di accelerazione.

Con questo sistema si mette bene in evidenza che le rampe devono durare un tempo determinato dalla velocità massima richiesta e dal numero di passi richiesti. Ad esempio su 100 passi richiesti non posso applicare le rampe su 50 step in quanto avrei un triangolo al posto del trapezio.

La cosa non è per niente semplice da realizzare anche se avessi un driver hardware, ancora più complesso se al posto di un solo motore voglio controllarne 3.

Se non vuoi usare librerie ti consiglio di studiare i timer hadware interni alla MCU (atmega328 per Arduino Uno).

Ciao. 

torn24

Comunque per controllare un braccio anche con movimenti semplici, bisognerebbe pensare a soluzioni diverse. Avendo cicli for in successione che compiono un numero di passi, non mi sembra che si possa far compiere movimenti che possano avere qualche funzione.

Per muovere un braccio con movimenti semplici seguirei altre soluzioni, provo a spiegarle.

1)Primo ragionerei in gradi, mi calcolo quanti passi sono necessari per una rotazione di un grado

2)Mi creo una funzione per rotazione motore, che accetta come parametri (motore,numero gradi)

3)Mi creo una matrice righe-colonne, le righe sono i motori le colonne sono i movimenti in gradi di ogni
   motore  matrice[3][10].

4)Programmo i movimenti che voglio fare compiere al braccio, inserendo i gradi nella matrice matrice[0][0] primo motore primo movimento, matrice[1][0] secondo motore primo movimento, matrice[2][0] terzo motore primo movimento

5) Alla pressione di un pulsante attivo un ciclo for che scorre la matrice, e richiamo la funzione rotazione, indicando il numero di motore e i gradi.


In questo modo sarebbe possibili, programmando i gradi per ciascun motore nella matrice, compiere una serie di movimenti, e facilmente modificabile, infatti per fare una cosa o un altra dovrò solo inserire dei gradi diversi nella matrice, potrei anche avere una variabile che indica quanti movimenti fare, esempio la matrice potrebbe contenere 20 posizioni per ciascun motore matrice[3][20], ma a seconda di quello che devo fare, posso indicare di fare solo 4 movimenti ad esempio.

1oniudra2

#14
May 20, 2019, 10:08 am Last Edit: May 20, 2019, 10:11 am by 1oniudra2
Si certo,occorrerebbe un approccio piu' professionale ma essendo le mie conoscenze approssimate cerco con quelle di fare quello che posso.
Comunque la posizione la conosco dando alla x il giusto valore, la velocita' pure cambiando il microdelay
gli if all'interno dei for mi danno la coordinazione dei motori, 
l'accelerazione e la decellerazione con questo schema ispirato a cio' che hai postato
Code: [Select]

const int stepPin1 = 2;//primo motore
const int dirPin1 = 3;//primo motore
const int stepPin2 = 6;//secondo motore
const int dirPin2 = 7; //secondo motore
const int stepPin3 = 10;//terzo motore
const int dirPin3 = 9;//terzo motore
int tempo=2500;
int prova=0;

 void setup()
 {
 
  // Sets the two pins as Outputs
  pinMode(stepPin1,OUTPUT);
  pinMode(dirPin1,OUTPUT);
  pinMode(stepPin2,OUTPUT);
  pinMode(dirPin2,OUTPUT);
   pinMode(stepPin3,OUTPUT);
  pinMode(dirPin3,OUTPUT);
   
  pinMode(13,OUTPUT);
 
}
void loop()
{
 if(prova==0)
 {
   
     for (int x = 0; x < 13800; x++)
     {
   
        digitalWrite(stepPin1,HIGH);
        delayMicroseconds(tempo);
        digitalWrite(stepPin1,LOW);
        delayMicroseconds(tempo);
       
        if( tempo>100)//lentezza della velocita' che prende dopo accelerazione piu' e' alto e piu' va piano 400
        {
             tempo-=2;
             digitalWrite(13,HIGH);
             prova=1;
        }
     
    }
   }
   if(prova==1)
   {
for (int x = 13800; x < 15000; x++)
     {
   
        digitalWrite(stepPin1,HIGH);
        delayMicroseconds(tempo);
        digitalWrite(stepPin1,LOW);
        delayMicroseconds(tempo);
       
        if( tempo<=2500) 
        {
    tempo+=2;
    digitalWrite(13,LOW);
    prova=2;
    }
    }
  }
   }
   
     
   Posizione e velocita' per fortuna non richiamano la fisica quantistica e la relativa funzione d'onda
(scusa la divagazione).
In effetti il progettino si conclude con l'inserimento di due servo per il movimento della pinza e dell'ultimo braccio.L'accelerazione e decellerazione mi sono utili per non far vibrare troppo la pinza quando afferra
un oggetto e lo scarica in altra posizione.
Penso ormai ,grazie ai vostri suggerimenti, di avere le conoscenze di base per procedere,anche se
lo skech completo di arduino farebbe abbrividire chi di queste cose se ne intende come voi.
Comunque leggero' sempre con molta attenzione i vostri suggerimenti e per questo vi ringrazio ancora.
 

Go Up