Giorno, scrivo questo post poiché durante il mio primo progetto, movimentazione di un motore stepper tramite arduino, ho avuto mille difficoltà, ho avuto, più volte l impulso di chiedere aiuto al forum, ma leggendo e rileggendo vari argomenti, sono riuscito in automonia a fare ciò che volevo.. Muovere in loop, avanti e indietro, quando toccare un fine corsa cambia direzione, con due fine corsa uno in alto uno in basso nella cosa della slitta e il gioco è fatto. È una piccola ma grande soddisfazione. Soprattutto perché io non sono un programmatore e di elettronica ne sono pochissimo, https://youtube.com/shorts/kfrSJvl9sH4?si=6L-T0Q838dkER57W
Ogni tanto I.A. ce la fa (vabbè, dai, era semplice).
Ma non ti ci abituare: spesso non ce la fa!!!
Benvenuto e buon divertimento.
... ce la fa se tu sai quello che ti serve e continui a correggere e migliorare le specifiche fino a quando tira fuori qualche cosa di decente ![]()
Guglielmo
Infatti perseverare è stato quello che ho fatto.. Non so quanti sketch ho fatto, per una settimana. Poi ho letto la funzione break, ho portato qualche esempio a I. A è dopo vari tentativi ci sono riuscìto. Come detto prima ho avuto molte volte la voglia di chiedere aiuto
una cosa semplice, prima era difficile, spero che le cose diventino semplici anche per me😁
Facci vedere questo sketch!
Hai messo solo il video, ma noi qui ci divertiamo con il listato del codice ![]()
![]()
![]()
// Funzione principale di loop
void loop() {
moveMotor(); // Muovi il motore
checkLimitSwitches(); // Controlla il fine corsa
}
// Funzione per controllare gli interruttori di fine corsa
void checkLimitSwitches() {
if (digitalRead(limitSwitchUpPin) == LOW) {
Serial.println("Attivato fine corsa superiore!");
changeDirection(LOW); // Cambia direzione verso il basso
}
if (digitalRead(limitSwitchDownPin) == LOW) {
Serial.println("Attivato fine corsa inferiore!");
changeDirection(HIGH); // Cambia direzione verso l'alto
}
}
// Funzione per cambiare la direzione del motore
void changeDirection(int dir) {
digitalWrite(dirPin, dir);
while (digitalRead(limitSwitchUpPin) == LOW || digitalRead(limitSwitchDownPin) == LOW) {
stepMotor(); // Muovi il motore finché il fine corsa è attivo
}
}
// Funzione per muovere il motore
void moveMotor() {
for (int i = 0; i < stepsPerMillimeter * distanceToMove; i++) {
if (digitalRead(limitSwitchUpPin) == LOW || digitalRead(limitSwitchDownPin) == LOW) {
Serial.println("Movimento interrotto per attivazione del fine corsa!");
break; // Interrompi il movimento se un fine corsa è attivato
}
stepMotor(); // Muovi il motore
}
}
// Funzione per generare un impulso al motore
void stepMotor() {
digitalWrite(stepPin, HIGH); // Impulso alto
delayMicroseconds(500); // Durata dell'impulso
digitalWrite(stepPin, LOW); // Impulso basso
delayMicroseconds(500); // Intervallo tra gli impulsi
Ecco fatti delle risate.. Non ho messo la parte iniziale quella delle definizione dei pin.. Ora la prossima mossa è mettere un potenziometro
Il codice ha margini di miglioramento, ma come impianto di base non è male.
Non mi torna molto il discorso del while sul cambio direzione, secondo me lo puoi rimuovere.
Secondo me come prossima mossa ti conviene dare una rampa di accelerazione e decelerazione al motore, che implica la revisione completa della funzione stepMotor() oppure l'utilizzo di una libreria fatta allo scopo.
Adesso lo stai provando a vuoto, ma quando ci metterai un carico da movimentare potresti perdere passi.
Cmq per evitare proprio la perdita di passi ho messo i due fine corsa. perché la slitta deve arrivare dove si trova il fine corsa.. In teoria il motore, deve percorrere una distanza maggiore della corsa effettiva che mi serve, anche se perdesse passi prima o poi tocca il fine corsa e cambia direzione, questa è stata la mia idea. Poi un altra cosa, quando accendi e spegni il motore parte alla cavolo con i fine corsa ho risolto pure questo problema.
Cmq accetto il consiglio e ti ringrazio vedrò cosa posso fare, con le mie capacità abbastanza limitate
Il finecorsa va benissimo per l'homing e come extra-corsa di sicurezza, ma non per compensare eventuali perdite di passi.
Il problema con gli stepper è che quando inizi a perdere troppi passi, perdi il sincronismo con il rotore ed il motore potrebbe non girare affatto o avanzare a singhiozzi.
Durante il normale funzionamento è una cosa che si deve cercare di evitare assolutamente regolando correttamente, oltre alla corrente, anche velocità massima e accelerazione.
A questo punto, tanto vale che ci metti un classico motore DC
Vedrò di usare delle librerie per controllare accelerazio e rallentamento in modo da gestire meglio il motore
Una delle librerie più utilizzate e versatili è la libreria AccelStepper che può funzionare sia in modo bloccante (in pratica secondo lo stesso principio che hai usato nel tuo sketch) e sia in modo non bloccante.
Se vuoi prendere ispirazione, ho qualche progetto di esempio "non bloccante" su wokwi come ad esempio questi due (non prendere a riferimento i collegamenti perché il simulatore tiene conto solo dei segnali step e dir).
Se cerchi "wokwi accelstepper" ne troverai molti altri.
Appena ritorna a casa metto a lavoro grazie ancora
Grazie e grazie ancora
const int stepPin = 2; // Pin per il segnale STEP
const int dirPin = 5; // Pin per la direzione DIR
const int enablePin = 8; // Pin per abilitare il driver
const int limitSwitchUpPin = 9; // Pin per il fine corsa superiore
const int limitSwitchDownPin = 10; // Pin per il fine corsa inferiore
const int potPin = A0; // Pin per il potenziometro
const int stepsPerMillimeter = 100; // Passi per mm
const int distanceToMove = 100; // Distanza da muovere in mm
const int stepsPerRevolution = 200; // Passi per rivoluzione del motore
unsigned long lastStepTime = 0; // Tempo in cui è stato generato l'ultimo impulso
int stepInterval = 500; // Intervallo tra gli impulsi in microsecondi
// Soglia per il potenziometro
const int potThreshold = 10; // Soglia minima per attivare il motore
void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(enablePin, OUTPUT);
pinMode(limitSwitchUpPin, INPUT_PULLUP);
pinMode(limitSwitchDownPin, INPUT_PULLUP);
digitalWrite(enablePin, LOW);
Serial.begin(9600);
}
void loop() {
moveMotor(); // Muovi il motore
checkLimitSwitches(); // Controlla il fine corsa
}
// Funzione per controllare gli interruttori di fine corsa
void checkLimitSwitches() {
if (digitalRead(limitSwitchUpPin) == LOW) {
Serial.println("Attivato fine corsa superiore!");
changeDirection(LOW); // Cambia direzione verso il basso
}
if (digitalRead(limitSwitchDownPin) == LOW) {
Serial.println("Attivato fine corsa inferiore!");
changeDirection(HIGH); // Cambia direzione verso l'alto
}
}
// Funzione per cambiare la direzione del motore
void changeDirection(int dir) {
digitalWrite(dirPin, dir);
while (digitalRead(limitSwitchUpPin) == LOW || digitalRead(limitSwitchDownPin) == LOW) {
stepMotor(); // Muovi il motore finché il fine corsa è attivo
}
}
// Funzione per muovere il motore
void moveMotor() {
for (int i = 0; i < stepsPerMillimeter * distanceToMove; i++) {
if (digitalRead(limitSwitchUpPin) == LOW || digitalRead(limitSwitchDownPin) == LOW) {
Serial.println("Movimento interrotto per attivazione del fine corsa!");
break; // Interrompi il movimento se un fine corsa è attivato
}
stepMotor(); // Muovi il motore
}
}
// Funzione per generare un impulso al motore usando millis()
void stepMotor() {
unsigned long currentMicros = micros(); // Usa micros() per tempi brevi
// Leggi il valore del potenziometro
int potValue = analogRead(potPin);
// Controlla se il valore del potenziometro è sopra una soglia
if (potValue > potThreshold) {
if (currentMicros - lastStepTime >= stepInterval) {
lastStepTime = currentMicros;
digitalWrite(stepPin, HIGH);
delayMicroseconds(10); // Breve impulso per assicurare il segnale
digitalWrite(stepPin, LOW);
// Aggiornamento stepInterval usando il valore del potenziometro
stepInterval = map(potValue, 0, 1023, 2000, 100);
}
}
}
ho cambiato i delay con millis poi ho aggiunto il potenziometro. fico wowki non lo conoscevo. in teoria cosi dovrebbe anche controllare accelerazione
