robobuggy / arduino / InterruptRCRecieverReference / RCArduinoFastLib.h @ c5d6b0e8
History | View | Annotate | Download (6.67 KB)
1 |
/*****************************************************************************************************************************/
|
---|---|
2 |
// RCArduinoFastLib by DuaneB is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
3 |
//
|
4 |
// http://rcarduino.blogspot.com
|
5 |
//
|
6 |
/*****************************************************************************************************************************/
|
7 |
|
8 |
#include "Arduino.h" |
9 |
|
10 |
// COMMENT OR UNCOMMENT THIS LINE TO ENABLE THE SECOND BANK OF SERVOS
|
11 |
//#define MORE_SERVOS_PLEASE 1
|
12 |
|
13 |
// the first bank of servos uses OC1A - this will disable PWM on digital pin 9 - a small price for 10 fast and smooth servos
|
14 |
// the second bank of servos uses OC1B - this will disable PWM on digital pin 10 - a small price for 10 more fast and smooth servos
|
15 |
|
16 |
// The library blindly pulses all ten servos one and after another
|
17 |
// If you change the RC_CHANNEL_OUT_COUNT to 4 servos, the library will pulse them more frequently than
|
18 |
// it can ten -
|
19 |
// 10 servos at 1500us = 15ms = 66Hz
|
20 |
// 4 Servos at 1500us = 6ms = 166Hz
|
21 |
// if you wanted to go even higher, run two servos on each timer
|
22 |
// 2 Servos at 1500us = 3ms = 333Hz
|
23 |
//
|
24 |
// You might not want a high refresh rate though, so the setFrameSpace function is provided for you to
|
25 |
// add a pause before the library begins its next run through the servos
|
26 |
// for 50 hz, the pause should be to (20,000 - (RC_CHANNEL_OUT_COUNT * 2000))
|
27 |
|
28 |
// Change to set the number of servos/ESCs
|
29 |
#define RC_CHANNEL_OUT_COUNT 4 |
30 |
|
31 |
#if defined (MORE_SERVOS_PLEASE)
|
32 |
#define RCARDUINO_MAX_SERVOS (RC_CHANNEL_OUT_COUNT*2) |
33 |
#else
|
34 |
#define RCARDUINO_MAX_SERVOS (RC_CHANNEL_OUT_COUNT)
|
35 |
#endif
|
36 |
|
37 |
// Minimum and Maximum servo pulse widths, you could change these,
|
38 |
// Check the servo library and use that range if you prefer
|
39 |
#define RCARDUINO_SERIAL_SERVO_MIN 1000 |
40 |
#define RCARDUINO_SERIAL_SERVO_MAX 2000 |
41 |
#define RCARDUINO_SERIAL_SERVO_DEFAULT 1500 |
42 |
|
43 |
#define RC_CHANNELS_NOPORT 0 |
44 |
#define RC_CHANNELS_PORTB 1 |
45 |
#define RC_CHANNELS_PORTC 2 |
46 |
#define RC_CHANNELS_PORTD 3 |
47 |
#define RC_CHANNELS_NOPIN 255 |
48 |
|
49 |
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
50 |
//
|
51 |
// CRCArduinoFastServos
|
52 |
//
|
53 |
// A class for generating signals in combination with a 4017 Counter
|
54 |
//
|
55 |
// Output upto 10 Servo channels using just digital pins 9 and 12
|
56 |
// 9 generates the clock signal and must be connected to the clock pin of the 4017
|
57 |
// 12 generates the reset pulse and must be connected to the master reset pin of the 4017
|
58 |
//
|
59 |
// The class uses Timer1, as this prevents use with the servo library
|
60 |
// The class uses pins 9 and 12
|
61 |
// The class does not adjust the servo frame to account for variations in pulse width,
|
62 |
// on the basis that many RC transmitters and receivers designed specifically to operate with servos
|
63 |
// output signals between 50 and 100hz, this is the same range as the library
|
64 |
//
|
65 |
// Use of an additional pin would provide for error detection, however using pin 12 to pulse master reset
|
66 |
// at the end of every frame means that the system is essentially self correcting
|
67 |
//
|
68 |
// Note
|
69 |
// This is a simplified derivative of the Arduino Servo Library created by Michael Margolis
|
70 |
// The simplification has been possible by moving some of the flexibility provided by the Servo library
|
71 |
// from software to hardware.
|
72 |
//
|
73 |
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
74 |
|
75 |
|
76 |
class CRCArduinoFastServos |
77 |
{ |
78 |
public:
|
79 |
static void setup(); |
80 |
|
81 |
// configures timer1
|
82 |
static void begin(); |
83 |
|
84 |
// called by the timer interrupt service routine, see the cpp file for details.
|
85 |
static void OCR1A_ISR(); |
86 |
|
87 |
#if defined(MORE_SERVOS_PLEASE)
|
88 |
static void OCR1B_ISR(); |
89 |
#endif
|
90 |
|
91 |
// called to set the pulse width for a specific channel, pulse widths are in microseconds - degrees are for wimps !
|
92 |
static void attach(uint8_t nChannel,uint8_t nPin); |
93 |
static void writeMicroseconds(uint8_t nChannel,uint16_t nMicroseconds); |
94 |
static void setFrameSpaceA(uint8_t sChannel,uint16_t unMicroseconds); |
95 |
static void setFrameSpaceB(uint8_t sChannel,uint16_t unMicroseconds); |
96 |
|
97 |
protected:
|
98 |
class CPortPin |
99 |
{ |
100 |
public:
|
101 |
//uint8_t m_sPort;
|
102 |
volatile unsigned char *m_pPort; |
103 |
uint8_t m_sPinMask; |
104 |
uint16_t m_unPulseWidth; |
105 |
}; |
106 |
|
107 |
// this sets the value of the timer1 output compare register to a point in the future
|
108 |
// based on the required pulse with for the current servo
|
109 |
static void setOutputTimerForPulseDurationA() __attribute__((always_inline)); |
110 |
|
111 |
|
112 |
static void setChannelPinLowA(uint8_t sChannel) __attribute__((always_inline)); |
113 |
static void setCurrentChannelPinHighA(); |
114 |
|
115 |
// Easy to optimise this, but lets keep it readable instead, its short enough.
|
116 |
static volatile uint8_t* getPortFromPin(uint8_t sPin) __attribute__((always_inline)); |
117 |
static uint8_t getPortPinMaskFromPin(uint8_t sPin) __attribute__((always_inline));
|
118 |
|
119 |
// Records the current output channel values in timer ticks
|
120 |
// Manually set by calling writeChannel, the function adjusts from
|
121 |
// user supplied micro seconds to timer ticks
|
122 |
volatile static CPortPin m_ChannelOutA[RC_CHANNEL_OUT_COUNT]; |
123 |
// current output channel, used by the timer ISR to track which channel is being generated
|
124 |
static uint8_t m_sCurrentOutputChannelA;
|
125 |
|
126 |
#if defined(MORE_SERVOS_PLEASE)
|
127 |
// Optional channel B for servo number 10 to 19
|
128 |
volatile static CPortPin m_ChannelOutB[RC_CHANNEL_OUT_COUNT]; |
129 |
static uint8_t m_sCurrentOutputChannelB;
|
130 |
static void setOutputTimerForPulseDurationB(); |
131 |
|
132 |
static void setChannelPinLowB(uint8_t sChannel) __attribute__((always_inline)); |
133 |
static void setCurrentChannelPinHighB() __attribute__((always_inline)); |
134 |
#endif
|
135 |
|
136 |
// two helper functions to convert between timer values and microseconds
|
137 |
static uint16_t ticksToMicroseconds(uint16_t unTicks) __attribute__((always_inline));
|
138 |
static uint16_t microsecondsToTicks(uint16_t unMicroseconds) __attribute__((always_inline));
|
139 |
}; |
140 |
|
141 |
// Change to set the number of channels in PPM Input stream
|
142 |
#define RC_CHANNEL_IN_COUNT 3 |
143 |
// two ticks per us, 3000 us * 2 ticks = 6000 minimum frame space
|
144 |
#define MINIMUM_FRAME_SPACE 6000 |
145 |
#define MAXIMUM_PULSE_SPACE 5000 |
146 |
|
147 |
class CRCArduinoPPMChannels |
148 |
{ |
149 |
public:
|
150 |
static void begin(); |
151 |
static void INT0ISR(); |
152 |
static uint16_t getChannel(uint8_t nChannel);
|
153 |
static uint8_t getSynchErrorCounter();
|
154 |
|
155 |
protected:
|
156 |
static void forceResynch(); |
157 |
|
158 |
static volatile uint16_t m_unChannelSignalIn[RC_CHANNEL_IN_COUNT]; |
159 |
static uint8_t m_sCurrentInputChannel;
|
160 |
|
161 |
static uint16_t m_unChannelRiseTime;
|
162 |
static volatile uint8_t m_sOutOfSynchErrorCounter; |
163 |
}; |