Files
AutoFilm-ESP32/components/hal_temp/hal_temp.c

158 lines
3.6 KiB
C

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "onewire_bus.h"
#include "board.h"
#include "hal_temp.h"
#define TEMP_OFFSET 0.4f
#define CMD_SKIP_ROM 0xCC
#define CMD_CONVERT_T 0x44
#define CMD_READ_SCRATCH 0xBE
static const char *TAG = "temp";
#define TEMP_CONV_MS 750
typedef enum {
T_START,
T_WAIT,
} temp_state_t;
static onewire_bus_handle_t s_bus;
static bool s_inited;
static float s_last_c;
static bool s_last_ok;
static temp_state_t s_state = T_START;
static uint32_t s_deadline_ms;
static uint32_t now_ms(void)
{
return (uint32_t)(esp_timer_get_time() / 1000ULL);
}
static bool scratch_valid(const uint8_t *sp)
{
/* DS18B20 CRC8 over first 8 bytes, poly 0x8C reflected. */
uint8_t crc = 0;
for (int i = 0; i < 8; i++) {
uint8_t in = sp[i];
for (int b = 0; b < 8; b++) {
uint8_t mix = (crc ^ in) & 0x01;
crc >>= 1;
if (mix) {
crc ^= 0x8C;
}
in >>= 1;
}
}
return crc == sp[8];
}
void hal_temp_tick(void)
{
if (s_bus == NULL) {
s_last_ok = false;
return;
}
uint32_t now = now_ms();
if (s_state == T_START) {
if (now < s_deadline_ms) {
return;
}
if (onewire_bus_reset(s_bus) != ESP_OK) {
s_last_ok = false;
s_deadline_ms = now + TEMP_CONV_MS;
return;
}
uint8_t conv[2] = {CMD_SKIP_ROM, CMD_CONVERT_T};
if (onewire_bus_write_bytes(s_bus, conv, 2) != ESP_OK) {
s_last_ok = false;
s_deadline_ms = now + TEMP_CONV_MS;
return;
}
s_deadline_ms = now + TEMP_CONV_MS;
s_state = T_WAIT;
return;
}
/* T_WAIT */
if (now < s_deadline_ms) {
return;
}
s_state = T_START;
s_deadline_ms = now;
if (onewire_bus_reset(s_bus) != ESP_OK) {
s_last_ok = false;
s_deadline_ms = now + TEMP_CONV_MS;
return;
}
uint8_t rd[2] = {CMD_SKIP_ROM, CMD_READ_SCRATCH};
if (onewire_bus_write_bytes(s_bus, rd, 2) != ESP_OK) {
s_last_ok = false;
s_deadline_ms = now + TEMP_CONV_MS;
return;
}
uint8_t sp[9];
memset(sp, 0, sizeof(sp));
if (onewire_bus_read_bytes(s_bus, sp, sizeof(sp)) != ESP_OK) {
s_last_ok = false;
s_deadline_ms = now + TEMP_CONV_MS;
return;
}
if (!scratch_valid(sp)) {
s_last_ok = false;
s_deadline_ms = now + TEMP_CONV_MS;
return;
}
int16_t raw = (int16_t)((uint16_t)sp[0] | ((uint16_t)sp[1] << 8));
float t = ((float)raw) / 16.0f + TEMP_OFFSET;
s_last_c = t;
s_last_ok = true;
}
void hal_temp_init(void)
{
if (s_inited) {
return;
}
gpio_num_t pin = board_pin_temp();
if (pin == GPIO_NUM_NC) {
ESP_LOGW(TAG, "no temp pin on this board");
s_inited = true;
return;
}
onewire_bus_config_t bus_config = {
.bus_gpio_num = pin,
.flags = {
.en_pull_up = true,
},
};
onewire_bus_rmt_config_t rmt_config = {
.max_rx_bytes = 10,
};
if (onewire_new_bus_rmt(&bus_config, &rmt_config, &s_bus) != ESP_OK) {
s_bus = NULL;
ESP_LOGE(TAG, "onewire_bus install failed pin=%d", pin);
}
s_last_ok = false;
s_last_c = 0.0f;
s_inited = true;
ESP_LOGI(TAG, "init onewire_bus pin=%d offset=%.1f", pin, (double)TEMP_OFFSET);
}
esp_err_t hal_temp_read_c(float *out)
{
if (!s_last_ok) {
return ESP_FAIL;
}
if (out != NULL) {
*out = s_last_c;
}
return ESP_OK;
}