Merge pull request #9 from VIPQualityPost/currentsense

Working current sense firmware
This commit is contained in:
VIPQualityPost
2023-11-17 20:47:25 -05:00
committed by GitHub
24 changed files with 753 additions and 237 deletions

View File

@@ -110,12 +110,12 @@ DQCurrent_s CurrentSense::getFOCCurrents(float angle_el)
/** /**
Driver linking to the current sense Driver linking to the current sense
*/ */
void CurrentSense::linkDriver(BLDCDriver *_driver) void CurrentSense::linkDriver(FOCDriver *_driver)
{ {
driver = _driver; driver = _driver;
} }
void CurrentSense::linkDriver(StepperDriver *_driver) // void CurrentSense::linkDriver(StepperDriver *_driver)
{ // {
driver = _driver; // driver = _driver;
} // }

View File

@@ -24,8 +24,8 @@ class CurrentSense{
* Linking the current sense with the motor driver * Linking the current sense with the motor driver
* Only necessary if synchronisation in between the two is required * Only necessary if synchronisation in between the two is required
*/ */
void linkDriver(BLDCDriver *driver); void linkDriver(FOCDriver *driver);
void linkDriver(StepperDriver *driver); // void linkDriver(StepperDriver *driver);
// variables // variables
bool skip_align = false; //!< variable signaling that the phase current direction should be verified during initFOC() bool skip_align = false; //!< variable signaling that the phase current direction should be verified during initFOC()

View File

@@ -1,7 +1,8 @@
#ifndef FOCMOTOR_H #ifndef FOCDRIVER_H
#define FOTMOTOR_H #define FOCDRIVER_H
#include "Arduino.h" #include "Arduino.h"
#include "../foc_utils.h"
class FOCDriver{ class FOCDriver{
public: public:
@@ -11,6 +12,9 @@ class FOCDriver{
virtual void disable() = 0; virtual void disable() = 0;
virtual void setPwm(float a, float b, float c) = 0;
// virtual void setPwm(uint8_t a, uint8_t b);
long pwm_frequency; long pwm_frequency;
float voltage_power_supply; float voltage_power_supply;
float voltage_limit; float voltage_limit;

View File

@@ -12,7 +12,7 @@ class StepperDriver: public FOCDriver{
* @param Ua phase A voltage * @param Ua phase A voltage
* @param Ub phase B voltage * @param Ub phase B voltage
*/ */
virtual void setPwm(float Ua, float Ub) = 0; virtual void setPwm(float Ua, float Ub, float Uc=NOT_SET) = 0;
}; };
#endif #endif

View File

@@ -1,4 +1,6 @@
#include "../hardware_api.h" #include "../hardware_api.h"
#include "communication/SimpleFOCDebug.h"
// function reading an ADC value and returning the read voltage // function reading an ADC value and returning the read voltage
__attribute__((weak)) float _readADCVoltageInline(const int pinA, const void* cs_params){ __attribute__((weak)) float _readADCVoltageInline(const int pinA, const void* cs_params){

View File

@@ -86,7 +86,7 @@ int StepperDriver2PWM::init() {
// Set voltage to the pwm pin // Set voltage to the pwm pin
void StepperDriver2PWM::setPwm(float Ua, float Ub) { void StepperDriver2PWM::setPwm(float Ua, float Ub, float Uc) {
float duty_cycle1(0.0f),duty_cycle2(0.0f); float duty_cycle1(0.0f),duty_cycle2(0.0f);
// limit the voltage in driver // limit the voltage in driver
Ua = _constrain(Ua, -voltage_limit, voltage_limit); Ua = _constrain(Ua, -voltage_limit, voltage_limit);

View File

@@ -58,7 +58,7 @@ class StepperDriver2PWM: public StepperDriver
* @param Ua phase A voltage * @param Ua phase A voltage
* @param Ub phase B voltage * @param Ub phase B voltage
*/ */
void setPwm(float Ua, float Ub) override; void setPwm(float Ua, float Ub, float NOT_USED=NOT_SET) override;
private: private:

View File

@@ -60,8 +60,9 @@ int StepperDriver4PWM::init() {
} }
// Set voltage to the pwm pin // Set voltage to the pwm pin
void StepperDriver4PWM::setPwm(float Ualpha, float Ubeta) { void StepperDriver4PWM::setPwm(float Ualpha, float Ubeta, float Uc) {
float duty_cycle1A(0.0f),duty_cycle1B(0.0f),duty_cycle2A(0.0f),duty_cycle2B(0.0f); float duty_cycle1A(0.0f),duty_cycle1B(0.0f),duty_cycle2A(0.0f),duty_cycle2B(0.0f);
// limit the voltage in driver // limit the voltage in driver
Ualpha = _constrain(Ualpha, -voltage_limit, voltage_limit); Ualpha = _constrain(Ualpha, -voltage_limit, voltage_limit);

View File

@@ -45,7 +45,8 @@ class StepperDriver4PWM: public StepperDriver
* @param Ua phase A voltage * @param Ua phase A voltage
* @param Ub phase B voltage * @param Ub phase B voltage
*/ */
void setPwm(float Ua, float Ub) override; void setPwm(float Ua, float Ub, float NOT_USED = NOT_SET) override;
// void setPwm(float Ua, float Ub) override;
private: private:

View File

@@ -0,0 +1,255 @@
#include "InlineCurrentSenseSync.h"
#include "communication/SimpleFOCDebug.h"
// InlineCurrentSensor constructor
// - shunt_resistor - shunt resistor value
// - gain - current-sense op-amp gain
// - phA - A phase adc pin
// - phB - B phase adc pin
// - phC - C phase adc pin (optional)
InlineCurrentSenseSync::InlineCurrentSenseSync(float _shunt_resistor, float _gain, int _pinA, int _pinB, int _pinC){
pinA = _pinA;
pinB = _pinB;
pinC = _pinC;
shunt_resistor = _shunt_resistor;
amp_gain = _gain;
volts_to_amps_ratio = 1.0f /_shunt_resistor / _gain; // volts to amps
// gains for each phase
gain_a = volts_to_amps_ratio;
gain_b = volts_to_amps_ratio;
gain_c = volts_to_amps_ratio;
};
InlineCurrentSenseSync::InlineCurrentSenseSync(float _mVpA, int _pinA, int _pinB, int _pinC){
pinA = _pinA;
pinB = _pinB;
pinC = _pinC;
volts_to_amps_ratio = 1000.0f / _mVpA; // mV to amps
// gains for each phase
gain_a = volts_to_amps_ratio;
gain_b = volts_to_amps_ratio;
gain_c = volts_to_amps_ratio;
};
// Inline sensor init function
int InlineCurrentSenseSync::init(){
SIMPLEFOC_DEBUG("CS:Init Current Sense Inline Sync");
// if no linked driver its fine in this case
// at least for init()
void* drv_params = driver ? driver->params : nullptr;
// configure ADC variables
params = _configureADCInline(drv_params,pinA,pinB,pinC);
// if init failed return fail
if (params == SIMPLEFOC_CURRENT_SENSE_INIT_FAILED) return 0;
_driverSyncLowSide(driver->params, params);
// calibrate zero offsets
calibrateOffsets();
// set the initialized flag
initialized = (params!=SIMPLEFOC_CURRENT_SENSE_INIT_FAILED);
// return success
return 1;
}
// Function finding zero offsets of the ADC
void InlineCurrentSenseSync::calibrateOffsets(){
const int calibration_rounds = 1000;
// find adc offset = zero current voltage
offset_ia = 0;
offset_ib = 0;
offset_ic = 0;
// read the adc voltage 1000 times ( arbitrary number )
for (int i = 0; i < calibration_rounds; i++) {
if(_isset(pinA)) offset_ia += _readADCVoltageInline(pinA, params);
if(_isset(pinB)) offset_ib += _readADCVoltageInline(pinB, params);
if(_isset(pinC)) offset_ic += _readADCVoltageInline(pinC, params);
_delay(1);
}
// calculate the mean offsets
if(_isset(pinA)) offset_ia = offset_ia / calibration_rounds;
if(_isset(pinB)) offset_ib = offset_ib / calibration_rounds;
if(_isset(pinC)) offset_ic = offset_ic / calibration_rounds;
}
// read all three phase currents (if possible 2 or 3)
PhaseCurrent_s InlineCurrentSenseSync::getPhaseCurrents(){
PhaseCurrent_s current;
current.a = (!_isset(pinA)) ? 0 : (_readADCVoltageInline(pinA, params) - offset_ia)*gain_a;// amps
current.b = (!_isset(pinB)) ? 0 : (_readADCVoltageInline(pinB, params) - offset_ib)*gain_b;// amps
current.c = (!_isset(pinC)) ? 0 : (_readADCVoltageInline(pinC, params) - offset_ic)*gain_c; // amps
return current;
}
// Function aligning the current sense with motor driver
// if all pins are connected well none of this is really necessary! - can be avoided
// returns flag
// 0 - fail
// 1 - success and nothing changed
// 2 - success but pins reconfigured
// 3 - success but gains inverted
// 4 - success but pins reconfigured and gains inverted
int InlineCurrentSenseSync::driverAlign(float voltage){
int exit_flag = 1;
if(skip_align) return exit_flag;
if (driver==nullptr) {
SIMPLEFOC_DEBUG("CUR: No driver linked!");
return 0;
}
if (!initialized) return 0;
if(_isset(pinA)){
// set phase A active and phases B and C down
driver->setPwm(voltage, 0, 0);
_delay(2000);
PhaseCurrent_s c = getPhaseCurrents();
// read the current 100 times ( arbitrary number )
for (int i = 0; i < 100; i++) {
PhaseCurrent_s c1 = getPhaseCurrents();
c.a = c.a*0.6f + 0.4f*c1.a;
c.b = c.b*0.6f + 0.4f*c1.b;
c.c = c.c*0.6f + 0.4f*c1.c;
_delay(3);
}
driver->setPwm(0, 0, 0);
// align phase A
float ab_ratio = c.b ? fabs(c.a / c.b) : 0;
float ac_ratio = c.c ? fabs(c.a / c.c) : 0;
if(_isset(pinB) && ab_ratio > 1.5f ){ // should be ~2
gain_a *= _sign(c.a);
}else if(_isset(pinC) && ac_ratio > 1.5f ){ // should be ~2
gain_a *= _sign(c.a);
}else if(_isset(pinB) && ab_ratio < 0.7f ){ // should be ~0.5
// switch phase A and B
int tmp_pinA = pinA;
pinA = pinB;
pinB = tmp_pinA;
float tmp_offsetA = offset_ia;
offset_ia = offset_ib;
offset_ib = tmp_offsetA;
gain_a *= _sign(c.b);
exit_flag = 2; // signal that pins have been switched
}else if(_isset(pinC) && ac_ratio < 0.7f ){ // should be ~0.5
// switch phase A and C
int tmp_pinA = pinA;
pinA = pinC;
pinC= tmp_pinA;
float tmp_offsetA = offset_ia;
offset_ia = offset_ic;
offset_ic = tmp_offsetA;
gain_a *= _sign(c.c);
exit_flag = 2;// signal that pins have been switched
}else{
// error in current sense - phase either not measured or bad connection
return 0;
}
}
if(_isset(pinB)){
// set phase B active and phases A and C down
driver->setPwm(0, voltage, 0);
_delay(200);
PhaseCurrent_s c = getPhaseCurrents();
// read the current 50 times
for (int i = 0; i < 100; i++) {
PhaseCurrent_s c1 = getPhaseCurrents();
c.a = c.a*0.6 + 0.4f*c1.a;
c.b = c.b*0.6 + 0.4f*c1.b;
c.c = c.c*0.6 + 0.4f*c1.c;
_delay(3);
}
driver->setPwm(0, 0, 0);
float ba_ratio = c.a ? fabs(c.b / c.a) : 0;
float bc_ratio = c.c ? fabs(c.b / c.c) : 0;
if(_isset(pinA) && ba_ratio > 1.5f ){ // should be ~2
gain_b *= _sign(c.b);
}else if(_isset(pinC) && bc_ratio > 1.5f ){ // should be ~2
gain_b *= _sign(c.b);
}else if(_isset(pinA) && ba_ratio < 0.7f ){ // it should be ~0.5
// switch phase A and B
int tmp_pinB = pinB;
pinB = pinA;
pinA = tmp_pinB;
float tmp_offsetB = offset_ib;
offset_ib = offset_ia;
offset_ia = tmp_offsetB;
gain_b *= _sign(c.a);
exit_flag = 2; // signal that pins have been switched
}else if(_isset(pinC) && bc_ratio < 0.7f ){ // should be ~0.5
// switch phase A and C
int tmp_pinB = pinB;
pinB = pinC;
pinC = tmp_pinB;
float tmp_offsetB = offset_ib;
offset_ib = offset_ic;
offset_ic = tmp_offsetB;
gain_b *= _sign(c.c);
exit_flag = 2; // signal that pins have been switched
}else{
// error in current sense - phase either not measured or bad connection
return 0;
}
}
// if phase C measured
if(_isset(pinC)){
// set phase C active and phases A and B down
driver->setPwm(0, 0, voltage);
_delay(200);
PhaseCurrent_s c = getPhaseCurrents();
// read the adc voltage 500 times ( arbitrary number )
for (int i = 0; i < 100; i++) {
PhaseCurrent_s c1 = getPhaseCurrents();
c.a = c.a*0.6 + 0.4f*c1.a;
c.b = c.b*0.6 + 0.4f*c1.b;
c.c = c.c*0.6 + 0.4f*c1.c;
_delay(3);
}
driver->setPwm(0, 0, 0);
float ca_ratio = c.a ? fabs(c.c / c.a) : 0;
float cb_ratio = c.b ? fabs(c.c / c.b) : 0;
if(_isset(pinA) && ca_ratio > 1.5f ){ // should be ~2
gain_c *= _sign(c.c);
}else if(_isset(pinB) && cb_ratio > 1.5f ){ // should be ~2
gain_c *= _sign(c.c);
}else if(_isset(pinA) && ca_ratio < 0.7f ){ // it should be ~0.5
// switch phase A and C
int tmp_pinC = pinC;
pinC = pinA;
pinA = tmp_pinC;
float tmp_offsetC = offset_ic;
offset_ic = offset_ia;
offset_ia = tmp_offsetC;
gain_c *= _sign(c.a);
exit_flag = 2; // signal that pins have been switched
}else if(_isset(pinB) && cb_ratio < 0.7f ){ // should be ~0.5
// switch phase B and C
int tmp_pinC = pinC;
pinC = pinB;
pinB = tmp_pinC;
float tmp_offsetC = offset_ic;
offset_ic = offset_ib;
offset_ib = tmp_offsetC;
gain_c *= _sign(c.b);
exit_flag = 2; // signal that pins have been switched
}else{
// error in current sense - phase either not measured or bad connection
return 0;
}
}
if(gain_a < 0 || gain_b < 0 || gain_c < 0) exit_flag +=2;
// exit flag is either
// 0 - fail
// 1 - success and nothing changed
// 2 - success but pins reconfigured
// 3 - success but gains inverted
// 4 - success but pins reconfigured and gains inverted
return exit_flag;
}

View File

@@ -0,0 +1,75 @@
#ifndef INLINE_CS_SYNC_LIB_H
#define INLINE_CS_SYNC_LIB_H
#include "Arduino.h"
#include "SimpleFOC.h"
#include "common/foc_utils.h"
#include "common/time_utils.h"
#include "common/defaults.h"
#include "common/base_classes/CurrentSense.h"
#include "common/lowpass_filter.h"
// #include "current_sense/hardware_api.h"
#include "utils.h"
class InlineCurrentSenseSync: public CurrentSense{
public:
/**
InlineCurrentSense class constructor
@param shunt_resistor shunt resistor value
@param gain current-sense op-amp gain
@param phA A phase adc pin
@param phB B phase adc pin
@param phC C phase adc pin (optional)
*/
InlineCurrentSenseSync(float shunt_resistor, float gain, int pinA, int pinB, int pinC = NOT_SET);
/**
InlineCurrentSense class constructor
@param mVpA mV per Amp ratio
@param phA A phase adc pin
@param phB B phase adc pin
@param phC C phase adc pin (optional)
*/
InlineCurrentSenseSync(float mVpA, int pinA, int pinB, int pinC = NOT_SET);
// CurrentSense interface implementing functions
int init() override;
PhaseCurrent_s getPhaseCurrents() override;
int driverAlign(float align_voltage) override;
// ADC measuremnet gain for each phase
// support for different gains for different phases of more commonly - inverted phase currents
// this should be automated later
float gain_a; //!< phase A gain
float gain_b; //!< phase B gain
float gain_c; //!< phase C gain
// // per phase low pass fileters
// LowPassFilter lpf_a{DEF_LPF_PER_PHASE_CURRENT_SENSE_Tf}; //!< current A low pass filter
// LowPassFilter lpf_b{DEF_LPF_PER_PHASE_CURRENT_SENSE_Tf}; //!< current B low pass filter
// LowPassFilter lpf_c{DEF_LPF_PER_PHASE_CURRENT_SENSE_Tf}; //!< current C low pass filter
float offset_ia; //!< zero current A voltage value (center of the adc reading)
float offset_ib; //!< zero current B voltage value (center of the adc reading)
float offset_ic; //!< zero current C voltage value (center of the adc reading)
private:
// hardware variables
int pinA; //!< pin A analog pin for current measurement
int pinB; //!< pin B analog pin for current measurement
int pinC; //!< pin C analog pin for current measurement
// gain variables
float shunt_resistor; //!< Shunt resistor value
float amp_gain; //!< amp gain value
float volts_to_amps_ratio; //!< Volts to amps ratio
/**
* Function finding zero offsets of the ADC
*/
void calibrateOffsets();
};
#endif

View File

@@ -5,8 +5,6 @@ ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1; DMA_HandleTypeDef hdma_adc1;
DMA_HandleTypeDef hdma_adc2; DMA_HandleTypeDef hdma_adc2;
uint32_t HAL_RCC_ADC12_CLK_ENABLED = 0;
void MX_ADC1_Init(void) void MX_ADC1_Init(void)
{ {
ADC_MultiModeTypeDef multimode = {0}; ADC_MultiModeTypeDef multimode = {0};
@@ -21,13 +19,17 @@ void MX_ADC1_Init(void)
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1; hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_TRGO; hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = ENABLE; hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE; hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
if (HAL_ADC_Init(&hadc1) != HAL_OK) if (HAL_ADC_Init(&hadc1) != HAL_OK)
SIMPLEFOC_DEBUG("HAL ADC1 Init fail."); SIMPLEFOC_DEBUG("HAL ADC1 Init fail.");
@@ -35,6 +37,7 @@ void MX_ADC1_Init(void)
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK) if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
SIMPLEFOC_DEBUG("HAL ADC1 multimode configuration fail."); SIMPLEFOC_DEBUG("HAL ADC1 multimode configuration fail.");
// sConfig.Channel = ADC_CHANNEL_VOPAMP1;
sConfig.Channel = ADC_CHANNEL_VOPAMP1; sConfig.Channel = ADC_CHANNEL_VOPAMP1;
sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5; sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
@@ -44,8 +47,13 @@ void MX_ADC1_Init(void)
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
SIMPLEFOC_DEBUG("HAL ADC OPAMP1 init failed!"); SIMPLEFOC_DEBUG("HAL ADC OPAMP1 init failed!");
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1; sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_2; sConfig.Rank = ADC_REGULAR_RANK_2;
if(HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
SIMPLEFOC_DEBUG("HAL ADC Vmotor init failed!");
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1;
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
SIMPLEFOC_DEBUG("HAL ADC temp init failed!"); SIMPLEFOC_DEBUG("HAL ADC temp init failed!");
} }
@@ -65,11 +73,15 @@ void MX_ADC2_Init(void)
hadc2.Init.ContinuousConvMode = DISABLE; hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.NbrOfConversion = 2; hadc2.Init.NbrOfConversion = 2;
hadc2.Init.DiscontinuousConvMode = DISABLE; hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_TRGO; hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc2.Init.DMAContinuousRequests = ENABLE; hadc2.Init.DMAContinuousRequests = ENABLE;
hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc2.Init.OversamplingMode = DISABLE; hadc2.Init.OversamplingMode = DISABLE;
hadc2.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc2.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
hadc2.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc2.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
if (HAL_ADC_Init(&hadc2) != HAL_OK) if (HAL_ADC_Init(&hadc2) != HAL_OK)
SIMPLEFOC_DEBUG("HAL ADC2 init failed!"); SIMPLEFOC_DEBUG("HAL ADC2 init failed!");
@@ -88,95 +100,51 @@ void MX_ADC2_Init(void)
SIMPLEFOC_DEBUG("HAL ADC OPAMP3 init failed!"); SIMPLEFOC_DEBUG("HAL ADC OPAMP3 init failed!");
} }
void ADC_DMA_Init(ADC_HandleTypeDef* adcHandle) uint32_t HAL_RCC_ADC12_CLK_ENABLED = 0;
void ADC_DMA_Init(void)
{ {
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(adcHandle->Instance==ADC1)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
SIMPLEFOC_DEBUG("Error initializing peripheral clock in adc.cpp");
HAL_RCC_ADC12_CLK_ENABLED++;
if (HAL_RCC_ADC12_CLK_ENABLED == 1)
{ {
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12; __HAL_RCC_ADC12_CLK_ENABLE();
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
HAL_RCC_ADC12_CLK_ENABLED++;
if(HAL_RCC_ADC12_CLK_ENABLED==1){
__HAL_RCC_ADC12_CLK_ENABLE();
}
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_NORMAL;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);
} }
else if(adcHandle->Instance==ADC2)
{
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
HAL_RCC_ADC12_CLK_ENABLED++; /* ADC1 DMA Init */
if(HAL_RCC_ADC12_CLK_ENABLED==1){ hdma_adc1.Instance = DMA1_Channel1;
__HAL_RCC_ADC12_CLK_ENABLE(); hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
} hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
SIMPLEFOC_DEBUG("HAL error enabling DMA1 channel 1.");
/* ADC2 DMA Init */ __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
/* ADC2 Init */
hdma_adc2.Instance = DMA1_Channel2;
hdma_adc2.Init.Request = DMA_REQUEST_ADC2;
hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc2.Init.Mode = DMA_CIRCULAR;
hdma_adc2.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc2); /* ADC2 DMA Init */
} hdma_adc2.Instance = DMA1_Channel2;
hdma_adc2.Init.Request = DMA_REQUEST_ADC2;
hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc2.Init.Mode = DMA_CIRCULAR;
hdma_adc2.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
SIMPLEFOC_DEBUG("HAL error enabling DMA1 channel 2.");
__HAL_LINKDMA(&hadc2, DMA_Handle, hdma_adc2);
} }
// void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
// {
// if(adcHandle->Instance==ADC1)
// {
// HAL_RCC_ADC12_CLK_ENABLED--;
// if(HAL_RCC_ADC12_CLK_ENABLED==0){
// __HAL_RCC_ADC12_CLK_DISABLE();
// }
// HAL_DMA_DeInit(adcHandle->DMA_Handle);
// }
// else if(adcHandle->Instance==ADC2)
// {
// HAL_RCC_ADC12_CLK_ENABLED--;
// if(HAL_RCC_ADC12_CLK_ENABLED==0){
// __HAL_RCC_ADC12_CLK_DISABLE();
// }
// HAL_DMA_DeInit(adcHandle->DMA_Handle);
// }
// }

View File

@@ -3,6 +3,7 @@
#include "stm32g4xx_hal.h" #include "stm32g4xx_hal.h"
#include "stm32g4xx_hal_adc.h" #include "stm32g4xx_hal_adc.h"
#include "stm32g4xx_hal_adc_ex.h"
#include "communication/SimpleFOCDebug.h" #include "communication/SimpleFOCDebug.h"
extern ADC_HandleTypeDef hadc1; extern ADC_HandleTypeDef hadc1;
@@ -12,7 +13,7 @@ extern DMA_HandleTypeDef hdma_adc2;
void MX_ADC1_Init(void); void MX_ADC1_Init(void);
void MX_ADC2_Init(void); void MX_ADC2_Init(void);
void ADC_DMA_Init(ADC_HandleTypeDef* adcHandle); void ADC_DMA_Init(void);
#endif #endif

View File

@@ -4,7 +4,7 @@ void MX_DMA_Init(void)
{ {
__HAL_RCC_DMAMUX1_CLK_ENABLE(); __HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE(); // __HAL_RCC_DMA2_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
@@ -16,7 +16,6 @@ void MX_DMA_Init(void)
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12; PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK; PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
} }
extern "C" { extern "C" {

View File

@@ -4,72 +4,73 @@ OPAMP_HandleTypeDef hopamp1;
OPAMP_HandleTypeDef hopamp2; OPAMP_HandleTypeDef hopamp2;
OPAMP_HandleTypeDef hopamp3; OPAMP_HandleTypeDef hopamp3;
void initOPAMP(OPAMP_HandleTypeDef *hopamp, OPAMP_TypeDef *opamp) void configureOPAMPs(void)
{ {
hopamp1.Instance = opamp; hopamp1.Instance = OPAMP1;
hopamp1.Init.PowerMode = OPAMP_POWERMODE_NORMALSPEED; hopamp1.Init.PowerMode = OPAMP_POWERMODE_NORMALSPEED;
hopamp1.Init.Mode = OPAMP_PGA_MODE; hopamp1.Init.Mode = OPAMP_FOLLOWER_MODE;
hopamp1.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO1; hopamp1.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO1;
hopamp1.Init.InternalOutput = ENABLE; hopamp1.Init.InternalOutput = ENABLE;
hopamp1.Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE; hopamp1.Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE;
hopamp1.Init.PgaConnect = OPAMP_PGA_CONNECT_INVERTINGINPUT_NO;
hopamp1.Init.PgaGain = OPAMP_PGA_GAIN_16_OR_MINUS_15; // Adjust this to change the gains of the opamp.
hopamp1.Init.UserTrimming = OPAMP_TRIMMING_FACTORY; hopamp1.Init.UserTrimming = OPAMP_TRIMMING_FACTORY;
if (HAL_OPAMP_Init(hopamp) != HAL_OK) if(HAL_OPAMP_Init(&hopamp1) != HAL_OK)
SIMPLEFOC_DEBUG("HAL OPAMP Init failed!"); SIMPLEFOC_DEBUG("OPAMP1 init failed.");
hopamp2.Instance = OPAMP2;
hopamp2.Init.PowerMode = OPAMP_POWERMODE_NORMALSPEED;
hopamp2.Init.Mode = OPAMP_FOLLOWER_MODE;
hopamp2.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO2;
hopamp2.Init.InternalOutput = ENABLE;
hopamp2.Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE;
hopamp2.Init.UserTrimming = OPAMP_TRIMMING_FACTORY;
if(HAL_OPAMP_Init(&hopamp2) != HAL_OK)
SIMPLEFOC_DEBUG("OPAMP2 init failed.");
hopamp3.Instance = OPAMP3;
hopamp3.Init.PowerMode = OPAMP_POWERMODE_NORMALSPEED;
hopamp3.Init.Mode = OPAMP_FOLLOWER_MODE;
hopamp3.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO1;
hopamp3.Init.InternalOutput = ENABLE;
hopamp3.Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE;
hopamp3.Init.UserTrimming = OPAMP_TRIMMING_FACTORY;
if(HAL_OPAMP_Init(&hopamp3) != HAL_OK)
SIMPLEFOC_DEBUG("OPAMP3 init failed.");
} }
void configureOPAMPs(void) void OPAMP_GPIO_Init(void)
{ {
initOPAMP(&hopamp1, OPAMP1); // PA3
initOPAMP(&hopamp2, OPAMP2); // PB0
initOPAMP(&hopamp3, OPAMP3); // PA1
}
void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef* opampHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitTypeDef GPIO_InitStruct = {0};
if(opampHandle->Instance==OPAMP1)
{ __HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
} GPIO_InitStruct.Pin = GPIO_PIN_3;
else if(opampHandle->Instance==OPAMP2) HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
{
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_13;
} HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
else if(opampHandle->Instance==OPAMP3)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
} }
void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef* opampHandle) void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *opampHandle)
{ {
if(opampHandle->Instance==OPAMP1) if (opampHandle->Instance == OPAMP1)
{ {
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3);
} }
else if(opampHandle->Instance==OPAMP2) else if (opampHandle->Instance == OPAMP2)
{ {
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_0);
} }
else if(opampHandle->Instance==OPAMP3) else if (opampHandle->Instance == OPAMP3)
{ {
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);
} }
} }

View File

@@ -12,6 +12,7 @@ extern OPAMP_HandleTypeDef hopamp2;
extern OPAMP_HandleTypeDef hopamp3; extern OPAMP_HandleTypeDef hopamp3;
void configureOPAMPs(void); void configureOPAMPs(void);
void OPAMP_GPIO_Init(void);
#endif #endif

View File

@@ -7,10 +7,10 @@
#include "opamp.h" #include "opamp.h"
float adcResolution = 4096.0f; // 12 bit ADC float adcResolution = 4096.0f; // 12 bit ADC
float voltageScale = 3.3f; // full scale voltage range of ADC float voltageScale = 2.9f; // full scale voltage range of ADC
float adcSens = adcResolution * voltageScale; float adcSens = voltageScale / adcResolution;
volatile uint16_t adc1Result[2] = {0}; volatile uint16_t adc1Result[3] = {0};
volatile uint16_t adc2Result[2] = {0}; volatile uint16_t adc2Result[2] = {0};
void MX_GPIO_Init(void) void MX_GPIO_Init(void)
@@ -20,30 +20,36 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_ADC12_CLK_ENABLE(); __HAL_RCC_ADC12_CLK_ENABLE();
OPAMP_GPIO_Init();
} }
float _readVoltageInline(const uint8_t pin, const void *cs_params) float _readADCVoltageInline(const int pin, const void *cs_params)
{ {
uint32_t rawResult; // SIMPLEFOC_DEBUG("READ ADC VOLTAGE");
uint16_t rawResult;
switch (pin) switch (pin)
{ {
case PA3: case PA3:
rawResult = adc1Result[0]; // ADC1 CH13 -> Vopamp1 internal output rawResult = adc1Result[0];
break;
case PB13:
rawResult = adc2Result[0]; // ADC1 CH13 -> Vopamp1 internal output
break; break;
case PB0: case PB0:
rawResult = adc2Result[0]; // ADC2 CH16 -> Vopamp2 internal output rawResult = adc2Result[1]; // ADC2 CH16 -> Vopamp2 internal output
break; break;
case PA1: // case PA13:
rawResult = adc2Result[1]; // ADC2 CH18 -> Vopamp3 internal output // rawResult = adc2Result[2]; // ADC2 CH18 -> Vopamp3 internal output
break; // break;
case PA2: // case PA2:
rawResult = adc1Result[1]; // ADC1 CH16 -> not sure what pin should represent this? // rawResult = adc1Result[1]; // ADC1 CH16 -> not sure what pin should represent this?
break; // break;
default: default:
return 0.0f; return 0.0f;
@@ -60,19 +66,25 @@ float _readVoltageLowSide(const int pinA, const void *cs_params)
void *_configureADCInline(const void *driver_params, const int pinA, const int pinB, const int pinC) void *_configureADCInline(const void *driver_params, const int pinA, const int pinB, const int pinC)
{ {
SIMPLEFOC_DEBUG("Configure Utils ADCInline");
_UNUSED(driver_params); _UNUSED(driver_params);
HAL_Init(); HAL_Init();
HAL_SYSCFG_VREFBUF_VoltageScalingConfig(SYSCFG_VREFBUF_VOLTAGE_SCALE2);
HAL_SYSCFG_EnableVREFBUF();
HAL_SYSCFG_VREFBUF_HighImpedanceConfig(SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE);
MX_GPIO_Init(); MX_GPIO_Init();
MX_DMA_Init(); MX_DMA_Init();
MX_ADC1_Init(); MX_ADC1_Init();
MX_ADC2_Init(); MX_ADC2_Init();
configureOPAMPs(); configureOPAMPs();
ADC_DMA_Init(&hadc1); ADC_DMA_Init();
ADC_DMA_Init(&hadc2);
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1Result, 1) != HAL_OK) HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1Result, 3) != HAL_OK)
{ {
SIMPLEFOC_DEBUG("DMA1 read init failed"); SIMPLEFOC_DEBUG("DMA1 read init failed");
} }
@@ -106,18 +118,28 @@ void *_configureADCLowSide(const void *driver_params, const int pinA, const int
void _driverSyncLowSide(void *_driver_params, void *_cs_params) void _driverSyncLowSide(void *_driver_params, void *_cs_params)
{ {
SIMPLEFOC_DEBUG("CS: Sync CS to driver");
STM32DriverParams* driver_params = (STM32DriverParams*)_driver_params; STM32DriverParams* driver_params = (STM32DriverParams*)_driver_params;
Stm32CurrentSenseParams* cs_params = (Stm32CurrentSenseParams*)_cs_params; Stm32CurrentSenseParams* cs_params = (Stm32CurrentSenseParams*)_cs_params;
_stopTimers(driver_params->timers, 6); _stopTimers(driver_params->timers, 6);
// See RM0440 pg. 1169 // See RM0440 pg. 1169
// This grabs the timer handle used for ADC and sets the direction bit as upcounting (?) // Grab the timer handle used for ADC and sets the direction bit as upcounting
cs_params->timer_handle->getHandle()->Instance->CR1 |= TIM_CR1_DIR; cs_params->timer_handle->getHandle()->Instance->CR1 |= TIM_CR1_DIR;
// This sets the value of the timer to the reload value. I think this is so that an event is immediately fired /** Set the value of the timer to the reload value, so that overflow event is generated immediately.
* This is because we are using repetition counter to count every other event, skipping the underflow at
* valleys of PWM. We can downsample every other peak if repetition counter is increased to 3
*/
cs_params->timer_handle->getHandle()->Instance->CNT = cs_params->timer_handle->getHandle()->Instance->ARR; cs_params->timer_handle->getHandle()->Instance->CNT = cs_params->timer_handle->getHandle()->Instance->ARR;
// Set TIM_CR1_URS to 0b1 -> only update events are overflows/underflow
cs_params->timer_handle->getHandle()->Instance->CR1 |= 0x0004;
// Set TIM_CR2_MMS to 0b010 -> update event (overflow and underflow) mapped to tim2_trgo
cs_params->timer_handle->getHandle()->Instance->CR2 |= 0x0020;
_startTimers(driver_params->timers, 6); _startTimers(driver_params->timers, 6);
} }

View File

@@ -6,9 +6,16 @@
#include "stm32g4xx_hal.h" #include "stm32g4xx_hal.h"
#include "communication/SimpleFOCDebug.h" #include "communication/SimpleFOCDebug.h"
#include "current_sense/hardware_api.h" // #include "current_sense/hardware_api.h"
#include "current_sense/hardware_specific/stm32/stm32_mcu.h" #include "current_sense/hardware_specific/stm32/stm32_mcu.h"
#include "drivers/hardware_specific/stm32/stm32_mcu.h" #include "drivers/hardware_specific/stm32/stm32_mcu.h"
float _readADCVoltageInline(const int pinA, const void* cs_params);
// float _readADCVoltageInline(const uint8_t pin, const void *cs_params);
float _readVoltageLowSide(const int pinA, const void *cs_params);
void *_configureADCInline(const void *driver_params, const int pinA, const int pinB, const int pinC);
void *_configureADCLowSide(const void *driver_params, const int pinA, const int pinB, const int pinC);
void _driverSyncLowSide(void *_driver_params, void *_cs_params);
#endif #endif
#endif #endif

View File

@@ -1,33 +1,33 @@
#include "pins_arduino.h" #include "pins_arduino.h"
/** /**
* @brief System Clock Configuration * @brief System Clock Configuration
* @retval None * @retval None
*/ */
void SystemClock_Config(void) void SystemClock_Config(void)
{ {
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
#ifdef USBCON
RCC_PeriphCLKInitTypeDef PeriphClkInit = {};
#endif
/** Configure the main internal regulator output voltage /** Configure the main internal regulator output voltage
*/ */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
/** Initializes the RCC Oscillators according to the specified parameters /** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure. * in the RCC_OscInitTypeDef structure.
*/ */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSE;
|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1; RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
RCC_OscInitStruct.PLL.PLLN = 28; RCC_OscInitStruct.PLL.PLLN = 85;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV8; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{ {
@@ -35,9 +35,8 @@ void SystemClock_Config(void)
} }
/** Initializes the CPU, AHB and APB buses clocks /** Initializes the CPU, AHB and APB buses clocks
*/ */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
@@ -47,4 +46,13 @@ void SystemClock_Config(void)
{ {
Error_Handler(); Error_Handler();
} }
#ifdef USBCON
/* Initializes the peripherals clocks */
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
Error_Handler();
}
#endif
} }

View File

@@ -3,8 +3,8 @@
#include <SPI.h> #include <SPI.h>
#include <SimpleFOC.h> #include <SimpleFOC.h>
#include <SimpleFOCDrivers.h> #include "SimpleFOCDrivers.h"
#include "encoders/MT6835/MagneticSensorMT6835.h" #include "encoders/mt6835/MagneticSensorMT6835.h"
#include "encoders/stm32hwencoder/STM32HWEncoder.h" #include "encoders/stm32hwencoder/STM32HWEncoder.h"
#include "stm32g4xx_hal_conf.h" #include "stm32g4xx_hal_conf.h"
@@ -13,6 +13,7 @@
#include "can.h" #include "can.h"
#include "dfu.h" #include "dfu.h"
#include "utils.h" #include "utils.h"
#include "InlineCurrentSenseSync.h"
#include "lemon-pepper.h" #include "lemon-pepper.h"
#define USBD_MANUFACTURER_STRING "matei repair lab" #define USBD_MANUFACTURER_STRING "matei repair lab"
@@ -35,8 +36,8 @@ uint8_t updateData = 0;
const uint16_t magicWord = 0xAF0C; const uint16_t magicWord = 0xAF0C;
// canbus things // canbus things
extern uint8_t TxData[8]; extern volatile uint8_t TxData[8];
extern uint8_t RxData[8]; extern volatile uint8_t RxData[8];
// simpleFOC things // simpleFOC things
#define POLEPAIRS 50 #define POLEPAIRS 50
@@ -44,6 +45,10 @@ extern uint8_t RxData[8];
#define MOTORKV 40 #define MOTORKV 40
#define ENC_PPR 16383 // max 16383 (zero index) -> *4 for CPR, -1 is done in init to prevent rollover on 16 bit timer #define ENC_PPR 16383 // max 16383 (zero index) -> *4 for CPR, -1 is done in init to prevent rollover on 16 bit timer
#define SERIALPORT Serial3
HardwareSerial Serial3 = HardwareSerial(PB8, PB9);
/** /**
* SPI clockdiv of 16 gives ~10.5MHz clock. May still be stable with lower divisor. * SPI clockdiv of 16 gives ~10.5MHz clock. May still be stable with lower divisor.
* The HW encoder is configured using PPR, which is then *4 for CPR (full 12384 gives overflow on 16 bit timer.) * The HW encoder is configured using PPR, which is then *4 for CPR (full 12384 gives overflow on 16 bit timer.)
@@ -53,40 +58,58 @@ MagneticSensorMT6835 sensor = MagneticSensorMT6835(ENC_CS, myMT6835SPISettings);
STM32HWEncoder enc = STM32HWEncoder(ENC_PPR, ENC_A, ENC_B, ENC_Z); STM32HWEncoder enc = STM32HWEncoder(ENC_PPR, ENC_A, ENC_B, ENC_Z);
/** /**
* The current sense amps have a gain of 90mA/V -> over 1.5A this is 135mA so we need gain of 24 to get full-scale. * TODO: Change the current sense code to reflect the new inline current sense amplifier choice with sense resistor.
* Actually we are limited to powers of 2 for gain. So it should be 16. This gives sensitivity of 1440mV/A. */
* */ // InlineCurrentSenseSync currentsense = InlineCurrentSenseSync(90, ISENSE_U, ISENSE_V, ISENSE_W);
InlineCurrentSense currentsense = InlineCurrentSense(1440, ISENSE_U, ISENSE_V, ISENSE_W);
StepperDriver4PWM driver = StepperDriver4PWM(MOT_A1, MOT_A2, MOT_B1, MOT_B2); StepperDriver4PWM driver = StepperDriver4PWM(MOT_A1, MOT_A2, MOT_B1, MOT_B2);
// StepperMotor motor = StepperMotor(POLEPAIRS, RPHASE, MOTORKV, 0.0045);
StepperMotor motor = StepperMotor(POLEPAIRS); StepperMotor motor = StepperMotor(POLEPAIRS);
Commander commander = Commander(SerialUSB); Commander commander = Commander(SERIALPORT);
uint16_t counter = 0; uint16_t counter = 0;
extern volatile uint16_t adc1Result[3];
extern volatile uint16_t adc2Result[2];
DQCurrent_s foc_currents;
float electrical_angle;
PhaseCurrent_s phase_currents;
// Prototypes // Prototypes
uint8_t configureFOC(void); uint8_t configureFOC(void);
uint8_t configureCAN(void); uint8_t configureCAN(void);
uint8_t calibrateEncoder(void); uint8_t calibrateEncoder(void);
void userButton(void);
void setup() void setup()
{ {
pinMode(LED_GOOD, OUTPUT); pinMode(LED_GOOD, OUTPUT);
pinMode(LED_FAULT, OUTPUT); pinMode(LED_FAULT, OUTPUT);
pinMode(CAL_EN, OUTPUT); pinMode(CAL_EN, OUTPUT);
pinMode(MOT_EN, OUTPUT); pinMode(MOT_EN, OUTPUT);
pinMode(USER_BUTTON, INPUT);
SerialUSB.begin(115200); attachInterrupt(USER_BUTTON, userButton, RISING);
SERIALPORT.begin(115200);
EEPROM.get(0, boardData); EEPROM.get(0, boardData);
digitalWrite(MOT_EN, HIGH); digitalWrite(MOT_EN, HIGH);
digitalWrite(CAL_EN, LOW); digitalWrite(CAL_EN, LOW);
if (!configureCAN()) uint8_t ret;
SIMPLEFOC_DEBUG("CAN init failed."); // ret = configureCAN();
if (!configureFOC()) // if (!ret){
// SIMPLEFOC_DEBUG("CAN init failed.");
// digitalWrite(LED_FAULT, HIGH);
// }
ret = configureFOC();
if (!ret){
SIMPLEFOC_DEBUG("FOC init failed."); SIMPLEFOC_DEBUG("FOC init failed.");
digitalWrite(LED_FAULT, HIGH);
}
if (sensor.getABZResolution() != ENC_PPR) // Check that PPR of the encoder matches our expectation. if (sensor.getABZResolution() != ENC_PPR) // Check that PPR of the encoder matches our expectation.
{ {
@@ -137,21 +160,16 @@ void loop()
motor.move(); motor.move();
commander.run(); commander.run();
if (counter == 0xFFF) electrical_angle = motor.electricalAngle();
{ // phase_currents = currentsense.getPhaseCurrents();
digitalToggle(LED_GOOD); // foc_currents = currentsense.getFOCCurrents(electrical_angle);
SerialUSB.print(sensor.getAngle());
SerialUSB.print("\t");
SerialUSB.print(enc.getAngle());
SerialUSB.print("\t");
SerialUSB.println(sensor.getABZResolution());
// SerialUSB.printf("%d\t%d\t%d\n", sensor.getAngle(), sensor.getABZResolution(), enc.getAngle()); if(counter == 0xFFF){
digitalToggle(LED_GOOD);
// Serial.println(adc1Result[0]);
counter = 0; counter = 0;
} }
counter++;
counter++;
#ifdef HAS_MONITOR #ifdef HAS_MONITOR
motor.monitor(); motor.monitor();
#endif #endif
@@ -168,7 +186,7 @@ uint8_t configureFOC(void)
commander.verbose = VerboseMode::machine_readable; commander.verbose = VerboseMode::machine_readable;
#ifdef SIMPLEFOC_STM32_DEBUG #ifdef SIMPLEFOC_STM32_DEBUG
SimpleFOCDebug::enable(&SerialUSB); SimpleFOCDebug::enable(&SERIALPORT);
#endif #endif
// Encoder initialization. // Encoder initialization.
@@ -207,15 +225,17 @@ uint8_t configureFOC(void)
driver.init(); driver.init();
// Motor PID parameters. // Motor PID parameters.
motor.PID_velocity.P = 5; motor.PID_velocity.P = 0.035;
motor.PID_velocity.I = 24; motor.PID_velocity.I = 0.01;
motor.PID_velocity.D = 0.01; motor.PID_velocity.D = 0.000;
motor.LPF_velocity.Tf = 0.004;
motor.PID_velocity.output_ramp = 750; motor.PID_velocity.output_ramp = 750;
motor.PID_velocity.limit = 500; motor.PID_velocity.limit = 500;
motor.LPF_velocity.Tf = 4;
motor.P_angle.P = 600; motor.P_angle.P = 350;
motor.P_angle.limit = 10000; motor.P_angle.I = 8;
motor.P_angle.D = 0.3;
motor.LPF_angle = 0.001;
motor.LPF_angle.Tf = 0; // try to avoid motor.LPF_angle.Tf = 0; // try to avoid
// Motor initialization. // Motor initialization.
@@ -227,7 +247,7 @@ uint8_t configureFOC(void)
// Monitor initialization // Monitor initialization
#ifdef HAS_MONITOR #ifdef HAS_MONITOR
motor.useMonitoring(SerialUSB); motor.useMonitoring(SERIALPORT);
motor.monitor_start_char = 'M'; motor.monitor_start_char = 'M';
motor.monitor_end_char = 'M'; motor.monitor_end_char = 'M';
motor.monitor_downsample = 250; motor.monitor_downsample = 250;
@@ -236,10 +256,10 @@ uint8_t configureFOC(void)
motor.linkSensor(&sensor); motor.linkSensor(&sensor);
motor.linkDriver(&driver); motor.linkDriver(&driver);
currentsense.linkDriver(&driver); // currentsense.linkDriver(&driver);
currentsense.init(); // int ret = currentsense.init();
// SERIALPORT.printf("Current Sense init result: %i\n", ret);
motor.linkCurrentSense(&currentsense); // motor.linkCurrentSense(&currentsense);
motor.target = 10; motor.target = 10;
@@ -283,13 +303,13 @@ uint8_t calibrateEncoder(void)
currentSettings.autocal_freq = 0x1; currentSettings.autocal_freq = 0x1;
sensor.setOptions4(currentSettings); sensor.setOptions4(currentSettings);
uint16_t calTime = micros(); uint32_t calTime = micros();
while (calTime - micros() < 2000000) while ((micros() - calTime) < 2000000)
{ {
motor.loopFOC(); motor.loopFOC();
motor.move(); motor.move();
if (calTime - micros() > 2000) if ((micros() -calTime) > 2000)
{ {
// after motor is spinning at constant speed, enable calibration. // after motor is spinning at constant speed, enable calibration.
digitalWrite(LED_GOOD, HIGH); digitalWrite(LED_GOOD, HIGH);
@@ -302,3 +322,9 @@ uint8_t calibrateEncoder(void)
return sensor.getCalibrationStatus(); return sensor.getCalibrationStatus();
} }
void userButton(void)
{
if(USB->DADDR != 0)
jump_to_bootloader();
}

View File

@@ -648,6 +648,10 @@
(stroke (width 0) (type default)) (stroke (width 0) (type default))
(uuid 729cc6be-8aa4-41f4-be98-ff91b8dfb517) (uuid 729cc6be-8aa4-41f4-be98-ff91b8dfb517)
) )
(wire (pts (xy 148.59 127) (xy 157.48 127))
(stroke (width 0) (type default))
(uuid 72c65ad4-7171-4f7e-9fdb-92b5a6e36ed1)
)
(wire (pts (xy 208.28 135.89) (xy 208.28 139.7)) (wire (pts (xy 208.28 135.89) (xy 208.28 139.7))
(stroke (width 0) (type default)) (stroke (width 0) (type default))
(uuid 76cc1c25-d03c-4186-9987-57e46edfc330) (uuid 76cc1c25-d03c-4186-9987-57e46edfc330)
@@ -792,6 +796,10 @@
(stroke (width 0) (type default)) (stroke (width 0) (type default))
(uuid fef7ec77-0cf9-49f6-9253-634118909a52) (uuid fef7ec77-0cf9-49f6-9253-634118909a52)
) )
(wire (pts (xy 148.59 91.44) (xy 157.48 91.44))
(stroke (width 0) (type default))
(uuid ff03524d-69d1-4f45-9362-ad5afe606fd8)
)
(text "join at power connector" (at 189.23 127 0) (text "join at power connector" (at 189.23 127 0)
(effects (font (size 1.27 1.27)) (justify left bottom)) (effects (font (size 1.27 1.27)) (justify left bottom))
@@ -841,6 +849,32 @@
(uuid f27d6576-8dc6-4b35-a6ee-606d878ff90e) (uuid f27d6576-8dc6-4b35-a6ee-606d878ff90e)
) )
(symbol (lib_id "Device:R_Small_US") (at 146.05 127 90) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(uuid 084a4821-5263-43df-98a8-7fb0f03d0a22)
(property "Reference" "R703" (at 146.05 120.65 90)
(effects (font (size 1.27 1.27)))
)
(property "Value" "20R" (at 146.05 123.19 90)
(effects (font (size 1.27 1.27)))
)
(property "Footprint" "Resistor_SMD:R_0402_1005Metric" (at 146.05 127 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "~" (at 146.05 127 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid d71cd166-4c52-45d6-aaa3-2fa89ff75908))
(pin "2" (uuid cd22acb1-7602-45f3-97fa-03db382a1c81))
(instances
(project "lemon-pepper"
(path "/0306e2fa-4433-4288-91d9-65a3484207ad/41d11f3b-333a-47c0-a126-1f991ee11e83"
(reference "R703") (unit 1)
)
)
)
)
(symbol (lib_id "power:PWR_FLAG") (at 193.04 135.89 90) (unit 1) (symbol (lib_id "power:PWR_FLAG") (at 193.04 135.89 90) (unit 1)
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced) (in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
(uuid 08d81450-96ad-4d2c-9c7a-dc9ecb10ad44) (uuid 08d81450-96ad-4d2c-9c7a-dc9ecb10ad44)

View File

@@ -3948,6 +3948,60 @@
) )
) )
(footprint "Resistor_SMD:R_0402_1005Metric" (layer "F.Cu")
(tstamp 95bca4c9-8b19-49ca-886b-ad8247c70844)
(at 151.75 80.575 180)
(descr "Resistor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator")
(tags "resistor")
(property "Sheetfile" "currentsense.kicad_sch")
(property "Sheetname" "current sense")
(property "ki_description" "Resistor, small US symbol")
(property "ki_keywords" "r resistor")
(path "/41d11f3b-333a-47c0-a126-1f991ee11e83/7ea0b72c-9d2c-4584-ae0c-f1c3223e17c3")
(attr smd)
(fp_text reference "R702" (at 0 -1.17) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 6247f1a6-0294-4105-931c-92275fb1acbf)
)
(fp_text value "5k" (at 0 1.17) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 642f1893-5ce5-413d-9338-36db9b299530)
)
(fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab")
(effects (font (size 0.26 0.26) (thickness 0.04)))
(tstamp f04b372a-aa46-4335-b283-077355704754)
)
(fp_line (start -0.153641 -0.38) (end 0.153641 -0.38)
(stroke (width 0.12) (type solid)) (layer "F.SilkS") (tstamp d44eb6de-0228-4a23-8700-80099de6f412))
(fp_line (start -0.153641 0.38) (end 0.153641 0.38)
(stroke (width 0.12) (type solid)) (layer "F.SilkS") (tstamp cd65f080-b41e-42da-841b-46c1e4551fa5))
(fp_line (start -0.93 -0.47) (end 0.93 -0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 62d252bc-0199-400c-962b-fd91f823379b))
(fp_line (start -0.93 0.47) (end -0.93 -0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 07b7d8eb-2037-47dd-9e90-c40d4ee11a72))
(fp_line (start 0.93 -0.47) (end 0.93 0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 46ab5a3a-88d6-4848-b791-26903365f95d))
(fp_line (start 0.93 0.47) (end -0.93 0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 51ec5b0d-5582-448c-96ef-8cb6e953e93f))
(fp_line (start -0.525 -0.27) (end 0.525 -0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp 5e28671b-da8e-4f5d-835c-b69ae7c8cfc9))
(fp_line (start -0.525 0.27) (end -0.525 -0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp cdc0b3d3-45f5-406e-845e-3a19569b81d8))
(fp_line (start 0.525 -0.27) (end 0.525 0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp b4aade76-17cd-4f85-b3f9-af5de67d2c96))
(fp_line (start 0.525 0.27) (end -0.525 0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp 8623440b-838d-4c09-a92e-da5c344f18e0))
(pad "1" smd roundrect (at -0.51 0 180) (size 0.54 0.64) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25)
(net 89 "Net-(U702-VIOUT)") (pintype "passive") (tstamp c18b3391-9d17-444a-a37c-f9b574b9b512))
(pad "2" smd roundrect (at 0.51 0 180) (size 0.54 0.64) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25)
(net 17 "/current sense/V_SENSE") (pintype "passive") (tstamp 2499fba1-b026-4fce-b16c-c335e0e017c2))
(model "${KICAD6_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0402_1005Metric.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(footprint "mechanical:NEMA14" locked (layer "F.Cu") (footprint "mechanical:NEMA14" locked (layer "F.Cu")
(tstamp 95c5292d-b574-4ab1-ba30-310faa18e02f) (tstamp 95c5292d-b574-4ab1-ba30-310faa18e02f)
(at 146.3 86.975) (at 146.3 86.975)
@@ -6024,6 +6078,60 @@
) )
) )
(footprint "Resistor_SMD:R_0402_1005Metric" (layer "F.Cu")
(tstamp e69ae357-baf4-4ca2-a29c-a3d90a58930b)
(at 141.625 80.575 180)
(descr "Resistor SMD 0402 (1005 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator")
(tags "resistor")
(property "Sheetfile" "currentsense.kicad_sch")
(property "Sheetname" "current sense")
(property "ki_description" "Resistor, small US symbol")
(property "ki_keywords" "r resistor")
(path "/41d11f3b-333a-47c0-a126-1f991ee11e83/54a1fb90-bae5-4dd5-8295-b6d0f7fa3ae2")
(attr smd)
(fp_text reference "R701" (at 0 -1.17) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 84555ffc-f97f-4e2f-8445-c17efa744be1)
)
(fp_text value "5k" (at 0 1.17) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp a9d736e7-0902-4bf8-88ca-1e3cd6add12d)
)
(fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab")
(effects (font (size 0.26 0.26) (thickness 0.04)))
(tstamp 15d2c22e-0045-4429-9b25-506eb887bde5)
)
(fp_line (start -0.153641 -0.38) (end 0.153641 -0.38)
(stroke (width 0.12) (type solid)) (layer "F.SilkS") (tstamp 5a66ac82-6db9-43ca-b684-c72e5afc7def))
(fp_line (start -0.153641 0.38) (end 0.153641 0.38)
(stroke (width 0.12) (type solid)) (layer "F.SilkS") (tstamp acfb1a97-46ed-4da5-8d73-c3ecafb9650c))
(fp_line (start -0.93 -0.47) (end 0.93 -0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 7ce96ed2-9552-4191-89d8-2e72893cbd45))
(fp_line (start -0.93 0.47) (end -0.93 -0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 7fa0c713-2d68-4d7d-8c76-f3f09fcd26ef))
(fp_line (start 0.93 -0.47) (end 0.93 0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp de148a6d-f502-41c2-aa7c-a7abefca156b))
(fp_line (start 0.93 0.47) (end -0.93 0.47)
(stroke (width 0.05) (type solid)) (layer "F.CrtYd") (tstamp 8ab22f38-253d-42a6-a5e7-a298bc69cd2a))
(fp_line (start -0.525 -0.27) (end 0.525 -0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp bf5fe7db-4045-4d45-bfb3-8e8251d79bdc))
(fp_line (start -0.525 0.27) (end -0.525 -0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp 5f3f064d-940f-4e87-b3cc-ad14fae28ed3))
(fp_line (start 0.525 -0.27) (end 0.525 0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp 092d6890-db08-4c9f-9651-658bb81d65ba))
(fp_line (start 0.525 0.27) (end -0.525 0.27)
(stroke (width 0.1) (type solid)) (layer "F.Fab") (tstamp 50bbe285-0061-4deb-880b-6572d06e334a))
(pad "1" smd roundrect (at -0.51 0 180) (size 0.54 0.64) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25)
(net 88 "Net-(U701-VIOUT)") (pintype "passive") (tstamp 4aa895f7-e80a-4a4e-b224-5d13b7e92f23))
(pad "2" smd roundrect (at 0.51 0 180) (size 0.54 0.64) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25)
(net 16 "/current sense/U_SENSE") (pintype "passive") (tstamp fd1d151d-85f9-42b9-b634-e3adabe80824))
(model "${KICAD6_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0402_1005Metric.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(footprint "Resistor_SMD:R_0402_1005Metric" (layer "F.Cu") (footprint "Resistor_SMD:R_0402_1005Metric" (layer "F.Cu")
(tstamp eff89581-ca64-4897-b991-183a6047b0b7) (tstamp eff89581-ca64-4897-b991-183a6047b0b7)
(at 149.625 91.75) (at 149.625 91.75)
@@ -7418,11 +7526,13 @@
(segment (start 155.91038 94.385) (end 156.395 94.385) (width 0.25) (layer "F.Cu") (net 1) (tstamp e2bd038f-6de5-487d-950e-026bc6461a01)) (segment (start 155.91038 94.385) (end 156.395 94.385) (width 0.25) (layer "F.Cu") (net 1) (tstamp e2bd038f-6de5-487d-950e-026bc6461a01))
(segment (start 136.575 76.395) (end 136.61 76.395) (width 0.25) (layer "F.Cu") (net 1) (tstamp e43385e3-da36-4f95-be0c-a8a3ae4b8711)) (segment (start 136.575 76.395) (end 136.61 76.395) (width 0.25) (layer "F.Cu") (net 1) (tstamp e43385e3-da36-4f95-be0c-a8a3ae4b8711))
(segment (start 141.25 103.75) (end 140.44283 102.94283) (width 0.25) (layer "F.Cu") (net 1) (tstamp e4454056-1b5c-4fe8-8d26-a1180a03800a)) (segment (start 141.25 103.75) (end 140.44283 102.94283) (width 0.25) (layer "F.Cu") (net 1) (tstamp e4454056-1b5c-4fe8-8d26-a1180a03800a))
(segment (start 146.625 83.64038) (end 147.095 83.17038) (width 0.25) (layer "F.Cu") (net 1) (tstamp e4719c62-c6da-41ca-9408-7e6930f33b77))
(segment (start 152.472649 82.344096) (end 153.3 83.171447) (width 0.25) (layer "F.Cu") (net 1) (tstamp e4a9dff8-4710-4c5e-8b26-a683cf6f4897)) (segment (start 152.472649 82.344096) (end 153.3 83.171447) (width 0.25) (layer "F.Cu") (net 1) (tstamp e4a9dff8-4710-4c5e-8b26-a683cf6f4897))
(segment (start 155.425 84.225) (end 154 84.225) (width 0.25) (layer "F.Cu") (net 1) (tstamp e64208e8-a8cb-4e94-a5b2-dbf8b34295c6)) (segment (start 155.425 84.225) (end 154 84.225) (width 0.25) (layer "F.Cu") (net 1) (tstamp e64208e8-a8cb-4e94-a5b2-dbf8b34295c6))
(segment (start 147.775 93.1) (end 149.31 93.1) (width 0.25) (layer "F.Cu") (net 1) (tstamp e70c6643-48cc-4c3a-9c9c-8aaa2ae8253b)) (segment (start 147.775 93.1) (end 149.31 93.1) (width 0.25) (layer "F.Cu") (net 1) (tstamp e70c6643-48cc-4c3a-9c9c-8aaa2ae8253b))
(segment (start 142.0605 86.925) (end 142.05 86.9145) (width 0.25) (layer "F.Cu") (net 1) (tstamp e75bdc4e-838b-402f-905a-e2f2c94b3d38)) (segment (start 142.0605 86.925) (end 142.05 86.9145) (width 0.25) (layer "F.Cu") (net 1) (tstamp e75bdc4e-838b-402f-905a-e2f2c94b3d38))
(segment (start 154.59 97.295) (end 154.59 97.39) (width 0.25) (layer "F.Cu") (net 1) (tstamp e8dbc1e0-802e-494b-8b9b-105e03bf313d)) (segment (start 154.59 97.295) (end 154.59 97.39) (width 0.25) (layer "F.Cu") (net 1) (tstamp e8dbc1e0-802e-494b-8b9b-105e03bf313d))
(segment (start 146.625 84.2) (end 146.625 83.64038) (width 0.25) (layer "F.Cu") (net 1) (tstamp e93d71b6-80da-43c4-8d73-ca538df56daf))
(segment (start 138.76 91.84) (end 138.76 91.04) (width 0.25) (layer "F.Cu") (net 1) (tstamp e9d2e006-b8c3-44df-827c-6e0e3dedaa32)) (segment (start 138.76 91.84) (end 138.76 91.04) (width 0.25) (layer "F.Cu") (net 1) (tstamp e9d2e006-b8c3-44df-827c-6e0e3dedaa32))
(segment (start 147.275 83.43) (end 147.275 84.2) (width 0.25) (layer "F.Cu") (net 1) (tstamp ea4475b3-0d49-4cfa-82fc-cfa5a51cd07a)) (segment (start 147.275 83.43) (end 147.275 84.2) (width 0.25) (layer "F.Cu") (net 1) (tstamp ea4475b3-0d49-4cfa-82fc-cfa5a51cd07a))
(segment (start 136.388533 93.008293) (end 136.883507 93.008293) (width 0.25) (layer "F.Cu") (net 1) (tstamp eb4cc686-22a8-4de1-af9f-411e18b7abe3)) (segment (start 136.388533 93.008293) (end 136.883507 93.008293) (width 0.25) (layer "F.Cu") (net 1) (tstamp eb4cc686-22a8-4de1-af9f-411e18b7abe3))

View File

@@ -1,6 +1,6 @@
{ {
"board": { "board": {
"active_layer": 2, "active_layer": 0,
"active_layer_preset": "", "active_layer_preset": "",
"auto_track_width": true, "auto_track_width": true,
"hidden_netclasses": [], "hidden_netclasses": [],

View File

@@ -10,7 +10,6 @@
[platformio] [platformio]
default_envs = lemon-pepper default_envs = lemon-pepper
boards_dir = firmware/boards
src_dir = firmware/src src_dir = firmware/src
lib_dir = firmware/lib lib_dir = firmware/lib
include_dir = firmware/include include_dir = firmware/include
@@ -19,7 +18,7 @@ test_dir = firmware/test
[env:lemon-pepper] [env:lemon-pepper]
platform = ststm32 platform = ststm32
board = genericSTM32G431CB board = genericSTM32G431CB
board_build.f_cpu = 168000000 ; board_build.f_cpu = 170000000
framework = arduino framework = arduino
upload_protocol = stlink upload_protocol = stlink
debug_tool = stlink debug_tool = stlink
@@ -34,10 +33,12 @@ build_flags =
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-D HAL_FDCAN_MODULE_ENABLED -D HAL_FDCAN_MODULE_ENABLED
-D HAL_OPAMP_MODULE_ENABLED -D HAL_OPAMP_MODULE_ENABLED
-D HSE_VALUE=12000000U
-D FDCAN_ALT1 -D FDCAN_ALT1
-D SN65HVD23x -D SN65HVD23x
-D ARDUINO_GENERIC_G431CBUX -D ARDUINO_GENERIC_G431CBUX
-D SIMPLEFOC_STM32_CUSTOMCURRENTSENSE -D SIMPLEFOC_STM32_CUSTOMCURRENTSENSE
-D LEMONPEPPER
; -D PCB_REV1 ; or PCB_REV2 ; -D PCB_REV1 ; or PCB_REV2
; -D HAS_MONITOR ; -D HAS_MONITOR