Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« on: May 14, 2012, 12:58:54 pm » |
Vorrei realizzare un pan&tilt per foto panoramiche (economico). L'idea è di utilizzare due servo con ruote di riduzione (circa 5:1) per avere una buona coppia (tipo questo http://www.flickr.com/photos/philwarner/2281423194/in/set-72157603776902016/,dove viene utilizzato un servo che permette 1260° di rotazione, 3.5 rivoluzioni, gli Hitec HS785HB, costosi e difficili da trovare, almeno mi sembra). Secondo voi è ipotizzabile un sistema composto da un servo 360° (tipo questo http://www.dfrobot.com/index.php?route=product/product&path=47&product_id=123, che non ha feedback sulla posizione, o qualunque altro servo modificato) e da un rotary encoder (tipo questo http://www.sparkfun.com/products/9117) che, accoppiato alla ruota dentata finale, dia la posizione attuale? Per la lettura dell'encoder ho trovato questo tut, http://www.circuitsathome.com/mcu/programming/reading-rotary-encoder-on-arduino, è sufficiente per un controllo abbastanza preciso del servo?
|
|
|
|
|
Logged
|
|
|
|
|
BZ (I)
Online
Brattain Member
Karma: 160
Posts: 15587
+39 349 2158303
|
 |
« Reply #1 on: May 14, 2012, 01:55:48 pm » |
No. quel rotary encoder é fatto per usarlo come manopola di inserimento manuale. Ha solo 12 impulsi per rotazione. Gli encoder per motori sono costosi: http://www.robot-italy.com/product_info.php?products_id=1352http://www.robot-italy.com/product_info.php?products_id=285È meglio e meno costoso e legi anche la posizione assoluta se usi un potenziometro multigiro (10 giri) e monti quello con un opportuna ruota dentata. Sai che ci sono le istruzioni per toglere il potenziometro interno del servo e di fare praticamente di qualsiasi servo uno a rotazione continua. Usando il potenziometro esterno dimensionando tutto in modo giusto puoi sostituire il potenziometro interno con quello esterno e avere cosí un servo che gira 400 gradi (qualche grado in piú per fare sicuramente i 360 Gradi). L' altra soluzione é usare motori passo passo. Ciao Uwe
|
|
|
|
|
Logged
|
|
|
|
|
|
|
Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« Reply #3 on: May 14, 2012, 04:03:43 pm » |
Grazie per le info. Ci sono dei codici di esempio per imparare la lettura di questi encoder? Vale il tut che ho scritto prima? Tenendo conto che parto da 0 ...
|
|
|
|
|
Logged
|
|
|
|
|
BZ (I)
Online
Brattain Member
Karma: 160
Posts: 15587
+39 349 2158303
|
 |
« Reply #4 on: May 14, 2012, 06:03:45 pm » |
Questi encoder danno un segnale rettangolare a ogni passo e un secondo segnale sfasato di 90 gradi. cosi si puó capire la direzione e la velocitá di rotazione. Oltre questo segnale danno un segnale PWM proporzionale al angolo di rotazione e hanno un interfaccia I2C dove si puó leggere il valore di posizione. Il mangnete deve essere posizionato abbasztanza precisamente sul centro del integrato e deve essere applicato sul asse im modo centrato. Ciao Uwe
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Edison Member
Karma: 7
Posts: 2148
Arduino rocks
|
 |
« Reply #5 on: May 14, 2012, 06:34:15 pm » |
Quegli encoder risolvono molti problemi degli encoder ottici ad esempio la dimensione del disco e sempre grande per encoder con alta risoluzione. Poi c'è anche l'interfaccia I2c.
Il link me lo sono conservato grazie per la segnalazione.
Ciao.
|
|
|
|
|
Logged
|
|
|
|
|
Torino
Offline
Newbie
Karma: 0
Posts: 17
|
 |
