mirror of https://github.com/rusefi/wideband.git
implement sampling math
This commit is contained in:
parent
c19c6445bd
commit
fbc6430aba
|
@ -108,6 +108,7 @@ include $(CHIBIOS)/os/common/ports/ARMv6-M/compilers/GCC/mk/port.mk
|
||||||
# Auto-build files in ./source recursively.
|
# Auto-build files in ./source recursively.
|
||||||
include $(CHIBIOS)/tools/mk/autobuild.mk
|
include $(CHIBIOS)/tools/mk/autobuild.mk
|
||||||
# Other files (optional).
|
# Other files (optional).
|
||||||
|
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
|
||||||
|
|
||||||
# Define linker script file here
|
# Define linker script file here
|
||||||
LDSCRIPT= $(STARTUPLD)/STM32F042x6.ld
|
LDSCRIPT= $(STARTUPLD)/STM32F042x6.ld
|
||||||
|
@ -125,6 +126,7 @@ CPPSRC = $(ALLCPPSRC) \
|
||||||
lambda_lookup.cpp \
|
lambda_lookup.cpp \
|
||||||
pwm.cpp \
|
pwm.cpp \
|
||||||
pump_dac.cpp \
|
pump_dac.cpp \
|
||||||
|
sampling.cpp \
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
# List ASM source files here.
|
# List ASM source files here.
|
||||||
|
@ -151,7 +153,8 @@ CPPWARN = -Wall -Wextra -Wundef
|
||||||
#
|
#
|
||||||
|
|
||||||
# List all user C define here, like -D_DEBUG=1
|
# List all user C define here, like -D_DEBUG=1
|
||||||
UDEFS =
|
UDEFS = -DCHPRINTF_USE_FLOAT=1
|
||||||
|
|
||||||
|
|
||||||
# Define ASM defines here
|
# Define ASM defines here
|
||||||
UADEFS =
|
UADEFS =
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
|
|
||||||
#define ADC_CHANNEL_COUNT 3
|
#define ADC_CHANNEL_COUNT 3
|
||||||
#define ADC_OVERSAMPLE 4
|
#define ADC_OVERSAMPLE 16
|
||||||
|
|
||||||
static adcsample_t adcBuffer[ADC_CHANNEL_COUNT * ADC_OVERSAMPLE];
|
static adcsample_t adcBuffer[ADC_CHANNEL_COUNT * ADC_OVERSAMPLE];
|
||||||
|
|
||||||
|
@ -38,9 +38,11 @@ AnalogResult AnalogSample()
|
||||||
{
|
{
|
||||||
adcConvert(&ADCD1, &convGroup, adcBuffer, ADC_OVERSAMPLE);
|
adcConvert(&ADCD1, &convGroup, adcBuffer, ADC_OVERSAMPLE);
|
||||||
|
|
||||||
|
constexpr float nernstInputGain = 1 / 2.7f;
|
||||||
|
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
.NernstVoltage = AverageSamples(adcBuffer, 0),
|
.NernstVoltage = AverageSamples(adcBuffer, 0) * nernstInputGain,
|
||||||
.VirtualGroundVoltage = AverageSamples(adcBuffer, 1),
|
.VirtualGroundVoltage = AverageSamples(adcBuffer, 1),
|
||||||
.PumpCurrentVoltage = AverageSamples(adcBuffer, 2),
|
.PumpCurrentVoltage = AverageSamples(adcBuffer, 2),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
|
#include "chprintf.h"
|
||||||
|
|
||||||
#include "analog_input.h"
|
|
||||||
#include "can.h"
|
#include "can.h"
|
||||||
#include "pwm.h"
|
#include "pwm.h"
|
||||||
#include "pump_dac.h"
|
#include "pump_dac.h"
|
||||||
|
#include "sampling.h"
|
||||||
|
|
||||||
// 400khz / 1024 = 390hz PWM
|
// 400khz / 1024 = 390hz PWM
|
||||||
// TODO: this is wired to an inverted output, what do?
|
// TODO: this is wired to an inverted output, what do?
|
||||||
|
@ -20,12 +21,14 @@ static const UARTConfig uartCfg =
|
||||||
.timeout_cb = nullptr,
|
.timeout_cb = nullptr,
|
||||||
|
|
||||||
.timeout = 0,
|
.timeout = 0,
|
||||||
.speed = 230400,
|
.speed = 500000,
|
||||||
.cr1 = 0,
|
.cr1 = 0,
|
||||||
.cr2 = 0,
|
.cr2 = 0,
|
||||||
.cr3 = 0,
|
.cr3 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char strBuffer[200];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Application entry point.
|
* Application entry point.
|
||||||
*/
|
*/
|
||||||
|
@ -33,35 +36,36 @@ int main() {
|
||||||
halInit();
|
halInit();
|
||||||
chSysInit();
|
chSysInit();
|
||||||
|
|
||||||
|
StartSampling();
|
||||||
|
|
||||||
InitPumpDac();
|
InitPumpDac();
|
||||||
|
|
||||||
InitCan();
|
InitCan();
|
||||||
|
|
||||||
uartStart(&UARTD1, &uartCfg);
|
uartStart(&UARTD1, &uartCfg);
|
||||||
|
|
||||||
adcStart(&ADCD1, nullptr);
|
|
||||||
|
|
||||||
heaterPwm.Start();
|
heaterPwm.Start();
|
||||||
|
|
||||||
heaterPwm.SetDuty(0.2f);
|
heaterPwm.SetDuty(0.2f);
|
||||||
|
|
||||||
while (true) {
|
|
||||||
// auto result = AnalogSample();
|
|
||||||
|
|
||||||
// // dummy data
|
/*for (int i = 0; i < 500; i++) {
|
||||||
// SendCanData(0.5f, 300);
|
SetPumpCurrentTarget(current);
|
||||||
|
chThdSleepMilliseconds(50);
|
||||||
|
|
||||||
// uartStartSend(&UARTD1, 13, "Hello, world!");
|
auto result = AnalogSample();
|
||||||
// chThdSleepMilliseconds(10);
|
|
||||||
|
|
||||||
|
//size_t writeCount = chsnprintf(strBuffer, 200, "I: %d\t\tVM: %.3f\tIp: %.3f\n", current, result.VirtualGroundVoltage, result.PumpCurrentVoltage);
|
||||||
|
size_t writeCount = chsnprintf(strBuffer, 200, "%d\t%.4f\n", current, result.PumpCurrentVoltage);
|
||||||
|
uartStartSend(&UARTD1, writeCount, strBuffer);
|
||||||
|
|
||||||
SetPumpCurrentTarget(-1000);
|
//current += 10;
|
||||||
chThdSleepMilliseconds(10);
|
}*/
|
||||||
|
|
||||||
SetPumpCurrentTarget(0);
|
|
||||||
chThdSleepMilliseconds(10);
|
|
||||||
|
|
||||||
SetPumpCurrentTarget(1000);
|
while(1) {
|
||||||
chThdSleepMilliseconds(10);
|
size_t writeCount = chsnprintf(strBuffer, 200, "%.4f\t%.2f\n", GetNernstDc() * 1000, GetSensorInternalResistance());
|
||||||
|
uartStartSend(&UARTD1, writeCount, strBuffer);
|
||||||
|
|
||||||
|
chThdSleepMilliseconds(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
#include "sampling.h"
|
||||||
|
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#include "analog_input.h"
|
||||||
|
|
||||||
|
// Stored results
|
||||||
|
float nernstAc = 0;
|
||||||
|
float nernstDc = 0;
|
||||||
|
volatile float pumpCurrentSenseVoltage = 0;
|
||||||
|
|
||||||
|
constexpr float f_abs(float x)
|
||||||
|
{
|
||||||
|
return x > 0 ? x : -x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static THD_WORKING_AREA(waSamplingThread, 256);
|
||||||
|
|
||||||
|
static void SamplingThread(void*)
|
||||||
|
{
|
||||||
|
float r_2 = 0;
|
||||||
|
float r_3 = 0;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
// First toggle the pin
|
||||||
|
palTogglePad(GPIOB, 8);
|
||||||
|
auto result = AnalogSample();
|
||||||
|
|
||||||
|
float r_1 = result.NernstVoltage;
|
||||||
|
|
||||||
|
// Compute results
|
||||||
|
|
||||||
|
// r2_opposite_phase estimates where the previous sample would be had we not been toggling
|
||||||
|
// AKA the absolute value of the difference between r2_opposite_phase and r2 is the amplitude
|
||||||
|
// of the AC component on the nernst voltage. We have to pull this trick so as to use the past 3
|
||||||
|
// samples to cancel out any slope in the DC (aka actual nernst cell output) from the AC measurement
|
||||||
|
float r2_opposite_phase = (r_1 + r_3) / 2;
|
||||||
|
|
||||||
|
nernstAc = f_abs(r2_opposite_phase - r_2);
|
||||||
|
nernstDc = (r2_opposite_phase + r_2) / 2;
|
||||||
|
|
||||||
|
pumpCurrentSenseVoltage = 0.8f * pumpCurrentSenseVoltage + 0.2f * (result.PumpCurrentVoltage - 1.65f);
|
||||||
|
|
||||||
|
// Shift history over by one
|
||||||
|
r_3 = r_2;
|
||||||
|
r_2 = r_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartSampling()
|
||||||
|
{
|
||||||
|
adcStart(&ADCD1, nullptr);
|
||||||
|
chThdCreateStatic(waSamplingThread, sizeof(waSamplingThread), NORMALPRIO + 5, SamplingThread, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetNernstAc()
|
||||||
|
{
|
||||||
|
return nernstAc;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetSensorInternalResistance()
|
||||||
|
{
|
||||||
|
// Sensor is the lowside of a divider, top side is 22k, and 3.3v AC pk-pk is injected
|
||||||
|
return 22000 / (3.3f / GetNernstAc() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetNernstDc()
|
||||||
|
{
|
||||||
|
return nernstDc;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetPumpNominalCurrent()
|
||||||
|
{
|
||||||
|
// Gain is 10x, then a 61.9 ohm resistor
|
||||||
|
// Effective resistance with the gain is 619 ohms
|
||||||
|
// 1000 is to convert to milliamperes
|
||||||
|
constexpr float ratio = 1000 / 619.0f;
|
||||||
|
return pumpCurrentSenseVoltage * ratio;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void StartSampling();
|
||||||
|
|
||||||
|
float GetNernstAc();
|
||||||
|
float GetSensorInternalResistance();
|
||||||
|
float GetNernstDc();
|
||||||
|
|
||||||
|
float GetPumpNominalCurrent();
|
Loading…
Reference in New Issue