Skip to content

Commit e543cd2

Browse files
author
Richard Unger
committed
Merge branch 'dev' of github.com:runger1101001/Arduino-FOC into dev
2 parents fb88707 + 132e7b0 commit e543cd2

File tree

12 files changed

+88
-23
lines changed

12 files changed

+88
-23
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ Please do not hesitate to leave an issue if you have problems/advices/suggestion
115115

116116
Pull requests are welcome, but let's first discuss them in [community forum](https://community.simplefoc.com)!
117117

118-
If you'd like to contribute to this porject but you are not very familiar with github, don't worry, let us know either by posting at the community forum , by posting a github issue or at our discord server.
118+
If you'd like to contribute to this project but you are not very familiar with github, don't worry, let us know either by posting at the community forum , by posting a github issue or at our discord server.
119+
120+
If you are familiar, we accept pull requests to the dev branch!
119121

120122
## Arduino code example
121123
This is a simple Arduino code example implementing the velocity control program of a BLDC motor with encoder.

src/common/foc_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define _sqrt(a) (_sqrtApprox(a))
1313
#define _isset(a) ( (a) != (NOT_SET) )
1414
#define _UNUSED(v) (void) (v)
15+
#define _powtwo(x) (1 << (x))
1516

1617
// utility defines
1718
#define _2_SQRT3 1.15470053838f

