Servomotore non si blocca a 0 gradi

Salve a tutti,
sto realizzando l'apertura a la chiusura di alcune serrande di aspirazione polveri e ho pensato di utilizzare dei servomotori.
Aprendosi e chiudendosi tra 0 e 180 gradi svolgerebbero il loro compito egregiamente, ma non sono nemmeno partito e ho già un problema:

Nello sketch super base che ho fatto il servomotore dovrebbe partire posizionandosi a 0 gradi (serranda chiusa) e quando premo il pulsante dovrebbe aprirsi andando a 180 gradi.

Problema 1:
il servomotore (di cui vi lascio il link più sotto) quando si porta a 0 gradi poi fa un altro "colpetto" e si sposta di qualche grado ... perchè non si blocca?

Problema 2:
come faccio a farlo fermare a 180 gradi una volta premuto il pulsante?

Problema 3:
a quanto ho capito il servomotore è sempre alimentato, non c'è la possibilità di metterlo in una sorta di stasi quando non è sollecitato? Forse è la parte hardware sbagliata per questo progetto?

#include <Servo.h>

Servo servo1;

void setup() {
  
  pinMode(2, INPUT_PULLUP); 

  servo1.attach(7);
  servo1.write(0);
  delay(500);
}

void loop() {
  if ( digitalRead(2) == LOW ){
      servo1.write(180);
      delay(1000);
      
  }      
          
}


Servomotore utilizzato

Piccola premessa, i servo che hai preso sono delle cineserie low cost, questo significa che oltre a doverti aspettare il mancato rispetto delle caratteristiche dichiarate sicuramente avranno una vita breve, per capirci un singolo servo RC da 15 kg*cm di qualità decente cosa non meno di 40E per il più economico.
Per il fatto che quando lo mandi a zero gradi fa un ulteriore scatto il problema è sicuramente del servo stesso, possibile qualche anomalia nel trascinamento del potenziometro che rileva la posizione o nell'elettronica interna del servo.
I servo si spostano alla posizione determinata dalla lunghezza dell'impulso di controllo, se questa rimane costante mantengono la loro posizione, sotto presenza di un carico meccanico, oltre ad assorbire corrente, possono vibrare emettendo un ronzio.
E' implicito nel modo di funzionamento dei servo che devono rimanere sempre alimentati e presentano un costante assorbimento di corrente anche quando sono fermi senza nessun carico meccanico, in presenza di un carico meccanico si oppongono al movimento e aumenta l'assorbimento.
Visto il tipo di applicazione potresti optare un banale motoriduttore, ne esistono di molto economici, che aziona la serranda con due switch di fine corsa per sapere quando è nella corretta posizione, in questo caso puoi letteralmente spegnere l'elettronica, un H-BRIDGE, che controlla il motore riducendo l'assorbimento a livelli molto bassi, se poi metti in sleep il processore, si sveglia solo quando premi i pulsanti di controllo, puoi ridurre l'assorbimento complessivo a meno di 1mA in stato di standby.

Con 3 pulsanti e un paio di rele in autoritenuta azzeri proprio il consumo dell'elettronica: la elimini del tutto

Comunque cosa ti fa pensare che il "colpetto" lo faccia dopo essersi posizionato a zero ?

Forse lo fa prima, metti qualche stampa e qualche delay (il tempo di leggere le stampe) e vediamo

me lo fa pensare il fatto che 0 dovrebbe teoricamente essere la posizione (supponiamo più a destra) ci va e poi torna indietro, quindi lo fa dopo il movimento.

quindi se capisco bene suggerisci di usare ad esempio uno stepper motor tipo quelli da stampa 3D.
Per dirne una potrei usare l'A4988 che ha tutto integrato giusto?

una cosa così potrebbe funzionare?

#define stepMotor 6 // pin movimento motore
#define dirMotor 7 // pin direzione motore

void setup(){

  // definizione pin 
  pinMode(2, INPUT_PULLUP); //fine corsa dx serranda chiusa
  pinMode(3, INPUT_PULLUP); //fine cors sx serranda aperta
  pinMode(4, INPUT_PULLUP); //cmd apertura serranda
  pinMode(5, INPUT_PULLUP); //cmd chiusura serranda
  pinMode(7, OUTPUT); // cmd motore stepper 1
  pinMode (stepMotor, OUTPUT);
  pinMode (dirMotor, OUTPUT);

// situazione iniziale tutte le serrande chiuse
 while( digitalRead(2) == LOW){
    digitalWrite(dirMotor, LOW);
    digitalWrite(stepMotor, HIGH);
    delay(500);
    digitalWrite(stepMotor, LOW);
    delay(500);
 }
}

