Fertirrega_v6 AD5934 frequency at 2.5kHz
This commit is contained in:
@@ -87,10 +87,14 @@ extern "C" {
|
||||
|
||||
|
||||
// Values for frequency counts = (freq*2^27)/(1MHz/16)
|
||||
#define AD5934_FREQ_4K882HZ 0x009FF92F // 4.882kHz
|
||||
#define AD5934_FREQ_2K5HZ 0x0051EB86 // 2.5kHz
|
||||
#define AD5934_FREQ_1K953HZ 0x003FFEF3 // 1.953kHz
|
||||
#define AD5934_FREQ_1K590HZ 0x003419E3 // 1.59kHz
|
||||
#define AD5934_FREQ_0HZ 0x00000000 // 0Hz
|
||||
#define AD5934_STEP_FREQ_0 0x0000 // 0 passos
|
||||
#define AD5934_SETTLING_TIME_0S01 0x000C // 0,01s
|
||||
//#define AD5934_SETTLING_TIME_0S01 0x000C // 0,01s
|
||||
#define AD5934_SETTLING_TIME_0S01 0x0080
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************************** Command Codes **********************************/
|
||||
@@ -122,7 +126,7 @@ extern "C" {
|
||||
#define AD5934_CH_EC_10MS 0x21
|
||||
#define AD5934_CH_EC_5MS 0x22
|
||||
*/
|
||||
|
||||
/*
|
||||
#define AD5934_CH_REF100R_LOW_GAIN 0x09
|
||||
#define AD5934_CH_REF100R_MID_GAIN 0x0A
|
||||
#define AD5934_CH_REF100R_HIGH_GAIN 0x0C
|
||||
@@ -138,7 +142,7 @@ extern "C" {
|
||||
#define AD5934_CH_EC_LOW_GAIN 0x81
|
||||
#define AD5934_CH_EC_MID_GAIN 0x82
|
||||
#define AD5934_CH_EC_HIGH_GAIN 0x84
|
||||
|
||||
*/
|
||||
#define AD5934_LOW_GAIN_BASE 0x01
|
||||
#define AD5934_MID_GAIN_BASE 0x02
|
||||
#define AD5934_HIGH_GAIN_BASE 0x04
|
||||
@@ -161,9 +165,11 @@ extern "C" {
|
||||
#define AD5934_RTD_A 3.9083e-3f
|
||||
#define AD5934_RTD_B (-5.775e-7f)
|
||||
|
||||
#define AD5934_TEMP_AVERAGES 8
|
||||
#define AD5934_EC_AVERAGES 8
|
||||
#define AD5934_TEMP_AVERAGES 16
|
||||
#define AD5934_EC_AVERAGES 16
|
||||
|
||||
#define AD5934_EC_ALPHA_PER_C 0.02f
|
||||
#define AD5934_EC_TEMP_REF_C 25.0f
|
||||
|
||||
union Bytes2Int
|
||||
{
|
||||
@@ -183,13 +189,59 @@ union Short2Long
|
||||
uint32_t number;
|
||||
};
|
||||
|
||||
extern int16_t temperature_dut_samples[AD5934_TEMP_AVERAGES][2];
|
||||
extern int16_t temperature_ref_samples[AD5934_TEMP_AVERAGES][2];
|
||||
typedef enum {
|
||||
AD5934_CH_REF100R_LOW_GAIN = 0,
|
||||
AD5934_CH_REF100R_MID_GAIN,
|
||||
AD5934_CH_REF100R_HIGH_GAIN,
|
||||
|
||||
AD5934_CH_REF1K_LOW_GAIN,
|
||||
AD5934_CH_REF1K_MID_GAIN,
|
||||
AD5934_CH_REF1K_HIGH_GAIN,
|
||||
|
||||
AD5934_CH_REF10K_LOW_GAIN,
|
||||
AD5934_CH_REF10K_MID_GAIN,
|
||||
AD5934_CH_REF10K_HIGH_GAIN,
|
||||
|
||||
AD5934_CH_RTD_LOW_GAIN,
|
||||
AD5934_CH_RTD_MID_GAIN,
|
||||
AD5934_CH_RTD_HIGH_GAIN,
|
||||
|
||||
AD5934_CH_EC_LOW_GAIN,
|
||||
AD5934_CH_EC_MID_GAIN,
|
||||
AD5934_CH_EC_HIGH_GAIN,
|
||||
|
||||
AD5934_CH_MAX // Guarda automaticamente o número total de canais (15)
|
||||
} AD5934_Channel_t;
|
||||
|
||||
static const uint8_t ADG715_Channel_Map[AD5934_CH_MAX] = {
|
||||
[AD5934_CH_REF100R_LOW_GAIN] = (ADG715_SW1 | ADG715_SW4),
|
||||
[AD5934_CH_REF100R_MID_GAIN] = (ADG715_SW2 | ADG715_SW4),
|
||||
[AD5934_CH_REF100R_HIGH_GAIN] = (ADG715_SW3 | ADG715_SW4),
|
||||
|
||||
[AD5934_CH_REF1K_LOW_GAIN] = (ADG715_SW1 | ADG715_SW5),
|
||||
[AD5934_CH_REF1K_MID_GAIN] = (ADG715_SW2 | ADG715_SW5),
|
||||
[AD5934_CH_REF1K_HIGH_GAIN] = (ADG715_SW3 | ADG715_SW5),
|
||||
|
||||
[AD5934_CH_REF10K_LOW_GAIN] = (ADG715_SW1 | ADG715_SW6),
|
||||
[AD5934_CH_REF10K_MID_GAIN] = (ADG715_SW2 | ADG715_SW6),
|
||||
[AD5934_CH_REF10K_HIGH_GAIN] = (ADG715_SW3 | ADG715_SW6),
|
||||
|
||||
[AD5934_CH_RTD_LOW_GAIN] = (ADG715_SW1 | ADG715_SW7),
|
||||
[AD5934_CH_RTD_MID_GAIN] = (ADG715_SW2 | ADG715_SW7),
|
||||
[AD5934_CH_RTD_HIGH_GAIN] = (ADG715_SW3 | ADG715_SW7),
|
||||
|
||||
[AD5934_CH_EC_LOW_GAIN] = (ADG715_SW1 | ADG715_SW8),
|
||||
[AD5934_CH_EC_MID_GAIN] = (ADG715_SW2 | ADG715_SW8),
|
||||
[AD5934_CH_EC_HIGH_GAIN] = (ADG715_SW3 | ADG715_SW8)
|
||||
};
|
||||
|
||||
extern int16_t temperature_dut_samples[2][AD5934_TEMP_AVERAGES];
|
||||
extern int16_t temperature_ref_samples[2][AD5934_TEMP_AVERAGES];
|
||||
extern float temperature_display[AD5934_TEMP_AVERAGES];
|
||||
|
||||
extern int16_t ec_dut_samples[AD5934_EC_AVERAGES][2];
|
||||
extern int16_t ec_ref1_samples[AD5934_EC_AVERAGES][2];
|
||||
extern int16_t ec_ref2_samples[AD5934_EC_AVERAGES][2];
|
||||
extern int16_t ec_dut_samples[2][AD5934_EC_AVERAGES];
|
||||
extern int16_t ec_ref1_samples[2][AD5934_EC_AVERAGES];
|
||||
extern int16_t ec_ref2_samples[2][AD5934_EC_AVERAGES];
|
||||
extern float ec_display[AD5934_EC_AVERAGES];
|
||||
extern float ec_temp_dut[AD5934_EC_AVERAGES];
|
||||
|
||||
@@ -211,7 +263,9 @@ uint32_t AD5934_Sweep(void);
|
||||
|
||||
void AD5934_RestartSweep(void);
|
||||
|
||||
float AD5934_GetTemperature(void);
|
||||
float AD5934_Get_Ref_Resistance(void);
|
||||
|
||||
float AD5934_GetTemperature(float mag_ref);
|
||||
|
||||
float AD5934_GetImpedance(float temperature_dut);
|
||||
|
||||
@@ -221,7 +275,9 @@ float AD5934_Round_Float_Precision(float value, uint8_t number_of_decimals);
|
||||
|
||||
float AD5934_Linear_Correction(float raw_value);
|
||||
|
||||
float AD5934_Get_Target_Conductivity(float temp);
|
||||
float AD5934_EC_Compensate_To_25C(float ec_raw_uScm, float temp_C);
|
||||
|
||||
float AD5934_EC_Calibrate_Temperature(float temp_C);
|
||||
|
||||
void ADG715_SetRegisterValue(char value);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define INC_ADS1015_DRIVER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "main.h" // Assuming HAL is included via main.h
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "flash_manager.h"
|
||||
@@ -125,9 +126,9 @@ extern "C" {
|
||||
|
||||
#define ADS1015_KELVIN_OFFSET 273.15f // Constante de conversão Kelvin
|
||||
#define ADS1015_ADC_MAX 4095.0f
|
||||
#define ADS1015_ADC_VREF 3.3f
|
||||
#define ADS1015_ADC_VREF 1024.0f //1.024V in mV
|
||||
#define PH_DELTA_CALIB 3.0f // Difference between pH 7 and pH 4 used in calibration
|
||||
#define ADS1015_PH_AVERAGES 8
|
||||
#define ADS1015_PH_AVERAGES 16
|
||||
|
||||
#define ADS1015_TEMPERATURE_ROW 0
|
||||
#define ADS1015_PH_4_BUFFER_ROW 1
|
||||
@@ -149,7 +150,7 @@ typedef enum {
|
||||
|
||||
|
||||
|
||||
extern float ph_averages[ADS1015_PH_AVERAGES];
|
||||
extern float ph_dut_samples[ADS1015_PH_AVERAGES];
|
||||
|
||||
|
||||
|
||||
@@ -171,9 +172,10 @@ void ADSstartComparator_SingleEnded(ADS1015_I2C* i2c, uint8_t channel, int16_t
|
||||
int16_t ADSgetLastConversionResults();
|
||||
void ADSsetGain(ADS1015_I2C* i2c, adsGain_t gain);
|
||||
adsGain_t ADSgetGain(ADS1015_I2C* i2c);
|
||||
float ADSCalculate_ph_Volts(void);
|
||||
float ADSCalculate_ph_mV(void);
|
||||
float ADSCalculate_ph_Compensated(float temp_dut);
|
||||
float ADSCalculate_ph_Uncompensated(void);
|
||||
float ADSinterpolate_ph(float temp_dut, uint8_t row_index);
|
||||
float ADSRound_Float_Precision(float value, uint8_t number_of_decimals);
|
||||
|
||||
#endif /* INC_ADS1015_DRIVER_H_ */
|
||||
|
||||
@@ -27,14 +27,17 @@
|
||||
typedef struct __attribute__((packed, aligned(4)))
|
||||
{
|
||||
uint32_t magic_number; // 4 bytes (Validação)
|
||||
float ph4_volts; // 4 bytes
|
||||
float ph7_volts; // 4 bytes
|
||||
float ph4_mV; // 4 bytes
|
||||
float ph7_mV; // 4 bytes
|
||||
float ph_temperature; // 4 bytes
|
||||
float ph_slope_mV; // 4 bytes
|
||||
float ph7_real; // 4 bytes
|
||||
float ec1413_mag; // 4 bytes
|
||||
float ec0_mag; // 4 bytes
|
||||
float temperature_value; // 4 bytes
|
||||
float ec_factor; // 4 bytes
|
||||
uint8_t PT100_PT1000_switch; // 1 byte
|
||||
uint8_t EC10mS_EC5mS_switch; // 1 byte
|
||||
uint8_t reserved[998]; // Preenchimento para completar 1024 bytes (1KB)
|
||||
uint8_t reserved[986]; // Preenchimento para completar 1024 bytes (1KB)
|
||||
} FlashPage_t;
|
||||
|
||||
extern FlashPage_t flash_data;
|
||||
|
||||
@@ -127,12 +127,13 @@ void Error_Handler(void);
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
#define STATE_RUNNING_OK 0x00
|
||||
#define STATE_SETUP_CALIBRATION 0x01
|
||||
#define STATE_RS485_SUPPLY_FAULT 0x02
|
||||
#define STATE_PH_SUPPLY_FAULT 0x03
|
||||
#define STATE_EC_RTD_SUPPLY_FAULT 0x04
|
||||
#define STATE_NO_SETUP_CALIBRATION 0x05
|
||||
#define STATE_HIGH_AMBIENT_TEMPERATURE 0x06
|
||||
#define STATE_NO_SETUP_CALIBRATION 0x01
|
||||
#define STATE_PH4_DRY_EC_CALIBRATION 0x02
|
||||
#define STATE_PH7_WET_EC_CALIBRATION 0x03
|
||||
#define STATE_RS485_SUPPLY_FAULT 0x04
|
||||
#define STATE_PH_SUPPLY_FAULT 0x05
|
||||
#define STATE_EC_RTD_SUPPLY_FAULT 0x06
|
||||
#define STATE_HIGH_AMBIENT_TEMPERATURE 0x07
|
||||
|
||||
extern uint8_t main_state;
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
|
||||
#include "ad5934_driver.h"
|
||||
|
||||
int16_t temperature_dut_samples[AD5934_TEMP_AVERAGES][2]={{0},{0}};
|
||||
int16_t temperature_ref_samples[AD5934_TEMP_AVERAGES][2]={{0},{0}};
|
||||
int16_t temperature_dut_samples[2][AD5934_TEMP_AVERAGES]={{0},{0}};
|
||||
int16_t temperature_ref_samples[2][AD5934_TEMP_AVERAGES]={{0},{0}};
|
||||
float temperature_display[AD5934_TEMP_AVERAGES] = {0};
|
||||
|
||||
|
||||
int16_t ec_dut_samples[AD5934_EC_AVERAGES][2]={{0},{0}};
|
||||
int16_t ec_dut_samples[2][AD5934_EC_AVERAGES]={{0},{0}};
|
||||
float ec_display[AD5934_EC_AVERAGES] = {0};
|
||||
|
||||
/******************************************************************************
|
||||
@@ -142,7 +142,7 @@ void AD5934_Init(void)
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_LB, (AD5934_CONTROL_FUNCTION(AD5934_RESET)), 1);
|
||||
|
||||
// Configure starting frequency
|
||||
AD5934_SetRegisterValue(AD5934_START_FREQ_REG_LB, AD5934_FREQ_1K590HZ, 3);
|
||||
AD5934_SetRegisterValue(AD5934_START_FREQ_REG_LB, AD5934_FREQ_2K5HZ, 3);
|
||||
|
||||
// Configure frequency increment step
|
||||
AD5934_SetRegisterValue(AD5934_FREQ_INCR_REG_LB, AD5934_FREQ_0HZ, 3);
|
||||
@@ -165,22 +165,22 @@ void AD5934_Init(void)
|
||||
void AD5934_RestartSweep(void)
|
||||
{
|
||||
// Place AD5934 in standby
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, (AD5934_CONTROL_FUNCTION(AD5934_STANDBY) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X5)), 1);
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, (AD5934_CONTROL_FUNCTION(AD5934_STANDBY) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X1)), 1);
|
||||
|
||||
// Initialize starting frequency, Start frequency sweep, standby
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, ((AD5934_CONTROL_FUNCTION(AD5934_INIT_START_FREQ)) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X5)), 1);
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, ((AD5934_CONTROL_FUNCTION(AD5934_INIT_START_FREQ)) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X1)), 1);
|
||||
|
||||
// Disable Internal Reset State
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_LB, AD5934_CONTROL_FUNCTION(AD5934_RESERVED), 1);
|
||||
|
||||
// Configure Range Output, PGA gain andPlace AD5934 in sweep
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, (AD5934_CONTROL_FUNCTION(AD5934_START_FREQ_SWEEP) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X5)), 1);
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, (AD5934_CONTROL_FUNCTION(AD5934_START_FREQ_SWEEP) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X1)), 1);
|
||||
|
||||
// Wait for data to be valid
|
||||
AD5934_Wait_For_Data_Valid();
|
||||
|
||||
// Power Down
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, (AD5934_CONTROL_FUNCTION(AD5934_POWER_DOWN) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X5)), 1);
|
||||
AD5934_SetRegisterValue(AD5934_CONTROL_REG_HB, (AD5934_CONTROL_FUNCTION(AD5934_POWER_DOWN) | AD5934_CONTROL_RANGE(AD5934_400mVpp_RANGE) | AD5934_PGA_GAIN(AD5934_PGA_GAIN_X1)), 1);
|
||||
|
||||
}
|
||||
|
||||
@@ -212,54 +212,44 @@ uint32_t AD5934_Sweep(void)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* @brief Calculate Temperature.
|
||||
* @brief Get Reference Resistance on Board.
|
||||
*
|
||||
* @param channel - AD5934_CH_PT100 or AD5934_CH_PT1000.
|
||||
*
|
||||
* @return impedance.
|
||||
******************************************************************************/
|
||||
float AD5934_GetTemperature(void)
|
||||
float AD5934_Get_Ref_Resistance(void)
|
||||
{
|
||||
uint8_t i, ch_dut, ch_ref;
|
||||
uint8_t i;
|
||||
uint32_t sample;
|
||||
int32_t ref_sum[2], dut_sum[2];
|
||||
float real_ref,imag_ref, real_dut, imag_dut, ratio, discriminant, mag_dut, mag_ref, ratio_mag, impedance_dut, temperature_sum, gain_factor;
|
||||
int32_t ref_sum[2];
|
||||
float real_ref,imag_ref, real_dut, mag_ref;
|
||||
|
||||
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) == GPIO_PIN_SET) // OFF = PT1000, ON = PT100, PA7 has internal pull-up and switch connects to GND
|
||||
{
|
||||
ch_ref = AD5934_CH_REF100R_LOW_GAIN;
|
||||
ch_dut = AD5934_CH_RTD_LOW_GAIN; //PT100
|
||||
gain_factor = 100.0f;
|
||||
}
|
||||
ADG715_Update(AD5934_CH_REF100R_LOW_GAIN); // Set the Reference Resistor on board in the Analog Mux
|
||||
else
|
||||
{
|
||||
ch_ref = AD5934_CH_REF1K_MID_GAIN;
|
||||
ch_dut = AD5934_CH_RTD_MID_GAIN; //PT1000
|
||||
gain_factor = 1000.0f;
|
||||
}
|
||||
ADG715_Update(AD5934_CH_REF1K_MID_GAIN); // Set the Reference Resistor on board in the Analog Mux
|
||||
|
||||
ADG715_Update(ch_ref); // Set the Reference Resistor on board in the Analog Mux
|
||||
HAL_Delay(2); //Wait a little
|
||||
|
||||
sample = AD5934_Sweep(); // Get Reference Resistor Values from ADC
|
||||
|
||||
// Move values in the vectors
|
||||
for (i = (AD5934_TEMP_AVERAGES-1); i > 0; i--)
|
||||
{
|
||||
temperature_ref_samples[i][0] = temperature_ref_samples[i-1][0]; //real
|
||||
temperature_ref_samples[i][1] = temperature_ref_samples[i-1][1]; //imag
|
||||
temperature_ref_samples[0][i] = temperature_ref_samples[0][i-1]; //real
|
||||
temperature_ref_samples[1][i] = temperature_ref_samples[1][i-1]; //imag
|
||||
}
|
||||
|
||||
// Read real and imaginary data
|
||||
temperature_ref_samples[0][0] = (int16_t)(sample & 0x0000FFFF); //real
|
||||
//temperature_ref_samples[0][1] = 0xFFFF-(((sample & 0xFFFF0000)>>16)); //imag
|
||||
temperature_ref_samples[0][1] = (int16_t)((sample & 0xFFFF0000)>>16); //imag
|
||||
//temperature_ref_samples[1][0] = 0xFFFF-(((sample & 0xFFFF0000)>>16)); //imag
|
||||
temperature_ref_samples[1][0] = (int16_t)((sample & 0xFFFF0000)>>16); //imag
|
||||
|
||||
// Sum values in the vectors
|
||||
for (i = 0, ref_sum[0]=0, ref_sum[1]=0; i < AD5934_TEMP_AVERAGES; i++)
|
||||
{
|
||||
ref_sum[0] += (int32_t)temperature_ref_samples[i][0]; //real
|
||||
ref_sum[1] += (int32_t)temperature_ref_samples[i][1]; //imag
|
||||
ref_sum[0] += (int32_t)temperature_ref_samples[0][i]; //real
|
||||
ref_sum[1] += (int32_t)temperature_ref_samples[1][i]; //imag
|
||||
}
|
||||
|
||||
real_ref = ((float)ref_sum[0])/((float)AD5934_TEMP_AVERAGES);
|
||||
@@ -268,27 +258,54 @@ float AD5934_GetTemperature(void)
|
||||
// Calculate gain factor impedance
|
||||
mag_ref = sqrtf((real_ref * real_ref) + (imag_ref * imag_ref));
|
||||
|
||||
ADG715_Update(ch_dut);
|
||||
HAL_Delay(2);
|
||||
return mag_ref;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* @brief Calculate Temperature.
|
||||
*
|
||||
* @param channel - Magnitude of the Reference Resistor.
|
||||
*
|
||||
* @return impedance.
|
||||
******************************************************************************/
|
||||
float AD5934_GetTemperature(float mag_ref)
|
||||
{
|
||||
uint8_t i, ch_ref;
|
||||
uint32_t sample;
|
||||
int32_t dut_sum[2];
|
||||
float real_dut, imag_dut, ratio, discriminant, mag_dut, ratio_mag, impedance_dut, temperature_sum, gain_factor, temp_result;
|
||||
|
||||
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) == GPIO_PIN_SET) // OFF = PT1000, ON = PT100, PA7 has internal pull-up and switch connects to GND
|
||||
{
|
||||
ch_ref = AD5934_CH_RTD_LOW_GAIN; //PT100
|
||||
gain_factor = AD5934_GAIN_FACTOR_100R;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch_ref = AD5934_CH_RTD_MID_GAIN; //PT1000
|
||||
gain_factor = AD5934_GAIN_FACTOR_1K;
|
||||
}
|
||||
|
||||
ADG715_Update(ch_ref);
|
||||
|
||||
sample = AD5934_Sweep(); // Get PT100/PT1000 Values from ADC
|
||||
|
||||
|
||||
for (i = (AD5934_TEMP_AVERAGES-1); i > 0; i--)
|
||||
{
|
||||
temperature_dut_samples[i][0] = temperature_dut_samples[i-1][0]; //real
|
||||
temperature_dut_samples[i][1] = temperature_dut_samples[i-1][1]; //imag
|
||||
temperature_dut_samples[0][i] = temperature_dut_samples[0][i-1]; //real
|
||||
temperature_dut_samples[1][i] = temperature_dut_samples[1][i-1]; //imag
|
||||
}
|
||||
|
||||
// Read real and imaginary data
|
||||
temperature_dut_samples[0][0] = (int16_t)(sample & 0x0000FFFF); //real
|
||||
//temperature_dut_samples[0][1] = 0xFFFF-(((sample & 0xFFFF0000)>>16)); //imag
|
||||
temperature_dut_samples[0][1] = (int16_t)((sample & 0xFFFF0000)>>16); //imag
|
||||
temperature_dut_samples[1][0] = (int16_t)((sample & 0xFFFF0000)>>16); //imag
|
||||
|
||||
for (i = 0, dut_sum[0]=0, dut_sum[1]=0; i < AD5934_TEMP_AVERAGES; i++)
|
||||
{
|
||||
dut_sum[0] += (int32_t)temperature_dut_samples[i][0]; //real
|
||||
dut_sum[1] += (int32_t)temperature_dut_samples[i][1]; //imag
|
||||
dut_sum[0] += (int32_t)temperature_dut_samples[0][i]; //real
|
||||
dut_sum[1] += (int32_t)temperature_dut_samples[1][i]; //imag
|
||||
}
|
||||
|
||||
real_dut = ((float)dut_sum[0])/((float)AD5934_TEMP_AVERAGES);
|
||||
@@ -297,8 +314,8 @@ float AD5934_GetTemperature(void)
|
||||
// Calculate magnitude
|
||||
mag_dut = sqrtf((real_dut * real_dut) + (imag_dut * imag_dut));
|
||||
|
||||
for (i = (AD5934_TEMP_AVERAGES-1); i > 0; i--)
|
||||
temperature_display[i] = temperature_display[i-1];
|
||||
//for (i = (AD5934_TEMP_AVERAGES-1); i > 0; i--)
|
||||
//temperature_display[i] = temperature_display[i-1];
|
||||
|
||||
ratio_mag = mag_ref / mag_dut;
|
||||
|
||||
@@ -313,18 +330,23 @@ float AD5934_GetTemperature(void)
|
||||
// Calculate impedance discriminant with the ratio
|
||||
discriminant = (AD5934_RTD_A*AD5934_RTD_A)-(4.0f * AD5934_RTD_B * (1.0f - ratio));
|
||||
|
||||
//temp_result = (-AD5934_RTD_A + sqrtf(discriminant)/(2.0f * AD5934_RTD_B));
|
||||
|
||||
return (AD5934_Round_Float_Precision(((-AD5934_RTD_A + sqrtf(discriminant))/(2.0f * AD5934_RTD_B)),2));
|
||||
//return (AD5934_Round_Float_Precision(temp_result,1));
|
||||
|
||||
// Calculate new temperature with the discriminant
|
||||
temperature_display[0] = (-AD5934_RTD_A + sqrtf(discriminant))/(2.0f * AD5934_RTD_B);
|
||||
//temperature_display[0] = (-AD5934_RTD_A + sqrtf(discriminant))/(2.0f * AD5934_RTD_B);
|
||||
|
||||
// Sum of all temperatures
|
||||
for (i = 0, temperature_sum=0.0f; i < AD5934_TEMP_AVERAGES; i++)
|
||||
temperature_sum += temperature_display[i];
|
||||
// for (i = 0, temperature_sum=0.0f; i < AD5934_TEMP_AVERAGES; i++)
|
||||
// temperature_sum += temperature_display[i];
|
||||
|
||||
// Is the temperature stable?
|
||||
if(temperature_display[0]>0.0f && (abs(temperature_display[0]-temperature_display[AD5934_TEMP_AVERAGES-1])/temperature_display[0])<0.1f)
|
||||
return(AD5934_Round_Float_Precision(temperature_sum/((float)AD5934_TEMP_AVERAGES),1)); // Sum / number of averages
|
||||
else
|
||||
return 0.0f; //instable values return always 0
|
||||
//if(temperature_display[0]>0.0f && (abs(temperature_display[0]-temperature_display[AD5934_TEMP_AVERAGES-1])/temperature_display[0])<0.1f)
|
||||
//return(AD5934_Round_Float_Precision(temperature_sum/((float)AD5934_TEMP_AVERAGES),1)); // Sum / number of averages
|
||||
//else
|
||||
//return 0.0f; //instable values return always 0
|
||||
}
|
||||
|
||||
|
||||
@@ -348,11 +370,11 @@ float AD5934_GetImpedance(float temperature_dut)
|
||||
else
|
||||
ec_gain = AD5934_CH_EC_MID_GAIN;
|
||||
|
||||
if((ec_gain != flash_data.EC10mS_EC5mS_switch) && (main_state != STATE_SETUP_CALIBRATION))
|
||||
if((ec_gain != flash_data.EC10mS_EC5mS_switch) && (main_state != STATE_PH4_DRY_EC_CALIBRATION || main_state != STATE_PH7_WET_EC_CALIBRATION))
|
||||
return -1.0f; // Fatal error because the gain used in calibration is different
|
||||
|
||||
ADG715_Update(ec_gain);
|
||||
HAL_Delay(2);
|
||||
//HAL_Delay(5);
|
||||
|
||||
/* 2. Data Acquisition */
|
||||
sample_dut = AD5934_Sweep();
|
||||
@@ -360,19 +382,21 @@ float AD5934_GetImpedance(float temperature_dut)
|
||||
// Shift buffer for moving average
|
||||
for (i = (AD5934_EC_AVERAGES - 1); i > 0; i--)
|
||||
{
|
||||
ec_dut_samples[i][0] = ec_dut_samples[i-1][0];
|
||||
ec_dut_samples[i][1] = ec_dut_samples[i-1][1];
|
||||
ec_dut_samples[0][i] = ec_dut_samples[0][i-1];
|
||||
ec_dut_samples[1][i] = ec_dut_samples[1][i-1];
|
||||
}
|
||||
|
||||
|
||||
// Deconstruct 32-bit sample into Real and Imaginary components
|
||||
ec_dut_samples[0][0] = (float)(int16_t)(sample_dut & 0xFFFF);
|
||||
ec_dut_samples[0][1] = (float)(int16_t)((sample_dut >> 16) & 0xFFFF);
|
||||
ec_dut_samples[1][0] = (float)(int16_t)((sample_dut >> 16) & 0xFFFF);
|
||||
|
||||
|
||||
/* 3. Compute Averages */
|
||||
for (i = 0; i < AD5934_EC_AVERAGES; i++)
|
||||
{
|
||||
dut_sum[0] += (int32_t)ec_dut_samples[i][0];
|
||||
dut_sum[1] += (int32_t)ec_dut_samples[i][1];
|
||||
dut_sum[0] += (int32_t)ec_dut_samples[0][i];
|
||||
dut_sum[1] += (int32_t)ec_dut_samples[1][i];
|
||||
}
|
||||
|
||||
real_avg = (float)dut_sum[0] / (float)AD5934_EC_AVERAGES;
|
||||
@@ -384,7 +408,7 @@ float AD5934_GetImpedance(float temperature_dut)
|
||||
/* 5. Calibration Logic Implementation */
|
||||
|
||||
// Mode: CALIBRATION SETUP (User is defining the reference magnitude)
|
||||
if(main_state == STATE_SETUP_CALIBRATION)
|
||||
if(main_state == STATE_PH4_DRY_EC_CALIBRATION || main_state == STATE_PH7_WET_EC_CALIBRATION)
|
||||
{
|
||||
return mag_dut;
|
||||
}
|
||||
@@ -393,7 +417,7 @@ float AD5934_GetImpedance(float temperature_dut)
|
||||
{
|
||||
slope = (AD5934_GAIN_FACTOR_1413US/(flash_data.ec1413_mag-flash_data.ec0_mag));
|
||||
|
||||
return(AD5934_GAIN_FACTOR_1413US + (mag_dut - flash_data.ec1413_mag) * slope);
|
||||
return(AD5934_GAIN_FACTOR_1413US + (AD5934_EC_Compensate_To_25C(mag_dut,temperature_dut) - flash_data.ec1413_mag) * slope);
|
||||
}
|
||||
else
|
||||
return 0.0f; // Calibration error fallback
|
||||
@@ -476,52 +500,97 @@ float AD5934_Linear_Correction(float raw_value)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Internal helper to interpolate conductivity from the temperature matrix.
|
||||
* @param temp The current temperature in Celsius.
|
||||
* @return Interpolated conductivity value in uS/cm.
|
||||
* @brief Temperature compensation with drift equal to 2%
|
||||
* @param admittance raw in uS/cm
|
||||
* @param temperature_celsius Temperature in degrees Celsius
|
||||
* @return admittance compensated
|
||||
*/
|
||||
float AD5934_Get_Target_Conductivity(float temp)
|
||||
float AD5934_EC_Compensate_To_25C(float ec_raw_uScm, float temp_C)
|
||||
{
|
||||
/* Matrix: Row 0 = Temperature (ºC), Row 1 = Conductivity (uS/cm) */
|
||||
const float matrix[2][12] = {
|
||||
{5, 10, 15, 18, 20, 22, 25, 30, 35, 40, 45, 50},
|
||||
{893, 1018, 1149, 1225, 1278, 1329, 1413, 1552, 1691, 1843, 1988, 2145}
|
||||
};
|
||||
|
||||
// Boundary Check: Lower
|
||||
if (temp <= matrix[0][0])
|
||||
temp = 5;
|
||||
float factor = 1.0f + AD5934_EC_ALPHA_PER_C * (temp_C - AD5934_EC_TEMP_REF_C);
|
||||
|
||||
// Boundary Check: Upper
|
||||
if (temp >= matrix[0][11])
|
||||
temp = 50;
|
||||
if (factor < 0.1f)
|
||||
factor = 0.1f;
|
||||
|
||||
// Linear Interpolation logic
|
||||
for (int i = 0; i < 11; i++)
|
||||
{
|
||||
if (temp >= matrix[0][i] && temp <= matrix[0][i+1])
|
||||
{
|
||||
float t0 = matrix[0][i];
|
||||
float t1 = matrix[0][i+1];
|
||||
float c0 = matrix[1][i];
|
||||
float c1 = matrix[1][i+1];
|
||||
|
||||
// Formula: y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0))
|
||||
return c0 + (temp - t0) * ((c1 - c0) / (t1 - t0));
|
||||
}
|
||||
}
|
||||
return (matrix[1][6]); // Mid point Fallback
|
||||
return (ec_raw_uScm / factor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calibrates EC sensor reading to 25°C reference point
|
||||
* @param temp_C Temperature of the liquid in Celsius
|
||||
* @return Temperature-compensated Correction factor value at 25°C reference
|
||||
*/
|
||||
float AD5934_EC_Calibrate_Temperature(float temp_C)
|
||||
{
|
||||
// Calibration data points for standard solution (1413 uS/cm)
|
||||
const float temps[] = {5, 10, 15, 18, 20, 22, 25, 30, 35, 40, 45, 50};
|
||||
const float conductivities[] = {893, 1018, 1149, 1225, 1278, 1329, 1413, 1552, 1691, 1843, 1988, 2145};
|
||||
|
||||
// Find the two nearest temperature points for interpolation
|
||||
int32_t temp_index = -1;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (temps[i] >= temp_C)
|
||||
{
|
||||
temp_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle boundary cases
|
||||
if (temp_index == -1) {
|
||||
// Temperature higher than max point (50°C)
|
||||
temp_index = 10;
|
||||
} else if (temp_index == 0) {
|
||||
// Temperature lower than min point (5°C)
|
||||
temp_index = 0;
|
||||
}
|
||||
|
||||
// Interpolate conductivity at measured temperature
|
||||
float temp1 = temps[temp_index - 1];
|
||||
float temp2 = temps[temp_index];
|
||||
float cond1 = conductivities[temp_index - 1];
|
||||
float cond2 = conductivities[temp_index];
|
||||
|
||||
// Linear interpolation to get conductivity at measured temperature
|
||||
float interpolated_cond = cond1 + (cond2 - cond1) * (temp_C - temp1) / (temp2 - temp1);
|
||||
|
||||
// Return real conductivity at the temperature
|
||||
return(interpolated_cond/1413.0f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calibrate AD5934 using dry probe and standard solution
|
||||
*
|
||||
* @param dry_probe_real Raw real value from dry probe measurement
|
||||
* @param dry_probe_imag Raw imaginary value from dry probe measurement
|
||||
* @param standard_real Raw real value from 1413 uS/cm standard solution
|
||||
* @param standard_imag Raw imaginary value from 1413 uS/cm standard solution
|
||||
* @return float Calibration factor for converting raw readings to admittance
|
||||
*/
|
||||
float AD5934_Calibrate(float dry_probe_real, float dry_probe_imag, float standard_real, float standard_imag)
|
||||
{
|
||||
// Calculate magnitude of dry probe reading
|
||||
float dry_magnitude = sqrtf(dry_probe_real * dry_probe_real + dry_probe_imag * dry_probe_imag);
|
||||
|
||||
// Calculate magnitude of standard solution reading
|
||||
float standard_magnitude = sqrtf(standard_real * standard_real + standard_imag * standard_imag);
|
||||
|
||||
// Calculate calibration factor based on known standard (1413 uS/cm)
|
||||
// This assumes the standard provides a known conductance value
|
||||
float calibration_factor = 1413.0f / standard_magnitude;
|
||||
|
||||
return calibration_factor;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* ADG715
|
||||
*****************************************************************************
|
||||
* @brief Writes data into a register.
|
||||
*
|
||||
* @param registerAddress - Address of the register.
|
||||
* @param registerValue - Data value to write.
|
||||
* @param bytesNumber - Number of bytes.
|
||||
* @param value - Data value to write.
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
@@ -549,78 +618,24 @@ void ADG715_ResetChannels(void)
|
||||
/******************************************************************************
|
||||
* @brief Update Channels on the ADG715 and stop-start AD5934.
|
||||
*
|
||||
* @param: channel = AD5934_CH_REF_100R, AD5934_CH_REF_1K, AD5934_CH_REF_10K, AD5934_CH_PT100, AD5934_CH_PT1000 or AD5934_CH_EC
|
||||
* @param: channel = AD5934_CH_REF_100R, AD5934_CH_REF_1K, AD5934_CH_REF_10K, AD5934_CH_PT100, AD5934_CH_PT1000, AD5934_CH_EC, ...
|
||||
*
|
||||
* @return none.
|
||||
******************************************************************************/
|
||||
void ADG715_Update(uint8_t channel)
|
||||
void ADG715_Update(AD5934_Channel_t channel)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
// Garante que o índice recebido não ultrapassa os limites do vetor
|
||||
if (channel >= AD5934_CH_MAX)
|
||||
return;
|
||||
|
||||
// Disconnect all Analog Switches
|
||||
ADG715_ResetChannels();
|
||||
// Envia o byte combinado via I2C (Make-before-break nativo por barramento)
|
||||
ADG715_SetRegisterValue(ADG715_Channel_Map[channel]);
|
||||
|
||||
// Set the pair of connections
|
||||
if(channel == AD5934_CH_REF100R_LOW_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW1, ADG715_SW4); // Rf = 150R, Ch = Ref_100R
|
||||
}
|
||||
else if(channel == AD5934_CH_REF100R_MID_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW2, ADG715_SW4); // Rf = 1k5, Ch = Ref_100R
|
||||
}
|
||||
else if(channel == AD5934_CH_REF100R_HIGH_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW3, ADG715_SW4); // Rf = 6k2, Ch = Ref_100R
|
||||
}
|
||||
else if(channel == AD5934_CH_REF1K_LOW_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW1, ADG715_SW5); // Rf = 150R, Ch = Ref_1k
|
||||
}
|
||||
else if(channel == AD5934_CH_REF1K_MID_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW2, ADG715_SW5); // Rf = 1k5, Ch = Ref_1k
|
||||
}
|
||||
else if(channel == AD5934_CH_REF1K_HIGH_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW3, ADG715_SW5); // Rf = 6k2, Ch = Ref_1k
|
||||
}
|
||||
else if(channel == AD5934_CH_REF10K_LOW_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW1, ADG715_SW6); // Rf = 150R, Ch = Ref_10k
|
||||
}
|
||||
else if(channel == AD5934_CH_REF10K_MID_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW2, ADG715_SW6); // Rf = 1k5, Ch = Ref_10k
|
||||
}
|
||||
else if(channel == AD5934_CH_REF10K_HIGH_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW3, ADG715_SW6); // Rf = 6k2, Ch = Ref_10k
|
||||
}
|
||||
else if(channel == AD5934_CH_RTD_LOW_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW1, ADG715_SW7); // Rf = 150R, Ch = RTD
|
||||
}
|
||||
else if(channel == AD5934_CH_RTD_MID_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW2, ADG715_SW7); // Rf = 1k5, Ch = RTD
|
||||
}
|
||||
else if(channel == AD5934_CH_RTD_HIGH_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW3, ADG715_SW7); // Rf = 6k2, Ch = RTD
|
||||
}
|
||||
else if(channel == AD5934_CH_EC_LOW_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW1, ADG715_SW8); // Rf = 150R, Ch = EC
|
||||
}
|
||||
else if(channel == AD5934_CH_EC_MID_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW2, ADG715_SW8); // Rf = 1k5, Ch = EC
|
||||
}
|
||||
else if(channel == AD5934_CH_EC_HIGH_GAIN)
|
||||
{
|
||||
ADG715_SetChannels(ADG715_SW3, ADG715_SW8); // Rf = 6k2, Ch = EC
|
||||
}
|
||||
// Gestão inteligente do delay de acomodação
|
||||
if (channel >= AD5934_CH_EC_LOW_GAIN)
|
||||
HAL_Delay(20); // Canais de Condutividade Elétrica (CE) necessitam de maior estabilização química
|
||||
else
|
||||
HAL_Delay(10); // Resistores puros e RTD estabilizam mais rapidamente
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ int16_t ADSgetLastConversionResults(ADS1015_I2C *i2c) {
|
||||
}
|
||||
}
|
||||
|
||||
float ADSCalculate_ph_Volts(void)
|
||||
float ADSCalculate_ph_mV(void) // pH in mV
|
||||
{
|
||||
float ph_dut_sum;
|
||||
uint8_t i;
|
||||
@@ -279,14 +279,12 @@ float ADSCalculate_ph_Volts(void)
|
||||
for (i = (ADS1015_PH_AVERAGES-1); i > 0; i--)
|
||||
ph_dut_samples[i] = ph_dut_samples[i-1];
|
||||
|
||||
ph_dut_samples[0] = (((float)(2048 - ADSreadADC_Differential_0_1(&i2c)) * ADS1015_ADC_VREF) / ADS1015_ADC_MAX); // 1. Converter leitura bruta do ADC para tensão real (Volts)
|
||||
ph_dut_samples[0] = (((float)(ADSreadADC_Differential_0_1(&i2c)) * ADS1015_ADC_VREF) / ADS1015_ADC_MAX); // 1. Converter leitura bruta do ADC para tensão real (mV)
|
||||
|
||||
for (i = 0, ph_dut_sum=0; i < ADS1015_PH_AVERAGES; i++)
|
||||
ph_dut_sum += ph_dut_samples[i];
|
||||
|
||||
ph_dut_sum /= ADS1015_PH_AVERAGES;
|
||||
|
||||
return (ph_dut_sum);
|
||||
return (ADSRound_Float_Precision((ph_dut_sum/ADS1015_PH_AVERAGES),2));
|
||||
}
|
||||
|
||||
|
||||
@@ -301,43 +299,24 @@ float ADSCalculate_ph_Volts(void)
|
||||
*
|
||||
* @return float Valor de pH calculado (0.0 a 14.0).
|
||||
*/
|
||||
|
||||
float ADSCalculate_ph_Compensated(float temp_dut)
|
||||
{
|
||||
// 1. Converter leitura bruta do ADC para tensão real (Volts)
|
||||
float v_measured = ((float)(2048 - ADSreadADC_Differential_0_1(&i2c)) * ADS1015_ADC_VREF) / ADS1015_ADC_MAX;
|
||||
|
||||
// 2. Calcular o Slope original (medido na temperatura da calibração)
|
||||
// Delta pH é fixo em 3.0 (de pH 7 para pH 4)
|
||||
float delta_v_calib = flash_data.ph7_volts - flash_data.ph4_volts;
|
||||
float dut_mV = ADSCalculate_ph_mV();
|
||||
|
||||
if (delta_v_calib == 0.0f)
|
||||
{
|
||||
return 0.0f; // Proteção contra erro de calibração/divisão por zero
|
||||
}
|
||||
float t_cal_k = flash_data.ph_temperature + 273.15f;
|
||||
float t_dut_k = temp_dut + 273.15f;
|
||||
|
||||
float slope_at_calib = PH_DELTA_CALIB / delta_v_calib;
|
||||
float slope_dut = flash_data.ph_slope_mV * (t_dut_k / t_cal_k);
|
||||
|
||||
// 3. Calcular o Fator de Correção Térmica (Equação de Nernst)
|
||||
float temp_k_now = temp_dut + ADS1015_KELVIN_OFFSET;
|
||||
float temp_k_ref = flash_data.temperature_value + ADS1015_KELVIN_OFFSET;
|
||||
float ph_result = (flash_data.ph7_real + ((dut_mV - flash_data.ph7_mV) / slope_dut));
|
||||
|
||||
// Fator: (T_atual / T_referencia)
|
||||
float thermal_factor = temp_k_now / temp_k_ref;
|
||||
return (ADSRound_Float_Precision(ph_result,2));
|
||||
|
||||
/*
|
||||
* 4. Cálculo Final do pH
|
||||
* O Slope ajustado para a temperatura atual é: slope_at_calib / thermal_factor
|
||||
* Fórmula: pH = pH_ref + (V_medido - V_ref_7) * Slope_ajustado
|
||||
*/
|
||||
float ph_result = 7.0f + ((v_measured - flash_data.ph7_volts) * (slope_at_calib / thermal_factor));
|
||||
|
||||
// 5. Clamping (Garantir limites físicos)
|
||||
if (ph_result < 0.0f) ph_result = 0.0f;
|
||||
if (ph_result > 14.0f) ph_result = 14.0f;
|
||||
|
||||
return ph_result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculates the pH value without temperature compensation.
|
||||
*
|
||||
@@ -361,7 +340,7 @@ float ADSCalculate_ph_Uncompensated(void)
|
||||
* PH_DELTA_CALIB is a constant representing the pH difference between
|
||||
* calibration points (e.g., |7.0 - 4.0| = 3.0).
|
||||
*/
|
||||
float delta_v_calib = flash_data.ph7_volts - flash_data.ph4_volts;
|
||||
float delta_v_calib = flash_data.ph7_mV - flash_data.ph4_mV;
|
||||
|
||||
/* Safety check: Prevent division by zero if calibration data is invalid */
|
||||
if (delta_v_calib == 0.0f)
|
||||
@@ -377,7 +356,7 @@ float ADSCalculate_ph_Uncompensated(void)
|
||||
* Formula: pH = pH_ref + (V_measured - V_ref_7) * Slope
|
||||
* Where pH_ref is 7.0.
|
||||
*/
|
||||
float ph_result = 7.0f + ((v_measured - flash_data.ph7_volts) * slope_at_calib);
|
||||
float ph_result = 7.0f + ((v_measured - flash_data.ph7_mV) * slope_at_calib);
|
||||
|
||||
/* 4. Clamping (Ensure physical limits of the pH scale) */
|
||||
if (ph_result < 0.0f)
|
||||
@@ -410,8 +389,10 @@ float ADSinterpolate_ph(float temp_target, uint8_t row_index)
|
||||
uint8_t i = 0;
|
||||
|
||||
/* Boundary Check: Clamp to first or last index if out of range */
|
||||
if (temp_target <= lut_matrix_buffer_ph[0][0]) return lut_matrix_buffer_ph[row_index][0];
|
||||
if (temp_target >= lut_matrix_buffer_ph[0][ADS1015_PH_TEMP_INTER_POINTS-1]) return lut_matrix_buffer_ph[row_index][ADS1015_PH_TEMP_INTER_POINTS-1];
|
||||
if (temp_target <= lut_matrix_buffer_ph[0][0])
|
||||
return lut_matrix_buffer_ph[row_index][0];
|
||||
if (temp_target >= lut_matrix_buffer_ph[0][ADS1015_PH_TEMP_INTER_POINTS-1])
|
||||
return lut_matrix_buffer_ph[row_index][ADS1015_PH_TEMP_INTER_POINTS-1];
|
||||
|
||||
/* Find interpolation interval */
|
||||
while (i < (ADS1015_PH_TEMP_INTER_POINTS-1) && lut_matrix_buffer_ph[0][i+1] < temp_target)
|
||||
@@ -428,4 +409,21 @@ float ADSinterpolate_ph(float temp_target, uint8_t row_index)
|
||||
return y0 + (temp_target - x0) * ((y1 - y0) / (x1 - x0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reduz a precisão decimal de um float através de truncamento.
|
||||
*
|
||||
* @param valor O valor float original.
|
||||
* @param casas_decimais Quantidade de casas que devem permanecer após a vírgula.
|
||||
* @return float O valor com as casas decimais excedentes removidas.
|
||||
*/
|
||||
float ADSRound_Float_Precision(float value, uint8_t number_of_decimals)
|
||||
{
|
||||
float multiply = 1.0f;
|
||||
|
||||
for (uint8_t i = 0; i < number_of_decimals; i++)
|
||||
multiply *= 10.0f;
|
||||
|
||||
return roundf(value * multiply) / multiply;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -67,14 +67,16 @@ uint8_t rs485_text[6];
|
||||
|
||||
|
||||
uint8_t newline[]={'\n','\0'};
|
||||
uint8_t doubleSpace[]={'_','_'};
|
||||
uint8_t doubleSpace[]={'_','_','\0'};
|
||||
uint8_t newline_ph[]={'_','p','H','\n','\0'};
|
||||
uint8_t newline_admi[]={'_','u','S','\n','\0'};
|
||||
uint8_t newline_temp[]={' ','°','C','\n','\0'};
|
||||
uint8_t newline_imag[]={'_','O','h','m','\n','\0'};
|
||||
uint8_t newline_485[]={'_','a','d','\n','\0'};
|
||||
uint8_t minus[]={'-',' '};
|
||||
|
||||
uint8_t ad_t[]={'A','d',':',' ','\0'};
|
||||
uint8_t ph_t[]={'p','H',':',' ','\0'};
|
||||
uint8_t tm_t[]={'T','M',':',' ','\0'};
|
||||
|
||||
uint8_t main_state = STATE_RUNNING_OK;
|
||||
uint8_t rs485_address=0;
|
||||
@@ -121,7 +123,7 @@ int main(void)
|
||||
uint32_t previous_millis_red = 0;
|
||||
uint32_t current_millis;
|
||||
|
||||
float temperature_RTD, admittance_EC, ph_compensated;
|
||||
float temperature_RTD, admittance_EC, refResistance, update_value, ph7_interp, ph4_interp, ph_compensated;
|
||||
|
||||
|
||||
|
||||
@@ -173,9 +175,11 @@ int main(void)
|
||||
// Initialize RS-485 driver
|
||||
rs485_init();
|
||||
|
||||
ADS1015(&i2c, &hi2c1, ADS_ADDR_GND);
|
||||
ADSsetGain(&i2c, GAIN_SIXTEEN);
|
||||
|
||||
ADS1015(&i2c, &hi2c1, ADS_ADDR_GND);
|
||||
ADSsetGain(&i2c, GAIN_FOUR);
|
||||
|
||||
ADG715_ResetChannels();
|
||||
// Start CE and RTD Measurement
|
||||
AD5934_Init();
|
||||
|
||||
@@ -186,19 +190,28 @@ int main(void)
|
||||
/* Infinite loop */
|
||||
/* USER CODE BEGIN WHILE */
|
||||
|
||||
for(i=0;i<AD5934_TEMP_AVERAGES;i++) // Loop to get stability and get averages
|
||||
{
|
||||
refResistance = AD5934_Get_Ref_Resistance(); // On Board Resistor
|
||||
temperature_RTD = AD5934_GetTemperature(refResistance); // Liquid Temperature is stored
|
||||
admittance_EC = AD5934_GetImpedance(temperature_RTD);
|
||||
ph_compensated = ADSCalculate_ph_Compensated(temperature_RTD);
|
||||
}
|
||||
|
||||
|
||||
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3) == GPIO_PIN_RESET) // When PB3 (with internal pull up) in the Prog Header is set to GND
|
||||
{
|
||||
|
||||
main_state = STATE_SETUP_CALIBRATION;
|
||||
main_state = STATE_PH4_DRY_EC_CALIBRATION;
|
||||
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); // Red LED On
|
||||
|
||||
for(i=0;i<32;i++) // Loop to get stability and get averages
|
||||
for(i=0;i<(2*AD5934_TEMP_AVERAGES);i++) // Loop to get stability and get averages
|
||||
{
|
||||
flash_data.ph4_volts = ADSCalculate_ph_Volts();
|
||||
flash_data.temperature_value = AD5934_GetTemperature(); // Air Temperature is not stored, just used to calculate impedance
|
||||
flash_data.ec0_mag = AD5934_GetImpedance(flash_data.temperature_value); // Dry Probe
|
||||
flash_data.ph4_mV = ADSCalculate_ph_mV();
|
||||
temperature_RTD = AD5934_GetTemperature(refResistance); // Air Temperature is not used in the function
|
||||
flash_data.ec0_mag = AD5934_GetImpedance(temperature_RTD); // Dry Probe
|
||||
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) == GPIO_PIN_SET)
|
||||
flash_data.EC10mS_EC5mS_switch = AD5934_CH_EC_HIGH_GAIN; // 5mS/cm option
|
||||
else
|
||||
@@ -209,29 +222,50 @@ int main(void)
|
||||
flash_data.PT100_PT1000_switch = AD5934_CH_RTD_MID_GAIN; //PT1000 option
|
||||
|
||||
}
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); // Green LED On
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
|
||||
|
||||
|
||||
while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3) == GPIO_PIN_RESET);
|
||||
HAL_Delay(500);
|
||||
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); // Green LED On
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
|
||||
main_state = STATE_PH7_WET_EC_CALIBRATION;
|
||||
|
||||
for(i=0;i<32;i++) // Loop to get stability and get averages
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); // Red LED On
|
||||
|
||||
|
||||
|
||||
for(i=0;i<(2*AD5934_TEMP_AVERAGES);i++) // Loop to get stability and get averages
|
||||
{
|
||||
flash_data.temperature_value = AD5934_GetTemperature(); // Liquid Temperature is stored
|
||||
flash_data.ph7_volts = ADSCalculate_ph_Volts();
|
||||
flash_data.ec1413_mag = AD5934_GetImpedance(flash_data.temperature_value); // Get the impedance of the reference liquid
|
||||
Flash_Save_Page(&flash_data); // Store Calibration parameters in Flash
|
||||
temperature_RTD = AD5934_GetTemperature(refResistance); // Liquid Temperature is stored
|
||||
flash_data.ec_factor = AD5934_EC_Calibrate_Temperature(temperature_RTD);
|
||||
flash_data.ph7_mV = ADSCalculate_ph_mV();
|
||||
flash_data.ec1413_mag = AD5934_GetImpedance(temperature_RTD)*flash_data.ec_factor; // Get the magnitude of the reference liquid and compensate it to 25ºC
|
||||
|
||||
}
|
||||
|
||||
ph7_interp = ADSinterpolate_ph(temperature_RTD,ADS1015_PH_7_BUFFER_ROW);
|
||||
ph4_interp = ADSinterpolate_ph(temperature_RTD,ADS1015_PH_4_BUFFER_ROW);
|
||||
|
||||
flash_data.ph_temperature = temperature_RTD;
|
||||
flash_data.ph_slope_mV = (flash_data.ph7_mV - flash_data.ph4_mV) / (ph7_interp - ph4_interp);
|
||||
flash_data.ph7_real = ph7_interp;
|
||||
|
||||
Flash_Save_Page(&flash_data); // Store Calibration parameters in Flash
|
||||
|
||||
|
||||
HAL_Delay(500);
|
||||
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); // Green LED On
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); // Red LED On
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
|
||||
|
||||
|
||||
main_state = STATE_RUNNING_OK;
|
||||
|
||||
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
@@ -256,15 +290,6 @@ int main(void)
|
||||
|
||||
}
|
||||
|
||||
temperature_RTD = AD5934_GetTemperature();
|
||||
FloatToString(tempString, temperature_RTD);
|
||||
status0 = rs485_send_broadcast(tempString, (strlen((char*)tempString)-1));
|
||||
status1 = rs485_send_broadcast(newline_temp, strlen((char*)newline_temp));
|
||||
|
||||
admittance_EC = AD5934_GetImpedance(temperature_RTD);
|
||||
FloatToString(tempString, admittance_EC);
|
||||
status0 = rs485_send_broadcast(tempString, (strlen((char*)tempString)-1));
|
||||
status1 = rs485_send_broadcast(newline_admi, strlen((char*)newline_admi));
|
||||
|
||||
}
|
||||
|
||||
@@ -283,12 +308,26 @@ int main(void)
|
||||
|
||||
}
|
||||
|
||||
status1 = rs485_send_broadcast(tm_t, strlen((char*)tm_t));
|
||||
temperature_RTD = AD5934_GetTemperature(refResistance);
|
||||
FloatToString(tempString, temperature_RTD);
|
||||
status0 = rs485_send_broadcast(tempString, (strlen((char*)tempString)-1));
|
||||
status1 = rs485_send_broadcast(newline_temp, strlen((char*)newline_temp));
|
||||
|
||||
ph_compensated = ADSCalculate_ph_Uncompensated();
|
||||
status1 = rs485_send_broadcast(ad_t, strlen((char*)ad_t));
|
||||
admittance_EC = AD5934_GetImpedance(temperature_RTD);
|
||||
FloatToString(tempString, admittance_EC);
|
||||
status0 = rs485_send_broadcast(tempString, (strlen((char*)tempString)-1));
|
||||
status1 = rs485_send_broadcast(newline_admi, strlen((char*)newline_admi));
|
||||
|
||||
status1 = rs485_send_broadcast(ph_t, strlen((char*)ph_t));
|
||||
ph_compensated = 10*ADSCalculate_ph_mV();//ADSCalculate_ph_Compensated(temperature_RTD);
|
||||
FloatToString(tempString, ph_compensated);
|
||||
|
||||
status0 = rs485_send_broadcast(tempString, (strlen((char*)tempString)-1));
|
||||
status1 = rs485_send_broadcast(newline_ph, strlen((char*)newline_ph));
|
||||
|
||||
status1 = rs485_send_broadcast(newline, strlen((char*)newline));
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user