Stepper motor rotazione e Delay modificabile con potenziometro

ciao,
sto scrivendo un programma per creare un taglia pasta automatico.
é il mio primo programma e sono un po in difficoltà.
Riassumo in breve quello che vorrei fare e il mio problema:
Comando il mio stepper motor per fargli fare una rotazione di 360 gradi (la velocità di rotazione è sempre la stessa, quella massima supportata dal mio motore) e poi farlo fermare per un delay di tempo che modifico grazie ad un potenziometro da 10 K ohm.Ho inserito valori per fare in modo di avere 100 differenti tempi di attesa tra una rotazione e l' altra del motore e tutto funzionava correttamente.
Ora ho cercato di aumentare i tempi di attesa tra una rotazione e l' altra da 100 a 500 (per avere più possibilità di regolazione) ma dopo la compilazione del programma mi appare l' errore perché ho superato la memoria disponibile. Potreste darmi consigli su come ridurre l' uso della memoria? proprio no saprei come fare... grazie per il supporto e buon pomeriggio!
di seguito parte del mio programma (si ripete per tutte le 500 volte dei vari tempi di attesa)

const int stepPin = 5; 
const int dirPin = 2; 
const int enPin = 8;
int potPin = 0;


void setup() { 
Serial.begin(9600);
 pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(enPin,OUTPUT);
  digitalWrite(enPin,LOW);

}