src/current_sense/GenericCurrentSense.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ int GenericCurrentSense::driverAlign(float voltage){
6262
int exit_flag = 1;
6363
if(skip_align) return exit_flag;
6464

65+
if (!initialized) return 0;
66+
6567
// // set phase A active and phases B and C down
6668
// driver->setPwm(voltage, 0, 0);
6769
// _delay(200);

src/current_sense/InlineCurrentSense.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "InlineCurrentSense.h"
2+
#include "communication/SimpleFOCDebug.h"
23
// InlineCurrentSensor constructor
34
// - shunt_resistor - shunt resistor value
45
// - gain - current-sense op-amp gain
@@ -93,6 +94,13 @@ int InlineCurrentSense::driverAlign(float voltage){
9394
int exit_flag = 1;
9495
if(skip_align) return exit_flag;
9596

97+
if (driver==nullptr) {
98+
SIMPLEFOC_DEBUG("CUR: No driver linked!");
99+
return 0;
100+
}
101+
102+
if (!initialized) return 0;
103+
96104
if(_isset(pinA)){
97105
// set phase A active and phases B and C down
98106
driver->setPwm(voltage, 0, 0);

src/current_sense/LowsideCurrentSense.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "LowsideCurrentSense.h"
2+
#include "communication/SimpleFOCDebug.h"
23
// LowsideCurrentSensor constructor
34
// - shunt_resistor - shunt resistor value
45
// - gain - current-sense op-amp gain
@@ -35,6 +36,12 @@ LowsideCurrentSense::LowsideCurrentSense(float _mVpA, int _pinA, int _pinB, int
3536

3637
// Lowside sensor init function
3738
int LowsideCurrentSense::init(){
39+
40+
if (driver==nullptr) {
41+
SIMPLEFOC_DEBUG("CUR: Driver not linked!");
42+
return 0;
43+
}
44+
3845
// configure ADC variables
3946
params = _configureADCLowSide(driver->params,pinA,pinB,pinC);
4047
// if init failed return fail
@@ -89,10 +96,12 @@ PhaseCurrent_s LowsideCurrentSense::getPhaseCurrents(){
8996
// 3 - success but gains inverted
9097
// 4 - success but pins reconfigured and gains inverted
9198
int LowsideCurrentSense::driverAlign(float voltage){
92-
99+
93100
int exit_flag = 1;
94101
if(skip_align) return exit_flag;
95102

103+
if (!initialized) return 0;
104+
96105
if(_isset(pinA)){
97106
// set phase A active and phases B and C down
98107
driver->setPwm(voltage, 0, 0);

src/current_sense/hardware_specific/rp2040/rp2040_mcu.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ float _readADCVoltageInline(const int pinA, const void* cs_params) {
2525
// return readings from the same ADC conversion run. The ADC on RP2040 is anyway in round robin mode :-(
2626
// like this we either have to block interrupts, or of course have the chance of reading across
2727
// new ADC conversions, which probably won't improve the accuracy.
28+
_UNUSED(cs_params);
2829

2930
if (pinA>=26 && pinA<=29 && engine.channelsEnabled[pinA-26]) {
3031
return engine.lastResults.raw[pinA-26]*engine.adc_conv;
@@ -36,6 +37,8 @@ float _readADCVoltageInline(const int pinA, const void* cs_params) {
3637

3738

3839
void* _configureADCInline(const void *driver_params, const int pinA, const int pinB, const int pinC) {
40+
_UNUSED(driver_params);
41+
3942
if( _isset(pinA) )
4043
engine.addPin(pinA);
4144
if( _isset(pinB) )

src/drivers/hardware_specific/esp32/esp32_driver_mcpwm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef struct ESP32MCPWMDriverParams {
8888
mcpwm_unit_t mcpwm_unit;
8989
mcpwm_operator_t mcpwm_operator1;
9090
mcpwm_operator_t mcpwm_operator2;
91+
float deadtime;
9192
} ESP32MCPWMDriverParams;
9293

9394

src/drivers/hardware_specific/esp32/esp32_mcu.cpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC)
44

5+
#ifndef SIMPLEFOC_ESP32_HW_DEADTIME
6+
#define SIMPLEFOC_ESP32_HW_DEADTIME true // TODO: Change to false when sw-deadtime & phase_state is approved ready for general use.
7+
#endif
8+
59
// define bldc motor slots array
610
bldc_3pwm_motor_slots_t esp32_bldc_3pwm_motor_slots[4] = {
711
{_EMPTY_SLOT, &MCPWM0, MCPWM_UNIT_0, MCPWM_OPR_A, MCPWM0A, MCPWM1A, MCPWM2A}, // 1st motor will be MCPWM0 channel A
@@ -41,18 +45,36 @@ void _configureTimerFrequency(long pwm_frequency, mcpwm_dev_t* mcpwm_num, mcpwm
4145

4246
mcpwm_config_t pwm_config;
4347
pwm_config.counter_mode = MCPWM_UP_DOWN_COUNTER; // Up-down counter (triangle wave)
44-
pwm_config.duty_mode = MCPWM_DUTY_MODE_0; // Active HIGH
48+
pwm_config.duty_mode = (_isset(dead_zone) || SIMPLEFOC_PWM_ACTIVE_HIGH == true) ? MCPWM_DUTY_MODE_0 : MCPWM_DUTY_MODE_1; // Normally Active HIGH (MCPWM_DUTY_MODE_0)
4549
pwm_config.frequency = 2*pwm_frequency; // set the desired freq - just a placeholder for now https://github.com/simplefoc/Arduino-FOC/issues/76
4650
mcpwm_init(mcpwm_unit, MCPWM_TIMER_0, &pwm_config); //Configure PWM0A & PWM0B with above settings
4751
mcpwm_init(mcpwm_unit, MCPWM_TIMER_1, &pwm_config); //Configure PWM1A & PWM1B with above settings
4852
mcpwm_init(mcpwm_unit, MCPWM_TIMER_2, &pwm_config); //Configure PWM2A & PWM2B with above settings
4953

5054
if (_isset(dead_zone)){
5155
// dead zone is configured
52-
float dead_time = (float)(_MCPWM_FREQ / (pwm_frequency)) * dead_zone;
53-
mcpwm_deadtime_enable(mcpwm_unit, MCPWM_TIMER_0, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, dead_time/2.0, dead_time/2.0);
54-
mcpwm_deadtime_enable(mcpwm_unit, MCPWM_TIMER_1, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, dead_time/2.0, dead_time/2.0);
55-
mcpwm_deadtime_enable(mcpwm_unit, MCPWM_TIMER_2, MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE, dead_time/2.0, dead_time/2.0);
56+
57+
// When using hardware deadtime, setting the phase_state parameter is not supported.
58+
#if SIMPLEFOC_ESP32_HW_DEADTIME == true
59+
float dead_time = (float)(_MCPWM_FREQ / (pwm_frequency)) * dead_zone;
60+
mcpwm_deadtime_type_t pwm_mode;
61+
if ((SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH == true) && (SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH == true)) {pwm_mode = MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE;} // Normal, noninverting driver
62+
else if ((SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH == true) && (SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH == false)){pwm_mode = MCPWM_ACTIVE_HIGH_MODE;} // Inverted lowside driver
63+
else if ((SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH == false) && (SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH == true)) {pwm_mode = MCPWM_ACTIVE_LOW_MODE;} // Inverted highside driver
64+
else if ((SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH == false) && (SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH == false)){pwm_mode = MCPWM_ACTIVE_LOW_COMPLIMENT_MODE;} // Inverted low- & highside driver. Caution: This may short the FETs on reset of the ESP32, as both pins get pulled low!
65+
mcpwm_deadtime_enable(mcpwm_unit, MCPWM_TIMER_0, pwm_mode, dead_time/2.0, dead_time/2.0);
66+
mcpwm_deadtime_enable(mcpwm_unit, MCPWM_TIMER_1, pwm_mode, dead_time/2.0, dead_time/2.0);
67+
mcpwm_deadtime_enable(mcpwm_unit, MCPWM_TIMER_2, pwm_mode, dead_time/2.0, dead_time/2.0);
68+
#else // Software deadtime
69+
for (int i = 0; i < 3; i++){
70+
if (SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH == true) {mcpwm_set_duty_type(mcpwm_unit, (mcpwm_timer_t) i, MCPWM_GEN_A, MCPWM_DUTY_MODE_0);} // Normal, noninverted highside
71+
else if (SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH == false) {mcpwm_set_duty_type(mcpwm_unit, (mcpwm_timer_t) i, MCPWM_GEN_A, MCPWM_DUTY_MODE_1);} // Inverted highside driver
72+
73+
if (SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH == true) {mcpwm_set_duty_type(mcpwm_unit, (mcpwm_timer_t) i, MCPWM_GEN_B, MCPWM_DUTY_MODE_1);} // Normal, complementary lowside
74+
else if (SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH == false) {mcpwm_set_duty_type(mcpwm_unit, (mcpwm_timer_t) i, MCPWM_GEN_B, MCPWM_DUTY_MODE_0);} // Inverted lowside driver
75+
}
76+
#endif
77+
5678
}
5779
_delay(100);
5880

@@ -369,7 +391,10 @@ void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, cons
369391
ESP32MCPWMDriverParams* params = new ESP32MCPWMDriverParams {
370392
.pwm_frequency = pwm_frequency,
371393
.mcpwm_dev = m_slot.mcpwm_num,
372-
.mcpwm_unit = m_slot.mcpwm_unit
394+
.mcpwm_unit = m_slot.mcpwm_unit,
395+
.mcpwm_operator1 = m_slot.mcpwm_operator1,
396+
.mcpwm_operator2 = m_slot.mcpwm_operator2,
397+
.deadtime = _isset(dead_zone) ? dead_zone : 0
373398
};
374399
return params;
375400
}
@@ -381,15 +406,26 @@ void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, cons
381406
// - BLDC driver - 6PWM setting
382407
// - hardware specific
383408
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void* params){
384-
// se the PWM on the slot timers
409+
// set the PWM on the slot timers
385410
// transform duty cycle from [0,1] to [0,100.0]
386-
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_0, MCPWM_OPR_A, dc_a*100.0);
387-
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_0, MCPWM_OPR_B, dc_a*100.0);
388-
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_1, MCPWM_OPR_A, dc_b*100.0);
389-
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_1, MCPWM_OPR_B, dc_b*100.0);
390-
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_2, MCPWM_OPR_A, dc_c*100.0);
391-
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_2, MCPWM_OPR_B, dc_c*100.0);
392-
_UNUSED(phase_state);
411+
#if SIMPLEFOC_ESP32_HW_DEADTIME == true
412+
// Hardware deadtime does deadtime insertion internally
413+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_0, MCPWM_OPR_A, dc_a*100.0f);
414+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_0, MCPWM_OPR_B, dc_a*100.0f);
415+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_1, MCPWM_OPR_A, dc_b*100.0f);
416+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_1, MCPWM_OPR_B, dc_b*100.0f);
417+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_2, MCPWM_OPR_A, dc_c*100.0f);
418+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_2, MCPWM_OPR_B, dc_c*100.0f);
419+
_UNUSED(phase_state);
420+
#else
421+
float deadtime = 0.5f*((ESP32MCPWMDriverParams*)params)->deadtime;
422+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_0, MCPWM_OPR_A, (phase_state[0] == PHASE_ON || phase_state[0] == PHASE_HI) ? _constrain(dc_a-deadtime, 0.0f, 1.0f) * 100.0f : 0);
423+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_0, MCPWM_OPR_B, (phase_state[0] == PHASE_ON || phase_state[0] == PHASE_LO) ? _constrain(dc_a+deadtime, 0.0f, 1.0f) * 100.0f : 100.0f);
424+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_1, MCPWM_OPR_A, (phase_state[1] == PHASE_ON || phase_state[1] == PHASE_HI) ? _constrain(dc_b-deadtime, 0.0f, 1.0f) * 100.0f : 0);
425+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_1, MCPWM_OPR_B, (phase_state[1] == PHASE_ON || phase_state[1] == PHASE_LO) ? _constrain(dc_b+deadtime, 0.0f, 1.0f) * 100.0f : 100.0f);
426+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_2, MCPWM_OPR_A, (phase_state[2] == PHASE_ON || phase_state[2] == PHASE_HI) ? _constrain(dc_c-deadtime, 0.0f, 1.0f) * 100.0f : 0);
427+
mcpwm_set_duty(((ESP32MCPWMDriverParams*)params)->mcpwm_unit, MCPWM_TIMER_2, MCPWM_OPR_B, (phase_state[2] == PHASE_ON || phase_state[2] == PHASE_LO) ? _constrain(dc_c+deadtime, 0.0f, 1.0f) * 100.0f : 100.0f);
428+
#endif
393429
}
394430

