Arduino Visual basic Firmata

Salve ragazzi, sto realizzando un software in VB per poter gestire un Arm a 4 assi. Uso il protocollo Firmata precaricato nell'arduino. Leggo i valori in input dati dai potenziometri ma non riesco ad inviare tali valori in angoli per l'output digitale ai servo. Sono giorni che cerco in rete e non sono un'esperto di VB, sto andando a tentativi e l'ultimo è stato un ripiego, nel senso che ho diviso i valori dell'analog input per 5.69 ma non so se sia corretto.Quando però provo ad inviare tali risultati al pin digitale cui si trova il servo non succede niente.Se c' è qualcuno esperto in VB potrebbe darmi una mano nella soluzione? Se volete posso riportare l'elaborato del programma

Nel Timer associato al potenziometro 1 c'è:

potPin1 = FirmataVB1.AnalogRead (0) LggIngAnalog1.Text = potPin1 Angolo1 = potPin1 / 5.69 FirmataVB1. DigitalWrite (6, Angolo1)

Secondo me il firmare/sketch Firmata standard NON è in grado di pilotare un servo. Solo una mia opinione, non conosco bene Firmata.

In tutti i casi, da VB scrivi i comandi che faresti su Arduino. Se il servo accetta un segnale PWM (dubito), allora su Arduino si usa analogWrite() su pin digitale ma che permette il PWM (su Arduino uno sono quelli indicati con ~ ) Si spera che anche da firmata lato vb ci sia un analogWrite

Quello che manca in ciò che vuoi fare è la funzione che lega la posizione del potenziometro, e quindi il valore analogico che leggi, con la posizione del servo. Credo che se i potenziometri sono lineari dovrebbe venir fuori una retta (Angolo1 = potPin1 / 5.69 sarebbe una retta se non sto dormendo) ma se i potenziometri sono logaritmici le cose si complicano di poco.

Premetto che sto lavorando e al momento non posso portare molte delucidazioni ma... Il servo collegato è sul pin 6 quindi PWM , ho già eseguito un programma test sui motori con potenziometri in arduino e funzionano quindi tu dici che dovrei cambiare se ho capito bene solo l'invio sul pin digitale e cioè:

potPin1 = FirmataVB1.AnalogRead (0) // leggo LggIngAnalog1.Text = potPin1 // Trasferisco al potenziometro Angolo1 = potPin1 / 5.69 // Converto

Ed anzichè FirmataVB1. DigitalWrite (6, Angolo1) // Invio in digitale

dovrò fare FirmataVB1. AnalogWrite(6, Angolo1) // Invio in PWM

Provo e vi faccio sapere

Ma un'occhiata al file dll di firmata gliela do comunque

Non so se sono logaritmici o lineari i potenziometri ma la conversione alla fine avviene in decimale non dovrebbe comportarmi problemi

Traduco in parole terra terra: se il potenziometro è tutto a destra il servo in che posizione deve essere? Se il potenziometro è tutto a sinistra il servo in che posizione deve essere? Infine se il potenziometro è nel mezzo il servo in che posizione deve essere? Se il potenziometro è lineare mi aspetto che il valore letto nella posizione di mezzo sia ... nel mezzo dell'intervallo letto nelle due posizioni estreme. Se è logaritmico no. Ad esempio per un potenziometro da 10K Ohm mi aspetto che nel mezzo legga un valore che corrisponde a circa 5K Ohm. Significa che ad esempio FirmataVB1.AnalogRead (0) mi restituisce 0 a sinistra 1000 a destra e 500 nel mezzo.

Ho usato Firmata una sola volta anni fa e non ricordo bene.I valori per analogWrite dovrebbero essere degli interi ma tu esegui una divisione con un float. Angolo1 dovrebbe essere un intero ma non ne sono sicuro. Inoltre fai attenzione all'intervallo di Timer1, le istruzioni contenute devono essere svolte prima che scada l'intervallo.

Ricorda che non tutti i pin di Arduino supportano il PWM per cui puoi attaccare un servo solo ai pin 3,5,6,9,10,11

Eccomi. ..allora l'errore che commettevo stava nel fatto di voler comandare il servo con uscite digitali a non in pwm, come mi ha fatto notare nid69ita.Adesso qualcosa viene fuori il motore per un attimo ha ruotato rispondendo all'impulsi inviati dalla rotazione del potenziometro ma tira fuori all'aumentare dei Volt dei sibili di tenzione che non succede quando comando i motori direttamente da arduino sempre tramite l'uso del medesimo potenziometro. A questo punto credo che la conversione non sia più corretta e che quindi debba dividere i valori dell'ingresso analogico per i segnali in uscita in PWM ed infine portarli a valori angolari da inviare al motore. Non credo sia cosa facile e se avete dritte sono ben accette

