Skip to content

Firmware v3 #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 72 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
8f82dc7
added calculation of the offset amplifier
JochiSt Mar 7, 2023
156bffd
added calculation for voltage before bias amplifier
JochiSt Mar 7, 2023
c69e269
moved #define of PCB version to own header file
JochiSt Mar 7, 2023
e108ae9
use gain config only for PCB v2
JochiSt Mar 7, 2023
022e805
for PCBv1 use a much simpler calculation
JochiSt Mar 7, 2023
e56d752
change Uout with Uadc and solve to Uin
JochiSt Mar 7, 2023
443b38a
created build settings for each PCB revision (and added them to ignore)
JochiSt Mar 7, 2023
3694d97
store resistor values in config
JochiSt Mar 7, 2023
cf39be4
added conversion factor for voltage controlled current source
JochiSt Mar 7, 2023
007107b
fixed printf output formatting
JochiSt Mar 7, 2023
e443531
updated some comments
JochiSt Mar 7, 2023
e37acd8
updated voltage and current reading
JochiSt Mar 7, 2023
a3914fc
drafted PCBv3 handling of currents and voltages together with the offset
JochiSt Mar 7, 2023
8358781
added PyLTSpice as submodule
JochiSt Mar 8, 2023
5dc2568
changed to transient simulation
JochiSt Mar 8, 2023
1fb6b8d
started simulation using PyLTSpice
JochiSt Mar 8, 2023
b79f3e3
restructured imports
JochiSt Mar 8, 2023
592931c
import OFM PT100 for conversion
JochiSt Mar 8, 2023
f3ed350
no longer print trace name and properties
JochiSt Mar 8, 2023
1b87568
get and print traces and their properties
JochiSt Mar 8, 2023
e0c4858
remove not needed part of the template
JochiSt Mar 8, 2023
446a656
limit the number of parallel simulations
JochiSt Mar 8, 2023
b1d41d3
ignore .fail files
JochiSt Mar 8, 2023
e4f8561
updated simulation to run with multiple Uset
JochiSt Mar 8, 2023
346eebe
started full OFM simulation for a single channel
JochiSt Mar 8, 2023
80d8549
tweaked simulation settings for a fast simulation with and without bias
JochiSt Mar 8, 2023
aa0f83c
updated PyLTSpice to the dev branch
JochiSt Mar 8, 2023
c32175d
started full OFM simulation with python and LTspice
JochiSt Mar 8, 2023
cc8b7f0
updated simulation processing to full OFM simulation
JochiSt Mar 9, 2023
29a4f49
include simulation of ADC convert voltage in LSBs
JochiSt Mar 9, 2023
79434b3
added a 10M resistor across the 4066 to speed up simulation
JochiSt Mar 10, 2023
bcea5bc
included the PWM for the bias voltage
JochiSt Mar 10, 2023
8f87378
pretty print for traces and properties
JochiSt Mar 10, 2023
d4e8f23
set switch voltage and readback the CCR for Iset and Bias
JochiSt Mar 10, 2023
f658428
optimised simulation options to speed up LTSpice when switch is opened
JochiSt Mar 10, 2023
c732c4f
step switch setting between 0 and 3.3
JochiSt Mar 10, 2023
afde725
evaluate steps / gain (bias) setting
JochiSt Mar 10, 2023
0a705d6
store PWM values in variables
JochiSt Mar 10, 2023
fce281f
use update_wrapper to create proper callback function
JochiSt Mar 10, 2023
f097fbf
print forwarded PWM values
JochiSt Mar 10, 2023
2f7bd73
disabled debug print of trace names
JochiSt Mar 10, 2023
f3545c4
disabled debug print of property dict
JochiSt Mar 10, 2023
4739486
removed debug print and disabled pretty print
JochiSt Mar 10, 2023
f987b7d
save simulation results as NPZ
JochiSt Mar 10, 2023
a0ad6a4
evaluate different PWM settings
JochiSt Mar 10, 2023
12da8ff
import time
JochiSt Mar 10, 2023
caa27a3
remove simulation files (they are no longer needed)
JochiSt Mar 10, 2023
ff302e3
started plotting / analysis script for OFM simulation
JochiSt Mar 10, 2023
1668b85
use name == main and restructured imports
JochiSt Mar 10, 2023
03afd4a
fixed conversion for a whole array
JochiSt Mar 10, 2023
8bc9272
convert into the real ADC values
JochiSt Mar 10, 2023
7786e9e
reformatted plotting of first axis
JochiSt Mar 10, 2023
25798c5
added second y axis for plotting the ADC output values (LSB)
JochiSt Mar 10, 2023
9194bbe
added R_PT100 for 40 degC as backup
JochiSt Mar 10, 2023
bc7ea01
moved pprint import to place, where it is really needed
JochiSt Mar 10, 2023
eee9dc2
LTSteps are not needed to be imported
JochiSt Mar 10, 2023
f0361db
ensure, that the temperature is set for each simulation run
JochiSt Mar 10, 2023
efa4491
added more plots and calculations to see, whether all calculations ar…
JochiSt Mar 10, 2023
ce20600
update gain setting resistor to 56k
JochiSt Mar 10, 2023
eb5f725
add proper X label
JochiSt Mar 10, 2023
b493de8
plotted bias PWM value
JochiSt Mar 10, 2023
1670b7f
increase linewidth for voltage before amplifier
JochiSt Mar 10, 2023
8a8c0c9
skip PWM = 0
JochiSt Mar 10, 2023
6dfdab6
reduce temperature to 40 degC
JochiSt Mar 10, 2023
1af788b
set proper y limits
JochiSt Mar 10, 2023
deded49
update value gain resistor to 39k
JochiSt Mar 10, 2023
a0334ad
moved simADC function to own file
JochiSt Mar 13, 2023
78f0058
need to import numpy again
JochiSt Mar 13, 2023
526b9d3
added direct analysis of simulated file
JochiSt Mar 13, 2023
fb075a3
added simulation for the current source submodule
JochiSt Mar 13, 2023
c9d6e11
increasing the gain of the current measurement inside the current source
JochiSt Mar 13, 2023
c73975b
added patch for AISLER upload
JochiSt Mar 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ software/FlowMeasurement/*.png
firmware/.settings/*.prefs
firmware/.project
firmware/Debug/*
firmware/Debug*
firmware/Release/*
*.launch

# EmBitz
*.ebTemp

*.fail
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
[submodule "Kicad-Wago-733"]
path = Kicad-Wago-733
url = https://github.com/phd0/Kicad-Wago-733.git
[submodule "simulations/PyLTSpice"]
path = simulations/PyLTSpice
url = https://github.com/nunobrum/PyLTSpice.git
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[![Upload to - AISLER](https://img.shields.io/badge/Upload_to_-AISLER-ff8000)](https://aisler.net/p/new?url=https://github.com/JochiSt/OpenFlowMeter/blob/main/OpenFlowMeter.kicad_pcb&ref=github)
# OpenFlowMeter
## Purpose
Measuring flow of gases and maybe liquids.
Expand Down
269 changes: 268 additions & 1 deletion firmware/.cproject

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion firmware/Inc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ extern "C" {
#endif

#include <stdint.h>

#include "pcb_version.h"
#include "pid.h"

#define ISATURATION_LSB 3970
#define USATURATION_LSB 3970

extern const float LSB2U;
extern const float LSB2I;
extern const float U2I;

typedef struct {
float Ugain;
Expand Down Expand Up @@ -83,10 +84,19 @@ typedef struct {
* only the high gain is stored here, the lower gain is always 1
* @{
*/
#if defined(PCB_V2)
gain_config_t GAIN[2];
#endif

