[PRZYKŁAD] P-NUCLEO-IKA02A1 – zestaw rozwojowy do współpracy z czujnikami gazów
Po wygenerowaniu szablonu projektu należy uzupełnić kod przykładu. Część kodu inspirowana jest paczką programową od firmy STMicroelectronics – X-CUBE-IKA02A1. Paczka dostępna jest za darmo po uprzedniej rejestracji.
W pierwszej kolejności należy dodać zmienne niezbędne w dalszej części programu. Najpierw inicjalizowane są zmienne, w których przechowywane są odczyty z przetwornika ADC. W kolejnych zmiennych przechowywane są obliczone dane dotyczące stężenia, temperatury i stężenia po kompensacji temperaturowej. W ostatniej linijce znajdują zmienne przechowujące wzmocnienie układu dopasowującego sygnał (można je zmienić zworką na nakładce) oraz czułość sensora.
uint16_t sens_val_raw = 0, sens_ref_raw = 0, sens_temp_raw = 0; float temperatura, stezenie, stezenie_po_kompensacji; float gain = 470000, sens = 2.207;
W pętli głównej najpierw należy pobrać wartości z przetwornika ADC. Niestety w mikrokontrolerach z serii STM32L0 nie można użyć DMA w celu pobierania wielu kanałów przetwornika. W takim wypadku należy po każdym pomiarze zmieniać kanał zapisując numer kanału do rejestru CHSELR struktury hadc.Instance.
while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if (HAL_ADC_PollForConversion(&hadc, 10) == HAL_OK){ sens_ref_raw = HAL_ADC_GetValue(&hadc); } hadc.Instance->CHSELR = ADC_CHANNEL_8; HAL_ADC_Start(&hadc); if (HAL_ADC_PollForConversion(&hadc, 10) == HAL_OK){ sens_val_raw = HAL_ADC_GetValue(&hadc); } hadc.Instance->CHSELR = ADC_CHANNEL_10; HAL_ADC_Start(&hadc); if (HAL_ADC_PollForConversion(&hadc, 10) == HAL_OK){ sens_temp_raw = HAL_ADC_GetValue(&hadc); } hadc.Instance->CHSELR = ADC_CHANNEL_4; HAL_ADC_Start(&hadc); ...
Dysponując próbkami można wyznaczyć stężenie gazu, temperatury otoczenia oraz dokonać kompensacji temperaturowej odczytu. Do wyliczenia stężenia i temperatury użyłem następujących wzorów pochodzących z paczki X-CUBE-IKA02A1.
... HAL_Delay(100); temperatura = (-1481.96+sqrt(2196200+(1.8639-3.3*sens_temp_raw/4096)/3.88*1000000)); stezenie = ((float)sens_val_raw-sens_ref_raw)*805664/gain/sens; stezenie_po_kompensacji = Get_comp_gas_concentration(stezenie, (int8_t)round(temperatura)); } /* USER CODE END 3 */ }
Z tej paczki pochodzi także funkcja Get_comp_gas_concentration, której zadaniem jest kompensacja błędów odczytu sensora spowodowanych wpływem temperatury otoczenia. Jako argumenty należy podać uzyskane stężenie (bez kompensacji) oraz temperaturę otoczenia w formacie 8-bitowej zmiennej typu int.
float Get_comp_gas_concentration(float gas_ppm, int8_t temp){ //check to be in boundaries of lookup table if(temp+COMP_SHIFT>=LOOKUP_LENGTH){ temp=LOOKUP_LENGTH-1; }else if(temp+COMP_SHIFT<0){ temp=0; }else{ temp=temp+COMP_SHIFT; } return gas_ppm/TEMP_COMPENSATION[temp]; }
Także do pliku main.h należy dodać tablicę zawierającą dane konieczne do kompensacji.
/* USER CODE BEGIN Private defines */ #define LOOKUP_LENGTH 61 #define COMP_SHIFT 10 //to be able to compensate in negative temperatures static const float TEMP_COMPENSATION[61]={0.6745, 0.6854, 0.6963, 0.7072, 0.7181, 0.7290, 0.7399, 0.7508, 0.7617, 0.7726, 0.7835, 0.7944, 0.8053, 0.8162, 0.8271, 0.8380, 0.8489, 0.8598, 0.8707, 0.8816, 0.8925, 0.9034, 0.9143, 0.9252, 0.9361, 0.9470, 0.9579, 0.9688, 0.9797, 0.9906, 1.0000, 1.0075, 1.0150, 1.0225, 1.0300, 1.0375, 1.0450, 1.0525, 1.0600, 1.0675, 1.0750, 1.0825, 1.0900, 1.0975, 1.1050, 1.1125, 1.1200, 1.1275, 1.1350, 1.1425, 1.1500, 1.1575, 1.1650, 1.1725, 1.1800, 1.1875, 1.1950, 1.2025, 1.2100, 1.2175, 1.2250}; /* USER CODE END Private defines */
Poniżej znajduje się zrzut ekranu programu STMStudio prezentujący odczyt po kompensacji w zadymionym pomieszczeniu. W normalnych warunkach (wentylowane pomieszczenie, bez żadnych źródeł czadu) odczyt nie powinien przekroczyć ok. 3 ppm.
Rys. 4. Zrzut ekranu programu STM Studio demonstrujący działanie przykładu