1+ #if defined(ARDUINO_ARCH_MBED)
2+
3+ #include < Arduino.h>
4+ #include < Servo.h>
5+
6+ class ServoImpl {
7+ mbed::DigitalOut *pin;
8+ mbed::Timeout timeout; // calls a callback once when a timeout expires
9+ mbed::Ticker ticker; // calls a callback repeatedly with a timeout
10+
11+ public:
12+ ServoImpl (PinName _pin) {
13+ pin = new mbed::DigitalOut (_pin);
14+ }
15+
16+ ~ServoImpl () {
17+ ticker.detach ();
18+ timeout.detach ();
19+ delete pin;
20+ }
21+
22+ void start (uint32_t duration_us) {
23+ duration = duration_us;
24+ ticker.attach (mbed::callback (this , &ServoImpl::call), 0 .02f );
25+ }
26+
27+ void call () {
28+ timeout.attach (mbed::callback (this , &ServoImpl::toggle), duration / 1e6 );
29+ toggle ();
30+ }
31+
32+ void toggle () {
33+ *pin = !*pin;
34+ }
35+
36+ int32_t duration = -1 ;
37+ };
38+
39+ static ServoImpl* servos[MAX_SERVOS]; // static array of servo structures
40+ uint8_t ServoCount = 0 ; // the total number of attached servos
41+
42+ #define SERVO_MIN () (MIN_PULSE_WIDTH - this ->min) // minimum value in uS for this servo
43+ #define SERVO_MAX () (MAX_PULSE_WIDTH - this ->max) // maximum value in uS for this servo
44+
45+ #define TRIM_DURATION 15 // callback overhead (35 uS) -> 15uS if toggle() is called after starting the timeout
46+
47+ Servo::Servo ()
48+ {
49+ if (ServoCount < MAX_SERVOS) {
50+ this ->servoIndex = ServoCount++;
51+ } else {
52+ this ->servoIndex = INVALID_SERVO; // too many servos
53+ }
54+ }
55+
56+ uint8_t Servo::attach (int pin)
57+ {
58+ return this ->attach (pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
59+ }
60+
61+ uint8_t Servo::attach (int pin, int min, int max)
62+ {
63+ pinMode (pin, OUTPUT); // set servo pin to output
64+ servos[this ->servoIndex ] = new ServoImpl (digitalPinToPinName (pin));
65+
66+ this ->min = (MIN_PULSE_WIDTH - min);
67+ this ->max = (MAX_PULSE_WIDTH - max);
68+ return this ->servoIndex ;
69+ }
70+
71+ void Servo::detach ()
72+ {
73+ delete servos[this ->servoIndex ];
74+ servos[this ->servoIndex ] = NULL ;
75+ }
76+
77+ void Servo::write (int value)
78+ {
79+ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
80+ if (value < MIN_PULSE_WIDTH)
81+ {
82+ if (value < 0 )
83+ value = 0 ;
84+ else if (value > 180 )
85+ value = 180 ;
86+
87+ value = map (value, 0 , 180 , SERVO_MIN (), SERVO_MAX ());
88+ }
89+ writeMicroseconds (value);
90+ }
91+
92+ void Servo::writeMicroseconds (int value)
93+ {
94+ if (!servos[this ->servoIndex ]) {
95+ return ;
96+ }
97+ // calculate and store the values for the given channel
98+ byte channel = this ->servoIndex ;
99+ if ( (channel < MAX_SERVOS) ) // ensure channel is valid
100+ {
101+ if (value < SERVO_MIN ()) // ensure pulse width is valid
102+ value = SERVO_MIN ();
103+ else if (value > SERVO_MAX ())
104+ value = SERVO_MAX ();
105+
106+ value = value - TRIM_DURATION;
107+ if (servos[this ->servoIndex ]->duration == -1 ) {
108+ servos[this ->servoIndex ]->start (value);
109+ }
110+ servos[this ->servoIndex ]->duration = value;
111+ }
112+ }
113+
114+ int Servo::read () // return the value as degrees
115+ {
116+ return map (readMicroseconds (), SERVO_MIN (), SERVO_MAX (), 0 , 180 );
117+ }
118+
119+ int Servo::readMicroseconds ()
120+ {
121+ if (!servos[this ->servoIndex ]) {
122+ return 0 ;
123+ }
124+ return servos[this ->servoIndex ]->duration ;
125+ }
126+
127+ bool Servo::attached ()
128+ {
129+ return servos[this ->servoIndex ] != NULL ;
130+ }
131+
132+ #endif
0 commit comments