void loop(){

// apertura serranda con pressione pulsante
 if ( digitalRead(4) == LOW) {
   while( digitalRead(3) == LOW){
    digitalWrite(dirMotor, HIGH);
    digitalWrite(stepMotor, HIGH);
    delay(500);
    digitalWrite(stepMotor, LOW);
    delay(500);
   }
 }

// chiusura serranda con pressione pulsante
 if ( digitalRead(5) == LOW) {
   while( digitalRead(2) == LOW){
    digitalWrite(dirMotor, LOW);
    digitalWrite(stepMotor, HIGH);
    delay(500);
    digitalWrite(stepMotor, LOW);
    delay(500);
   }
 }
}

Io non ne sarei sicuro, controlla

E nemmeno credo che gli stepper vadano così

Ma un riduttore a vite senza fine e un motore da tergicristallo ti fanno così schifo ?

te lo giuro ste risposte mi fanno ricordare il perchè non frequento spesso i forum...

devo muovere in automatico 5 serrande, selezionarne una e far chiudere le altre, se hai una soluzione alternativa mostrala, io ho pensato a questa.

se inoltre sei certo che gli stepper non vadano così dimmi come vanno perchè è ovvio che se l'ho scritto così è perchè ho controllato e per dove arrivo io sembra corretto (fatto salvo il pin7).

Ma io ti ho fatto domande, sei tu che non hai risposto

Hai messo delle stampe per sapere 'quando' realmente si muove il servo?
No
E quindi?
Come io e mio fratello potremmo dirti altro?

Possiamo dirti che a noi risulta che il servo, all'accensione si muove 'da solo' fino al suo punto di riposo, che non è 0 gradi
Potrebbe essere questo il primo movimento errato, che tu potresti aver scambiato, credendolo il primo 'giusto' e credendo invece errato il secondo

Come si fa a sapere?
Si mettono le stampe, cosa che devi fare tu
Fallo!

Non posso mostrarti una soluzione se tu non mi dici tutto
Altrimenti sarebbero solo soluzioni inutili e parziali

Hai mai sentito del 'problema XY'?

Dici tutto quello che ti serve e solo dopo si possono cercare soluzioni

Tutto bello e tutto vero

Ma le domande importanti sono altre:
Quanto pesa la serranda?
Almeno una delle due posizioni estreme sta ferma da sola oppure serve di tenere sempre in coppia il motore?

Sapendo questo tutto il resto è in discesa

Certamente si tratta di modellini, dato il peso che può muovere quel servo
Stiamo parlando, ad andare bene, di 1 Nm

Edit, altrimenti il fratello non mi molla più

Coppia, non peso

è il "modo" Ducembarr, non quello che dici.
Detto ciò, ripartiamo da zero:

la domanda di questo thread è ormai superata perchè @m_frt mi ha convinto in poche righe che il servo non è l'hardware corretto, molto meglio un motore stepper, quindi a questo punto sarebbe più corretto aprire una nuova stanza con il titolo giusto e spiegarvi lì tutto quanto, giusto?

Perché vuoi utilizzare un motore passo passo? Usa un motore normale e due fine corsa, a meno che a fine corsa il motore debba tenere la serranda. Questa è una domanda a cui non hai risposto.

mah molto banalmente perchè ho dei nema17 raccattati da varie stampanti 3D inutilizzati.

Comunque visto che proseguiamo qui:

PROGETTO
le serrande sono serrande per un impianto di aspirazione polveri in una falegnameria.
Saranno stampate in 3D e le ho progettate a "spicchio di pizza", con il fulcro che dovrebbe ruotare intorno ad un perno (del motore) e passare da chiusa ad aperta.
Il peso quindi è irrisorio, parliamo di qualche grammo.
Lo spicchio (un triangolo in sostanza) ha un raggio di circa 19cm e copre poco meno di 180gradi per uno spessore di 2mm in PLA o ABS.
Le serrande saranno 5, quando se ne apre una le altre devono chiudersi.
L'attivazione sarò data da un quadro pulsanti facenti riferimento ad arduino e in parallelo avranno degli shelly per il comando domotico che faranno la stessa cosa dei pulsanti.

