Skip to content

Commit 9f6e5fd

Browse files
Merge pull request #227 from runger1101001/dev
Fix compilation problems on teensy and nrf52
2 parents f74e0cf + 43723a5 commit 9f6e5fd

File tree

8 files changed

+384
-14
lines changed

8 files changed

+384
-14
lines changed

src/BLDCMotor.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ int BLDCMotor::initFOC( float zero_electric_offset, Direction _sensor_direction
113113
// added the shaft_angle update
114114
sensor->update();
115115
shaft_angle = shaftAngle();
116-
}else
116+
}else {
117+
exit_flag = 0; // no FOC without sensor
117118
SIMPLEFOC_DEBUG("MOT: No sensor.");
119+
}
118120

119121
// aligning the current sensor - can be skipped
120122
// checks if driver phases are the same as current sense phases
@@ -201,7 +203,8 @@ int BLDCMotor::alignSensor() {
201203
setPhaseVoltage(0, 0, 0);
202204
_delay(200);
203205
// determine the direction the sensor moved
204-
if (mid_angle == end_angle) {
206+
float moved = fabs(mid_angle - end_angle);
207+
if (moved<MIN_ANGLE_DETECT_MOVEMENT) { // minimum angle to detect movement
205208
SIMPLEFOC_DEBUG("MOT: Failed to notice movement");
206209
return 0; // failed calibration
207210
} else if (mid_angle < end_angle) {
@@ -212,7 +215,6 @@ int BLDCMotor::alignSensor() {
212215
sensor_direction = Direction::CW;
213216
}
214217
// check pole pair number
215-
float moved = fabs(mid_angle - end_angle);
216218
if( fabs(moved*pole_pairs - _2PI) > 0.5f ) { // 0.5f is arbitrary number it can be lower or higher!
217219
SIMPLEFOC_DEBUG("MOT: PP check: fail - estimated pp: ", _2PI/moved);
218220
} else

src/common/base_classes/Sensor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ void Sensor::update() {
1818
float Sensor::getVelocity() {
1919
// calculate sample time
2020
float Ts = (angle_prev_ts - vel_angle_prev_ts)*1e-6;
21-
if (Ts < min_elapsed_time) return velocity; // don't update velocity if Ts is too small
21+
// TODO handle overflow - we do need to reset vel_angle_prev_ts
22+
if (Ts < min_elapsed_time) return velocity; // don't update velocity if deltaT is too small
2223

2324
velocity = ( (float)(full_rotations - vel_full_rotations)*_2PI + (angle_prev - vel_angle_prev) ) / Ts;
2425
vel_angle_prev = angle_prev;

src/common/foc_utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define _ACTIVE 1
3535
#define _NC (NOT_SET)
3636

37+
#define MIN_ANGLE_DETECT_MOVEMENT (_2PI/101.0f)
38+
3739
// dq current structure
3840
struct DQCurrent_s
3941
{

src/communication/StepDirListener.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "../common/foc_utils.h"
66

77

8-
#if defined(_STM32_DEF_) || defined(ESP_H) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_SAM_DUE)
8+
#if defined(_STM32_DEF_) || defined(ESP_H) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_SAM_DUE) || defined(CORE_TEENSY) || defined(NRF52_SERIES)
99
#define PinStatus int
1010
#endif
1111

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
2+
#if defined(TARGET_RP2040)
3+
4+
5+
#include "../../hardware_api.h"
6+
#include "./rp2040_mcu.h"
7+
#include "../../../drivers/hardware_specific/rp2040_mcu.h"
8+
#include "communication/SimpleFOCDebug.h"
9+
10+
#include "hardware/dma.h"
11+
#include "hardware/irq.h"
12+
#include "hardware/pwm.h"
13+
14+
15+
/* Singleton instance of the ADC engine */
16+
RP2040ADCEngine engine;
17+
18+
alignas(32) const uint32_t trigger_value = ADC_CS_START_ONCE_BITS; // start once
19+
20+
/* Hardware API implementation */
21+
22+
float _readADCVoltageInline(const int pinA, const void* cs_params) {
23+
// not super-happy with this. Here we have to return 1 phase current at a time, when actually we want to
24+
// return readings from the same ADC conversion run. The ADC on RP2040 is anyway in round robin mode :-(
25+
// like this we have block interrupts 3x instead of just once, and of course have the chance of reading across
26+
// new ADC conversions, which probably won't improve the accuracy.
27+
28+
if (pinA>=26 && pinA<=29 && engine.channelsEnabled[pinA-26]) {
29+
return engine.lastResults[pinA-26]*engine.adc_conv;
30+
}
31+
32+
// otherwise return NaN
33+
return NAN;
34+
};
35+
36+
37+
void* _configureADCInline(const void *driver_params, const int pinA, const int pinB, const int pinC) {
38+
if( _isset(pinA) )
39+
engine.addPin(pinA);
40+
if( _isset(pinB) )
41+
engine.addPin(pinB);
42+
if( _isset(pinC) )
43+
engine.addPin(pinC);
44+
engine.init(); // TODO this has to happen later if we want to support more than one motor...
45+
engine.start();
46+
return &engine;
47+
};
48+
49+
50+
void* _configureADCLowSide(const void *driver_params, const int pinA, const int pinB, const int pinC) {
51+
if( _isset(pinA) )
52+
engine.addPin(pinA);
53+
if( _isset(pinB) )
54+
engine.addPin(pinB);
55+
if( _isset(pinC) )
56+
engine.addPin(pinC);
57+
engine.setPWMTrigger(((RP2040DriverParams*)driver_params)->slice[0]);
58+
engine.init();
59+
engine.start();
60+
return &engine;
61+
};
62+
63+
64+
void _startADC3PinConversionLowSide() {
65+
// what is this for?
66+
};
67+
68+
69+
float _readADCVoltageLowSide(const int pinA, const void* cs_params) {
70+
// not super-happy with this. Here we have to return 1 phase current at a time, when actually we want to
71+
// return readings from the same ADC conversion run. The ADC on RP2040 is anyway in round robin mode :-(
72+
// like this we have block interrupts 3x instead of just once, and of course have the chance of reading across
73+
// new ADC conversions, which probably won't improve the accuracy.
74+
75+
if (pinA>=26 && pinA<=29 && engine.channelsEnabled[pinA-26]) {
76+
return engine.lastResults[pinA-26]*engine.adc_conv;
77+
}
78+
79+
// otherwise return NaN
80+
return NAN;
81+
};
82+
83+
84+
void _driverSyncLowSide(void* driver_params, void* cs_params) {
85+
// nothing to do
86+
};
87+
88+
89+
90+
volatile int rp2040_intcount = 0;
91+
92+
void _adcConversionFinishedHandler() {
93+
// conversion of all channels finished. copy results.
94+
volatile uint8_t* from = engine.samples;
95+
if (engine.channelsEnabled[0])
96+
engine.lastResults[0] = (*from++);
97+
if (engine.channelsEnabled[1])
98+
engine.lastResults[1] = (*from++);
99+
if (engine.channelsEnabled[2])
100+
engine.lastResults[2] = (*from++);
101+
if (engine.channelsEnabled[3])
102+
engine.lastResults[3] = (*from++);
103+
// TODO clear interrupt? dma_hw->ints0 = 1u << channel;
104+
//irq_clear(DMA_IRQ_0);
105+
//dma_channel_acknowledge_irq0(engine.copyDMAChannel);
106+
// dma_start_channel_mask( (1u << engine.readDMAChannel) | (1u << engine.copyDMAChannel) );
107+
dma_hw->ints0 = 1u << engine.readDMAChannel;
108+
//dma_start_channel_mask( (1u << engine.readDMAChannel) );
109+
dma_channel_set_write_addr(engine.readDMAChannel, engine.samples, true);
110+
if (engine.triggerPWMSlice>=0)
111+
dma_channel_set_trans_count(engine.triggerDMAChannel, 1, true);
112+
rp2040_intcount++;
113+
};
114+
115+
116+
117+
/* ADC engine implementation */
118+
119+
120+
RP2040ADCEngine::RP2040ADCEngine() {
121+
channelsEnabled[0] = false;
122+
channelsEnabled[1] = false;
123+
channelsEnabled[2] = false;
124+
channelsEnabled[3] = false;
125+
initialized = false;
126+
};
127+
128+
129+
130+
void RP2040ADCEngine::addPin(int pin){
131+
if (pin>=26 && pin<=29)
132+
channelsEnabled[pin-26] = true;
133+
else
134+
SIMPLEFOC_DEBUG("RP2040-CUR: ERR: Not an ADC pin: ", pin);
135+
};
136+
137+
138+
139+
void RP2040ADCEngine::setPWMTrigger(uint slice){
140+
triggerPWMSlice = slice;
141+
};
142+
143+
144+
145+
146+
bool RP2040ADCEngine::init(){
147+
if (initialized)
148+
return true;
149+
150+
adc_init();
151+
int enableMask = 0x00;
152+
int channelCount = 0;
153+
for (int i = 3; i>=0; i--) {
154+
if (channelsEnabled[i]){
155+
adc_gpio_init(i+26);
156+
enableMask |= 0x01;
157+
channelCount++;
158+
}
159+
enableMask = (enableMask<<1);
160+
}
161+
adc_set_round_robin(enableMask);
162+
adc_fifo_setup(
163+
true, // Write each completed conversion to the sample FIFO
164+
true, // Enable DMA data request (DREQ)
165+
channelCount, // DREQ (and IRQ) asserted when all samples present
166+
false, // We won't see the ERR bit because of 8 bit reads; disable.
167+
true // Shift each sample to 8 bits when pushing to FIFO
168+
);
169+
samples_per_second = 20000;
170+
if (samples_per_second<1 || samples_per_second>=500000) {
171+
samples_per_second = 0;
172+
adc_set_clkdiv(0);
173+
}
174+
else
175+
adc_set_clkdiv(48000000/samples_per_second);
176+
SIMPLEFOC_DEBUG("RP2040-CUR: ADC init");
177+
178+
readDMAChannel = dma_claim_unused_channel(true);
179+
dma_channel_config cc1 = dma_channel_get_default_config(readDMAChannel);
180+
channel_config_set_transfer_data_size(&cc1, DMA_SIZE_8);
181+
channel_config_set_read_increment(&cc1, false);
182+
channel_config_set_write_increment(&cc1, true);
183+
channel_config_set_dreq(&cc1, DREQ_ADC);
184+
channel_config_set_irq_quiet(&cc1, false);
185+
dma_channel_configure(readDMAChannel,
186+
&cc1,
187+
samples, // dest
188+
&adc_hw->fifo, // source
189+
channelCount, // count
190+
false // defer start
191+
);
192+
dma_channel_set_irq0_enabled(readDMAChannel, true);
193+
irq_add_shared_handler(DMA_IRQ_0, _adcConversionFinishedHandler, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
194+
195+
// copyDMAChannel = dma_claim_unused_channel(true);
196+
// dma_channel_config cc2 = dma_channel_get_default_config(copyDMAChannel);
197+
// channel_config_set_transfer_data_size(&cc2, DMA_SIZE_32);
198+
// channel_config_set_read_increment(&cc2, false);
199+
// channel_config_set_write_increment(&cc2, false);
200+
// channel_config_set_chain_to(&cc2, readDMAChannel);
201+
// channel_config_set_irq_quiet(&cc2, false);
202+
// dma_channel_configure(copyDMAChannel,
203+
// &cc2,
204+
// nextResults, // dest
205+
// samples, // source
206+
// 1, // count
207+
// false // defer start
208+
// );
209+
// dma_channel_set_irq0_enabled(copyDMAChannel, true);
210+
// irq_add_shared_handler(DMA_IRQ_0, _adcConversionFinishedHandler, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
211+
SIMPLEFOC_DEBUG("RP2040-CUR: DMA init");
212+
213+
if (triggerPWMSlice>=0) { // if we have a trigger
214+
triggerDMAChannel = dma_claim_unused_channel(true);
215+
dma_channel_config cc3 = dma_channel_get_default_config(triggerDMAChannel);
216+
channel_config_set_transfer_data_size(&cc3, DMA_SIZE_32);
217+
channel_config_set_read_increment(&cc3, false);
218+
channel_config_set_write_increment(&cc3, false);
219+
channel_config_set_irq_quiet(&cc3, true);
220+
channel_config_set_dreq(&cc3, DREQ_PWM_WRAP0+triggerPWMSlice); //pwm_get_dreq(triggerPWMSlice));
221+
pwm_set_irq_enabled(triggerPWMSlice, true);
222+
dma_channel_configure(triggerDMAChannel,
223+
&cc3,
224+
hw_set_alias_untyped(&adc_hw->cs), // dest
225+
&trigger_value, // source
226+
1, // count
227+
true // defer start
228+
);
229+
SIMPLEFOC_DEBUG("RP2040-CUR: PWM trigger init slice ", triggerPWMSlice);
230+
}
231+
232+
initialized = true;
233+
return initialized;
234+
};
235+
236+
237+
238+
239+
void RP2040ADCEngine::start(){
240+
SIMPLEFOC_DEBUG("RP2040-CUR: ADC engine starting");
241+
irq_set_enabled(DMA_IRQ_0, true);
242+
dma_start_channel_mask( (1u << readDMAChannel) ); // | (1u << copyDMAChannel));
243+
for (int i=0;i<4;i++) {
244+
if (channelsEnabled[i]) {
245+
adc_select_input(i); // set input to first enabled channel
246+
break;
247+
}
248+
}
249+
if (triggerPWMSlice>=0) {
250+
dma_start_channel_mask( (1u << triggerDMAChannel) );
251+
//hw_set_bits(&adc_hw->cs, trigger_value);
252+
}
253+
else
254+
adc_run(true);
255+
SIMPLEFOC_DEBUG("RP2040-CUR: ADC engine started");
256+
};
257+
258+
void RP2040ADCEngine::stop(){
259+
adc_run(false);
260+
dma_channel_abort(readDMAChannel);
261+
if (triggerPWMSlice>=0)
262+
dma_channel_abort(triggerDMAChannel);
263+
adc_fifo_drain();
264+
SIMPLEFOC_DEBUG("RP2040-CUR: ADC engine stopped");
265+
};
266+
267+
268+
#endif

0 commit comments

Comments
 (0)