Giro il potenziometro tutto da un lato, prendo il valore dell'ADC m1. Giro il potenziometro dall'altro lato e prendo il valore dell'ADC m2.

Il più piccolo lo chiamo Bitmin e il più grande Bitmax.

Prendo gli estremi dei valori che devo fornire al servo in corrispondenza dei due estremi del potenziometro, quelloin corrispondenza di bitmin lo chiamo valMin e l'altro valMax, questo anche se il valore di valMax è minore del valore di valMin.

Chiamiamo Valore_ADC adesso il valore che leggiamo dall'ADC per una qualsiasi posizione del potenziometro e Angolo il valore da calcolare.

Angolo=(Valore_ADC - Bitmin) / (Bitmax - Bitmin) *  (valMax - valMin) + valMin

Le due differenze Bitmax - Bitmin e valMax - valMin sono sempre le stesse e le puoi sostituire con i valori precalcolati.

Arduino ha la stessa funzione che si chiama Map

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Grazie per l’aiuto che mi state dando lo apprezzo…se ruoto tutto a sinistra il potenziometro è pari a 0 mentre tutto a destra è 1023, aumentando in maniera graduale.Quando con un firmware in arduino ho testato il motore, se giravo il potenziometro tutto a sinistra si posizionava tutto da un lato a destra tutto dal lato opposto e nel mezzo si trovava esattamente a metà tra i due estremi.Adesso proverò ad eseguire con queste modalita…vi tengo aggiornati.

Se leggi 0 da un lato e 1023 dall'altro stai attento a cosa succede quando le posizioni sono molto vicine agli estremi. Se, per esempio, a pochi gradi dagli estremi leggi già i valori estremi, 0 da un lato e 1023 dall'altro, succederà che in quell'intervallo la lettura del potenziometro è sempre la stessa. Ma hai fatto un test e te ne saresti accorto per cui se tale zona morta c'è è molto poccola. Dal test che hai fatto con l'altro firmware si può dedurre che il potenzimetro è lineare a meno che nel firmware c'era una correzione per i potenziometri logaritmici ma lo ritengo improbabile.

La formula riportata prima è quella di una retta che passa per i 2 punti bitmin, valmin e bitmax, valmax, significa che la relazione tra le due grandezze è lineare.

Non ho ancora provato ma mi sono documentato sulla formula e mi si è accesa una lampadina....(che apre una parentesi e la richiude) Ma utilizzando medesima formula potrei far eseguire un movimento lineare al robot?

Anche io dubito che Firmata possa pilotare un servomotore... non lo uso mai, quindi potrei anche avere torto. Quando lo hai provato con quel firmware, senza collegarlo al PC e senza Firmata, sicuramente avrai caricato la libreria servo.

Io in questi casi - come ho scritto prima - non uso Firmata, molto più semplicemente creo un piccolo protocollo di comunicazione seriale fra il programma sul PC ed il firmware sulla scheda. Se invio "A120" dal PC, leggo questo dato e faccio posizionare il servomotore A alla posizione 120, tramite l'apposita libreria. Semplice ed efficace. Per il potenziometro puoi fare al contrario, invii al PC qualcosa che comunica il valore. Qui hai diversi metodi per farlo, o invii l'informazione periodicamente, o la invii solo quando il valore cambia, o la invii come risposta ad una interrogazione proveniente dal PC (ti basta in questo caso adoperare un altro timer del VB). Così il PC riceve "P1000" e sai cosa hai letto... ovviamente ti conviene passare attraverso il PC solo se hai intenzione di intervenire in qualche modo sulla posizione del servomotore anche tramite PC, altrimenti sarebbe sufficiente una semplice comunicazione della posizione per visualizzarla a schermo.

Mork11: Ma utilizzando medesima formula potrei far eseguire un movimento lineare al robot?

Non ho capito cosa vorresti fare. La formula lega due grandezze con una relazione lineare. Ciò che significano le due grandezze sta a te così come la loro trasformazione in un movimento o in qualcos'altro come la posizione di un punto su uno schermo.

@paulus1969 Firmata è un modo per comandare l'Arduino dall'esterno come se il dispositivo esterno avesse lui le API di Arduino. E' un'astrazione. Se per esempio vuoi alzare un piedino X mandi il comando "Alza il piedinoX" e Arduino esegue. Se vuoi un valore Analogico chiedi il valore. Se vuoi mandare un PWM fai lo stesso. La logica del programma si troverà nel dispositivo esterno, in questo caso il PC. Ovviamente il tutto a scapito della velocità.

