Compare commits
2 Commits
23e754ab2a
...
850d84140e
Author | SHA1 | Date | |
---|---|---|---|
850d84140e | |||
8af10dd52c |
5949
measurement-data/1000OhmSampling1ms.csv
Normal file
5949
measurement-data/1000OhmSampling1ms.csv
Normal file
File diff suppressed because it is too large
Load Diff
12577
measurement-data/1000OhmSampling1ms_later.csv
Normal file
12577
measurement-data/1000OhmSampling1ms_later.csv
Normal file
File diff suppressed because it is too large
Load Diff
104974
measurement-data/1000OhmSamplingTimerTriggered800ARR.csv
Normal file
104974
measurement-data/1000OhmSamplingTimerTriggered800ARR.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -75,6 +75,36 @@
|
|||||||
" return temp"
|
" return temp"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def plot_histogram(ax, data, bin_count, title, signal_name):\n",
|
||||||
|
" n, bins, patches = ax.hist(data, bin_count, density=1, color='navy')\n",
|
||||||
|
" mu = np.mean(data)\n",
|
||||||
|
" sigma = np.std(data)\n",
|
||||||
|
" y = ((1 / (np.sqrt(2 * np.pi) * sigma)) * np.exp(-0.5 * (1 / sigma * (bins - mu))**2))\n",
|
||||||
|
" ax.plot(bins, y, color='darkorange')\n",
|
||||||
|
" ax.set_title(title)\n",
|
||||||
|
" ax.set_ylabel(signal_name + ' probability (normalized)')\n",
|
||||||
|
" ax.set_xlabel(signal_name)\n",
|
||||||
|
" # Plot sigma and mu lines\n",
|
||||||
|
" ax.axvline(x=mu-sigma, ls='--', color='magenta')\n",
|
||||||
|
" ax.axvline(x=mu+sigma, ls='--', color='magenta')\n",
|
||||||
|
" ax.axvline(x=mu, ls='--', color='lawngreen')\n",
|
||||||
|
"\n",
|
||||||
|
" #Plot textbox\n",
|
||||||
|
" textstr = '\\n'.join((\n",
|
||||||
|
" r'$\\mu=%.2f$' % (mu, ),\n",
|
||||||
|
" r'$\\sigma=%.3f$' % (sigma, ),\n",
|
||||||
|
" r'$N_{Sa} =%d$' % (len(data), )))\n",
|
||||||
|
" props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)\n",
|
||||||
|
" ax.text(0.05, 0.95, textstr, transform=ax.transAxes, fontsize=14,\n",
|
||||||
|
" verticalalignment='top', bbox=props)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
@ -117,33 +147,14 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"fig, axes = plt.subplots(nrows=3, ncols=3, figsize=(28,20))\n",
|
|
||||||
"plot_data = [(one_k_sampling_trafo, '1 kOhm Sampling Transformer powered', 0), (two_k_sampling_trafo, '2 kOhm Sampling Transformer powered' , 0), (constant_sampling, '1 kOhm Sampling', 100)]\n",
|
"plot_data = [(one_k_sampling_trafo, '1 kOhm Sampling Transformer powered', 0), (two_k_sampling_trafo, '2 kOhm Sampling Transformer powered' , 0), (constant_sampling, '1 kOhm Sampling', 100)]\n",
|
||||||
"signal_list = [('adc_results.pa2_raw', 20), ('ext_lf_corr', 20), ('temp_calculated', 20)]\n",
|
"signal_list = [('ext_lf_corr', 20), ('temp_calculated', 20)]\n",
|
||||||
|
"\n",
|
||||||
|
"fig, axes = plt.subplots(nrows=len(plot_data), ncols=len(signal_list), figsize=(28,20))\n",
|
||||||
"\n",
|
"\n",
|
||||||
"for (data_df, title, start_idx), ax_rows in zip(plot_data, axes):\n",
|
"for (data_df, title, start_idx), ax_rows in zip(plot_data, axes):\n",
|
||||||
" for ax,sig in zip(ax_rows, signal_list):\n",
|
" for ax,sig in zip(ax_rows, signal_list):\n",
|
||||||
" n, bins, patches = ax.hist(data_df[sig[0]][start_idx:], sig[1], density=1, color='navy')\n",
|
" plot_histogram(ax, data_df[sig[0]][start_idx:], sig[1], title,sig[0])\n",
|
||||||
" mu = np.mean(data_df[sig[0]][start_idx:])\n",
|
|
||||||
" sigma = np.std(data_df[sig[0]][start_idx:])\n",
|
|
||||||
" y = ((1 / (np.sqrt(2 * np.pi) * sigma)) * np.exp(-0.5 * (1 / sigma * (bins - mu))**2))\n",
|
|
||||||
" ax.plot(bins, y, color='darkorange')\n",
|
|
||||||
" ax.set_title(title)\n",
|
|
||||||
" ax.set_ylabel(sig[0] + ' probability (normalized)')\n",
|
|
||||||
" ax.set_xlabel(sig[0])\n",
|
|
||||||
" # Plot sigma and mu lines\n",
|
|
||||||
" ax.axvline(x=mu-sigma, ls='--', color='magenta')\n",
|
|
||||||
" ax.axvline(x=mu+sigma, ls='--', color='magenta')\n",
|
|
||||||
" ax.axvline(x=mu, ls='--', color='lawngreen')\n",
|
|
||||||
" \n",
|
|
||||||
" #Plot textbox\n",
|
|
||||||
" textstr = '\\n'.join((\n",
|
|
||||||
" r'$\\mu=%.2f$' % (mu, ),\n",
|
|
||||||
" r'$\\sigma=%.2f$' % (sigma, ),\n",
|
|
||||||
" r'$N_{Sa} =%d$' % (len(data_df[sig[0]][start_idx:], ))))\n",
|
|
||||||
" props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)\n",
|
|
||||||
" ax.text(0.05, 0.95, textstr, transform=ax.transAxes, fontsize=14,\n",
|
|
||||||
" verticalalignment='top', bbox=props)\n",
|
|
||||||
"\n",
|
"\n",
|
||||||
" \n",
|
" \n",
|
||||||
"plt.tight_layout()\n",
|
"plt.tight_layout()\n",
|
||||||
@ -310,6 +321,66 @@
|
|||||||
"ax.set_title('Cooldown without airflow | Convection has to be taken into account') \n",
|
"ax.set_title('Cooldown without airflow | Convection has to be taken into account') \n",
|
||||||
"plt.show()"
|
"plt.show()"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"---\n",
|
||||||
|
"# Target Implementation Sampling of 1k Resistor"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Histograms"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Read in data\n",
|
||||||
|
"kilo_ohm_sampling1 = pd.read_csv(r'1000OhmSampling1ms.csv')\n",
|
||||||
|
"kilo_ohm_sampling2 = pd.read_csv(r'1000OhmSampling1ms_later.csv')\n",
|
||||||
|
"kilo_ohm_sampling2_fast = pd.read_csv(r'1000OhmSamplingTimerTriggered800ARR.csv')\n",
|
||||||
|
"plot_data_tuples = [(kilo_ohm_sampling1, 'Day 1 Sampling'), (kilo_ohm_sampling2, 'Day 2 sampling'), (kilo_ohm_sampling2_fast,'Day 2 sampling faster (ARR=700)')]\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"# def plot_histogram(ax, data, bin_count, title, signal_name):\n",
|
||||||
|
"# def calculate_temp_for_df(data_frame, resistance_col_name='ext_lf_corr', temp_col_name='temp_calculated'):\n",
|
||||||
|
"\n",
|
||||||
|
"fig, axes = plt.subplots(nrows=len(plot_data_tuples), ncols=2, sharex='col', figsize=(28, 16))\n",
|
||||||
|
"\n",
|
||||||
|
"for df, title in plot_data_tuples:\n",
|
||||||
|
" calculate_temp_for_df(df, resistance_col_name='pt1000_res_raw_lf')\n",
|
||||||
|
"\n",
|
||||||
|
"for (df,title),ax in zip(plot_data_tuples, axes):\n",
|
||||||
|
" plot_histogram(ax[0], df['pt1000_res_raw_lf'], 20, title, 'PT1000 Resistance')\n",
|
||||||
|
" plot_histogram(ax[1], df['temp_calculated'], 20, title, 'Calculated Temperature in °C')\n",
|
||||||
|
"\n",
|
||||||
|
"plt.tight_layout()\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"calc_temp(1097)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
|
@ -1,30 +1,98 @@
|
|||||||
#include <adc-meas.h>
|
#include <adc-meas.h>
|
||||||
#include <stm32f4xx.h>
|
#include <stm32f4xx.h>
|
||||||
|
#include <core_cm4.h>
|
||||||
#include <stm32-gpio-macros.h>
|
#include <stm32-gpio-macros.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static float pt1000_offset;
|
static float pt1000_offset;
|
||||||
static float pt1000_sens_dev;
|
static float pt1000_sens_dev;
|
||||||
static bool calibration_active;
|
static bool calibration_active;
|
||||||
static float filter_alpha;
|
static float filter_alpha;
|
||||||
static float pt1000_adc_raw_lf;
|
static volatile float pt1000_res_raw_lf;
|
||||||
static bool streaming_active;
|
static volatile bool streaming_active;
|
||||||
static volatile bool filter_ready;
|
static volatile bool filter_ready;
|
||||||
static volatile enum adc_p1000_error pt1000_error;
|
static volatile enum adc_pt1000_error pt1000_error;
|
||||||
|
static volatile uint8_t *dma_flag_ptr = NULL;
|
||||||
|
static uint32_t filter_startup_cnt;
|
||||||
|
|
||||||
#define ADC_TO_RES(adc) ((float)(adc) / 4096.0f * 2500.0f)
|
#define ADC_TO_RES(adc) ((float)(adc) / 4096.0f * 2500.0f)
|
||||||
|
|
||||||
|
static inline void adc_pt1000_stop_sample_frequency_timer()
|
||||||
|
{
|
||||||
|
TIM2->CR1 &= ~TIM_CR1_CEN;
|
||||||
|
RCC->APB1ENR &= ~RCC_APB1ENR_TIM2EN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void adc_pt1000_setup_sample_frequency_timer()
|
||||||
|
{
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||||
|
|
||||||
|
/* Divide 42 MHz peripheral clock by 42 */
|
||||||
|
TIM2->PSC = (42UL-1UL);
|
||||||
|
|
||||||
|
/* Reload value */
|
||||||
|
TIM2->ARR = ADC_PT1000_SAMPLE_CNT_DELAY;
|
||||||
|
|
||||||
|
/* Trigger output at update event */
|
||||||
|
TIM2->CR2 = TIM_CR2_MMS_1;
|
||||||
|
|
||||||
|
/* Start Timer in downcounting mode with autoreload */
|
||||||
|
TIM2->CR1 = TIM_CR1_DIR | TIM_CR1_CEN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void adc_pt1000_disable_adc()
|
||||||
|
{
|
||||||
|
ADC1->CR2 &= ~ADC_CR2_ADON;
|
||||||
|
DMA2_Stream0->CR = 0;
|
||||||
|
RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN;
|
||||||
|
}
|
||||||
|
|
||||||
void adc_pt1000_setup_meas()
|
void adc_pt1000_setup_meas()
|
||||||
{
|
{
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||||
RCC->AHB1ENR |= ADC_PT1000_PORT_RCC_MASK;
|
RCC->AHB1ENR |= ADC_PT1000_PORT_RCC_MASK;
|
||||||
ADC_PT1000_PORT->MODER |= ANALOG(ADC_PT1000_PIN);
|
ADC_PT1000_PORT->MODER |= ANALOG(ADC_PT1000_PIN);
|
||||||
|
|
||||||
|
/* Set S&H time for PT1000 ADC channel */
|
||||||
|
#if ADC_PT1000_CHANNEL < 10
|
||||||
|
ADC1->SMPR2 |= (7U << (3*ADC_PT1000_CHANNEL));
|
||||||
|
#else
|
||||||
|
ADC1->SMPR1 |= (7U << (3*(ADC_PT1000_CHANNEL-10)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ADC->CCR |= (0x2<<16);
|
||||||
|
|
||||||
|
/* Set watchdog limits */
|
||||||
|
ADC1->HTR = ADC_PT1000_UPPER_WATCHDOG;
|
||||||
|
ADC1->LTR = ADC_PT1000_LOWER_WATCHDOG;
|
||||||
|
|
||||||
|
/* Set length of sequence to 1 */
|
||||||
|
ADC1->SQR1 = (0UL<<20);
|
||||||
|
|
||||||
|
/* Set channel as 1st element in sequence */
|
||||||
|
ADC1->SQR3 = (ADC_PT1000_CHANNEL<<0);
|
||||||
|
|
||||||
|
ADC1->CR1 = ADC_CR1_OVRIE | ADC_CR1_AWDEN | ADC_CR1_EOCIE;
|
||||||
|
ADC1->CR2 = ADC_CR2_EXTEN_0 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_ADON;
|
||||||
|
|
||||||
|
adc_pt1000_set_moving_average_filter_param(ADC_PT1000_FILTER_WEIGHT);
|
||||||
|
adc_pt1000_set_resistance_calibration(0, 0, false);
|
||||||
|
streaming_active = false;
|
||||||
|
pt1000_res_raw_lf = 0.0f;
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(ADC_IRQn);
|
||||||
|
|
||||||
|
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
|
||||||
|
|
||||||
|
adc_pt1000_setup_sample_frequency_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_pt1000_set_moving_average_filter_param(float alpha)
|
void adc_pt1000_set_moving_average_filter_param(float alpha)
|
||||||
{
|
{
|
||||||
filter_alpha = alpha;
|
filter_alpha = alpha;
|
||||||
|
filter_ready = false;
|
||||||
|
filter_startup_cnt = ADC_FILTER_STARTUP_CYCLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_pt1000_set_resistance_calibration(float offset, float sensitivity_deviation, bool active)
|
void adc_pt1000_set_resistance_calibration(float offset, float sensitivity_deviation, bool active)
|
||||||
@ -44,6 +112,15 @@ void adc_pt1000_get_resistance_calibration(float *offset, float *sensitivity_dev
|
|||||||
*active = calibration_active;
|
*active = calibration_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float adc_pt1000_apply_calibration(float raw_resistance)
|
||||||
|
{
|
||||||
|
if (calibration_active)
|
||||||
|
return pt1000_res_raw_lf * (1.0f + pt1000_sens_dev) + pt1000_offset;
|
||||||
|
else
|
||||||
|
return raw_resistance;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int adc_pt1000_get_current_resistance(float *resistance)
|
int adc_pt1000_get_current_resistance(float *resistance)
|
||||||
{
|
{
|
||||||
int ret_val = 0;
|
int ret_val = 0;
|
||||||
@ -51,24 +128,22 @@ int adc_pt1000_get_current_resistance(float *resistance)
|
|||||||
if (!resistance)
|
if (!resistance)
|
||||||
return -1001;
|
return -1001;
|
||||||
|
|
||||||
if (calibration_active)
|
*resistance = adc_pt1000_apply_calibration(pt1000_res_raw_lf);
|
||||||
*resistance = ADC_TO_RES(pt1000_adc_raw_lf) * (1 + pt1000_sens_dev) + pt1000_offset;
|
|
||||||
else
|
|
||||||
*resistance = ADC_TO_RES(pt1000_adc_raw_lf);
|
|
||||||
|
|
||||||
if (adc_pt1000_check_error()) {
|
if (adc_pt1000_check_error()) {
|
||||||
ret_val = -100;
|
ret_val = -100;
|
||||||
goto return_value;
|
goto return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!filter_ready) {
|
||||||
|
ret_val = 2;
|
||||||
|
goto return_value;
|
||||||
|
}
|
||||||
|
|
||||||
if (streaming_active) {
|
if (streaming_active) {
|
||||||
ret_val = 1;
|
ret_val = 1;
|
||||||
goto return_value;
|
goto return_value;
|
||||||
}
|
}
|
||||||
if (!filter_ready)
|
|
||||||
{
|
|
||||||
ret_val = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return_value:
|
return_value:
|
||||||
return ret_val;
|
return ret_val;
|
||||||
@ -76,7 +151,44 @@ return_value:
|
|||||||
|
|
||||||
int adc_pt1000_stream_raw_value_to_memory(uint16_t *adc_array, uint32_t length, volatile uint8_t *flag_to_set)
|
int adc_pt1000_stream_raw_value_to_memory(uint16_t *adc_array, uint32_t length, volatile uint8_t *flag_to_set)
|
||||||
{
|
{
|
||||||
|
static volatile uint8_t alt_flag;
|
||||||
|
int ret_val = 0;
|
||||||
|
|
||||||
|
if (!(ADC1->CR2 & ADC_CR2_ADON))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!adc_array || !length)
|
||||||
|
return -1000;
|
||||||
|
|
||||||
|
if (flag_to_set)
|
||||||
|
dma_flag_ptr = flag_to_set;
|
||||||
|
else
|
||||||
|
dma_flag_ptr = &alt_flag;
|
||||||
|
|
||||||
|
*dma_flag_ptr = 0;
|
||||||
|
streaming_active = true;
|
||||||
|
|
||||||
|
ADC1->CR2 &= ~ADC_CR2_ADON;
|
||||||
|
DMA2_Stream0->CR &= ~DMA_SxCR_EN;
|
||||||
|
|
||||||
|
DMA2_Stream0->M0AR = (uint32_t)adc_array;
|
||||||
|
DMA2_Stream0->PAR = (uint32_t)&ADC1->DR;
|
||||||
|
|
||||||
|
DMA2_Stream0->CR = DMA_SxCR_PL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_TCIE;
|
||||||
|
DMA2_Stream0->NDTR = length;
|
||||||
|
NVIC_EnableIRQ(DMA2_Stream0_IRQn);
|
||||||
|
|
||||||
|
DMA2_Stream0->CR |= DMA_SxCR_EN;
|
||||||
|
ADC1->CR2 |= ADC_CR2_ADON | ADC_CR2_DMA;
|
||||||
|
|
||||||
|
if (!flag_to_set) {
|
||||||
|
while(!alt_flag);
|
||||||
|
|
||||||
|
if (alt_flag < 0)
|
||||||
|
ret_val = -alt_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, uint16_t *raw_source, uint32_t count)
|
void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, uint16_t *raw_source, uint32_t count)
|
||||||
@ -84,7 +196,7 @@ void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, ui
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum adc_p1000_error adc_pt1000_check_error()
|
enum adc_pt1000_error adc_pt1000_check_error()
|
||||||
{
|
{
|
||||||
return pt1000_error;
|
return pt1000_error;
|
||||||
}
|
}
|
||||||
@ -94,9 +206,20 @@ void adc_pt1000_clear_error()
|
|||||||
pt1000_error = ADC_PT1000_NO_ERR;
|
pt1000_error = ADC_PT1000_NO_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adc_pt1000_filter(uint16_t adc_value)
|
void adc_pt1000_disable()
|
||||||
{
|
{
|
||||||
pt1000_adc_raw_lf = (1-filter_alpha) * pt1000_adc_raw_lf + filter_alpha * (float)adc_value;
|
adc_pt1000_disable_adc();
|
||||||
|
adc_pt1000_stop_sample_frequency_timer();
|
||||||
|
filter_ready = false;
|
||||||
|
pt1000_res_raw_lf = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((optimize("O3"))) void adc_pt1000_filter(uint16_t adc_value)
|
||||||
|
{
|
||||||
|
if (!filter_ready && --filter_startup_cnt <= 0)
|
||||||
|
filter_ready = true;
|
||||||
|
|
||||||
|
pt1000_res_raw_lf = (1-filter_alpha) * pt1000_res_raw_lf + filter_alpha * ADC_TO_RES((float)adc_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADC_IRQHandler(void)
|
void ADC_IRQHandler(void)
|
||||||
@ -111,13 +234,38 @@ void ADC_IRQHandler(void)
|
|||||||
|
|
||||||
if (adc1_sr & ADC_SR_OVR) {
|
if (adc1_sr & ADC_SR_OVR) {
|
||||||
ADC1->SR &= ~ADC_SR_OVR;
|
ADC1->SR &= ~ADC_SR_OVR;
|
||||||
pt1000_error = ADC_PT1000_OVERFLOW;
|
pt1000_error |= ADC_PT1000_OVERFLOW;
|
||||||
/* Disable ADC in case of overrrun*/
|
/* Disable ADC in case of overrrun*/
|
||||||
ADC1->CR2 &= ADC_CR2_ADON;
|
adc_pt1000_disable();
|
||||||
|
if (streaming_active) {
|
||||||
|
streaming_active = false;
|
||||||
|
*dma_flag_ptr = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adc1_sr & ADC_SR_AWD) {
|
if (adc1_sr & ADC_SR_AWD) {
|
||||||
ADC1->SR &= ~ADC_SR_AWD;
|
ADC1->SR &= ~ADC_SR_AWD;
|
||||||
pt1000_error = ADC_PT1000_WATCHDOG_ERROR;
|
pt1000_error |= ADC_PT1000_WATCHDOG_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DMA2_Stream0_IRQHandler()
|
||||||
|
{
|
||||||
|
uint32_t lisr;
|
||||||
|
|
||||||
|
lisr = DMA2->LISR;
|
||||||
|
DMA2->LIFCR = lisr;
|
||||||
|
|
||||||
|
if (lisr & DMA_LISR_TCIF0) {
|
||||||
|
*dma_flag_ptr = 1;
|
||||||
|
ADC1->CR2 &= ~ADC_CR2_DMA;
|
||||||
|
streaming_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lisr & DMA_LISR_TEIF0) {
|
||||||
|
*dma_flag_ptr = -2;
|
||||||
|
ADC1->CR2 &= ~ADC_CR2_DMA;
|
||||||
|
streaming_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
#define ADC_PT1000_PIN 2
|
#define ADC_PT1000_PIN 2
|
||||||
|
|
||||||
#define ADC_FILTER_STARTUP_CYCLES 200
|
#define ADC_FILTER_STARTUP_CYCLES 800
|
||||||
|
|
||||||
|
#define ADC_PT1000_SAMPLE_CNT_DELAY 2000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Lower value for valid input range for PT1000 measurement
|
* @brief Lower value for valid input range for PT1000 measurement
|
||||||
@ -35,7 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
#define ADC_PT1000_UPPER_WATCHDOG 4000
|
#define ADC_PT1000_UPPER_WATCHDOG 4000
|
||||||
|
|
||||||
enum adc_p1000_error {ADC_PT1000_NO_ERR= 0, ADC_PT1000_WATCHDOG_ERROR=-1, ADC_PT1000_OVERFLOW=2};
|
enum adc_pt1000_error {ADC_PT1000_NO_ERR= 0, ADC_PT1000_WATCHDOG_ERROR=(1UL<<0), ADC_PT1000_OVERFLOW=(1UL<<1)};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function sets up the ADC measurement fo the external PT1000 temperature sensor
|
* @brief This function sets up the ADC measurement fo the external PT1000 temperature sensor
|
||||||
@ -86,8 +88,7 @@ void adc_pt1000_get_resistance_calibration(float *offset, float *sensitivity_dev
|
|||||||
* If the reistance calibration is enabled, this function applies the calculations of the raw reistance reading and
|
* If the reistance calibration is enabled, this function applies the calculations of the raw reistance reading and
|
||||||
* returns the corrected value.
|
* returns the corrected value.
|
||||||
*
|
*
|
||||||
* If an ADC error is set, the status is negative. If the ADC is in streaming mode, the reistance reading is disabled and
|
* If an ADC error is set, the status is negative. The status is 2 during the first measurements with a given filter setting. Technically, the resistance value is
|
||||||
* the status is 1. The status is 2 during the first measurements with a given filter setting. Technically, the resistance value is
|
|
||||||
* correct but the filter is not stable yet.
|
* correct but the filter is not stable yet.
|
||||||
* Use adc_pt1000_check_error to check the error and reinitialize the ADC.
|
* Use adc_pt1000_check_error to check the error and reinitialize the ADC.
|
||||||
*
|
*
|
||||||
@ -102,7 +103,6 @@ int adc_pt1000_get_current_resistance(float *resistance);
|
|||||||
*
|
*
|
||||||
* Streaming is done using DMA2 Stream0.
|
* Streaming is done using DMA2 Stream0.
|
||||||
* This function is used for gathering fullspeed sampling data for external interfaces or calibration
|
* This function is used for gathering fullspeed sampling data for external interfaces or calibration
|
||||||
* During streaming, the adc_pt1000_get_current_resistance() function will return an error
|
|
||||||
*
|
*
|
||||||
* @param adc_array Array to stream data to
|
* @param adc_array Array to stream data to
|
||||||
* @param length Amount of data points to be measured
|
* @param length Amount of data points to be measured
|
||||||
@ -118,8 +118,10 @@ void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, ui
|
|||||||
*
|
*
|
||||||
* In case of an error, it may be necessary to call adc_pt1000_setup_meas() again in order to recover from the error
|
* In case of an error, it may be necessary to call adc_pt1000_setup_meas() again in order to recover from the error
|
||||||
*/
|
*/
|
||||||
enum adc_p1000_error adc_pt1000_check_error();
|
enum adc_pt1000_error adc_pt1000_check_error();
|
||||||
|
|
||||||
void adc_pt1000_clear_error();
|
void adc_pt1000_clear_error();
|
||||||
|
|
||||||
|
void adc_pt1000_disable();
|
||||||
|
|
||||||
#endif // __ADCMEAS_H__
|
#endif // __ADCMEAS_H__
|
||||||
|
@ -7,120 +7,39 @@
|
|||||||
#include <stm32f4xx.h>
|
#include <stm32f4xx.h>
|
||||||
#include <systick.h>
|
#include <systick.h>
|
||||||
//#include <arm_math.h>
|
//#include <arm_math.h>
|
||||||
|
#include <stm32-gpio-macros.h>
|
||||||
#include <system_stm32f4xx.h>
|
#include <system_stm32f4xx.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <adc-meas.h>
|
#include <adc-meas.h>
|
||||||
|
|
||||||
#define OUTPUT(pin) (0b01 << (pin * 2))
|
static void setup_nvic_priorities()
|
||||||
#define ANALOG(pin) (0x03 << (pin * 2))
|
|
||||||
|
|
||||||
struct adc_conversions {
|
|
||||||
uint16_t pa2_raw;
|
|
||||||
uint16_t ref_raw;
|
|
||||||
uint16_t temp_raw;
|
|
||||||
uint16_t vbat_raw;
|
|
||||||
};
|
|
||||||
|
|
||||||
static volatile struct adc_conversions adc_results;
|
|
||||||
|
|
||||||
volatile uint64_t sample_count = 0;
|
|
||||||
volatile uint8_t new_data = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void DMA2_Stream0_IRQHandler()
|
|
||||||
{
|
{
|
||||||
uint32_t lisr;
|
/* No sub priorities */
|
||||||
|
NVIC_SetPriorityGrouping(2);
|
||||||
lisr = DMA2->LISR;
|
|
||||||
DMA2->LIFCR = lisr;
|
|
||||||
|
|
||||||
if (lisr & DMA_LISR_TCIF0) {
|
|
||||||
if (new_data)
|
|
||||||
new_data = 2;
|
|
||||||
new_data = 1;
|
|
||||||
sample_count++;
|
|
||||||
|
|
||||||
GPIOB->ODR ^= (1<<3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Setup Priorities */
|
||||||
|
NVIC_SetPriority(ADC_IRQn, 1);
|
||||||
|
NVIC_SetPriority(DMA2_Stream0_IRQn, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_dma(void *dest, size_t size)
|
static float pt1000_value;
|
||||||
{
|
static volatile int pt1000_value_status;
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
|
|
||||||
|
|
||||||
DMA2_Stream0->M0AR = (uint32_t)dest;
|
|
||||||
DMA2_Stream0->PAR = (uint32_t)&ADC1->DR;
|
|
||||||
DMA2_Stream0->CR = DMA_SxCR_PL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC |
|
|
||||||
DMA_SxCR_CIRC | DMA_SxCR_TCIE;
|
|
||||||
DMA2_Stream0->NDTR = size;
|
|
||||||
NVIC_EnableIRQ(DMA2_Stream0_IRQn);
|
|
||||||
|
|
||||||
DMA2_Stream0->CR |= DMA_SxCR_EN;
|
|
||||||
new_data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float ext_lf_corr;
|
|
||||||
|
|
||||||
float temp_lf_corr;
|
|
||||||
|
|
||||||
float ref_lf;
|
|
||||||
float vdd_calculated = 3.3f;
|
|
||||||
|
|
||||||
float vbat_lf_corr;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void setup_timers(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
struct adc_conversions working;
|
|
||||||
|
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
|
||||||
__DSB();
|
__DSB();
|
||||||
GPIOB->MODER = OUTPUT(2) | OUTPUT(3);
|
GPIOB->MODER = OUTPUT(2) | OUTPUT(3);
|
||||||
GPIOA->MODER |= ANALOG(2);
|
|
||||||
GPIOB->ODR |= (1<<2);
|
GPIOB->ODR |= (1<<2);
|
||||||
|
|
||||||
ADC1->SMPR2 = (7U<<(3*2));
|
setup_nvic_priorities();
|
||||||
ADC1->SMPR1 = (7U<<18) | (7U<<21) | (7U<<24);
|
|
||||||
ADC1->SQR1 = (2<<20);
|
|
||||||
ADC1->SQR3 = (2<<0) | (16<<(5*2)) | (17<<(5*1));
|
|
||||||
|
|
||||||
ADC->CCR |= (0x2<<16) | ADC_CCR_TSVREFE;
|
|
||||||
ADC1->CR1 = ADC_CR1_SCAN;
|
|
||||||
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CONT | ADC_CR2_DMA | ADC_CR2_DDS;
|
|
||||||
|
|
||||||
//while(1);
|
|
||||||
|
|
||||||
systick_setup();
|
systick_setup();
|
||||||
|
|
||||||
setup_dma(&adc_results, 3);
|
//setup_dma(&adc_results, 3);
|
||||||
adc_pt1000_setup_meas();
|
adc_pt1000_setup_meas();
|
||||||
|
|
||||||
ADC1->CR2 |= ADC_CR2_SWSTART;
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if (!new_data) {
|
pt1000_value_status = adc_pt1000_get_current_resistance(&pt1000_value);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
memcpy(&working, &adc_results, sizeof(adc_results));
|
|
||||||
new_data = 0;
|
|
||||||
//ref_lf = 0.995f * ref_lf + 0.005f * (float)working.ref_raw;
|
|
||||||
//vdd_calculated = ((1.21f * 4096)/ ref_lf);
|
|
||||||
|
|
||||||
//temp_lf_corr = 0.99f * temp_lf_corr + 0.01 * (float)working.temp_raw * vdd_calculated / 2.495f;
|
|
||||||
ext_lf_corr = 0.995f * ext_lf_corr + 0.005f * (float)working.pa2_raw / 4096 * 2500.0f; // * vdd_calculated / 2.495f;
|
|
||||||
|
|
||||||
//vbat_lf_corr = 0.99 * vbat_lf_corr + 0.01 * (float)working.vbat_raw / 4096 * vdd_calculated * 2.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user