Servo 360° e rotary encoder?

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 Rotary Encoder - COM-09117 - SparkFun Electronics) 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?

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=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

io sto usando questi per modificare i servo risoluzione 10 bit il primo e 12 il secondo quindì 1024 step il primo e 4096 il secondo, ti mandano 3 campioni gratuiti dal sito, se li prendi ricordati di prendere da loro anche le calamite poichè sono polarizzate lungo il diametro e non lungo l'altezza.

as5040 ams OSRAM a global leader in optical solutions | ams OSRAM
as5141 ams OSRAM a global leader in optical solutions | ams OSRAM

puoi leggeri sia in quadratura, seriale e pwm!

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 ...

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

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.

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.

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?

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): Gravity: Analog Rotation Potentiometer Sensor for Arduino - Rotation 3600° - DFRobot. 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.

ma usare dei motori stepper non ti andrebbe bene? hanno solitamente 200 step per giro.

da quel che so, a parità di potenza sono cari e pesanti. Ho realizzato un dolly per timelapse ed avevo bisogno di circa 10 Kgcm, 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 Kgcm e i servo mi sembra siano il miglior compromesso.

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: Gigi site - AS5040 MRE
ciao
e grazie in particolare a GabrielD

http://jonathan.it/servocomandi/argani/analogici/hitec/446374_servocomando-hs785-hb-argano.html
beh 30€ non mi paiono tanti...

altrimenti li compri in cina e un servo simile lo paghi 10€ (ovviamente non ha la stessa qualità di cotruzione ma io li prenderei comunque)

in effetti pensavo a questo
http://www.springrc.com/new/en/ProductList.asp?SortID=59
17$ sped. compresa, ma non so quanto possano essere affidabili, in termini di meccanica e coppia ...
a cui aggiungere l'encoder magnetico di cui sopra