/** @}*/

#if defined(PCB_V3)
float U_R1[2];
float U_R2[2];
float I_R1[2];
float I_R2[2];
#endif

/** @}*/
} config_t;

Expand Down
30 changes: 30 additions & 0 deletions firmware/Inc/pcb_version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

/**
* PCB v1 compatibility mode
*/
//#define PCB_V1
/******************************************************************************/
/**
* PCB v2 compatibility mode
* enables:
* - dual gain ADC readout
* - I2C sensor readout
*/
//#define PCB_V2
#if defined(PCB_V2)
#undef PCB_V1
#endif
/******************************************************************************/
/**
* PCB v3 compatibility mode
* enables:
* - dual gain ADC readout
* - offset for ADC / differential amplifier
* - I2C sensor readout
*/
//#define PCB_V3
#if defined(PCB_V3)
#undef PCB_V1
#undef PCB_V2
#endif
1 change: 1 addition & 0 deletions firmware/Inc/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ uint8_t upper(uint16_t val);
uint8_t lower(uint16_t val);

float convertPT100_R2T(float resistance);
float getVoltageBeforeAmplifier(float Uadc, float Ubias, float R1, float R2);

#endif //__UTILS_H__
27 changes: 25 additions & 2 deletions firmware/Src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ config_t cfg;
const float LSB2U = 3.3 / 4096;
const float LSB2I = 3.3 / 4096 * 10e-3;

