ServoEasing
LightweightServo.h
Go to the documentation of this file.
1 /*
2  * LightweightServo.h
3  *
4  * Copyright (C) 2019-2024 Armin Joachimsmeyer
5  * armin.joachimsmeyer@gmail.com
6  *
7  * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
8  *
9  * ServoEasing is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  * See the GNU General Public License for more details.
18 
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
21  *
22  */
23 
24 #ifndef _LIGHTWEIGHT_SERVO_H
25 #define _LIGHTWEIGHT_SERVO_H
26 
27 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__) || defined(__AVR_ATmega2560__)
28 
29 #define VERSION_LIGHTWEIGHT_SERVO "2.0.0"
30 #define VERSION_LIGHTWEIGHT_SERVO_MAJOR 2
31 #define VERSION_LIGHTWEIGHT_SERVO_MINOR 0
32 
33 #include <stdint.h>
34 
35 /*
36  * Activating this saves 40 bytes program space. You must then use the init functions initLightweightServoPin*() manually.
37  */
38 //#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE
39 //
40 #define ISR_COUNT_FOR_20_MILLIS (F_CPU / (8 * 50)) // 40000 For 50 Hz, 20 ms using a prescaler of 8. You can modify this if you have servos which accept a higher rate
41 #define ISR_COUNT_FOR_2_5_MILLIS (F_CPU / (8 * 400)) // 5000 For 400 Hz, 2.5 ms using a prescaler of 8.
42 
43 #if defined(__AVR_ATmega2560__)
44 #define LIGHTWEIGHT_SERVO_CHANNEL_A_PIN 46
45 #define LIGHTWEIGHT_SERVO_CHANNEL_B_PIN 45
46 #define LIGHTWEIGHT_SERVO_CHANNEL_C_PIN 44
47 #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__)
48 #define LIGHTWEIGHT_SERVO_CHANNEL_A_PIN 9
49 #define LIGHTWEIGHT_SERVO_CHANNEL_B_PIN 10
50 #endif
51 
52 void initLightweightServoPins(); // currently only pin 44 = OC5C/PL5, 45 = OC5B/PL4 + 46 = OC5A/PL3 on 2560 and pin 9 = OC1A + 10 = OC1B on 328
53 void checkAndInitLightweightServoPin(uint8_t aPin);
54 void deinitLightweightServoPin(uint8_t aPin); // Set pin to input and disable non-inverting Compare Output mode
55 
56 int writeLightweightServoPin(int aDegree, uint8_t aPin, bool aUpdateFast = false);
57 // The last parameter requires 8 byte more than DISABLE_SERVO_TIMER_AUTO_INITIALIZE, if false, but saves around 60 bytes anyway
58 void writeMicrosecondsLightweightServoPin(int aMicroseconds, uint8_t aPin, bool aUpdateFast = false, bool aDoAutoInit = true);
59 
60 void setLightweightServoPulseMicrosFor0And180Degree(int aMicrosecondsForServo0Degree, int a180DegreeValue);
61 void setLightweightServoRefreshRate(unsigned int aRefreshPeriodMicroseconds);
62 
63 // convenience functions
64 int DegreeToMicrosecondsLightweightServo(int aDegree);
65 int MicrosecondsToDegreeLightweightServo(int aMicroseconds);
66 
67 #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__)
68 #define ISR1_COUNT_FOR_20_MILLIS ISR_COUNT_FOR_20_MILLIS
69 #define ISR1_COUNT_FOR_2_5_MILLIS ISR_COUNT_FOR_2_5_MILLIS
70 
71 /*
72  * Old and fast ATmega328 functions
73  * Uses timer1 and Pin 9 + 10 as output
74  */
75 void initLightweightServoPin9And10() __attribute__ ((deprecated ("Renamed to initLightweightServoPins()"))); // deprecated
76 void initLightweightServoPin9(); // Disables Pin 10!
77 void initLightweightServoPin10(); // Disables Pin 9!
78 void initLightweightServoPin9_10(bool aUsePin9, bool aUsePin10);
79 void deinitLightweightServoPin9_10(bool aUsePin9, bool aUsePin10);
80 
81 void write9(int aDegree, bool aUpdateFast = false); // setLightweightServoPulsePin9 Channel A
82 void writeMicroseconds9(int aMicroseconds, bool aUpdateFast = false);
83 void writeMicroseconds9Direct(int aMicroseconds);
84 
85 void write10(int aDegree, bool aUpdateFast = false); // setLightweightServoPulsePin10 Channel B
86 void writeMicroseconds10(int aMicroseconds, bool aUpdateFast = false);
87 void writeMicroseconds10Direct(int aMicroseconds);
88 
89 int writeLightweightServo(int aDegree, bool aUsePin9, bool aUpdateFast = false);
90 void writeMicrosecondsLightweightServo(int aMicroseconds, bool aUsePin9, bool aUpdateFast = false);
91 #endif // Old and fast ATmega328 functions
92 
93 class LightweightServo {
94 public:
95  uint8_t attach(int aPin);
96  uint8_t attach(int aPin, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
97  void detach();
98  void write(int aTargetDegreeOrMicrosecond);
99  void writeMicroseconds(int aTargetMicrosecond); // Write pulse width in microseconds
100  /*
101  * Variables to enable adjustment for different servo types
102  * 544 and 2400 are values compatible with standard arduino values
103  */
104  int MicrosecondsForServo0Degree = 544;
105  int MicrosecondsForServo180Degree = 2400;
106  uint8_t LightweightServoPin;
107 };
108 
109 #endif // defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__) || defined(__AVR_ATmega2560__)
110 
111 /*
112  * Version 2.0.0 - 10/2024
113  * - Improved API.
114  * - Support for ATmega2560.
115  *
116  * Version 1.1.0 - 11/2020
117  * - Improved API.
118  */
119 
120 #endif // _LIGHTWEIGHT_SERVO_H