-
Notifications
You must be signed in to change notification settings - Fork 400
/
Servo.h
90 lines (76 loc) · 4.42 KB
/
Servo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
PIO-based Servo class for Rasperry Pi Pico RP2040
Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
A servo is activated by creating an instance of the Servo class passing
the desired pin to the attach() method.
The servos are pulsed in the background using the value most recently
written using the write() method.
The methods are:
Servo - Class for manipulating servo motors connected to Arduino pins.
attach(pin) - Attaches a servo motor to an i/o pin.
attach(pin, min, max) - Attaches to a pin setting min and max values in microseconds
default min is 1000, max is 2000
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
writeMicroseconds() - Sets the servo pulse width in microseconds
read() - Gets the last written servo pulse width as an angle between 0 and 180.
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached() - Returns true if there is a servo attached.
detach() - Stops an attached servos from pulsing its i/o pin.
*/
#pragma once
#include <Arduino.h>
#include <hardware/pio.h>
// The following values are in us (microseconds).
// Since the defaults can be overwritten in the new attach() member function,
// they were modified from the Arduino AVR defaults to be in the safe range
// of publicly available specifications. While this implies that many 180°
// servos do not operate the full 0° to 180° sweep using these, it also prevents
// unsuspecting damage. For Arduino AVR, the same change is being discussed.
#define DEFAULT_MIN_PULSE_WIDTH 1000 // uncalibrated default, the shortest duty cycle sent to a servo
#define DEFAULT_MAX_PULSE_WIDTH 2000 // uncalibrated default, the longest duty cycle sent to a servo
#define DEFAULT_NEUTRAL_PULSE_WIDTH 1500 // default duty cycle when servo is attached
#define REFRESH_INTERVAL 20000 // classic default period to refresh servos in microseconds
#define MAX_SERVOS 8 // number of PIO state machines available, assuming nobody else is using them
class Servo {
public:
Servo();
~Servo();
// attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure.
// returns channel number or 0 if failure.
int attach(pin_size_t pin);
// attach the given pin to the next free channel, sets pinMode, min, and max values for write().
// returns channel number or 0 if failure.
int attach(pin_size_t pin, int min, int max);
// attach the given pin to the next free channel, sets pinMode, min, and max values for write(),
// and sets the initial value, the same as write().
// returns channel number or 0 if failure.
int attach(pin_size_t pin, int min, int max, int value);
void detach();
void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
private:
bool _attached;
pin_size_t _pin;
PIO _pio; // PIO0/1
int _smIdx; // The state machine inside
int _pgmOffset; // Where in the SM the code lives
int _minUs;
int _maxUs;
int _valueUs;
};