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