/* * temper.c * * Created on: 22.04.2016 * Author: pavel */ #include "common_config.h" #include "onewire.h" #include "gpio.h" #include "temper.h" #include #include #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #define ERRORS_LIMIT 5 #undef DBG #define DBG if(0) const unsigned char crc_table[] = { 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53 }; static uint8_t tBufExt[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; static uint16_t tempInt = 0; /** * @brief Cтруктура датчиков температуры (измерения, состояния, счетчики ошибок) */ TEMPERATURE_SENSORS_t sTemperSensors[MAX_T_SENSORS]; /** * @brief Временные флаги инициализации данных */ static bool fReady[MAX_T_SENSORS]; /** * @brief Глобальный флаг инициализации данных температурных датчиков */ bool fTemperDataReady = false; uint8_t CheckCRC(uint8_t *data, uint8_t len) { uint8_t crc = 0; while (len--) crc = crc_table[crc ^ *data++]; return crc; } /** * @brief Чтение температуры из датчика */ bool GetTemperature(uint8_t sensor) { float temperature = 85.0; static uint8_t state; bool dataReady = false; /* Запускаем преобразование температуры */ #ifdef DALLAS_TWO_LINE_SWITCH DALLAS_OutSetAsTX(sensor); #endif state = DALLAS_Send(sensor, DALLAS_SEND_RESET, (uint8_t *)"\xcc\x44", 2, NULL, 0, DALLAS_NO_READ); if ((state == DALLAS_ERROR) || (state == DALLAS_NO_DEVICE)) { sTemperSensors[sensor].ErrorCounter++; } #ifdef DALLAS_TWO_LINE_SWITCH DALLAS_OutSetAsPower(sensor); #endif /* Ждем пока датчики закончат преобразование */ vTaskDelay(800); /* Clear CRC byte */ tBufExt[8] = 0; /* Чтение температуры */ #ifdef DALLAS_TWO_LINE_SWITCH DALLAS_OutSetAsTX(sensor); #endif state = DALLAS_Send(sensor, DALLAS_SEND_RESET, (uint8_t *)"\xcc\xbe\xff\xff\xff\xff\xff\xff\xff\xff\xff", 11, tBufExt, 9, 2); if ((state == DALLAS_ERROR) || (state == DALLAS_NO_DEVICE)) { sTemperSensors[sensor].ErrorCounter++; } /* Check CRC */ if (state == DALLAS_OK) { /* Sometimes we get DALLAS_OK, and empty tBufExt, * while sensor surely not connected. For zero filled tBufExt * CRC is always ok. To detect this, furst check if buffer is empty */ uint8_t sum = 0; for (uint8_t i = 0; i < sizeof(tBufExt); i++) { sum |= tBufExt[i]; } uint8_t crc = CheckCRC(tBufExt, 9); if ((crc != 0) || (sum == 0)) { sTemperSensors[sensor].ErrorCounter++; } DBG { printf("Sensor %d: ", sensor); for (uint8_t i = 0; i < 9; i++) printf("0x%X ", tBufExt[i]); crc ? printf("CRC Fail\r\n") : printf("CRC OK\r\n"); } } /* ---------------------------------------------------------------------- */ /* Расчет температуры датчика */ if (!sTemperSensors[sensor].ErrorCounter) { tempInt = tBufExt[0]; tempInt |= tBufExt[1] << 8; /* Если число в дополнительном коде */ if ((tempInt & 0x8000)) { tempInt = ~tempInt + 1; temperature = -1*(tempInt/16.0); } else { temperature = tempInt/16.0; } DBG printf("temperature: %0.1f\r\n", temperature); if ((temperature != 85.0) && (temperature != -0.0625)) { sTemperSensors[sensor].Temperature = temperature; sTemperSensors[sensor].SensorState = 0; dataReady = true; } sTemperSensors[sensor].ErrorCycle = 0; } /* Если были ошибки, то показания тепературы не обновляем */ else { sTemperSensors[sensor].ErrorCycle++; sTemperSensors[sensor].ErrorCounter = 0; /* Произошло несколько ошибочных циклов общения с датчиком */ /* Выставляем признак отказа датчика */ if (sTemperSensors[sensor].ErrorCycle == ERRORS_LIMIT) { sTemperSensors[sensor].SensorState = 1; // Неисправность! sTemperSensors[sensor].ErrorCycle = 0; dataReady = true; } } DBG printf("Temperature sensor %d: %0.1f State = %d\r\n\r\n", sensor, sTemperSensors[sensor].Temperature, sTemperSensors[sensor].SensorState); return dataReady; } /** * @brief Опрос датчиков температуры */ void RequestSensors(void) { bool ready = true; for (uint8_t i = 0; i < MAX_T_SENSORS; i++) { ready &= GetTemperature(i); } /* Установка глобального флага готовности данных */ if (ready) { fTemperDataReady = true; } } /** * @brief Задача чтения температуры 1-wire */ void vTaskOwire(void *pvParameters) { (void)pvParameters; uint8_t i; for (i = 0; i < MAX_T_SENSORS; i++) { sTemperSensors[i].Temperature = 0.0; sTemperSensors[i].ErrorCounter = 0; sTemperSensors[i].ErrorCycle = 0; sTemperSensors[i].SensorState = 1; // По умолчанию устанавливаем признак неисправности } DALLAS_Init(); for (;;) { RequestSensors(); vTaskDelay(1000); } } void OW_Init(void) { xTaskCreate(vTaskOwire, "vTaskOwire", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); }