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