Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2017:envi-logger

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
2017:envi-logger [2018/01/22 05:19]
Miroslav Waldecker [TGS4161 a ADC]
2017:envi-logger [2018/01/22 06:23] (aktuální)
Miroslav Waldecker [Záver]
Řádek 266: Řádek 266:
 } }
 </​code>​ </​code>​
 +
 +==== SHT21, HP03M a ADC ====
 +
 +Nastavenie IIC periférie a GPIO pre ovládanie XCLR - reset signálu pre HP03M.
 +<code c>
 +void Init_iic(void) {
 + BOARD_I2C_ConfigurePins();​
 + gpio_pin_config_t xclr = { kGPIO_DigitalOutput,​ 0, };
 + GPIO_PinInit(GPIOB,​ 10U, &xclr);
 +
 + I2C_MasterGetDefaultConfig(&​masterConfig);​
 + masterConfig.baudRate_Bps = I2C_BAUDRATE;​
 +
 + sourceClock = I2C_MASTER_CLK_FREQ;​
 +
 + I2C_MasterInit(I2C0,​ &​masterConfig,​ sourceClock);​
 +
 +}
 +</​code>​
 +
 +Komunikácia s SHT21. Funkcie pre čítanie teploty a vlhkosti a ich prepočet na °C a %RH:
 +<code c>
 +float read_temp() {
 +
 + uint8_t data[5];
 + uint16_t itemp;
 + float ftemp;
 +
 + data[0] = (uint8_t) SHT21_TRIG_TEMP_HM;​
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ SHT21_I2C_ADDRESS,​ kI2C_Write))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ data, 1, kI2C_TransferNoStopFlag))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterRepeatedStart(I2C0,​ SHT21_I2C_ADDRESS,​ kI2C_Read))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterReadBlocking(I2C0,​ data, 3, kI2C_TransferCompleteFlag))
 + ;
 + itemp = data[0];
 + itemp = itemp << 8;
 + itemp |= data[1];
 + itemp &= 0xFFFC;
 + ftemp = -48.85 + (175.72 * ((float) itemp)) / 65536.0;
 +
 + return (ftemp);
 +}
 +
 +float read_hum() {
 +
 + uint8_t data[5];
 + uint16_t ihum;
 + float fhum;
 +
 + data[0] = (uint8_t) SHT21_TRIG_HUMIDITY_HM;​
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ SHT21_I2C_ADDRESS,​ kI2C_Write))
 + ;
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ data, 1, kI2C_TransferNoStopFlag))
 + ;
 + while (kStatus_Success
 + != I2C_MasterRepeatedStart(I2C0,​ SHT21_I2C_ADDRESS,​ kI2C_Read))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterReadBlocking(I2C0,​ data, 3, kI2C_TransferCompleteFlag))
 + ;
 + ihum = data[0];
 + ihum = ihum << 8;
 + ihum |= data[1];
 + ihum &= 0xFFFC;
 + fhum = -6.0 + 125.0 * ((float) ihum) / 65536.0;
 + return (fhum);
 +}
 +</​code>​
 +
 +Komunikácia s HP03M a výpočet barometrického tlaku, je zaujímavé,​ že tento senzor obsahuje 2 obvody, v jednom sú kalibračné a kompenzačné údaje, druhý je AD prevodník s meraním teploty pre kompenzáciu a tlaku. Každý z týchto obvodov má inú adresu a iný spôsob ich čítania:
 +
 +<code c>
 +float read_pressure() {
 +
 + uint8_t eeprom_data[18];​
 + uint16_t iPressure;
 + uint16_t iTemperature;​
 + uint8_t data_index;
 + uint16_t C[7];
 + uint8_t coef_A;
 + uint8_t coef_B;
 + uint8_t coef_C;
 + uint8_t coef_D;
 + float fTemp;
 + float fPressure;
 + float dut;
 + float offset;
 + float sensitivity;​
 + float xpress;
 +
 + GPIO_PinWrite(GPIOB,​ 10U, 1);
 +
 +
 + eeprom_data[0] = 0x10;
 +
 + while (kStatus_Success != I2C_MasterStop(I2C0))
 + ;
 +
 +
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ HP03_I2C_EEPROM_ADDRESS,​ kI2C_Write))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ eeprom_data,​ 1,
 + kI2C_TransferNoStopFlag))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterRepeatedStart(I2C0,​ HP03_I2C_EEPROM_ADDRESS,​ kI2C_Read))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterReadBlocking(I2C0,​ eeprom_data,​ 18,
 + kI2C_TransferCompleteFlag))
 + ;
 +
 + for (data_index = 0; data_index <= 6; data_index++) {
 + C[data_index] = eeprom_data[data_index * 2];
 + C[data_index] = C[data_index] << 8;
 + C[data_index] |= eeprom_data[(data_index * 2) + 1];
 + }
 +
 + coef_A = eeprom_data[14];​
 + coef_B = eeprom_data[15];​
 + coef_C = eeprom_data[16];​
 + coef_D = eeprom_data[17];​
 +
 +
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ HP03_I2C_AD_ADDRESS,​ kI2C_Write))
 + ;
 +
 + eeprom_data[0] = 0xFF;
 + eeprom_data[1] = 0xF0;
 +
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ eeprom_data,​ 2,
 + kI2C_TransferCompleteFlag))
 + ;
 +
 +
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ HP03_I2C_AD_ADDRESS,​ kI2C_Write))
 + ;
 + eeprom_data[0] = 0xFD;
 +
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ eeprom_data,​ 1,
 + kI2C_TransferNoStopFlag))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterRepeatedStart(I2C0,​ HP03_I2C_AD_ADDRESS,​ kI2C_Read))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterReadBlocking(I2C0,​ eeprom_data,​ 2,
 + kI2C_TransferCompleteFlag))
 + ;
 +
 + iPressure = eeprom_data[0];​
 + iPressure = iPressure << 8;
 + iPressure |= eeprom_data[1];​
 +
 +
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ HP03_I2C_AD_ADDRESS,​ kI2C_Write))
 + ;
 +
 + eeprom_data[0] = 0xFF;
 + eeprom_data[1] = 0xE8;
 +
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ eeprom_data,​ 2,
 + kI2C_TransferCompleteFlag))
 + ;
 +
 +
 + while (kStatus_Success
 + != I2C_MasterStart(I2C0,​ HP03_I2C_AD_ADDRESS,​ kI2C_Write))
 + ;
 + eeprom_data[0] = 0xFD;
 +
 + while (kStatus_Success
 + != I2C_MasterWriteBlocking(I2C0,​ eeprom_data,​ 1,
 + kI2C_TransferNoStopFlag))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterRepeatedStart(I2C0,​ HP03_I2C_AD_ADDRESS,​ kI2C_Read))
 + ;
 +
 + while (kStatus_Success
 + != I2C_MasterReadBlocking(I2C0,​ eeprom_data,​ 2,
 + kI2C_TransferCompleteFlag))
 + ;
 +
 + iTemperature = eeprom_data[0];​
 + iTemperature = iTemperature << 8;
 + iTemperature |= eeprom_data[1];​
 + GPIO_PinWrite(GPIOB,​ 10U, 0);
 +
 + fTemp = (float)iTemperature;​
 +
 + if(iTemperature >= C[4]){
 + dut = fTemp - (float)C[4] - ((fTemp-(float)C[4])/​128.0) * ((fTemp-(float)C[4])/​128.0) * (float)coef_A / (float)(2^coef_C);​
 + }else{
 + dut = fTemp - (float)C[4] - ((fTemp-(float)C[4])/​128.0) * ((fTemp-(float)C[4])/​128.0) * (float)coef_B / (float)(2^coef_C);​
 + }
 +
 + offset = ((float)C[1]+((float)C[3]-1024.0)*dut/​16384.0)*4.0;​
 + sensitivity = (float)C[0]+ (float)C[2]*dut/​1024.0;​
 + xpress = sensitivity * ((float)iPressure-7168.0)/​16384.0 - offset;
 + fPressure = xpress*10.0/​32.0+(float)C[6] + 253.0;
 + return (fPressure/​10.0);​
 +}
 +</​code>​
 +
 +==== TFT display a FlexBus ====
 +
 +Pre riadenie TFT display-u som využil hotovú knižnicu:
 +https://​www.element14.com/​community/​groups/​development-tools/​blog/​2012/​05/​26/​stm32f4-discovery-hy32d-tft-lcd Tú som však musel naportovať pre K64 procesor a zbernicu FluxBus:
 +Inicializácia:​
 +<code c>
 +void Init_FlexBus(void){
 + flexbus_config_t flexbusUserConfig;​
 +
 + FLEXBUS_GetDefaultConfig(&​flexbusUserConfig);​
 +
 + flexbusUserConfig.waitStates = 2U;
 + flexbusUserConfig.portSize = kFLEXBUS_2Bytes;​
 + flexbusUserConfig.chipBaseAddress = (uint32_t)TFT_DC_ADDRESS;​
 + flexbusUserConfig.chipBaseAddressMask = 1U;
 + flexbusUserConfig.byteLaneShift = kFLEXBUS_Shifted;​
 + flexbusUserConfig.autoAcknowledge = true;
 +
 + FLEXBUS_Init(FB,​ &​flexbusUserConfig);​
 + }
 +</​code>​
 +Zápis dát do pamäte a do registrov:
 +<code c>
 +void vfnSendDataWord(unsigned short value)
 +  {
 +    *((unsigned short*)TFT_BASE_ADDRESS) = value;
 +  }
 +
 +void vfnSendCmdWord(unsigned short cmd)
 +  {
 +    *((unsigned short*)TFT_DC_ADDRESS) = cmd;
 +  }
 +</​code>​
 +
 +==== RTC ====
 +
 +Inicializácia a nastavenie hodín reálneho času:
 +<code c>
 +void Init_rtc(void){
 +
 + rtc_config_t rtcConfig;
 +
 + RTC_GetDefaultConfig(&​rtcConfig);​
 + RTC_Init(RTC,​ &​rtcConfig);​
 +     /* Select RTC clock source */
 + RTC_SetClockSource(RTC);​
 +}
 +
 +void rtc_settime(rtc_datetime_t date){
 +
 +   RTC_StopTimer(RTC);​
 +   RTC_SetDatetime(RTC,​ &date);
 +   RTC_StartTimer(RTC);​
 +}
 +
 +rtc_datetime_t rtc_gettime(void){
 +
 + rtc_datetime_t date;
 +
 + RTC_GetDatetime(RTC,​ &date);
 + return(date);​
 +}
 +</​code>​
 +
 +==== Hlavná slučka a Fat FS ====
 +Kinetis software development kit obsahuje okrem štandardných ovládačov periférií aj middleware pre prácu s USB a SD kartami s podporou Fat FS, ktorý som použil. Tým, že zapisujem namerané údaje v textovom formáte, tieto sú po pripojeni SD karty do počítača bezproblémov spracovateľné. ​ V hlavnej slučke sa periodicky vyčítavajú údaje, ktoré sa okamžite zobrazujú na display-i a každých 10s sa otvorí súbor pre zápis a udaje sa zapíšu vo formáte dátum, čas, koncentrácia CO2, teplota, vlhkosť a tlak. Po zápise sa súbor okamžite uzavrie.
 +<code c>
 +while (1) {
 +
 + date = rtc_gettime();​
 + sprintf(str,​ "​%02hd-%02hd-%04hd %02hd:​%02hd:​%02hd ​    ",​ date.day,
 + date.month,​ date.year, date.hour, date.minute,​ date.second);​
 +
 + LCD_SetTextColor(ASSEMBLE_RGB(0,​ 0, 0));
 + LCD_CharSize(16);​
 + LCD_StringLine(1,​ 1, (uint8_t*) str);
 + co_value = get_concentration();​
 + sprintf(str,​ "​CO2:​%d ppm", co_value);
 + LCD_SetTextColor(ASSEMBLE_RGB(0,​ 0, 0xFF));
 + LCD_CharSize(24);​
 + LCD_StringLine(1,​ 16, (uint8_t*) str);
 +
 + temperature = read_temp();​
 + humidity = read_hum();
 + LCD_SetTextColor(ASSEMBLE_RGB(0xFF,​ 0, 0));
 + sprintf(str,​ "​T: ​  %2.2f C", temperature);​
 + LCD_StringLine(1,​ 40, (uint8_t*) str);
 + LCD_SetTextColor(ASSEMBLE_RGB(0,​ 0, 0xFF));
 + sprintf(str,​ "​RH: ​ %2.2f %%", humidity);
 + LCD_StringLine(1,​ 64, (uint8_t*) str);
 + LCD_SetTextColor(ASSEMBLE_RGB(0xFF,​ 0, 0));
 + pressure = read_pressure();​
 + sprintf(str,​ "​P:​%6.2fhPa",​ pressure);
 + LCD_StringLine(1,​ 88, (uint8_t*) str);
 + Delay(10);​
 +
 + if(card_ok && prev_second != date.second && !(date.second % 10)){
 + sprintf(g_bufferWrite,​ "​%02hd-%02hd-%04hd %02hd:​%02hd:​%02hd %d %2.2f %2.2f %6.2f \r\n", date.day,
 + date.month,​ date.year, date.hour, date.minute,​ date.second,​ co_value, temperature,​ humidity, pressure);
 + f_open(&​g_fileObject,​ _T("/​data.dat"​),​ (FA_WRITE | FA_READ | FA_OPEN_APPEND));​
 +
 + error = f_write(&​g_fileObject,​ g_bufferWrite,​ strlen(g_bufferWrite),​ &​bytesWritten);​
 + f_close(&​g_fileObject);​
 + prev_second = date.second;​
 + }
 + }
 +</​code>​
 +===== Video datalogger =====
 +{{youtube>​R_bAfAzXU1A?​medium}}
 +
 +===== Výpis dát =====
 +V tomto bolku je príklad zmeraných dát, potom ako som začal vetrať. Je vidieť, ako klesá koncentrácia CO2, ale zároveň aj s teplotou...
 +
 +<​file>​
 +14-01-2018 17:20:10 1052 21.98 27.91 1017.92 ​
 +14-01-2018 17:20:20 1021 21.99 27.36 1017.80 ​
 +14-01-2018 17:20:30 971 21.93 26.92 1017.80 ​
 +14-01-2018 17:20:40 955 21.92 26.60 1017.67 ​
 +14-01-2018 17:20:50 939 21.87 25.60 1017.90 ​
 +14-01-2018 17:21:00 920 21.83 24.97 1017.95 ​
 +14-01-2018 17:21:10 909 21.79 24.63 1017.90 ​
 +14-01-2018 17:21:20 884 21.73 24.27 1017.90 ​
 +14-01-2018 17:21:30 898 21.64 24.33 1017.95 ​
 +14-01-2018 17:21:40 883 21.58 23.90 1017.99 ​
 +14-01-2018 17:21:50 917 21.50 24.53 1017.89 ​
 +14-01-2018 17:22:00 905 21.41 24.16 1018.08 ​
 +14-01-2018 17:22:10 872 21.35 23.40 1017.94 ​
 +14-01-2018 17:22:20 862 21.24 23.51 1017.98 ​
 +14-01-2018 17:22:30 909 21.13 23.87 1017.94 ​
 +14-01-2018 17:22:40 861 21.13 22.79 1017.95 ​
 +14-01-2018 17:22:50 833 21.12 22.56 1017.95 ​
 +14-01-2018 17:23:00 841 21.11 22.62 1018.04 ​
 +14-01-2018 17:23:10 821 21.02 22.26 1017.94 ​
 +14-01-2018 17:23:20 814 20.96 22.06 1018.06 ​
 +14-01-2018 17:23:30 803 20.91 21.89 1018.05 ​
 +14-01-2018 17:23:40 819 20.86 21.93 1017.82 ​
 +14-01-2018 17:23:50 864 20.76 23.28 1018.07 ​
 +14-01-2018 17:24:00 841 20.71 22.27 1017.97 ​
 +14-01-2018 17:24:10 799 20.64 21.51 1018.00 ​
 +14-01-2018 17:24:20 794 20.58 21.94 1018.07 ​
 +</​file>​
 +
 +
 +==== Záver ====
 +
 +Tento projekt je prototyp, na ktorom som si overil rôzne senzory, vyskúšal som prostredie MCUXpresso firmy NXP a ich software-ové knižnice pre prácu s ARM procesormi Kinetis KSDK verzie 2.3. K tomu, aby to bol plnohodnotný projekt je nutné prerobiť a dorobiť niekoľko vecí. Najmä radiče pre komunikáciu prerobiť z blokovacieho na neblokovací režim, veľa času stráca procesor tým, že čaká, kým periféria zmeria a odpovie. Ďalej je nutné prerobiť HW vývojovej dosky na zálohovanie z batérie pre kalibračné dáta a hodiny reálneho času. Takisto ovládanie z konzoly a prekopírovávanie uložených dát. Z užívateľského rozhrania je vhodné dorobiť grafické zobrazenie údajov v čase. Debug sériový port, ktorý je teraz použitý previesť na USB com port, a tento sériový port priviesť na malý WiFi modul so serverom, na ktorom budú prístupné namerané údaje z lokálnej siete. Za úvahu stojí aj zmena senzora koncentrácie CO2, keďže je to už pomerne obsolete senzor, ktorý je náchylný na všetky parametre ako napájacie napätie, ktoré v tomto prípade nie je vôbec stabilné, nepresnosť,​ stále je nutné ho kalibrovať a náročný prepočet. ​
 +
 +Zdroje:{{ :​2017:​xwalde01:​envilogger.rar | Zdrojové súbory}}
 +
 +
2017/envi-logger.1516594757.txt.gz · Poslední úprava: 2018/01/22 05:19 autor: Miroslav Waldecker