zoomx: Se vuoi un valore Analogico chiedi il valore. Se vuoi mandare un PWM fai lo stesso.

Ma mandare un PWM non credo basta per pilotare il Servo. La libreria Servo fa ben di più.

nid69ita: Ma mandare un PWM non credo basta per pilotare il Servo. La libreria Servo fa ben di più.

Come Astro ha spiegato più di una volta, i servo NON lavorano in PWM, ma in PPM. Quoto le sue parole ...

In PWM l'informazione è veicolata dal rapporto tra parte bassa e parte alta del segnale, in PPM l'informazione può essere veicolata in due modi, sia dalla durata della sola parte alta, o parte bassa, del segnale, che dalla posizione dell'impulso se è un treno d'impulsi componente un pacchetto di dati.

Guglielmo

Questo è quello che ho:

Dim Angolo1 As Integer
Dim potPin1 As Integer
Dim BitMin As Long
Dim BitMax As Long
Dim ValAngMin As Integer
Dim ValAngMax As Integer
Dim VALANG As Integer
FirmataVB1.PinMode(6, OUTUPT)
potPin1 = 0

BitMin = 0
BitMax = 1023
ValAngMin = 0
ValAngMax = 179

Private Sub Tmr_AnalogIN_Pot1_Tick(sender As Object, e As EventArgs) Handles Tmr_AnalogIN_Pot1.Tick
potPin1 = FirmataVB1.AnalogRead(0) 'leggi lo stato del pin analogico A0 e assegnalo al potPin1
LggIngAnalog1.Text = potPin1 * (5 / 1023) 'quello che leggi sul potPin1 scrivilo nella label
CnvAnlINGrd1.Text = potPin1 / 5.69 'scrivi nella text box il valore di Angolo1
If Angolo1 < 20 Then 'fine corsa negativo
Tmr_AnalogOUT_J1.Enabled = False 'disabilita il timer
CnvAnlINGrd1.Text = " F.Corsa N " 'mess. finecorsa
ElseIf Angolo1 > 160 Then 'fine corsa positivo
Tmr_AnalogOUT_J1.Enabled = False 'disabilita il timer
CnvAnlINGrd1.Text = " F.Corsa P " 'mess. finecorsa
End If
VALANG = potPin1
Angolo1 = (VALANG - BitMin) / (BitMax - BitMin) * (ValAngMax - ValAngMin) + ValAngMin
FirmataVB1.AnalogWrite(6, Angolo1) 'invia il valore di angolo1 al pin digitale 6
End Sub

Ma in pratica accenna a muoversi in mal modo e a scatti non definiti ho verificato il valore di Angolo1 in ed effettivamente mi restituisce valori interi che vanno da 0 a massimo 179 interi ma il motore sibila ma non si muove.

Per spiegare l'intenzione della mia parentesi "flash" sull'uso della formula "per due punti una sola retta"...per far eseguire al robot un movimento lineare (in gergo MOVELINEAR) ossia un movimento da punto a punto con cinematica inversa e quindi nel più breve tempo possibile.

Memorizzo la posizione di un punto A nello spazio Memorizzo la posizione di un punto B nello spazio Esegui il movimento da punto "A" a punto "B" passando per la retta che unisce i due Lasciando libero arbitrio sull'utilizzo degli assi

cinematica inversa in robotica

Sto dormendo, mi sono concentrato sulla formuletta e non ho fatto caso all'uso del PWM per il servo.

Però mi pare di ricordare che con Firmata i servo si possano comandare.

Qui http://www.xorse.it/comandare-arduino-da-vb-net.html c'è anche un progetto in vb.net (CamMove) che muove 2 servo http://www.xorse.it/wp-content/plugins/download-monitor/download.php?id=28 Il progetto si carica con la versione 2010.

La formula che ho scritto va bene per una retta su un piano, nello spazio non va bene. Ma esiste pure la formula per quella. Che io non conosco.

zoomx:
Però mi pare di ricordare che con Firmata i servo si possano comandare.

Ho verificato, a quanto ho visto si può fare, oltre ai pinMode input e pinMode output, ce ne è uno apposito per i servo. Una volta inizializzato come servo, poi basta fare un analogwrite.

Quindi va cambiato questo FirmataVB1.PinMode(6, OUTUPT) in FirmataVB1.PinMode(6, SERVO) almeno secondo le specifiche http://firmata.org/wiki/V2.2ProtocolDetails#Servos