Extract slow adc (#2402)
* extract * guard * put some back * put back * slow is actually 500hz so slow is fine here * no magic * fix printFullAdcReport * cast * if we turn those off is it happy * stub cypress/kinetis * guard fast stuff better * bad merge Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
19983ee314
commit
f22f318bdb
|
@ -38,7 +38,7 @@
|
||||||
#include "perf_trace.h"
|
#include "perf_trace.h"
|
||||||
#include "thread_priority.h"
|
#include "thread_priority.h"
|
||||||
|
|
||||||
static NO_CACHE adcsample_t slowAdcSampleBuf[ADC_BUF_DEPTH_SLOW * ADC_MAX_CHANNELS_COUNT];
|
static adcsample_t slowAdcSamples[ADC_MAX_CHANNELS_COUNT];
|
||||||
static NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST * ADC_MAX_CHANNELS_COUNT];
|
static NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST * ADC_MAX_CHANNELS_COUNT];
|
||||||
|
|
||||||
static adc_channel_mode_e adcHwChannelEnabled[HW_MAX_ADC_INDEX];
|
static adc_channel_mode_e adcHwChannelEnabled[HW_MAX_ADC_INDEX];
|
||||||
|
@ -55,6 +55,7 @@ float getVoltage(const char *msg, adc_channel_e hwChannel DECLARE_ENGINE_PARAMET
|
||||||
return adcToVolts(getAdcValue(msg, hwChannel));
|
return adcToVolts(getAdcValue(msg, hwChannel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EFI_USE_FAST_ADC
|
||||||
AdcDevice::AdcDevice(ADCConversionGroup* hwConfig, adcsample_t *buf, size_t buf_len) {
|
AdcDevice::AdcDevice(ADCConversionGroup* hwConfig, adcsample_t *buf, size_t buf_len) {
|
||||||
this->hwConfig = hwConfig;
|
this->hwConfig = hwConfig;
|
||||||
this->samples = buf;
|
this->samples = buf;
|
||||||
|
@ -82,17 +83,14 @@ AdcDevice::AdcDevice(ADCConversionGroup* hwConfig, adcsample_t *buf, size_t buf_
|
||||||
#define GPT_PERIOD_FAST 10 /* PWM period (in PWM ticks). */
|
#define GPT_PERIOD_FAST 10 /* PWM period (in PWM ticks). */
|
||||||
#endif /* GPT_FREQ_FAST GPT_PERIOD_FAST */
|
#endif /* GPT_FREQ_FAST GPT_PERIOD_FAST */
|
||||||
|
|
||||||
// is there a reason to have this configurable at runtime?
|
#endif // EFI_USE_FAST_ADC
|
||||||
#ifndef ADC_SLOW_DEVICE
|
|
||||||
#define ADC_SLOW_DEVICE ADCD1
|
|
||||||
#endif /* ADC_SLOW_DEVICE */
|
|
||||||
|
|
||||||
// is there a reason to have this configurable at runtime?
|
// is there a reason to have this configurable at runtime?
|
||||||
#ifndef ADC_FAST_DEVICE
|
#ifndef ADC_FAST_DEVICE
|
||||||
#define ADC_FAST_DEVICE ADCD2
|
#define ADC_FAST_DEVICE ADCD2
|
||||||
#endif /* ADC_FAST_DEVICE */
|
#endif /* ADC_FAST_DEVICE */
|
||||||
|
|
||||||
static volatile int slowAdcCounter = 0;
|
static uint32_t slowAdcCounter = 0;
|
||||||
static LoggingWithStorage logger("ADC");
|
static LoggingWithStorage logger("ADC");
|
||||||
|
|
||||||
// todo: move this flag to Engine god object
|
// todo: move this flag to Engine god object
|
||||||
|
@ -115,57 +113,6 @@ static adcsample_t getAvgAdcValue(int index, adcsample_t *samples, int bufDepth,
|
||||||
// See https://github.com/rusefi/rusefi/issues/976 for discussion on these values
|
// See https://github.com/rusefi/rusefi/issues/976 for discussion on these values
|
||||||
#define ADC_SAMPLING_SLOW ADC_SAMPLE_56
|
#define ADC_SAMPLING_SLOW ADC_SAMPLE_56
|
||||||
#define ADC_SAMPLING_FAST ADC_SAMPLE_28
|
#define ADC_SAMPLING_FAST ADC_SAMPLE_28
|
||||||
/*
|
|
||||||
* ADC conversion group.
|
|
||||||
*/
|
|
||||||
static ADCConversionGroup adcgrpcfgSlow = {
|
|
||||||
.circular = FALSE,
|
|
||||||
.num_channels = 0,
|
|
||||||
.end_cb = nullptr,
|
|
||||||
.error_cb = nullptr,
|
|
||||||
/* HW dependent part.*/
|
|
||||||
.cr1 = 0,
|
|
||||||
.cr2 = ADC_CR2_SWSTART,
|
|
||||||
/**
|
|
||||||
* here we configure all possible channels for slow mode. Some channels would not actually
|
|
||||||
* be used hopefully that's fine to configure all possible channels.
|
|
||||||
*/
|
|
||||||
// sample times for channels 10...18
|
|
||||||
.smpr1 =
|
|
||||||
ADC_SMPR1_SMP_AN10(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR1_SMP_AN11(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR1_SMP_AN12(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR1_SMP_AN13(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR1_SMP_AN14(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR1_SMP_AN15(ADC_SAMPLING_SLOW) |
|
|
||||||
#if defined(STM32F7XX)
|
|
||||||
ADC_SMPR1_SMP_VBAT(ADC_SAMPLE_144) | /* input18 - temperature and vbat input on some STM32F7xx */
|
|
||||||
#endif
|
|
||||||
ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_144), /* input16 - temperature sensor input on STM32F4xx */
|
|
||||||
// In this field must be specified the sample times for channels 0...9
|
|
||||||
.smpr2 =
|
|
||||||
ADC_SMPR2_SMP_AN0(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN1(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN2(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN3(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN4(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN5(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN6(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN7(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN8(ADC_SAMPLING_SLOW) |
|
|
||||||
ADC_SMPR2_SMP_AN9(ADC_SAMPLING_SLOW),
|
|
||||||
.htr = 0,
|
|
||||||
.ltr = 0,
|
|
||||||
.sqr1 = 0, // Conversion group sequence 13...16 + sequence length
|
|
||||||
.sqr2 = 0, // Conversion group sequence 7...12
|
|
||||||
.sqr3 = 0, // Conversion group sequence 1...6
|
|
||||||
#if ADC_MAX_CHANNELS_COUNT > 16
|
|
||||||
.sqr4 = 0, // Conversion group sequence 19...24
|
|
||||||
.sqr5 = 0 // Conversion group sequence 25...30
|
|
||||||
#endif /* ADC_MAX_CHANNELS_COUNT */
|
|
||||||
};
|
|
||||||
|
|
||||||
AdcDevice slowAdc(&adcgrpcfgSlow, slowAdcSampleBuf, ARRAY_SIZE(slowAdcSampleBuf));
|
|
||||||
|
|
||||||
#if EFI_USE_FAST_ADC
|
#if EFI_USE_FAST_ADC
|
||||||
void adc_callback_fast(ADCDriver *adcp);
|
void adc_callback_fast(ADCDriver *adcp);
|
||||||
|
@ -271,11 +218,11 @@ int getInternalAdcValue(const char *msg, adc_channel_e hwChannel) {
|
||||||
#endif // EFI_USE_FAST_ADC
|
#endif // EFI_USE_FAST_ADC
|
||||||
|
|
||||||
if (adcHwChannelEnabled[hwChannel] != ADC_SLOW) {
|
if (adcHwChannelEnabled[hwChannel] != ADC_SLOW) {
|
||||||
// todo: make this not happen during hardware continuous integration
|
// todo: make this not happen during hardware continuous integration
|
||||||
warning(CUSTOM_OBD_WRONG_ADC_MODE, "ADC is off [%s] index=%d", msg, hwChannel);
|
warning(CUSTOM_OBD_WRONG_ADC_MODE, "ADC is off [%s] index=%d", msg, hwChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
return slowAdc.getAdcValueByHwChannel(hwChannel);
|
return slowAdcSamples[hwChannel - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EFI_USE_FAST_ADC
|
#if EFI_USE_FAST_ADC
|
||||||
|
@ -287,10 +234,6 @@ static GPTConfig fast_adc_config = {
|
||||||
#endif /* EFI_USE_FAST_ADC */
|
#endif /* EFI_USE_FAST_ADC */
|
||||||
|
|
||||||
adc_channel_mode_e getAdcMode(adc_channel_e hwChannel) {
|
adc_channel_mode_e getAdcMode(adc_channel_e hwChannel) {
|
||||||
if (slowAdc.isHwUsed(hwChannel)) {
|
|
||||||
return ADC_SLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if EFI_USE_FAST_ADC
|
#if EFI_USE_FAST_ADC
|
||||||
if (fastAdc.isHwUsed(hwChannel)) {
|
if (fastAdc.isHwUsed(hwChannel)) {
|
||||||
return ADC_FAST;
|
return ADC_FAST;
|
||||||
|
@ -300,6 +243,8 @@ adc_channel_mode_e getAdcMode(adc_channel_e hwChannel) {
|
||||||
return ADC_OFF;
|
return ADC_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EFI_USE_FAST_ADC
|
||||||
|
|
||||||
int AdcDevice::size() const {
|
int AdcDevice::size() const {
|
||||||
return channelCount;
|
return channelCount;
|
||||||
}
|
}
|
||||||
|
@ -364,19 +309,25 @@ void AdcDevice::enableChannelAndPin(const char *msg, adc_channel_e hwChannel) {
|
||||||
efiSetPadMode(msg, pin, PAL_MODE_INPUT_ANALOG);
|
efiSetPadMode(msg, pin, PAL_MODE_INPUT_ANALOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adc_channel_e AdcDevice::getAdcHardwareIndexByInternalIndex(int index) const {
|
||||||
|
return hardwareIndexByIndernalAdcIndex[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EFI_USE_FAST_ADC
|
||||||
|
|
||||||
static void printAdcValue(int channel) {
|
static void printAdcValue(int channel) {
|
||||||
int value = getAdcValue("print", (adc_channel_e)channel);
|
int value = getAdcValue("print", (adc_channel_e)channel);
|
||||||
float volts = adcToVoltsDivided(value);
|
float volts = adcToVoltsDivided(value);
|
||||||
scheduleMsg(&logger, "adc voltage : %.2f", volts);
|
scheduleMsg(&logger, "adc voltage : %.2f", volts);
|
||||||
}
|
}
|
||||||
|
|
||||||
adc_channel_e AdcDevice::getAdcHardwareIndexByInternalIndex(int index) const {
|
|
||||||
return hardwareIndexByIndernalAdcIndex[index];
|
static uint32_t slowAdcConversionCount = 0;
|
||||||
}
|
static uint32_t slowAdcErrorsCount = 0;
|
||||||
|
|
||||||
static void printFullAdcReport(Logging *logger) {
|
static void printFullAdcReport(Logging *logger) {
|
||||||
#if EFI_USE_FAST_ADC
|
#if EFI_USE_FAST_ADC
|
||||||
scheduleMsg(logger, "fast %d slow %d", fastAdc.conversionCount, slowAdc.conversionCount);
|
scheduleMsg(logger, "fast %d slow %d", fastAdc.conversionCount, slowAdcConversionCount);
|
||||||
|
|
||||||
for (int index = 0; index < fastAdc.size(); index++) {
|
for (int index = 0; index < fastAdc.size(); index++) {
|
||||||
appendMsgPrefix(logger);
|
appendMsgPrefix(logger);
|
||||||
|
@ -399,16 +350,16 @@ static void printFullAdcReport(Logging *logger) {
|
||||||
}
|
}
|
||||||
#endif // EFI_USE_FAST_ADC
|
#endif // EFI_USE_FAST_ADC
|
||||||
|
|
||||||
for (int index = 0; index < slowAdc.size(); index++) {
|
for (int index = 0; index < ADC_MAX_CHANNELS_COUNT; index++) {
|
||||||
appendMsgPrefix(logger);
|
appendMsgPrefix(logger);
|
||||||
|
|
||||||
adc_channel_e hwIndex = slowAdc.getAdcHardwareIndexByInternalIndex(index);
|
adc_channel_e hwIndex = static_cast<adc_channel_e>(index + EFI_ADC_0);
|
||||||
|
|
||||||
if (isAdcChannelValid(hwIndex)) {
|
if (isAdcChannelValid(hwIndex)) {
|
||||||
ioportid_t port = getAdcChannelPort("print", hwIndex);
|
ioportid_t port = getAdcChannelPort("print", hwIndex);
|
||||||
int pin = getAdcChannelPin(hwIndex);
|
int pin = getAdcChannelPin(hwIndex);
|
||||||
|
|
||||||
int adcValue = slowAdc.getAdcValueByIndex(index);
|
int adcValue = slowAdcSamples[index];
|
||||||
logger->appendPrintf(" S ch%d %s%d", index, portname(port), pin);
|
logger->appendPrintf(" S ch%d %s%d", index, portname(port), pin);
|
||||||
logger->appendPrintf(" ADC%d 12bit=%d", hwIndex, adcValue);
|
logger->appendPrintf(" ADC%d 12bit=%d", hwIndex, adcValue);
|
||||||
float volts = adcToVolts(adcValue);
|
float volts = adcToVolts(adcValue);
|
||||||
|
@ -426,10 +377,6 @@ static void setAdcDebugReporting(int value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForSlowAdc(int lastAdcCounter) {
|
void waitForSlowAdc(int lastAdcCounter) {
|
||||||
// don't halt the firmware if there are no slow channels assigned
|
|
||||||
if (slowAdc.size() < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// we use slowAdcCounter instead of slowAdc.conversionCount because we need ADC_COMPLETE state
|
// we use slowAdcCounter instead of slowAdc.conversionCount because we need ADC_COMPLETE state
|
||||||
// todo: use sync.objects?
|
// todo: use sync.objects?
|
||||||
while (slowAdcCounter <= lastAdcCounter) {
|
while (slowAdcCounter <= lastAdcCounter) {
|
||||||
|
@ -453,12 +400,9 @@ public:
|
||||||
{
|
{
|
||||||
ScopePerf perf(PE::AdcConversionSlow);
|
ScopePerf perf(PE::AdcConversionSlow);
|
||||||
|
|
||||||
slowAdc.conversionCount++;
|
slowAdcConversionCount++;
|
||||||
msg_t result = adcConvert(&ADC_SLOW_DEVICE, &adcgrpcfgSlow, slowAdc.samples, ADC_BUF_DEPTH_SLOW);
|
if (!readSlowAnalogInputs(slowAdcSamples)) {
|
||||||
|
slowAdcErrorsCount++;
|
||||||
// If something went wrong - try again later
|
|
||||||
if (result == MSG_RESET || result == MSG_TIMEOUT) {
|
|
||||||
slowAdc.errorsCount++;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,15 +418,6 @@ public:
|
||||||
{
|
{
|
||||||
ScopePerf perf(PE::AdcProcessSlow);
|
ScopePerf perf(PE::AdcProcessSlow);
|
||||||
|
|
||||||
/* Calculates the average values from the ADC samples.*/
|
|
||||||
for (int i = 0; i < slowAdc.size(); i++) {
|
|
||||||
adcsample_t value = getAvgAdcValue(i, slowAdc.samples, ADC_BUF_DEPTH_SLOW, slowAdc.size());
|
|
||||||
adcsample_t prev = slowAdc.values.adc_data[i];
|
|
||||||
float result = (slowAdcCounter == 0) ? value :
|
|
||||||
CONFIG(slowAdcAlpha) * value + (1 - CONFIG(slowAdcAlpha)) * prev;
|
|
||||||
|
|
||||||
slowAdc.values.adc_data[i] = (adcsample_t)result;
|
|
||||||
}
|
|
||||||
slowAdcCounter++;
|
slowAdcCounter++;
|
||||||
|
|
||||||
AdcSubscription::UpdateSubscribers(nowNt);
|
AdcSubscription::UpdateSubscribers(nowNt);
|
||||||
|
@ -501,15 +436,16 @@ void addChannel(const char *name, adc_channel_e setting, adc_channel_mode_e mode
|
||||||
|
|
||||||
adcHwChannelEnabled[setting] = mode;
|
adcHwChannelEnabled[setting] = mode;
|
||||||
|
|
||||||
AdcDevice* dev = &slowAdc;
|
|
||||||
|
|
||||||
#if EFI_USE_FAST_ADC
|
#if EFI_USE_FAST_ADC
|
||||||
if (mode == ADC_FAST) {
|
if (mode == ADC_FAST) {
|
||||||
dev = &fastAdc;
|
fastAdc.enableChannelAndPin(name, setting);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dev->enableChannelAndPin(name, setting);
|
// Slow ADC always samples all channels, simply set the input mode
|
||||||
|
brain_pin_e pin = getAdcChannelBrainPin(name, setting);
|
||||||
|
efiSetPadMode(name, pin, PAL_MODE_INPUT_ANALOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeChannel(const char *name, adc_channel_e setting) {
|
void removeChannel(const char *name, adc_channel_e setting) {
|
||||||
|
@ -533,7 +469,7 @@ static void configureInputs(void) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
addChannel("MAP", engineConfiguration->map.sensor.hwChannel, ADC_FAST);
|
addChannel("MAP", engineConfiguration->map.sensor.hwChannel, ADC_FAST);
|
||||||
addChannel("MAF", engineConfiguration->mafAdcChannel, ADC_FAST);
|
addChannel("MAF", engineConfiguration->mafAdcChannel, ADC_SLOW);
|
||||||
|
|
||||||
addChannel("HIP9011", engineConfiguration->hipOutputChannel, ADC_FAST);
|
addChannel("HIP9011", engineConfiguration->hipOutputChannel, ADC_FAST);
|
||||||
|
|
||||||
|
@ -595,8 +531,6 @@ void initAdcInputs() {
|
||||||
#if EFI_INTERNAL_ADC
|
#if EFI_INTERNAL_ADC
|
||||||
portInitAdc();
|
portInitAdc();
|
||||||
|
|
||||||
slowAdc.init();
|
|
||||||
|
|
||||||
// Start the slow ADC thread
|
// Start the slow ADC thread
|
||||||
slowAdcController.Start();
|
slowAdcController.Start();
|
||||||
|
|
||||||
|
|
|
@ -270,4 +270,9 @@ float getMcuTemperature() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
|
||||||
|
// TODO: implement me!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* EFI_PROD_CODE */
|
#endif /* EFI_PROD_CODE */
|
||||||
|
|
|
@ -275,4 +275,9 @@ float getMcuTemperature() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
|
||||||
|
// TODO: implement me!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* EFI_PROD_CODE */
|
#endif /* EFI_PROD_CODE */
|
||||||
|
|
|
@ -11,9 +11,12 @@ void baseMCUInit(void);
|
||||||
void jump_to_bootloader();
|
void jump_to_bootloader();
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
|
#if HAL_USE_ADC
|
||||||
void portInitAdc();
|
void portInitAdc();
|
||||||
float getMcuTemperature();
|
float getMcuTemperature();
|
||||||
|
// Convert all slow ADC inputs. Returns true if the conversion succeeded, false if a failure occured.
|
||||||
|
bool readSlowAnalogInputs(adcsample_t* convertedSamples);
|
||||||
|
#endif
|
||||||
|
|
||||||
// CAN bus
|
// CAN bus
|
||||||
#if HAL_USE_CAN
|
#if HAL_USE_CAN
|
||||||
|
|
|
@ -13,6 +13,11 @@
|
||||||
|
|
||||||
EXTERN_CONFIG;
|
EXTERN_CONFIG;
|
||||||
|
|
||||||
|
/* Depth of the conversion buffer, channels are sampled X times each.*/
|
||||||
|
#ifndef ADC_BUF_DEPTH_SLOW
|
||||||
|
#define ADC_BUF_DEPTH_SLOW 8
|
||||||
|
#endif /* ADC_BUF_DEPTH_SLOW */
|
||||||
|
|
||||||
void portInitAdc() {
|
void portInitAdc() {
|
||||||
// Init slow ADC
|
// Init slow ADC
|
||||||
adcStart(&ADCD1, NULL);
|
adcStart(&ADCD1, NULL);
|
||||||
|
@ -101,4 +106,74 @@ float getMcuTemperature() {
|
||||||
return degrees;
|
return degrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://github.com/rusefi/rusefi/issues/976 for discussion on these values
|
||||||
|
#define ADC_SAMPLING_SLOW ADC_SAMPLE_56
|
||||||
|
#define ADC_SAMPLING_FAST ADC_SAMPLE_28
|
||||||
|
|
||||||
|
// Slow ADC has 16 channels we can sample
|
||||||
|
constexpr size_t slowChannelCount = 16;
|
||||||
|
|
||||||
|
// Conversion group for slow channels
|
||||||
|
// This simply samples every channel in sequence
|
||||||
|
static constexpr ADCConversionGroup convGroupSlow = {
|
||||||
|
.circular = FALSE,
|
||||||
|
.num_channels = slowChannelCount,
|
||||||
|
.end_cb = nullptr,
|
||||||
|
.error_cb = nullptr,
|
||||||
|
/* HW dependent part.*/
|
||||||
|
.cr1 = 0,
|
||||||
|
.cr2 = ADC_CR2_SWSTART,
|
||||||
|
// Configure all channels to ADC_SAMPLING_SLOW sample time
|
||||||
|
.smpr1 =
|
||||||
|
ADC_SMPR1_SMP_AN10(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR1_SMP_AN11(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR1_SMP_AN12(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR1_SMP_AN13(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR1_SMP_AN14(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR1_SMP_AN15(ADC_SAMPLING_SLOW),
|
||||||
|
.smpr2 =
|
||||||
|
ADC_SMPR2_SMP_AN0(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN1(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN2(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN3(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN4(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN5(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN6(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN7(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN8(ADC_SAMPLING_SLOW) |
|
||||||
|
ADC_SMPR2_SMP_AN9(ADC_SAMPLING_SLOW),
|
||||||
|
.htr = 0,
|
||||||
|
.ltr = 0,
|
||||||
|
// Simply sequence every channel in order
|
||||||
|
.sqr1 = ADC_SQR1_SQ13_N(12) | ADC_SQR1_SQ14_N(13) | ADC_SQR1_SQ15_N(14) | ADC_SQR1_SQ16_N(15) | ADC_SQR1_NUM_CH(16), // Conversion group sequence 13...16 + sequence length
|
||||||
|
.sqr2 = ADC_SQR2_SQ7_N(6) | ADC_SQR2_SQ8_N(7) | ADC_SQR2_SQ9_N(8) | ADC_SQR2_SQ10_N(8) | ADC_SQR2_SQ11_N(10) | ADC_SQR2_SQ12_N(11), // Conversion group sequence 7...12
|
||||||
|
.sqr3 = ADC_SQR3_SQ1_N(0) | ADC_SQR3_SQ2_N(1) | ADC_SQR3_SQ3_N(2) | ADC_SQR3_SQ4_N(3) | ADC_SQR3_SQ5_N(4) | ADC_SQR3_SQ6_N(5), // Conversion group sequence 1...6
|
||||||
|
};
|
||||||
|
|
||||||
|
static NO_CACHE adcsample_t slowSampleBuffer[ADC_BUF_DEPTH_SLOW * slowChannelCount];
|
||||||
|
|
||||||
|
bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
|
||||||
|
msg_t result = adcConvert(&ADCD1, &convGroupSlow, slowSampleBuffer, ADC_BUF_DEPTH_SLOW);
|
||||||
|
|
||||||
|
// If something went wrong - try again later
|
||||||
|
if (result == MSG_RESET || result == MSG_TIMEOUT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Average samples to get some noise filtering and oversampling
|
||||||
|
for (int i = 0; i < slowChannelCount; i++) {
|
||||||
|
uint32_t sum = 0;
|
||||||
|
size_t index = i;
|
||||||
|
for (size_t j = 0; j < ADC_BUF_DEPTH_SLOW; j++) {
|
||||||
|
sum += slowSampleBuffer[index];
|
||||||
|
index += slowChannelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
adcsample_t value = static_cast<adcsample_t>(sum / ADC_BUF_DEPTH_SLOW);
|
||||||
|
convertedSamples[i] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAL_USE_ADC
|
#endif // HAL_USE_ADC
|
||||||
|
|
Loading…
Reference in New Issue