SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
atmega2560_mcu.cpp
Go to the documentation of this file.
1#include "../../hardware_api.h"
2
3#if defined(__AVR_ATmega2560__) || defined(AVR_ATmega1280)
4
5
6#pragma message("")
7#pragma message("SimpleFOC: compiling for Arduino/ATmega2560 or Arduino/ATmega1280")
8#pragma message("")
9
10
11#define _PWM_FREQUENCY 32000
12#define _PWM_FREQUENCY_MAX 32000
13#define _PWM_FREQUENCY_MIN 4000
14
15// set pwm frequency to 32KHz
16void _pinHighFrequency(const int pin, const long frequency){
17 bool high_fq = false;
18 // set 32kHz frequency if requested freq is higher than the middle of the range (14kHz)
19 // else set the 4kHz
20 if(frequency >= 0.5*(_PWM_FREQUENCY_MAX-_PWM_FREQUENCY_MIN)) high_fq=true;
21 // High PWM frequency
22 // https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-ATmega2560
23 // https://forum.arduino.cc/index.php?topic=72092.0
24 if (pin == 13 || pin == 4 ) {
25 TCCR0A = ((TCCR0A & 0b11111100) | 0x01); // configure the pwm phase-corrected mode
26 if(high_fq) TCCR0B = ((TCCR0B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
27 else TCCR0B = ((TCCR0B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
28 }
29 else if (pin == 12 || pin == 11 )
30 if(high_fq) TCCR1B = ((TCCR1B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
31 else TCCR1B = ((TCCR1B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
32 else if (pin == 10 || pin == 9 )
33 if(high_fq) TCCR2B = ((TCCR2B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
34 else TCCR2B = ((TCCR2B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
35 else if (pin == 5 || pin == 3 || pin == 2)
36 if(high_fq) TCCR3B = ((TCCR3B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
37 else TCCR3B = ((TCCR3B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
38 else if (pin == 8 || pin == 7 || pin == 6)
39 if(high_fq) TCCR4B = ((TCCR4B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
40 else TCCR4B = ((TCCR4B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
41 else if (pin == 44 || pin == 45 || pin == 46)
42 if(high_fq) TCCR5B = ((TCCR5B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
43 else TCCR5B = ((TCCR5B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
44
45}
46
47
48// function setting the high pwm frequency to the supplied pins
49// - Stepper motor - 2PWM setting
50// - hardware specific
51// supports Arduino/ATmega2560
52void* _configure1PWM(long pwm_frequency,const int pinA) {
53 if(!pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY; // default frequency 32kHz
54 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX); // constrain to 4-32kHz max
55 // High PWM frequency
56 // - always max 32kHz
57 _pinHighFrequency(pinA, pwm_frequency);
59 .pins = { pinA },
60 .pwm_frequency = pwm_frequency,
61 .dead_zone = 0.0f
62 };
63 return params;
64}
65
66// function setting the high pwm frequency to the supplied pins
67// - Stepper motor - 2PWM setting
68// - hardware specific
69// supports Arduino/ATmega2560
70void* _configure2PWM(long pwm_frequency,const int pinA, const int pinB) {
71 if(!pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY; // default frequency 32kHz
72 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX); // constrain to 4-32kHz max
73 // High PWM frequency
74 // - always max 32kHz
75 _pinHighFrequency(pinA, pwm_frequency);
76 _pinHighFrequency(pinB, pwm_frequency);
78 .pins = { pinA, pinB },
79 .pwm_frequency = pwm_frequency,
80 .dead_zone = 0.0f
81 };
82 return params;
83}
84
85// function setting the high pwm frequency to the supplied pins
86// - BLDC motor - 3PWM setting
87// - hardware specific
88// supports Arduino/ATmega2560
89void* _configure3PWM(long pwm_frequency,const int pinA, const int pinB, const int pinC) {
90 if(!pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY; // default frequency 32kHz
91 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX); // constrain to 4-32kHz max
92 // High PWM frequency
93 // - always max 32kHz
94 _pinHighFrequency(pinA, pwm_frequency);
95 _pinHighFrequency(pinB, pwm_frequency);
96 _pinHighFrequency(pinC, pwm_frequency);
98 .pins = { pinA, pinB, pinC },
99 .pwm_frequency = pwm_frequency,
100 .dead_zone = 0.0f
101 };
102 // _syncAllTimers();
103 return params;
104}
105
106// function setting the pwm duty cycle to the hardware
107// - Stepper motor - 2PWM setting
108// - hardware specific
109void _writeDutyCycle1PWM(float dc_a, void* params){
110 // transform duty cycle from [0,1] to [0,255]
111 analogWrite(((GenericDriverParams*)params)->pins[0], 255.0f*dc_a);
112}
113
114// function setting the pwm duty cycle to the hardware
115// - Stepper motor - 2PWM setting
116// - hardware specific
117void _writeDutyCycle2PWM(float dc_a, float dc_b, void* params){
118 // transform duty cycle from [0,1] to [0,255]
119 analogWrite(((GenericDriverParams*)params)->pins[0], 255.0f*dc_a);
120 analogWrite(((GenericDriverParams*)params)->pins[1], 255.0f*dc_b);
121}
122
123// function setting the pwm duty cycle to the hardware
124// - BLDC motor - 3PWM setting
125// - hardware specific
126void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void* params){
127 // transform duty cycle from [0,1] to [0,255]
128 analogWrite(((GenericDriverParams*)params)->pins[0], 255.0f*dc_a);
129 analogWrite(((GenericDriverParams*)params)->pins[1], 255.0f*dc_b);
130 analogWrite(((GenericDriverParams*)params)->pins[2], 255.0f*dc_c);
131}
132
133// function setting the high pwm frequency to the supplied pins
134// - Stepper motor - 4PWM setting
135// - hardware specific
136void* _configure4PWM(long pwm_frequency,const int pin1A, const int pin1B, const int pin2A, const int pin2B) {
137 if(!pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY; // default frequency 32kHz
138 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX); // constrain to 4-32kHz max
139 // High PWM frequency
140 // - always max 32kHz
141 _pinHighFrequency(pin1A,pwm_frequency);
142 _pinHighFrequency(pin1B,pwm_frequency);
143 _pinHighFrequency(pin2A,pwm_frequency);
144 _pinHighFrequency(pin2B,pwm_frequency);
146 .pins = { pin1A, pin1B, pin2A, pin2B },
147 .pwm_frequency = pwm_frequency,
148 .dead_zone = 0.0f
149 };
150 return params;
151}
152
153// function setting the pwm duty cycle to the hardware
154// - Stepper motor - 4PWM setting
155// - hardware specific
156void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void* params) {
157 // transform duty cycle from [0,1] to [0,255]
158 analogWrite(((GenericDriverParams*)params)->pins[0], 255.0f*dc_1a);
159 analogWrite(((GenericDriverParams*)params)->pins[1], 255.0f*dc_1b);
160 analogWrite(((GenericDriverParams*)params)->pins[2], 255.0f*dc_2a);
161 analogWrite(((GenericDriverParams*)params)->pins[3], 255.0f*dc_2b);
162}
163
164
165// function configuring pair of high-low side pwm channels, 32khz frequency and center aligned pwm
166// supports Arduino/ATmega2560
167// https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf
168// https://docs.arduino.cc/hacking/hardware/PinMapping2560
169int _configureComplementaryPair(const int pinH,const int pinL, long frequency) {
170 bool high_fq = false;
171 // set 32kHz frequency if requested freq is higher than the middle of the range (14kHz)
172 // else set the 4kHz
173 if(frequency >= 0.5*(_PWM_FREQUENCY_MAX-_PWM_FREQUENCY_MIN)) high_fq=true;
174
175 // configure pin pairs
176 if( (pinH == 4 && pinL == 13 ) || (pinH == 13 && pinL == 4 ) ){
177 // configure the pwm phase-corrected mode
178 TCCR0A = ((TCCR0A & 0b11111100) | 0x01);
179 // configure complementary pwm on low side
180 if(pinH == 13 ) TCCR0A = 0b10110000 | (TCCR0A & 0b00001111) ;
181 else TCCR0A = 0b11100000 | (TCCR0A & 0b00001111) ;
182 // set frequency
183 if(high_fq) TCCR0B = ((TCCR0B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
184 else TCCR0B = ((TCCR0B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
185 }else if( (pinH == 11 && pinL == 12 ) || (pinH == 12 && pinL == 11 ) ){
186 // set frequency
187 if(high_fq) TCCR1B = ((TCCR1B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
188 else TCCR1B = ((TCCR1B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
189 // configure complementary pwm on low side
190 if(pinH == 11 ) TCCR1A = 0b10110000 | (TCCR1A & 0b00001111) ;
191 else TCCR1A = 0b11100000 | (TCCR1A & 0b00001111) ;
192 }else if((pinH == 10 && pinL == 9 ) || (pinH == 9 && pinL == 10 ) ){
193 // set frequency
194 if(high_fq) TCCR2B = ((TCCR2B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
195 else TCCR2B = ((TCCR2B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
196 // configure complementary pwm on low side
197 if(pinH == 10 ) TCCR2A = 0b10110000 | (TCCR2A & 0b00001111) ;
198 else TCCR2A = 0b11100000 | (TCCR2A & 0b00001111) ;
199 }else if((pinH == 5 && pinL == 2 ) || (pinH == 2 && pinL == 5 ) ){
200 // set frequency
201 if(high_fq) TCCR3B = ((TCCR3B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
202 else TCCR3B = ((TCCR3B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
203 // configure complementary pwm on low side
204 if(pinH == 5 ) TCCR3A = 0b10110000 | (TCCR3A & 0b00001111) ;
205 else TCCR3A = 0b11100000 | (TCCR3A & 0b00001111) ;
206 }else if((pinH == 6 && pinL == 7 ) || (pinH == 7 && pinL == 6 ) ){
207 // set frequency
208 if(high_fq) TCCR4B = ((TCCR4B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
209 else TCCR4B = ((TCCR4B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
210 // configure complementary pwm on low side
211 if(pinH == 6 ) TCCR4A = 0b10110000 | (TCCR4A & 0b00001111) ;
212 else TCCR4A = 0b11100000 | (TCCR4A & 0b00001111) ;
213 }else if((pinH == 46 && pinL == 45 ) || (pinH == 45 && pinL == 46 ) ){
214 // set frequency
215 if(high_fq) TCCR5B = ((TCCR5B & 0b11110000) | 0x01); // set prescaler to 1 - 32kHz
216 else TCCR5B = ((TCCR5B & 0b11110000) | 0x02); // set prescaler to 2 - 4kHz
217 // configure complementary pwm on low side
218 if(pinH == 46 ) TCCR5A = 0b10110000 | (TCCR5A & 0b00001111) ;
219 else TCCR5A = 0b11100000 | (TCCR5A & 0b00001111) ;
220 }else{
221 return -1;
222 }
223 return 0;
224}
225
226// Configuring PWM frequency, resolution and alignment
227// - BLDC driver - setting
228// - hardware specific
229// supports Arduino/ATmega2560
230void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l) {
231 if(!pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY; // default frequency 32kHz
232 else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX); // constrain to 4-32kHz max
233 // High PWM frequency
234 // - always max 32kHz
235 int ret_flag = 0;
236 ret_flag += _configureComplementaryPair(pinA_h, pinA_l, pwm_frequency);
237 ret_flag += _configureComplementaryPair(pinB_h, pinB_l, pwm_frequency);
238 ret_flag += _configureComplementaryPair(pinC_h, pinC_l, pwm_frequency);
239 if (ret_flag!=0) return SIMPLEFOC_DRIVER_INIT_FAILED;
242 .pwm_frequency = pwm_frequency,
243 .dead_zone = dead_zone
244 };
245 // _syncAllTimers();
246 return params;
247}
248
249// function setting the
250void _setPwmPair(int pinH, int pinL, float val, int dead_time, PhaseState ps)
251{
252 int pwm_h = _constrain(val-dead_time/2,0,255);
253 int pwm_l = _constrain(val+dead_time/2,0,255);
254 // determine the phase state and set the pwm accordingly
255 // deactivate phases if needed
256 if((ps == PhaseState::PHASE_OFF) || (ps == PhaseState::PHASE_LO)){
257 digitalWrite(pinH, LOW);
258 }else{
259 analogWrite(pinH, pwm_h);
260 }
261 if((ps == PhaseState::PHASE_OFF) || (ps == PhaseState::PHASE_HI)){
262 digitalWrite(pinL, LOW);
263 }else{
264 if(pwm_l == 255 || pwm_l == 0)
265 digitalWrite(pinL, pwm_l ? LOW : HIGH);
266 else
267 analogWrite(pinL, pwm_l);
268 }
269
270}
271
272// Function setting the duty cycle to the pwm pin (ex. analogWrite())
273// - BLDC driver - 6PWM setting
274// - hardware specific
275// supports Arduino/ATmega328
276void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void* params){
277 _setPwmPair(((GenericDriverParams*)params)->pins[0], ((GenericDriverParams*)params)->pins[1], dc_a*255.0, ((GenericDriverParams*)params)->dead_zone*255.0, phase_state[0]);
278 _setPwmPair(((GenericDriverParams*)params)->pins[2], ((GenericDriverParams*)params)->pins[3], dc_b*255.0, ((GenericDriverParams*)params)->dead_zone*255.0, phase_state[1]);
279 _setPwmPair(((GenericDriverParams*)params)->pins[4], ((GenericDriverParams*)params)->pins[5], dc_c*255.0, ((GenericDriverParams*)params)->dead_zone*255.0, phase_state[2]);
280}
281
282#endif
PhaseState
Definition FOCDriver.h:7
@ PHASE_HI
Definition FOCDriver.h:10
@ PHASE_LO
Definition FOCDriver.h:11
@ PHASE_OFF
Definition FOCDriver.h:8
const int const int const int pinC
GenericCurrentSenseParams * params
void * _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B)
void * _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l)
void * _configure2PWM(long pwm_frequency, const int pinA, const int pinB)
void _writeDutyCycle2PWM(float dc_a, float dc_b, void *params)
void _writeDutyCycle1PWM(float dc_a, void *params)
#define SIMPLEFOC_DRIVER_INIT_FAILED
void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void *params)
void * _configure3PWM(long pwm_frequency, const int pinA, const int pinB, const int pinC)
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void *params)
void * _configure1PWM(long pwm_frequency, const int pinA)
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void *params)
float const int const int const int pinB_h
float const int const int const int const int pinB_l
const int const int pin1B
const int const int const int pin2A
float const int const int const int const int const int pinC_h
float float float dc_2b
float float PhaseState * phase_state
float const int const int const int const int const int const int pinC_l
float const int const int pinA_l
analogWrite(((GenericDriverParams *) params) ->pins[1], 255.0f *dc_b)
const int const int const int const int pin2B
#define _isset(a)
Definition foc_utils.h:13
#define _constrain(amt, low, high)
Definition foc_utils.h:11