implement sampling math

This commit is contained in:
Matthew Kennedy 2020-10-29 02:55:55 -07:00
parent c19c6445bd
commit fbc6430aba
5 changed files with 119 additions and 20 deletions

View File

@ -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 =

View File

@ -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),
}; };

View File

@ -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); while(1) {
chThdSleepMilliseconds(10); size_t writeCount = chsnprintf(strBuffer, 200, "%.4f\t%.2f\n", GetNernstDc() * 1000, GetSensorInternalResistance());
uartStartSend(&UARTD1, writeCount, strBuffer);
SetPumpCurrentTarget(1000); chThdSleepMilliseconds(5);
chThdSleepMilliseconds(10);
} }
} }

81
firmware/sampling.cpp Normal file
View File

@ -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;
}

9
firmware/sampling.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
void StartSampling();
float GetNernstAc();
float GetSensorInternalResistance();
float GetNernstDc();
float GetPumpNominalCurrent();