1 #ifndef EAGLE_EBOARD_HELPLIB_SERVO 2 #define EAGLE_EBOARD_HELPLIB_SERVO 7 typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
8 #define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo 9 #define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo 10 #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached 11 #define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds 13 #define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer 14 #define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER) 16 #define INVALID_SERVO 255 // flag indicating an invalid servo index 74 void write(
int value);
104 #define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009 105 #define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds 108 #define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009 112 static servo_t servos[MAX_SERVOS];
113 static volatile int8_t Channel[_Nbr_16timers ];
115 uint8_t ServoCount = 0;
118 #define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo 119 #define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer 120 #define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel 121 #define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel 123 #define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo 124 #define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo 126 static inline void handle_interrupts(timer16_Sequence_t timer,
volatile uint16_t *TCNTn,
volatile uint16_t* OCRnA)
128 if( Channel[timer] < 0 )
131 if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive ==
true )
132 digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW);
136 if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
137 *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
138 if(SERVO(timer,Channel[timer]).Pin.isActive ==
true)
139 digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH);
143 if( ((
unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) )
144 *OCRnA = (
unsigned int)usToTicks(REFRESH_INTERVAL);
151 #ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform 153 #if defined(_useTimer1) 154 SIGNAL (TIMER1_COMPA_vect)
156 handle_interrupts(_timer1, &TCNT1, &OCR1A);
161 #if defined(_useTimer1) 164 handle_interrupts(_timer1, &TCNT1, &OCR1A);
174 static void initISR(timer16_Sequence_t timer) {
175 if(timer == _timer1) {
180 TIMSK1 |= _BV(OCIE1A) ;
182 timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
187 static void finISR(timer16_Sequence_t timer) {
188 #if defined WIRING // Wiring 189 if(timer == _timer1) {
190 TIMSK &= ~_BV(OCIE1A) ;
191 timerDetach(TIMER1OUTCOMPAREA_INT);
193 else if(timer == _timer3) {
194 ETIMSK &= ~_BV(OCIE3A);
195 timerDetach(TIMER3OUTCOMPAREA_INT);
203 static boolean isTimerActive(timer16_Sequence_t timer) {
205 for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
206 if(SERVO(timer,channel).Pin.isActive ==
true)
213 if( ServoCount < MAX_SERVOS) {
222 return this->
attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
227 pinMode( pin, OUTPUT) ;
230 this->min = (MIN_PULSE_WIDTH -
min)/4;
231 this->max = (MAX_PULSE_WIDTH -
max)/4;
233 timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(
servoIndex);
234 if(isTimerActive(timer) ==
false)
243 timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(
servoIndex);
244 if(isTimerActive(timer) ==
false) {
250 if(value < MIN_PULSE_WIDTH)
252 if(value < 0) value = 0;
253 if(value > 180) value = 180;
254 value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
262 if( (channel < MAX_SERVOS) )
264 if( value < SERVO_MIN() )
266 else if( value > SERVO_MAX() )
269 value = value - TRIM_DURATION;
270 value = usToTicks(value);
272 uint8_t oldSREG = SREG;
274 servos[channel].
ticks = value;
281 unsigned int pulsewidth;
283 pulsewidth = ticksToUs(servos[this->
servoIndex].ticks) + TRIM_DURATION ;
void write(int value)
sets angle or pulse width of the Servo
ServoPin_t stores the data Set for any Servo usable by the Servo-Library.
ServoPin_t stores the data Set for any Pin usable by the Servo-Library.
bool attached()
check attached status
int read()
reads the current pulse width as angle
int8_t max
maximum is this value times 4 added to MAX_PULSE_WIDTH
volatile unsigned int ticks
the tick-speed for the Servo-Unit
void detach()
detaches the connected pin
ServoPin_t Pin
the used ServoPin
uint8_t attach(int pin)
this will tell the Servo-instance which pin the data cable is connected to
uint8_t isActive
checks if the Servo connected to this pin is currently active
void writeMicroseconds(int value)
sets pulse width of the Servo
uint8_t servoIndex
the channel index this servo is using
uint8_t nbr
stores the pinID [0;63]
int readMicroseconds()
reads the current pulse width
int8_t min
minimum is this value times 4 added to MIN_PULSE_WIDTH
The standard Arduino Servo Class.