void loop() { 
int potPin = analogRead(A0);
Serial.println (potPin);
delay (50);
if (potPin>=1000){                                                       
  delay (5000);                                                         
  digitalWrite(dirPin,HIGH);                                             
  for(int x = 0; x < 200; x++) {                                    
    digitalWrite(stepPin,HIGH);                                         
    delayMicroseconds(520);                                       
    digitalWrite(stepPin,LOW);                                          
    delayMicroseconds(520);                                            
  }}else if ((potPin<1000) && (potPin>998)) {                            
    delay (4550);                                                   
digitalWrite(dirPin,HIGH); 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
    }}else if ((potPin<=998) && (potPin>996)) {
    delay (4450);
digitalWrite(dirPin,HIGH); 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
    }}else if ((potPin<=996) && (potPin>994)) {
    delay (4350);
digitalWrite(dirPin,HIGH); 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
    }}else if ((potPin<=994) && (potPin>992)) { 
    delay (4250); 
digitalWrite(dirPin,HIGH); 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
    }}else if ((potPin<=992) && (potPin>990)) { 
    delay (4150);
digitalWrite(dirPin,HIGH); 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
}}else if ((potPin<=990) && (potPin>988)) {
    delay (4050);
digitalWrite(dirPin,HIGH); 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
    }}else if ((potPin<=988) && (potPin>986)) {
    delay (3950);
digitalWrite(dirPin,HIGH); // 
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(520); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(520);
    }}else if ((potPin<=986) && (potPin>984)) {
    delay (3850);

Forse il programma è troppo lungo. Posta il messaggio di errore con copia ed incolla, così si vede anche quale arduino stai usando.

Ciao.

@Maurotec: ... solo un po' lungo? :scream:

... hai notato la (NON) struttura e la sua frase:

In pratica non ha applicato nessuna map o conversione del valore che legge sull'analogico ma .... fa un infinità di if, tutte uguali, in cui cambia solo il valore di un delay() ... :crazy_face:

@ricky577: dove hai trovato la pazienza (... perché ci vuole veramente tanta pazienza) per scrivere una cosa simile?

Quel codice si scrive in poche righe, devi solo trovare una relazione tra il valore analogico che leggi e il tempo di ritardo che ti occorre ...

... mi sembra che ogni variazione di 2 del valore analogico vedo vari di 100 msec il delay ... o ci sono altre regole?

Guglielmo

lascio un paio di considerazioni che potrebbero, in futuro, aiutare il nostro amico

primo, al di la della "cascata di 500 elseif (costrutto che oltretutto io odio)
ci sono anche 500 ripetizioni delle stesse operazioni

vediamo come si potrebbe ridurre la cosa

passo 1, santo precompilatore
il precompilatore mi permette di sostituire parti di programma con "costanti letterali"

se io scrivessi
#define Albero "melo"
nel programma tutte le volte che c'è scritto Albero è come se io in realtà avessi scritto "melo", con le virgolette
proviamo a usarlo a nostro vantaggio

const int stepPin = 5; 
const int dirPin = 2; 
const int enPin = 8;
int potPin = 0;


// si usa solitamente il tutto maiuscolo, per riconoscerle
#define MUOVI  digitalWrite(dirPin,HIGH); /                                             
  for(int x = 0; x < 200; x++) {                           /         
    digitalWrite(stepPin,HIGH);                          /               
    delayMicroseconds(520);                               /        
    digitalWrite(stepPin,LOW);                              /            
    delayMicroseconds(520);                                          
  // l'ultima riga non ha la barra, la barra significa semplicemente di considerare la riga non finita

void setup() { 
Serial.begin(9600);
 pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(enPin,OUTPUT);
  digitalWrite(enPin,LOW);

}

void loop() { 
int potPin = analogRead(A0);
Serial.println (potPin);
delay (50);
if (potPin>=1000){                                                       
  delay (5000);                                                         
MUOVI  

}}else if ((potPin<1000) && (potPin>998)) {                            
    delay (4550);                                                   
MUOVI
    }}else if ((potPin<=998) && (potPin>996)) {
    delay (4450);

MUOVI
    }}else if ((potPin<=996) && (potPin>994)) {
    delay (4350);

MUOVI
    }}else if ((potPin<=994) && (potPin>992)) { 


e via così naturalmente

sarebbe un pochino più facile da scrivere, ma...
trattandosi di una sostituzione come testo, non cambierebbe nulla nella compilazione, stessi errori

però ci da un'idea
invece di usare una macro possiamo usare una funzione

const int stepPin = 5; 
const int dirPin = 2; 
const int enPin = 8;
int potPin = 0;



void muovi(){
  digitalWrite(dirPin,HIGH);                                              
  for(int x = 0; x < 200; x++) {                                   
    digitalWrite(stepPin,HIGH);                                      
    delayMicroseconds(520);                                  
    digitalWrite(stepPin,LOW);                                    
    delayMicroseconds(520);                           
}          
  

void setup() { 
Serial.begin(9600);
 pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(enPin,OUTPUT);
  digitalWrite(enPin,LOW);

}

void loop() { 
int potPin = analogRead(A0);
Serial.println (potPin);
delay (50);
if (potPin>=1000){                                                       
  delay (5000);                                                         
muovi();  

}}else if ((potPin<1000) && (potPin>998)) {                            
    delay (4550);                                                   
muovi();
    }}else if ((potPin<=998) && (potPin>996)) {
    delay (4450);
muovi();
    }}else if ((potPin<=996) && (potPin>994)) {
    delay (4350);
muovi();
    }}else if ((potPin<=994) && (potPin>992)) { 


e via così naturalmente

sostituiremmo 500 pezzi tutti uguali del programma con 500 "chiamate" allo stesso pezzo "separato e racchiuso" in una funzione

queste cose sono le basi della programmazione, in qualunque linguaggio appena appena più evoluto del GWBASIC, in qualunque ambiente e quindi anche su Arduino

dopo invece mostro qualche alternativa ad una lunga e tediosa cascata di elseif
però senza dare la pappa pronta...

adesso che abbiamo "ridotto" il lavoro nel corpo delle if() vediamo se possiamo ridurre la "condizione" delle if()

tu scrivi:

if (potpin>=1000){}
else if(potpin<1000 && potpin>998){}
else if.....

ma se ci pensi il caso che sia inferiore a 1000 nella seconda condizione lo potresti escludere perché se lo fosse avresti già eseguito la prima riga


if(p>=1000){
...
return
if (p>=998){
...
return 
}

e via così
return
termina la funzione (nel tuo caso la loop) e "evita" che siano provati gli if successivi, che sono inutili visto che hai già trovato quello che cerchi

usando i due metodi illustrati qui vedi bene che il programma ha cominciato a ridursi come un soufflè tirato fuori dal forno

e non siamo ancora andati a "vedere" se sia possibile ottenere la famosa relazione della quale parlava Guglielmo
te pensa quanto è possibile "migliorare" i programmi se ci si ferma un poco a pensare

nel prossimo futuro cerco la famosa relazione

Non sempre invece è possibile trovare una "relazione" del tipo che citava Guglielmo

in realtà la matematica "dimostra" che dato H punti in un piano cartesiano sia sempre possibile trovare una "relazione" che li unisce ovvero una "funzione" in senso matematico.
Peccato che viene dimostrato anche che per H punti la funzione si può esprimere con un polinomio di "al massimo" grado H+1
ora, scrivere una funzione in C che calcoli un polinomio di 501esimo grado non è una passeggiata, forse è meglio passare per tante if

però, anche qui si può pensare un poco a migliorarsi
ammesso che NON esista una relazione semplice piuttosto di fare un if() e 499 elseif() si potrebbe caricare una tabella di numeri e ciclare la tabella


int tabella[500]={0,2,4,6,8,10,12,14.......};
int tempi[500]={100, 102, 106, 122, 130, 131....
// ho usato volutamente valori che non sono facilmente prevedibili



// poi nella loop
...
...

for (int i=0; i<500; i++){
   if (pinpot>tabella[i]){

   ...
   delay(tempi[i]);
   break;

   }



}

...
...

qui ho aggiunto un break; per la stessa ragione del return di prima, è inutile andare avanti a cercare se abbiamo già trovato...
però c'è volutamente un errore
bisogna ragionare un poco per trovarlo

adesso invece vediamo il caso che la relazione esista e sia anche facile, come nel nostro caso

.
.
.
muovi()
delay(relazione(pinpot));
.
.

dove la funzione relazione(pinpot) la devi scrivere perché "calcoli" il giusto valore di delay
per esempio se il tempo di attesa fosse 1 secondo per letture oltre 1000 e mezzo per tutte le altre dovresti fare:

int relazione(int ingresso){
return 500+500*ingresso>1000;

se per caso non sei riuscito a seguire... "meglio"
perché sai dove hai criticità e la cosa ti servirà da stimolo per lo studio

... ovviamente; ci sono casi in cui la "relazione" matematica" è più complicata di una soluzione molto più prolissa e ripetitiva, per cui ... non ne vale la pena :roll_eyes: ... ma non è questo il caso :wink:

Guglielmo

Trattandosi semplicemente di un potenziometro per impostare dei tempi, si potrebbe anche fare qualche approssimazione ottenendo una formula molto semplice!
(Tra l'altro, mi aspetterei che potPin sia il pin a cui è collegato il cursore del potenziometro, non il valore letto!)

potPin=A0; // A0 è una variabile a cui è assegnato il numero dell'I/O di A0 per il microcontrollore in uso.

// --- loop() ---
analogRead(potPin); delay(4.5*analogRead(potPin));
digitalWrite(dirPin,HIGH); 
for(uint8_t x=0; x<200; x++)
  {
  digitalWrite(stepPin,HIGH); delayMicroseconds(520); 
  digitalWrite(stepPin,LOW); delayMicroseconds(520);
  }

Punto! :slight_smile:

Ciao,
grazie per la risposta. Uso Arduino uno R3. e questo è il messaggio di errore:

Lo sketch usa 37622 byte (116%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Sketch troppo grande; guarda https://support.arduino.cc/hc/en-us/articles/360013825179 per consigli su come ridurne la dimensione
Le variabili globali usano 188 byte (9%) di memoria dinamica, lasciando altri 1860 byte liberi per le variabili locali. Il massimo è 2048 byte.
la sezione del testo supera lo spazio disponibile nella scheda

Compilation error: la sezione del testo supera lo spazio disponibile nella scheda

grazie

Ciao, grazie per avermi scritto!
Il mio intento era mappare i valori letti dal potenziometro (0-1023) a step da circa 2 punti per volta in modo da avere circa 500 Delay diversi l' uno dal altro modificabili tramite il potenziometro...
Sono proprio alle prime armi e ho cercato di farlo leggendo un po di pagine online...
ora provo a leggere bene i vostri commenti e consigli per provare a ridurre la dimensione! speriamo di riuscirci :wink: grazie mille!

... che è esattamente quello che, passo passo, i vari post successivi ti hanno spiegato come fare senza ripetere 500 volte la stessa cosa :wink:

Buona lettura e buono studio :slight_smile:

Guglielmo

1 Like

ciao, grazie per tutta la lunga spiegazione ed esempi.
Ho capito ( o credo di aver capito) quanto mi hai spiegato fino a dove abbiamo ridotto gli else if (poco prima della relazione matematica) ma non riesco ad applicarlo al programma.. ho provato tutta la sera ma continua a darmi errore nella compilazione...
non so più come risolvere.

grazie
Riccardo

Forse dico una cosa inesatta, ma mi sembra che le tue scale dei ritardi non corrispondano a quelle delle letture (mi riferisco al pezzo di programma che hai postato per primo).

Non solo per il fatto che con 1000 di lettura, tu dai 5000 di delay, mentre con solo 2 in meno salti a 4550 (450 in meno), ma anche al fatto che ogni 2 di lettura poi scendi di 100, di sicuro non puoi farci stare 500 valori, perche' nel 5000, il 100 al massimo ci sta' 50 volte (ma magari hai solo sbagliato a trascrivere ?)

Comunque mi chiedo perche' tutti quegli if, forse basterebbe semplicemente fare una sola volta delay uguale lettura per 5 (se vuoi una scala lineare, che in questo caso ti darebbe 1000 valori, 999 di delay, piu lo zero) ...

O magari ho capito male io ?

EDIT: oppure se proprio si vogliono solo 500 passi, fare lettura diviso 2, e poi il risultato per 10, ma dichiarando le variabili come int, il che dovrebbe eliminare automaticamente le cifre decimali, per cui il numero finale cambierebbe solo ogni 2 di lettura (oppure e' troppo barbaro come sistema ? )

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.