« Reply #6 on: May 14, 2012, 07:00:04 pm » |
codice per la lettura sul pin 16
il risultato sarà la lettura da 0 a 1024/4909 step non la consiglio nel caso avessi bisogno della posizione assoluta su più giri.
const int ledPin = 13; //LED connected to digital pin 13 const int clockPin = 51; //output to clock const int CSnPin = 49; //output to chip select const int inputPin = 53; //read AS5040
int inputstream = 0; //one bit read from pin long packeddata = 0; //two bytes concatenated from inputstream long angle = 0; //holds processed angle value long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info long statusbits; //holds status/error information int DECn; //bit holding decreasing magnet field error data int INCn; //bit holding increasing magnet field error data int OCF; //bit holding startup-valid bit int COF; //bit holding cordic DSP processing error data int LIN; //bit holding magnet field displacement error data int debug = 0; //SET THIS TO 0 TO DISABLE PRINTING OF ERROR CODES int shortdelay = 100; // this is the microseconds of delay in the data clock int longdelay = 10; // this is the milliseconds between readings
void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); // visual signal of I/O to chip pinMode(clockPin, OUTPUT); // SCK pinMode(CSnPin, OUTPUT); // CSn -- has to toggle high and low to signal chip to start data transfer pinMode(inputPin, INPUT); // SDA }
void loop() { // CSn needs to cycle from high to low to initiate transfer. Then clock cycles. As it goes high // again, data will appear on sda digitalWrite(CSnPin, HIGH); // CSn high digitalWrite(clockPin, HIGH); // CLK high delay(longdelay);// time between readings digitalWrite(ledPin, HIGH); // signal start of transfer with LED digitalWrite(CSnPin, LOW); // CSn low: start of transfer delayMicroseconds(shortdelay); // delay for chip initialization digitalWrite(clockPin, LOW); // CLK goes low: start clocking delayMicroseconds(shortdelay); // hold low for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin { digitalWrite(clockPin, HIGH); //clock goes high delayMicroseconds(shortdelay); // inputstream =digitalRead(inputPin); // read one bit of data from pin //Serial.print(inputstream, DEC); packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value digitalWrite(clockPin, LOW); delayMicroseconds(shortdelay); // end of one clock cycle } // end of entire clock cycle //Serial.println(" "); digitalWrite(ledPin, LOW); // signal end of transmission // lots of diagnostics for verifying bitwise operations //Serial.print("packed:"); //Serial.println(packeddata,DEC); //Serial.print("pack bin: "); //Serial.println(packeddata,BIN); angle = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle. //Serial.print("mask: "); //Serial.println(anglemask, BIN); //Serial.print("bin angle:"); //Serial.println(angle, BIN); //Serial.print("angle: "); //Serial.println(angle, DEC); angle = (angle >> 6); // shift 16-digit angle right 6 digits to form 10-digit value //Serial.print("angleshft:"); //Serial.println(angle, BIN); //Serial.print("angledec: "); //Serial.println(angle, DEC); angle = angle * 0.3515; // angle * (360/1024) == actual degrees - annulla questa riga per la lettura in step totali Serial.print("angle: "); // and, finally, print it. Serial.println(angle, DEC); //Serial.println("--------------------"); //Serial.print("raw: "); // this was the prefix for the bit-by-bit diag output inside the loop. if (debug) { statusbits = packeddata & statusmask; DECn = statusbits & 2; // goes high if magnet moved away from IC INCn = statusbits & 4; // goes high if magnet moved towards IC LIN = statusbits & 8; // goes high for linearity alarm COF = statusbits & 16; // goes high for cordic overflow: data invalid OCF = statusbits & 32; // this is 1 when the chip startup is finished. if (DECn && INCn) { Serial.println("magnet moved out of range"); } else { if (DECn) { Serial.println("magnet moved away from chip"); } if (INCn) { Serial.println("magnet moved towards chip"); } } if (LIN) { Serial.println("linearity alarm: magnet misaligned? Data questionable."); } if (COF) { Serial.println("cordic overflow: magnet misaligned? Data invalid."); } }
packeddata = 0; // reset both variables to zero so they don't just accumulate angle = 0; }
codice per la lettura della quadratura a/b dai pin 3 e 4
il risultato sara da - infinito a + infinito utile per la posizione assoluta su più giri
#define ENCODER_A_PIN 2 //pin 3 dell' encoder #define ENCODER_B_PIN 3 //pin 4 dell' encoder
long position;
void setup() { Serial.begin(19200); Serial.println("Started"); pinMode(ENCODER_A_PIN, INPUT); pinMode(ENCODER_B_PIN, INPUT); attachInterrupt(0, read_quadrature, CHANGE); }
void loop() { Serial.print("Position: "); Serial.println(position, DEC);
void read_quadrature() { // found a low-to-high on channel A if (digitalRead(ENCODER_A_PIN) == HIGH) { // check channel B to see which way if (digitalRead(ENCODER_B_PIN) == LOW) position++; else position--; } // found a high-to-low on channel A else { // check channel B to see which way if (digitalRead(ENCODER_B_PIN) == LOW) position--; else position++; } }
ricordati sempre di inizializzare il pin csn nel setup a meno di non metterlo a massa con un condensatore da 30uF. Il pin 6 in modalità proporzionale (standard - pin 8 di programmazione a massa) funge da index, cioè va alto ad ogni giro, comunque il datasheet è completo ne consiglio la lettura! Sono encoder praticissimi il non perfetto allineamento non pregiudica così tanto la precisione (ricordati di prendere le calamite da loro perchè non ne trovi in giro polarizzate sul diametro) quindi non ti fare problemi di allineamenti al decimo, se ordini gli as5145 ricordati di prendere la versione B poichè la A è pre-programmata per la lettura in 10bit come gli as5040.
Il mio consiglio è quello di scollegare il potenziometro del servo dopo aver rimosso il fermo meccanico, in questo modo con il comando digital.write(0-180) avrai la regolazione della velocità, es:
digital.write(0) velocità massima antioraria digital.write(90) fermo digital.write(180) velocità massima oraria
il magnete è alto 2,5 mm quindi lo incolli alla base dell'asse del potenziometro che di solito fuoriesce al di sotto, e l'encoder lo piazzi sopra il driver del servo con opportuni spessori. dal servo usciranno 2 cavi per la quadratura, i classici tre del servo e a seconda di quello che ti serve pin index/csn/clk ecc, in pratica hai tutto quello che vuoi! La gestione della posizione e della velocità la sviluppi tutta su arduino lasciando all'integrato del servo solo la funzione di driver per la velocità e il senso di rotazione.
|
|
|
|
« Last Edit: May 14, 2012, 07:08:15 pm by GabrielD »
|
Logged
|
|
|
|
|
Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« Reply #7 on: May 15, 2012, 04:31:05 am » |
Grazie GabrielD, purtroppo come ho scritto prima sono quasi a 0 come livello di conoscenze, non so nemmeno cosa significhi quadratura, mi consigliate un link che spieghi il funz. generale degli encoder, per chi è a digiuno di elettronica? Mi sembra comunque che per avere la posizione assoluta (anche come numero di giri) sia sufficiente utilizzare la seconda parte del codice (pins 3-4), che prevede una sorta di counter, giusto? Se prendo il servo che ho segnalato sopra (DFRobot, a rotazione illimitata) non ho bisogno di modificarlo, o sbaglio? E' gia a 360 'multigiro' (l'hanno modificato loro ...) Comunque ho ordinato il 5040 con magnetini. Ho poi scoperto che sono IC SSOP (8 pins in 6 mm ...) come si fa a saldare/collegare?
|
|
|
|
« Last Edit: May 15, 2012, 09:32:03 am by GigiG »
|
Logged
|
|
|
|
|
Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« Reply #8 on: May 18, 2012, 04:07:19 am » |
Prima di affrontare la sfida hardware/software dei sensori magnetici (alquanto ardua, per quanto riguarda il mio scarso know-how ...), volevo sottoporvi una possibile alternativa (basandomi sulla proposta di Uwe dei potenziometri multigiro): http://www.dfrobot.com/index.php?route=product/product&filter_name=DFR0058&product_id=86. E' quello che proponeva Uwe? Opportunamente calettato all'albero motore dovrebbe fungere allo scopo, credo. In ogni caso i motori non dovrebbero fare più di 3.5 rotazioni complete, visto che i progetti di panohead che ho visto finora utilizzano i servo Hitec non modificati che fanno appunto max 3.5 rivoluzioni.
|
|
|
|
|
Logged
|
|
|
|
|
Deep south of Italy
Offline
Faraday Member
Karma: 6
Posts: 2953
The quieter you become, the more you can hear
|
 |
« Reply #9 on: May 18, 2012, 06:16:22 am » |
ma usare dei motori stepper non ti andrebbe bene? hanno solitamente 200 step per giro.
|
|
|
|
|
Logged
|
|
|
|
|
Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« Reply #10 on: May 18, 2012, 06:57:06 am » |
da quel che so, a parità di potenza sono cari e pesanti. Ho realizzato un dolly per timelapse ed avevo bisogno di circa 10 Kg*cm, il più economico che ho trovato è stato un nema23 da 0.6A a 34 euro. Per la panohead (almeno per il tilt) occorrono almeno 13 Kg*cm e i servo mi sembra siano il miglior compromesso.
|
|
|
|
|
Logged
|
|
|
|
|
Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« Reply #11 on: July 12, 2012, 06:11:58 am » |
Alla fine ho optato per una coppia di AS5040, e mi sono lanciato nel tentativo di un 'fai da me' per la saldatura del chip. Le cose sembrano funzionare, a parte la diagnostica del magnete che non fa esattamente quello che dovrebbe. Comunque, la segnalazione di 'out of range' la dà lo stesso. Ho messo alcuni appunti e foto qui: https://sites.google.com/site/gigimysite/home/as5040ciao e grazie in particolare a GabrielD
|
|
|
|
|
Logged
|
|
|
|
|
|
|
Torino, Italy
Offline
Newbie
Karma: 0
Posts: 27
|
 |
« Reply #13 on: July 13, 2012, 02:58:47 am » |
in effetti pensavo a questo http://www.springrc.com/new/en/ProductList.asp?SortID=5917$ sped. compresa, ma non so quanto possano essere affidabili, in termini di meccanica e coppia ... a cui aggiungere l'encoder magnetico di cui sopra
|
|
|
|
|
Logged
|
|
|
|
|
|