best way to read a servo signal on arduino

the atmega168 on the arduino has a timer1 which has input capture capability (see this application note and datasheet for atmega168 for details). using it, it's possible to do the pulse timing in completly in hardware (no errors, no jitter), and having a interupt readout the measured time.here's the code:unsigned int serinp[8]; //servo positionsvoid setup_timer1(){//disable all interuptsTIMSK1 &= ~( _BV(TOIE1) | _BV(ICIE1) | _BV(OCIE1A) | _BV(OCIE1B));//set timer modeTCCR1A &= ~( _BV(WGM11) | _BV(WGM10) );TCCR1B &= ~( _BV(WGM12) | _BV(WGM13) | _BV(ICNC1));//capture raising edgeTCCR1B |= _BV(ICES1); //capture raising edge//prescaler 1/8TCCR1B |= _BV(CS11);TCCR1B &= ~( _BV(CS12) | _BV(CS10) );//disable outputsTCCR1A &= ~( _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1));//enable capture interuptTIMSK1 |= (1<<ICIE1);}ISR(TIMER1_CAPT_vect){static unsigned int lasticr; //icr at last caputrestatic unsigned char cserinp; //current input servounsigned int licr;//TCCR1B ^= _BV(ICES1);licr=ICR1-lasticr;lasticr=ICR1;if(licr>5000){ //pulse too long, means start of new framecserinp=0;}else if(licr>1000){ //pulse good, take reading, go to next channelserinp[cserinp]=licr;if(cserinp<8){cserinp++;}}else{//too short, nothing to see here}}void setup()pinMode( 8, INPUT ); //sumsetup_timer1();}void loop(){//use serinp!!!}it'll take a sum signal on pin 8. you can also connect the signal for a single servo, then just serinp[0] will be populated. the values in serinp are 2 times the microseconds, so between 2000-4000 (instead of 1000-2000), yes, there's extra accuracy in there!the timer-capture only works on digital pin 8!if you don't have access to the sum signal, a possible way to read multiple servos would be to connect them all to pin 8. since the receivers usually output the pulses one after the other, this should work (you'll have to adjust the code in the capture-interupt).
E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones

Comments

  • Bink. And kaldak on RCGroups points out that the answer to my question is right in front of me. Sorry about that. :]
  • Okay. This is quite a bit over my head-- I really haven't gotten this far into Arduino yet, and this just makes my head spin. I understand that when you do this particular setup and connect a pulse train to pin 8, the serinp array will be populated with values corresponding to PWM values coming in on the train?

    What do the numbers in serinp correspond to? Milliseconds? Clock cycles? Something else?

    When I get back to my Arduino and RX, I'll test this out for myself and hopefully get some more understanding of this code. Sorry for such dumb questions-- if there's some resource I can use to learn this on my own, I'd be happy to do that. I understand you don't have all the time in the world. :]

    Thanks for any and all help.
This reply was deleted.