const float U2I = 10e-3; // TODO insert right value here

void generateDefaultCFG(config_t *cfg){
// set the board ID
cfg->board_ID = 1;
Expand Down Expand Up @@ -39,6 +41,7 @@ void generateDefaultCFG(config_t *cfg){
cfg->PID_flags.PID0_active = 0;
cfg->PID_flags.PID1_active = 0;

#if defined(PCB_V2)
// gain settings from calculations / optimisation
cfg->GAIN[0].Igain = 1 + 47.0e3 / 5.6e3;
cfg->GAIN[0].Ugain = 1 + 33.0e3 / 5.6e3;
Expand All @@ -49,6 +52,16 @@ void generateDefaultCFG(config_t *cfg){
cfg->GAIN[1].Ugain = 1 + 33.0e3 / 5.6e3;
cfg->GAIN[1].Ibias = 0.12;
cfg->GAIN[1].Ubias = 0.01;
#endif
#if defined(PCB_V3)
for(int i=0; i<2; i++){
cfg->U_R1[i] = 47e3;
cfg->U_R2[i] = 5.6e3;
cfg->I_R1[i] = 47e3;
cfg->I_R2[i] = 5.6e3;
}
#endif

}

/**
Expand All @@ -69,13 +82,23 @@ void printCfg(config_t *cfg){
printf("SMOO: %d\r\n", cfg->SMOO);
printf("SMOOMAX: %d\r\n", cfg->SMOO_MAX);

#if defined(PCB_V2)
printf("\r\n");
printf("Gain:");
printf("Gain:\r\n");
printf(" CH0 I %f U%f\r\n", cfg->GAIN[0].Igain, cfg->GAIN[0].Ugain);
printf(" CH1 I %f U%f\r\n", cfg->GAIN[1].Igain, cfg->GAIN[1].Ugain);
printf("Offset:");
printf("Offset:\r\n");
printf(" CH0 I %f U%f\r\n", cfg->GAIN[0].Ibias, cfg->GAIN[0].Ubias);
printf(" CH1 I %f U%f\r\n", cfg->GAIN[1].Ibias, cfg->GAIN[1].Ubias);
#endif
#if defined(PCB_V3)
printf("\r\n");
printf("Resistors:\r\n");
for(int i=0; i<2; i++){
printf(" U R1 %f R2 %f\r\n", cfg->U_R1[i], cfg->U_R2[i]);
printf(" I R1 %f R2 %f\r\n", cfg->I_R1[i], cfg->I_R2[i]);
}
#endif

printf("\r\n");
printf("PID 0: (%d)\r\n", cfg->PID_flags.PID0_active);
Expand Down
68 changes: 32 additions & 36 deletions firmware/Src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "pcb_version.h"
#include "syscalls.h"
#include "utils.h"
#include "i2c_scanner.h"
Expand Down Expand Up @@ -57,34 +58,7 @@
//#define PRINT_UART_ADC // print the ADC data
//#define PRINT_UART_CALC_TEMP // print the calculated temperatures
/******************************************************************************/
/**
* PCB v1 compatibility mode
*/
#define PCB_V1
/******************************************************************************/
/**
* PCB v2 compatibility mode
* enables:
* - dual gain ADC readout
* - I2C sensor readout
*/
//#define PCB_V2
#if defined(PCB_V2)
#undef PCB_V1
#define I2C_SENSOR_READOUT
#endif
/******************************************************************************/
/**
* PCB v3 compatibility mode
* enables:
* - dual gain ADC readout
* - offset for ADC / differential amplifier
* - I2C sensor readout
*/
//#define PCB_V3
#if defined(PCB_V3)
#undef PCB_V1
#undef PCB_V2
#if defined(PCB_V2) || defined(PCB_V3)
#define I2C_SENSOR_READOUT
#endif
/******************************************************************************/
Expand Down Expand Up @@ -399,8 +373,17 @@ int main(void)

// calculate coarse current and voltage for each channel
for(int i=0; i<2; i++){
#if defined(PCB_V1)
current[i] = (*avr_current[i][0] * LSB2I);
voltage[i] = (*avr_voltage[i][0] * LSB2U);
#elif defined(PCB_V2)
current[i] = (*avr_current[i][0] * LSB2I) + cfg.GAIN[i].Ibias/1000.;
voltage[i] = (*avr_voltage[i][0] * LSB2U) + cfg.GAIN[i].Ubias;
#elif defined(PCB_V3)
// TODO implement proper voltage / current reading
current[i] = (*avr_current[i][0] * LSB2I);
voltage[i] = (*avr_voltage[i][0] * LSB2U);
#endif
}

#if defined(PCB_V2)
Expand Down Expand Up @@ -436,10 +419,22 @@ int main(void)
offset[i] = 3.3 * (*PWMoffset[i]) / 4096;
}

// adjust the offset voltage

// if offset voltage is fine, we can use the high gain

for(int i=0; i<2; i++){
// check for saturation
if(*avr_voltage[i][1] >= USATURATION_LSB || *avr_current[i][1] >= ISATURATION_LSB){
// one of the high gain measurement is in saturation
// adjust the offset voltage
*PWMoffset[i] += 10;
continue;
}else if(*avr_voltage[i][1] == 0 || *avr_current[i][1] == 0){
*PWMoffset[i] += 10;
continue;
}else{
// if offset voltage is fine, we can use the high gain
voltage[i] = getVoltageBeforeAmplifier(*avr_voltage[i][1] * LSB2U, offset[i], cfg.U_R1[i], cfg.U_R2[i]);
current[i] = getVoltageBeforeAmplifier(*avr_current[i][1] * LSB2U, offset[i], cfg.I_R1[i], cfg.I_R2[i]) * U2I;
}
}
#endif
/** calculate temperatures ********************************************/
for(int i=0; i<2; i++){
Expand All @@ -449,23 +444,24 @@ int main(void)
/** run the PID controllers *******************************************/
for(int i=0; i<2; i++){
runPID(&pid[i]);

/** update the output, if the PID is active *************************/
if(pid[0].active){
*PWMcurrent[i] = PIDout[i];
}else{
*PWMcurrent[i] = PWM[i];
}
/** update the offset ***********************************************/
*PWMoffset[i] = 0.9 * (*PWMcurrent[i]);
}

// link the PID active to the configuration active
/** link the PID active to the configuration active *******************/
pid[0].active = cfg.PID_flags.PID0_active;
pid[1].active = cfg.PID_flags.PID1_active;
}

/*************************************************************************
/***************************************************************************
* Print some variables via UART
************************************************************************/
**************************************************************************/
if( cnt_print_uart >= cfg.interval_PRINT_UART
&& cfg.interval_PRINT_UART < 255
){
Expand Down
11 changes: 11 additions & 0 deletions firmware/Src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,14 @@ float convertPT100_R2T(float resistance){
const float R0 = 100;
return (resistance - R0)/(R0 * A);
}

/**
* calculate the voltage before the biases amplifier
* @param Ubias bias voltage
* @param Uadc measured voltage of the ADC (amplifier output)
* @param R1 gain setting resistor (upper)
* @param R2 gain setting resistor (lower)
*/
float getVoltageBeforeAmplifier(float Uadc, float Ubias, float R1, float R2){
return (R1 * Ubias + R2 * Uadc)/(R1 + R2);
}
28 changes: 28 additions & 0 deletions firmware/calculations/offset_amplifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
"""

"""
from sympy import Symbol, symbols, solve, pprint, Eq

Up, Un = symbols("U_+, U_-")


Uadc = Symbol("U_adc")
Ubias = Symbol("U_bias")

R1, R2 = symbols("R_1, R_2")

I_R1R2 = (Uadc - Ubias) / (R1 + R2)

Un = I_R1R2 * R2 + Ubias

eq1 = Eq( Up , Un )
pprint(eq1)

Uin = symbols("U_in")
eq1 = eq1.subs(Up, Uin)
pprint(eq1)

sol = solve(eq1, Uin)[0].factor()
pprint(sol)

3 changes: 2 additions & 1 deletion simulations/CurrentSource/current_source_mod_v1.asc
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ SYMATTR Value 8
SYMBOL res 352 912 R0
SYMATTR InstName R19
SYMATTR Value 8
TEXT -768 712 Left 2 !.dc V3 0 3.3 0.1\n.param R_PT100 100
TEXT -768 712 Left 2 ;.dc V3 0 3.3 0.1\n.param R_PT100 100
TEXT -552 216 Left 2 ;R2 and R4 define current per input voltage
TEXT -760 472 Left 2 ;max. 3.3V
TEXT -384 504 Left 2 ;"protection" resistor
Expand All @@ -206,6 +206,7 @@ TEXT -80 832 Left 2 ;PT100 temperature sensor
TEXT -760 880 Left 2 ;.tran 1\n.save V(voltage_measure) V(current_measure) I(Pt100)\n.step param R_PT100 100 150 10\n.measure Vmeas_avg avg V(voltage_measure)\n.measure Imeas_avg avg V(current_measure)\n.measure Ipt100_avg avg I(Pt100)
TEXT -784 848 Left 3 ;Simulate current vs PT100
TEXT -784 680 Left 3 ;Simulate current vs input voltage
TEXT -1328 536 Left 2 !.tran 1\n.TEMP=30\n.param R_PT100 {100*(1+3.85e-3*TEMP)}
LINE Normal 576 192 576 608 2
LINE Normal 1376 192 576 192 2
LINE Normal 576 608 1376 608 2
Expand Down
59 changes: 59 additions & 0 deletions simulations/CurrentSource/simulate_current_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
"""

"""
import os
import sys

from functools import partial # import partial for tweaking callback
import numpy as np

sys.path.append("../PyLTSpice/")
from PyLTSpice import SimCommander, LTSteps, RawRead

sys.path.append("../../software/")
sys.path.append("../../software/pyUSBtin")
from OpenFlowMeter import PT100

def processing_data(raw_filename, log_file, Uset):
print("Handling the simulation data of %s, log file %s" % (raw_filename, log_file))
LTR = RawRead(raw_filename)
# print all stored traces
#print(LTR.get_trace_names())

# print simulation properties
#print(LTR.get_raw_property())

current_setpoint= np.mean(LTR.get_trace("V(current_setpoint)").get_wave(0))

current_pt100 = np.mean(LTR.get_trace("I(PT100)").get_wave(0))*1000

current_measure = np.mean(LTR.get_trace("V(current_measure)").get_wave(0))
voltage_measure = np.mean(LTR.get_trace("V(voltage_measure)").get_wave(0))

print("I set ", current_setpoint)
print("I PT100 ", current_pt100)
print("I measure", current_measure)
print("U measure", voltage_measure)

R_PT100 = voltage_measure / (current_measure * 10 / 1000)
print("R_PT100: ", R_PT100)
print("Temperature", PT100.convertPT100_T(R_PT100))


# select spice model

LTC = SimCommander(
"./current_source_mod_v1.asc",
parallel_sims=2 # limit number of parallel simulations)
)
LTC.set_parameters(temp=40)

for Uset in [0.5, 1, 1.5, 2, 2.5, 3, 3.3]:
LTC.set_component_value('V3', Uset)
LTC.run(callback=partial(processing_data, Uset=None))

LTC.wait_completion()

# Sim Statistics
print('Successful/Total Simulations: ' + str(LTC.okSim) + '/' + str(LTC.runno))
Loading