395431
#endif

src/sensors/MagneticSensorI2C.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ MagneticSensorI2C::MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution,
2828
// angle read register of the magnetic sensor
2929
angle_register_msb = _angle_register_msb;
3030
// register maximum value (counts per revolution)
31-
cpr = pow(2, _bit_resolution);
31+
cpr = _powtwo(_bit_resolution);
3232

3333
// depending on the sensor architecture there are different combinations of
3434
// LSB and MSB register used bits
@@ -48,7 +48,7 @@ MagneticSensorI2C::MagneticSensorI2C(MagneticSensorI2CConfig_s config){
4848
// angle read register of the magnetic sensor
4949
angle_register_msb = config.angle_register;
5050
// register maximum value (counts per revolution)
51-
cpr = pow(2, config.bit_resolution);
51+
cpr = _powtwo(config.bit_resolution);
5252

5353
int bits_used_msb = config.data_start_bit - 7;
5454
lsb_used = config.bit_resolution - bits_used_msb;
@@ -95,7 +95,7 @@ int MagneticSensorI2C::read(uint8_t angle_reg_msb) {
9595
// notify the device that is aboout to be read
9696
wire->beginTransmission(chip_address);
9797
wire->write(angle_reg_msb);
98-
wire->endTransmission(false);
98+
currWireError = wire->endTransmission(false);
9999

100100
// read the data msb and lsb
101101
wire->requestFrom(chip_address, (uint8_t)2);

src/sensors/MagneticSensorI2C.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ class MagneticSensorI2C: public Sensor{
5151
/** experimental function to check and fix SDA locked LOW issues */
5252
int checkBus(byte sda_pin , byte scl_pin );
5353

54+
/** current error code from Wire endTransmission() call **/
55+
uint8_t currWireError = 0;
56+
5457
private:
5558
float cpr; //!< Maximum range of the magnetic sensor
5659
uint16_t lsb_used; //!< Number of bits used in LSB register

0 commit comments

Comments
 (0)