Le stampe della seriale degli sketch non posso ancora produrle perchè per ora vorrei capire teoricamente se lo sketch ha qualche problema clamoroso o non si può fare qualcosa, dopodichè prenderò tutto l'hardware necessario, progetterò le stampe 3D e monterò il prototipo.

RICHIESTA ATTUALE
Dimenticate i servomotori e passiamo ai nema se possibile.
Non sono un programmatore, sto eseguendo gli sketch seguendo lezioni online, quindi ci possono essere tranquillamente degli strafalcioni visibili anche senza nessuna stampa a confermarlo, per ora vi chiedo semplicemente di farmi notare questo.

Nello sketch che vi allego ad esempio ho ipotizzato di utilizzare l'A4988 e movimentare solo 2 motori.
Ho inserito le procedure a fine sketch per snellirne la sintassi ma nel setup (per fare il reset iniziale) non sapendo se le procedure possano esser lette le ho scritte per esteso.
Ho ipotizzato un pulsante per ogni serranda e ho inserito dei pin per collegare l'eventuale rilascio dei motori e la funzione sleep.
Le serrande e il movimento dei motori faranno riferimento a dei fine corsa, quindi la cosa che mi interessa è la direzione del motore perchè poi sarà il fine corsa a bloccarlo in posizione (con dei cicli while e degli if ... tutti annidati, qui non sono certo di quello che ho scritto).

#define s1_chiusa 2 //fine corsa serranda 1 chiusa
#define s1_aperta 3 //fine corsa serranda 1 aperta
#define pulls1 4 //cmd apertura s1
#define pulls2 5 //cmd apertura s2
#define stepMotor1 6 // pin movimento motore 1
#define dirMotor1 7 // pin direzione motore 1
#define stepMotor2 8 // pin movimento motore 2
#define dirMotor2 9 // pin direzione motore 2
#define s2_chiusa 10 //fine corsa serranda 2 chiusa
#define s2_aperta 11 //fine corsa serranda 2 aperta
#define free 12 //rilascio motori per movimenti manuali
#define pullfree 13 //pulsante di rilascio
#define sleep 14 //sistema dormiente

int stato = LOW; // variabile stato per rilascio driver

void setup(){

  Serial.begin(9600);

  // definizione pin 
  pinMode(s1_chiusa, INPUT_PULLUP); 
  pinMode(s1_aperta, INPUT_PULLUP); 
  pinMode(pulls1, INPUT_PULLUP); 
  pinMode(pulls2, INPUT_PULLUP); 
  pinMode (stepMotor1, OUTPUT); 
  pinMode (dirMotor1, OUTPUT); 
  pinMode (stepMotor2, OUTPUT); 
  pinMode (dirMotor2, OUTPUT); 
  pinMode (s2_chiusa, INPUT_PULLUP); 
  pinMode (s2_aperta, INPUT_PULLUP); 
  pinMode (free, OUTPUT);
  pinMode (pullfree, INPUT_PULLUP);
  pinMode (sleep, OUTPUT);
  
// attivazione driver e disabilitazione sleep

  digitalWrite(sleep, HIGH); // sistema attivo
  delay(1000);
  digitalWrite(free, LOW); // driver attivo
  delay(1000);

// situazione iniziale tutte le serrande chiuse  

 while( digitalRead(s1_chiusa) == LOW){
    digitalWrite(dirMotor1, LOW);
    digitalWrite(stepMotor1, HIGH);
    delay(500);
    digitalWrite(stepMotor1, LOW);
    delay(500);
 }

while( digitalRead(s2_chiusa) == LOW){
    digitalWrite(dirMotor2, LOW);
    digitalWrite(stepMotor2, HIGH);
    delay(500);
    digitalWrite(stepMotor2, LOW);
    delay(500);
 }

 digitalWrite(sleep, LOW);

}

void loop(){

// rilascio motori
 if ( digitalRead(pullfree) == LOW){
  rilascio();
 }  

// apre 1 chiude 2
 if ( digitalRead(pulls1) == LOW) {
  apri_1();
  chiudi_2();
   }
   
// apre 2 chiude 1
if ( digitalRead(pulls2) == LOW) {
  chiudi_1();
  apri_2();
   }
 }


// PROCEDURE

