Muovere un servo motore tramite pc

Salve a tutti, avrei necessità di muovere un servo motore con la tastiera del mio pc; mio spiego meglio: voglio utilizzare il pulsanti (numeri) da 0 a 7 per spostare il mio servo motore che fa una rotazione di 180°. ho scritto un codice che mi da dei problemi, mi fa girare il motore con i pulsanti, ma non torna indietro, incrementa solo i gradi, ad esempio premendo su pulsante 1 non torna in posizione 1 ma avanza e poi stranamente premendo un pulsante fuori range ad esempio 9 torna indietro un pò alla volta continuando a premere sempre 9 lo faccio ritornare alla posizione originaria.

Il codice:

int servoPin = 2; // Pin di controllo per il servo motore
int minPulse = 500; // Posizione minima del servo
int maxPulse = 2500; // Posizione massima del servo
int pulse = 0; // Quantità di impulso per il servo

long lastPulse = 0; // Tempo in millisecondi dell'ultimo impulso
int refreshTime = 20; // Tempo richiesto tra gli impulsi

int analogValue = 0; // Valore restituito dal sensore analogico
int analogPin = 0; // Pin analogico del potenziometro
int val;

void setup() {
pinMode(servoPin, OUTPUT); // Setta il pin del servo in modalità output
pulse = minPulse; // Setta la posizione del motore sul valore minimo
Serial.begin(9600);
}

void loop() {
if (Serial.available() >0) {
val = Serial.read();
pulse = map(val,0,7,minPulse,maxPulse); // Converte il valore analogico in un intervallo tra minPulse e maxPulse.

// Invia un nuovo impulso al servo se il tempo di refresh (20 ms) è trascorso

if (millis() - lastPulse >= refreshTime) { // millis() Restituisce il numero di millisecondi da quando la scheda Arduino ha iniziato l'esecuzione del programma corrente.
// Questo numero di overflow (tornare a zero), dopo circa 50 giorni.
digitalWrite(servoPin, HIGH); // Accende il motore
delayMicroseconds(pulse); // La lunghezza dell'impulso setta la posizione del motore.Mette in pausa il programma per la quantità di tempo specificato come parametro.
digitalWrite(servoPin, LOW); // Spegne il motore
lastPulse = millis(); // Salva il tempo dell'ultimo impulso
}
}
}

Aiuto!!! :wink:

ciao
ecco gli errori che vedo ad occhio:

val NON è il numero digitato nella seriale, ma il valore ascii corrispondente; il carattere '0' mi pare valga 46, e così via. Puoi trasformarlo in numero usando la funzione atoi() oppure facendo
int valoreIntero = val-'0'; (vale per un solo carattere, altrimenti ci son 1000 discussioni al riguardo)

map() esegue una mappatura, ma NON limita ai valori max e min; quindi se premi 14 (il doppio del tuo max che è 7) map restituisce 5000 (il doppio di maxpulse)

altro problema è la generazione del PPM: 20ms è la durata del segnale totale, non di solo quello basso: quindi
refreshTime=20000-pulse;
ovviamente ti tocca lavorare anche quì con i millisecondi

consiglio:
anzichè il PPM generato da te puoi usare il PWM (se non erro, e comunque non da 0 a 255 ma, valori a caso, da 20 a 200, dai una letta al comando analogWrite) oppure la libreria servo.h (che genera vero PPM)
Questo, oltre che risolvere i problemi soprastanti, rende la creazione del PPM "parallela" ripetto al loop usando gli interrupt: ciò vuol dire che il tuo loop può avere anche delay infiniti senza che il segnale PPM ne risenta!

buona programmazione

potresti apportare tu queste modifiche al mio codice e posterle per favore?
P.S. non devo e non posso usare la libreria servo.h
Grazie mille.....

no, se no che gusto c'è?
:smiley:

Comunque se usi rhinoceros e grasshopper, c'è un add-on di nome firefly che funziona molto bene.