Skip to content

Commit b20bc83

Browse files
committed
Initial porting to mbed cores
1 parent 2558771 commit b20bc83

File tree

4 files changed

+136
-1
lines changed

4 files changed

+136
-1
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ sentence=Allows Arduino/Genuino boards to control a variety of servo motors.
66
paragraph=This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos using only 1 timer.<br />On the Arduino Due you can control up to 60 servos.<br />
77
category=Device Control
88
url=http://www.arduino.cc/en/Reference/Servo
9-
architectures=avr,megaavr,sam,samd,nrf52,stm32f4
9+
architectures=avr,megaavr,sam,samd,nrf52,stm32f4,mbed

src/Servo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
#include "nrf52/ServoTimers.h"
7272
#elif defined(ARDUINO_ARCH_MEGAAVR)
7373
#include "megaavr/ServoTimers.h"
74+
#elif defined(ARDUINO_ARCH_MBED)
75+
#include "mbed/ServoTimers.h"
7476
#else
7577
#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."
7678
#endif

src/mbed/Servo.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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

src/mbed/ServoTimers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define _Nbr_16timers 32

0 commit comments

Comments
 (0)