void apri_1(){
  while( digitalRead(s1_aperta) == LOW){
    digitalWrite(sleep, HIGH);
    delay(1000);   
    digitalWrite(dirMotor1, HIGH);
    digitalWrite(stepMotor1, HIGH);
    delay(500);
    digitalWrite(stepMotor1, LOW);
    delay(500);
    }
}

void chiudi_1(){
while( digitalRead(s1_chiusa) == LOW){
    digitalWrite(sleep, HIGH);
    delay(1000);    
    digitalWrite(dirMotor1, LOW);
    digitalWrite(stepMotor1, HIGH);
    delay(500);
    digitalWrite(stepMotor1, LOW);
    delay(500);
 }
}

void apri_2(){
  while( digitalRead(s2_aperta) == LOW){
    digitalWrite(sleep, HIGH);
    delay(1000);
    digitalWrite(dirMotor2, HIGH);
    digitalWrite(stepMotor2, HIGH);
    delay(500);
    digitalWrite(stepMotor2, LOW);
    delay(500);
    }
}

void chiudi_2(){
while( digitalRead(s2_chiusa) == LOW){
    digitalWrite(sleep, HIGH);
    delay(1000);
    digitalWrite(dirMotor2, LOW);
    digitalWrite(stepMotor2, HIGH);
    delay(500);
    digitalWrite(stepMotor2, LOW);
    delay(500);
 }
}
 
void rilascio(){
 digitalWrite(sleep, HIGH);
 delay(1000);
 stato = !stato; // commuta l'uscita di rilascio ad ogni pressione del pulsante pullfree
 delay(200);
 if (stato == HIGH){
   digitalWrite(free, HIGH); //driver libero
 } else {
   digitalWrite(free, LOW); //driver attivo
 }
}

Il peso forse, gli effetti aerodinamici invece?

Per essere chiari: prima realizzi il dispositivo
Poi misuri gli sforzi e solo dopo sai che motore ti serve

Prima fai solo inutile rumore

non sto chiedendo lumi su quale motore scegliere, rileggi il post prima con più attenzione per cortesia.

lo sketch è corretto?

No

Non lo è

È scritto pessimamente, non documentato e inutilmente complicato

Sei contento adesso?

Adesso segui pure la tua strada, perchè spiegarti come fare le cose per bene non lo vuoi
Continua a farle così come sai

@Ducembarr: ... Come ho detto mille volte, invece di fare tutti questi commenti polemici, sé non vi sta bene come un utente descrive il suo problema, EVITATE di rispondere e ignorate la discussione ... Grazie!

Guglielmo

1 Like

Con questa risposta hai semplicemente dimostrato che la tua supponenza è superiore al tuo sapere.

spendere 4 righe per dirmi "come e perchè è sbagliato" era troppo complicato immagino.
io ho descritto il mio problema, ti ho spiegato che non è il mio pane e che la scelta del motore al momento non è basilare e comunque se deve esserlo ti ho anche spiegato quale userò e perchè.
Il punto è che "non faccio come vuoi tu".

Nuovamente, mio malgrado, mi ritrovo ad avere una pessima opinione dei forum e di chi li professa come "risorse" per chi cerca una mano, mi arrangerò come ho sempre fatto, sbagliando e imparando sulla mia pelle.
@gpb01 se vuoi puoi chiudere il thread

Adesso ho chiara la situazione di quello che devi fare, se non hai problemi di spazio gli stepper nema17 vanno benissimo come attuatori.
Nel tuo codice non va bene come azioni gli stepper, come stai facendo ci vuole una "vita" per ruotare lo stepper di 180°, quelli classici per stampanti richiedono 200 impulsi per un giro, quindi te ne servono 100 per fare 180°, ammesso che li piloti in modo 1:1 tramite il driver senza attivare il microstepping, questo perché commuti l'impulso ogni secondo, pertanto servono 100 secondi per cambiare la posizione, non credo ti servono così lenti i movimenti.
Esistono ottime librerie per il controllo degli stepper, dove puoi impostare sia la velocità massima che il numero di step che devi fare, in questo caso ti basta un solo fine corsa nella posizione di chiuso, all'avvio fai muovere gli stepper fino a che le griglie non sono tutte chiuse e a quel punto per aprirle ti basta fare 100 step, il valore esatto è da trovare provando, ogni volta che chiudi le serrande hai nuovamente il riferimento a zero.