1233 lines
30 KiB
C
Executable File
1233 lines
30 KiB
C
Executable File
|
|
|
|
// === Início de: components/peripherals/src/ds18x20.c ===
|
|
/*
|
|
* Copyright (c) 2016 Grzegorz Hetman <ghetman@gmail.com>
|
|
* Copyright (c) 2016 Alex Stewart <foogod@gmail.com>
|
|
* Copyright (c) 2018 Ruslan V. Uss <unclerus@gmail.com>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the copyright holder nor the names of itscontributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
#include <math.h>
|
|
#include <esp_log.h>
|
|
#include <freertos/FreeRTOS.h>
|
|
#include <freertos/task.h>
|
|
#include "ds18x20.h"
|
|
|
|
#define ds18x20_WRITE_SCRATCHPAD 0x4E
|
|
#define ds18x20_READ_SCRATCHPAD 0xBE
|
|
#define ds18x20_COPY_SCRATCHPAD 0x48
|
|
#define ds18x20_READ_EEPROM 0xB8
|
|
#define ds18x20_READ_PWRSUPPLY 0xB4
|
|
#define ds18x20_SEARCHROM 0xF0
|
|
#define ds18x20_SKIP_ROM 0xCC
|
|
#define ds18x20_READROM 0x33
|
|
#define ds18x20_MATCHROM 0x55
|
|
#define ds18x20_ALARMSEARCH 0xEC
|
|
#define ds18x20_CONVERT_T 0x44
|
|
|
|
#define CHECK(x) do { esp_err_t __; if ((__ = x) != ESP_OK) return __; } while (0)
|
|
#define CHECK_ARG(VAL) do { if (!(VAL)) return ESP_ERR_INVALID_ARG; } while (0)
|
|
|
|
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
|
|
|
static const char* TAG = "ds18x20";
|
|
|
|
esp_err_t ds18x20_measure(gpio_num_t pin, ds18x20_addr_t addr, bool wait)
|
|
{
|
|
if (!onewire_reset(pin))
|
|
return ESP_ERR_INVALID_RESPONSE;
|
|
|
|
if (addr == DS18X20_ANY)
|
|
onewire_skip_rom(pin);
|
|
else
|
|
onewire_select(pin, addr);
|
|
|
|
portENTER_CRITICAL(&mux);
|
|
onewire_write(pin, ds18x20_CONVERT_T);
|
|
// For parasitic devices, power must be applied within 10us after issuing
|
|
// the convert command.
|
|
onewire_power(pin);
|
|
portEXIT_CRITICAL(&mux);
|
|
|
|
if (wait){
|
|
vTaskDelay(pdMS_TO_TICKS(750));
|
|
onewire_depower(pin);
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18x20_read_scratchpad(gpio_num_t pin, ds18x20_addr_t addr, uint8_t* buffer)
|
|
{
|
|
CHECK_ARG(buffer);
|
|
|
|
uint8_t crc;
|
|
uint8_t expected_crc;
|
|
|
|
if (!onewire_reset(pin))
|
|
return ESP_ERR_INVALID_RESPONSE;
|
|
|
|
if (addr == DS18X20_ANY)
|
|
onewire_skip_rom(pin);
|
|
else
|
|
onewire_select(pin, addr);
|
|
onewire_write(pin, ds18x20_READ_SCRATCHPAD);
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
buffer[i] = onewire_read(pin);
|
|
crc = onewire_read(pin);
|
|
|
|
expected_crc = onewire_crc8(buffer, 8);
|
|
if (crc != expected_crc)
|
|
{
|
|
ESP_LOGE(TAG, "CRC check failed reading scratchpad: %02x %02x %02x %02x %02x %02x %02x %02x : %02x (expected %02x)", buffer[0], buffer[1],
|
|
buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], crc, expected_crc);
|
|
return ESP_ERR_INVALID_CRC;
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18x20_write_scratchpad(gpio_num_t pin, ds18x20_addr_t addr, uint8_t* buffer)
|
|
{
|
|
CHECK_ARG(buffer);
|
|
|
|
if (!onewire_reset(pin))
|
|
return ESP_ERR_INVALID_RESPONSE;
|
|
|
|
if (addr == DS18X20_ANY)
|
|
onewire_skip_rom(pin);
|
|
else
|
|
onewire_select(pin, addr);
|
|
onewire_write(pin, ds18x20_WRITE_SCRATCHPAD);
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
onewire_write(pin, buffer[i]);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18x20_copy_scratchpad(gpio_num_t pin, ds18x20_addr_t addr)
|
|
{
|
|
if (!onewire_reset(pin))
|
|
return ESP_ERR_INVALID_RESPONSE;
|
|
|
|
if (addr == DS18X20_ANY)
|
|
onewire_skip_rom(pin);
|
|
else
|
|
onewire_select(pin, addr);
|
|
|
|
portENTER_CRITICAL(&mux);
|
|
onewire_write(pin, ds18x20_COPY_SCRATCHPAD);
|
|
// For parasitic devices, power must be applied within 10us after issuing
|
|
// the convert command.
|
|
onewire_power(pin);
|
|
portEXIT_CRITICAL(&mux);
|
|
|
|
// And then it needs to keep that power up for 10ms.
|
|
vTaskDelay(pdMS_TO_TICKS(10));
|
|
onewire_depower(pin);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18b20_read_temperature(gpio_num_t pin, ds18x20_addr_t addr, int16_t* temperature)
|
|
{
|
|
CHECK_ARG(temperature);
|
|
|
|
uint8_t scratchpad[8];
|
|
int16_t temp;
|
|
|
|
CHECK(ds18x20_read_scratchpad(pin, addr, scratchpad));
|
|
|
|
temp = scratchpad[1] << 8 | scratchpad[0];
|
|
|
|
*temperature = ((int16_t)temp * 625.0) / 100;
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18s20_read_temperature(gpio_num_t pin, ds18x20_addr_t addr, int16_t* temperature)
|
|
{
|
|
CHECK_ARG(temperature);
|
|
|
|
uint8_t scratchpad[8];
|
|
int16_t temp;
|
|
|
|
CHECK(ds18x20_read_scratchpad(pin, addr, scratchpad));
|
|
|
|
temp = scratchpad[1] << 8 | scratchpad[0];
|
|
temp = ((temp & 0xfffe) << 3) + (16 - scratchpad[6]) - 4;
|
|
|
|
*temperature = (temp * 625) / 100 - 25;
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18x20_read_temperature(gpio_num_t pin, ds18x20_addr_t addr, int16_t* temperature)
|
|
{
|
|
if ((uint8_t)addr == DS18B20_FAMILY_ID) {
|
|
return ds18b20_read_temperature(pin, addr, temperature);
|
|
} else {
|
|
return ds18s20_read_temperature(pin, addr, temperature);
|
|
}
|
|
}
|
|
|
|
esp_err_t ds18b20_measure_and_read(gpio_num_t pin, ds18x20_addr_t addr, int16_t* temperature)
|
|
{
|
|
CHECK_ARG(temperature);
|
|
|
|
CHECK(ds18x20_measure(pin, addr, true));
|
|
return ds18b20_read_temperature(pin, addr, temperature);
|
|
}
|
|
|
|
esp_err_t ds18s20_measure_and_read(gpio_num_t pin, ds18x20_addr_t addr, int16_t* temperature)
|
|
{
|
|
CHECK_ARG(temperature);
|
|
|
|
CHECK(ds18x20_measure(pin, addr, true));
|
|
return ds18s20_read_temperature(pin, addr, temperature);
|
|
}
|
|
|
|
esp_err_t ds18x20_measure_and_read(gpio_num_t pin, ds18x20_addr_t addr, int16_t* temperature)
|
|
{
|
|
CHECK_ARG(temperature);
|
|
|
|
CHECK(ds18x20_measure(pin, addr, true));
|
|
return ds18x20_read_temperature(pin, addr, temperature);
|
|
}
|
|
|
|
esp_err_t ds18x20_measure_and_read_multi(gpio_num_t pin, ds18x20_addr_t* addr_list, size_t addr_count, int16_t* result_list)
|
|
{
|
|
CHECK_ARG(result_list && addr_count);
|
|
|
|
CHECK(ds18x20_measure(pin, DS18X20_ANY, true));
|
|
|
|
return ds18x20_read_temp_multi(pin, addr_list, addr_count, result_list);
|
|
}
|
|
|
|
esp_err_t ds18x20_scan_devices(gpio_num_t pin, ds18x20_addr_t* addr_list, size_t addr_count, size_t* found)
|
|
{
|
|
CHECK_ARG(addr_list && addr_count);
|
|
|
|
onewire_search_t search;
|
|
onewire_addr_t addr;
|
|
|
|
*found = 0;
|
|
onewire_search_start(&search);
|
|
while ((addr = onewire_search_next(&search, pin)) != ONEWIRE_NONE)
|
|
{
|
|
uint8_t family_id = (uint8_t)addr;
|
|
if (family_id == DS18B20_FAMILY_ID || family_id == DS18S20_FAMILY_ID)
|
|
{
|
|
if (*found < addr_count)
|
|
addr_list[*found] = addr;
|
|
*found += 1;
|
|
}
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t ds18x20_read_temp_multi(gpio_num_t pin, ds18x20_addr_t* addr_list, size_t addr_count, int16_t* result_list)
|
|
{
|
|
CHECK_ARG(result_list);
|
|
|
|
esp_err_t res = ESP_OK;
|
|
for (size_t i = 0; i < addr_count; i++)
|
|
{
|
|
esp_err_t tmp = ds18x20_read_temperature(pin, addr_list[i], &result_list[i]);
|
|
if (tmp != ESP_OK)
|
|
res = tmp;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// === Fim de: components/peripherals/src/ds18x20.c ===
|
|
|
|
|
|
// === Início de: components/peripherals/src/led.c ===
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/timers.h"
|
|
#include "esp_log.h"
|
|
#include "driver/gpio.h"
|
|
#include "led.h"
|
|
#include "board_config.h"
|
|
#include "evse_error.h"
|
|
#include "evse_api.h"
|
|
|
|
#define LED_UPDATE_INTERVAL_MS 100
|
|
#define BLOCK_TIME pdMS_TO_TICKS(10)
|
|
|
|
static const char *TAG = "led";
|
|
|
|
typedef struct {
|
|
gpio_num_t gpio;
|
|
bool on : 1;
|
|
uint16_t ontime;
|
|
uint16_t offtime;
|
|
TimerHandle_t timer;
|
|
led_pattern_t pattern;
|
|
uint8_t blink_count;
|
|
} led_t;
|
|
|
|
static led_t leds[LED_ID_MAX] = {0};
|
|
static TimerHandle_t led_update_timer = NULL;
|
|
static evse_state_t led_state = -1;
|
|
|
|
// ----------------------------
|
|
// Funções Internas
|
|
// ----------------------------
|
|
|
|
static void led_update_timer_callback(TimerHandle_t xTimer);
|
|
static void led_update(void);
|
|
static void led_apply_by_state(evse_state_t state);
|
|
|
|
static inline void led_gpio_write(gpio_num_t gpio, bool level) {
|
|
if (gpio != GPIO_NUM_NC)
|
|
gpio_set_level(gpio, level);
|
|
}
|
|
|
|
static void led_timer_callback(TimerHandle_t xTimer)
|
|
{
|
|
led_t *led = (led_t *)pvTimerGetTimerID(xTimer);
|
|
led->on = !led->on;
|
|
led_gpio_write(led->gpio, led->on);
|
|
uint32_t next_time = led->on ? led->ontime : led->offtime;
|
|
|
|
xTimerChangePeriod(led->timer, pdMS_TO_TICKS(next_time), BLOCK_TIME);
|
|
}
|
|
|
|
// ----------------------------
|
|
// Inicialização
|
|
// ----------------------------
|
|
|
|
void led_init(void)
|
|
{
|
|
gpio_config_t io_conf = {
|
|
.mode = GPIO_MODE_OUTPUT,
|
|
.intr_type = GPIO_INTR_DISABLE,
|
|
.pull_up_en = GPIO_PULLUP_DISABLE,
|
|
.pull_down_en = GPIO_PULLDOWN_ENABLE,
|
|
.pin_bit_mask = 0
|
|
};
|
|
|
|
for (int i = 0; i < LED_ID_MAX; i++) {
|
|
leds[i].gpio = GPIO_NUM_NC;
|
|
}
|
|
|
|
if (board_config.led_stop) {
|
|
leds[LED_ID_STOP].gpio = board_config.led_stop_gpio;
|
|
io_conf.pin_bit_mask |= BIT64(board_config.led_stop_gpio);
|
|
}
|
|
|
|
if (board_config.led_charging) {
|
|
leds[LED_ID_CHARGING].gpio = board_config.led_charging_gpio;
|
|
io_conf.pin_bit_mask |= BIT64(board_config.led_charging_gpio);
|
|
}
|
|
|
|
if (board_config.led_error) {
|
|
leds[LED_ID_ERROR].gpio = board_config.led_error_gpio;
|
|
io_conf.pin_bit_mask |= BIT64(board_config.led_error_gpio);
|
|
}
|
|
|
|
if (io_conf.pin_bit_mask != 0) {
|
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
|
}
|
|
|
|
if (!led_update_timer) {
|
|
led_update_timer = xTimerCreate("led_update_timer",
|
|
pdMS_TO_TICKS(LED_UPDATE_INTERVAL_MS),
|
|
pdTRUE, NULL,
|
|
led_update_timer_callback);
|
|
if (led_update_timer) {
|
|
xTimerStart(led_update_timer, BLOCK_TIME);
|
|
} else {
|
|
ESP_LOGE(TAG, "Failed to create LED update timer");
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------
|
|
// API Pública
|
|
// ----------------------------
|
|
|
|
void led_set_state(led_id_t led_id, uint16_t ontime, uint16_t offtime)
|
|
{
|
|
if (led_id >= LED_ID_MAX) return;
|
|
|
|
led_t *led = &leds[led_id];
|
|
if (led->gpio == GPIO_NUM_NC) return;
|
|
|
|
// Evita reconfiguração idêntica
|
|
if (led->ontime == ontime && led->offtime == offtime)
|
|
return;
|
|
|
|
if (led->timer) {
|
|
xTimerStop(led->timer, BLOCK_TIME);
|
|
}
|
|
|
|
led->ontime = ontime;
|
|
led->offtime = offtime;
|
|
|
|
if (ontime == 0) {
|
|
led->on = false;
|
|
led_gpio_write(led->gpio, 0);
|
|
} else if (offtime == 0) {
|
|
led->on = true;
|
|
led_gpio_write(led->gpio, 1);
|
|
} else {
|
|
led->on = true;
|
|
led_gpio_write(led->gpio, 1);
|
|
|
|
if (!led->timer) {
|
|
led->timer = xTimerCreate("led_timer", pdMS_TO_TICKS(ontime),
|
|
pdFALSE, (void *)led, led_timer_callback);
|
|
}
|
|
|
|
if (led->timer) {
|
|
xTimerStart(led->timer, BLOCK_TIME);
|
|
}
|
|
}
|
|
}
|
|
|
|
void led_apply_pattern(led_id_t id, led_pattern_t pattern)
|
|
{
|
|
if (id >= LED_ID_MAX) return;
|
|
|
|
led_t *led = &leds[id];
|
|
if (led->gpio == GPIO_NUM_NC) return;
|
|
|
|
if (led->pattern == pattern) return;
|
|
|
|
if (led->timer) {
|
|
xTimerStop(led->timer, BLOCK_TIME);
|
|
}
|
|
|
|
led->pattern = pattern;
|
|
led->blink_count = 0;
|
|
|
|
switch (pattern) {
|
|
case LED_PATTERN_OFF:
|
|
led_set_state(id, 0, 0);
|
|
break;
|
|
case LED_PATTERN_ON:
|
|
led_set_state(id, 1, 0);
|
|
break;
|
|
case LED_PATTERN_BLINK:
|
|
led_set_state(id, 500, 500);
|
|
break;
|
|
case LED_PATTERN_BLINK_FAST:
|
|
led_set_state(id, 200, 200);
|
|
break;
|
|
case LED_PATTERN_BLINK_SLOW:
|
|
led_set_state(id, 300, 1700);
|
|
break;
|
|
case LED_PATTERN_CHARGING_EFFECT:
|
|
led_set_state(id, 2000, 1000);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ----------------------------
|
|
// Controle por Estado
|
|
// ----------------------------
|
|
|
|
static void led_apply_by_state(evse_state_t state)
|
|
{
|
|
// Reset todos
|
|
led_apply_pattern(LED_ID_STOP, LED_PATTERN_OFF);
|
|
led_apply_pattern(LED_ID_CHARGING, LED_PATTERN_OFF);
|
|
led_apply_pattern(LED_ID_ERROR, LED_PATTERN_OFF);
|
|
|
|
switch (state) {
|
|
case EVSE_STATE_A:
|
|
led_apply_pattern(LED_ID_STOP, LED_PATTERN_ON);
|
|
break;
|
|
case EVSE_STATE_B1:
|
|
case EVSE_STATE_B2:
|
|
case EVSE_STATE_C1:
|
|
led_apply_pattern(LED_ID_CHARGING, LED_PATTERN_ON);
|
|
break;
|
|
case EVSE_STATE_C2:
|
|
led_apply_pattern(LED_ID_CHARGING, LED_PATTERN_CHARGING_EFFECT);
|
|
break;
|
|
case EVSE_STATE_D1:
|
|
case EVSE_STATE_D2:
|
|
led_apply_pattern(LED_ID_CHARGING, LED_PATTERN_BLINK_FAST);
|
|
break;
|
|
case EVSE_STATE_E:
|
|
case EVSE_STATE_F:
|
|
led_apply_pattern(LED_ID_ERROR, LED_PATTERN_BLINK_FAST);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ----------------------------
|
|
// Timer Update
|
|
// ----------------------------
|
|
|
|
static void led_update(void)
|
|
{
|
|
if (evse_error_is_active()) {
|
|
led_apply_pattern(LED_ID_ERROR, LED_PATTERN_BLINK_FAST);
|
|
led_apply_pattern(LED_ID_STOP, LED_PATTERN_OFF);
|
|
led_apply_pattern(LED_ID_CHARGING, LED_PATTERN_OFF);
|
|
return;
|
|
}
|
|
|
|
evse_state_t current = evse_get_state();
|
|
|
|
if (current != led_state) {
|
|
led_state = current;
|
|
led_apply_by_state(current);
|
|
}
|
|
}
|
|
|
|
static void led_update_timer_callback(TimerHandle_t xTimer)
|
|
{
|
|
(void)xTimer;
|
|
led_update();
|
|
}
|
|
|
|
// === Fim de: components/peripherals/src/led.c ===
|
|
|
|
|
|
// === Início de: components/peripherals/src/rcm.c ===
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/gpio.h"
|
|
#include "esp_log.h"
|
|
|
|
#include "rcm.h"
|
|
#include "board_config.h"
|
|
#include "evse_api.h"
|
|
|
|
// static bool do_test = false;
|
|
|
|
// static bool triggered = false;
|
|
|
|
// static bool test_triggered = false;
|
|
|
|
// static void IRAM_ATTR rcm_isr_handler(void* arg)
|
|
// {
|
|
// if (!do_test) {
|
|
// triggered = true;
|
|
// } else {
|
|
// test_triggered = true;
|
|
// }
|
|
// }
|
|
|
|
void rcm_init(void)
|
|
{
|
|
if (board_config.rcm) {
|
|
gpio_config_t io_conf = {};
|
|
|
|
io_conf.mode = GPIO_MODE_OUTPUT;
|
|
io_conf.pin_bit_mask = BIT64(board_config.rcm_test_gpio);
|
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
|
|
|
io_conf.mode = GPIO_MODE_INPUT;
|
|
// io_conf.intr_type = GPIO_INTR_POSEDGE;
|
|
io_conf.pin_bit_mask = BIT64(board_config.rcm_gpio);
|
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
|
//ESP_ERROR_CHECK(gpio_isr_handler_add(board_config.rcm_gpio, rcm_isr_handler, NULL));
|
|
}
|
|
}
|
|
|
|
bool rcm_test(void)
|
|
{
|
|
// do_test = true;
|
|
// test_triggered = false;
|
|
|
|
// gpio_set_level(board_config.rcm_test_gpio, 1);
|
|
// vTaskDelay(pdMS_TO_TICKS(100));
|
|
// gpio_set_level(board_config.rcm_test_gpio, 0);
|
|
|
|
// do_test = false;
|
|
|
|
// return test_triggered;
|
|
|
|
gpio_set_level(board_config.rcm_test_gpio, 1);
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
bool success = gpio_get_level(board_config.rcm_gpio) == 1;
|
|
gpio_set_level(board_config.rcm_test_gpio, 0);
|
|
|
|
return success;
|
|
}
|
|
|
|
bool rcm_is_triggered(void)
|
|
{
|
|
// bool _triggered = triggered;
|
|
// if (gpio_get_level(board_config.rcm_gpio) == 0) {
|
|
// triggered = false;
|
|
// }
|
|
// return _triggered;
|
|
if (gpio_get_level(board_config.rcm_gpio) == 1) {
|
|
vTaskDelay(pdMS_TO_TICKS(1));
|
|
return gpio_get_level(board_config.rcm_gpio) == 1;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
// === Fim de: components/peripherals/src/rcm.c ===
|
|
|
|
|
|
// === Início de: components/peripherals/src/adc.c ===
|
|
#include "adc.h"
|
|
#include "esp_log.h"
|
|
|
|
const static char* TAG = "adc";
|
|
|
|
adc_oneshot_unit_handle_t adc_handle;
|
|
|
|
adc_cali_handle_t adc_cali_handle;
|
|
|
|
void adc_init(void)
|
|
{
|
|
adc_oneshot_unit_init_cfg_t conf = {
|
|
.unit_id = ADC_UNIT_1
|
|
};
|
|
ESP_ERROR_CHECK(adc_oneshot_new_unit(&conf, &adc_handle));
|
|
|
|
bool calibrated = false;
|
|
|
|
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
|
|
if (!calibrated) {
|
|
ESP_LOGI(TAG, "Calibration scheme version is %s", "Curve Fitting");
|
|
adc_cali_curve_fitting_config_t cali_config = {
|
|
.unit_id = ADC_UNIT_1,
|
|
.atten = ADC_ATTEN_DB_12,
|
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
};
|
|
if (adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle) == ESP_OK) {
|
|
calibrated = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
|
|
if (!calibrated) {
|
|
ESP_LOGI(TAG, "Calibration scheme version is %s", "Line Fitting");
|
|
adc_cali_line_fitting_config_t cali_config = {
|
|
.unit_id = ADC_UNIT_1,
|
|
.atten = ADC_ATTEN_DB_12,
|
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
.default_vref = 1100
|
|
#endif
|
|
};
|
|
if (adc_cali_create_scheme_line_fitting(&cali_config, &adc_cali_handle) == ESP_OK) {
|
|
calibrated = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!calibrated) {
|
|
ESP_LOGE(TAG, "No calibration scheme");
|
|
ESP_ERROR_CHECK(ESP_FAIL);
|
|
}
|
|
}
|
|
// === Fim de: components/peripherals/src/adc.c ===
|
|
|
|
|
|
// === Início de: components/peripherals/src/adc121s021_dma.c ===
|
|
#include "driver/spi_master.h"
|
|
#include "driver/gpio.h"
|
|
#include "esp_log.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "adc121s021_dma.h"
|
|
|
|
#define TAG "adc_dma"
|
|
|
|
#define PIN_NUM_MOSI 23
|
|
#define PIN_NUM_MISO 19
|
|
#define PIN_NUM_CLK 18
|
|
#define PIN_NUM_CS 5
|
|
|
|
#define SPI_HOST_USED SPI2_HOST
|
|
#define SAMPLE_SIZE_BYTES 2
|
|
#define ADC_BITS 12
|
|
|
|
static spi_device_handle_t adc_spi;
|
|
|
|
void adc121s021_dma_init(void)
|
|
{
|
|
spi_bus_config_t buscfg = {
|
|
.mosi_io_num = PIN_NUM_MOSI,
|
|
.miso_io_num = PIN_NUM_MISO,
|
|
.sclk_io_num = PIN_NUM_CLK,
|
|
.quadwp_io_num = -1,
|
|
.quadhd_io_num = -1,
|
|
.max_transfer_sz = SAMPLE_SIZE_BYTES,
|
|
};
|
|
|
|
spi_device_interface_config_t devcfg = {
|
|
.clock_speed_hz = 6000000, // 6 MHz
|
|
.mode = 0,
|
|
.spics_io_num = PIN_NUM_CS,
|
|
.queue_size = 2,
|
|
.flags = SPI_DEVICE_NO_DUMMY,
|
|
};
|
|
|
|
ESP_ERROR_CHECK(spi_bus_initialize(SPI_HOST_USED, &buscfg, SPI_DMA_CH_AUTO));
|
|
ESP_ERROR_CHECK(spi_bus_add_device(SPI_HOST_USED, &devcfg, &adc_spi));
|
|
}
|
|
|
|
bool adc121s021_dma_get_sample(uint16_t *sample)
|
|
{
|
|
uint8_t tx_buffer[2] = {0x00, 0x00}; // Dummy TX
|
|
uint8_t rx_buffer[2] = {0};
|
|
|
|
spi_transaction_t t = {
|
|
.length = 16, // 16 bits
|
|
.tx_buffer = tx_buffer,
|
|
.rx_buffer = rx_buffer,
|
|
.flags = 0
|
|
};
|
|
|
|
esp_err_t err = spi_device_transmit(adc_spi, &t);
|
|
if (err != ESP_OK) {
|
|
ESP_LOGE(TAG, "SPI transmit error: %s", esp_err_to_name(err));
|
|
return false;
|
|
}
|
|
|
|
// Extrai os 12 bits significativos da resposta do ADC121S021
|
|
*sample = ((rx_buffer[0] << 8) | rx_buffer[1]) & 0x0FFF;
|
|
|
|
return true;
|
|
}
|
|
|
|
// === Fim de: components/peripherals/src/adc121s021_dma.c ===
|
|
|
|
|
|
// === Início de: components/peripherals/src/peripherals.c ===
|
|
#include "peripherals.h"
|
|
#include "adc.h"
|
|
#include "led.h"
|
|
#include "buzzer.h"
|
|
#include "proximity.h"
|
|
#include "ac_relay.h"
|
|
#include "socket_lock.h"
|
|
#include "rcm.h"
|
|
#include "aux_io.h"
|
|
#include "ntc_sensor.h"
|
|
|
|
void peripherals_init(void)
|
|
{
|
|
ac_relay_init();
|
|
led_init();
|
|
buzzer_init();
|
|
adc_init();
|
|
proximity_init();
|
|
// socket_lock_init();
|
|
// rcm_init();
|
|
//energy_meter_init();
|
|
// aux_init();
|
|
ntc_sensor_init();
|
|
}
|
|
// === Fim de: components/peripherals/src/peripherals.c ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/adc121s021_dma.h ===
|
|
#ifndef ADC_DMA_H_
|
|
#define ADC_DMA_H_
|
|
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
void adc121s021_dma_init(void);
|
|
bool adc121s021_dma_get_sample(uint16_t *sample);
|
|
|
|
|
|
#endif /* ADC_DMA_h_ */
|
|
|
|
// === Fim de: components/peripherals/include/adc121s021_dma.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/peripherals.h ===
|
|
#ifndef PERIPHERALS_H
|
|
#define PERIPHERALS_H
|
|
|
|
void peripherals_init(void);
|
|
|
|
#endif /* PERIPHERALS_H */
|
|
|
|
// === Fim de: components/peripherals/include/peripherals.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/rcm.h ===
|
|
#ifndef RCM_H_
|
|
#define RCM_H_
|
|
|
|
#include <stdbool.h>
|
|
|
|
/**
|
|
* @brief Initialize residual current monitor
|
|
*
|
|
*/
|
|
void rcm_init(void);
|
|
|
|
/**
|
|
* @brief Test residual current monitor
|
|
*
|
|
* @return true
|
|
* @return false
|
|
*/
|
|
bool rcm_test(void);
|
|
|
|
/**
|
|
* @brief Residual current monitor was detected leakage
|
|
*
|
|
* @return true
|
|
* @return false
|
|
*/
|
|
bool rcm_is_triggered(void);
|
|
|
|
#endif /* RCM_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/rcm.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/aux_io.h ===
|
|
#ifndef AUX_IO_H_
|
|
#define AUX_IO_H_
|
|
|
|
#include "esp_err.h"
|
|
|
|
/**
|
|
* @brief Initialize aux
|
|
*
|
|
*/
|
|
void aux_init(void);
|
|
|
|
/**
|
|
* @brief Read digital input
|
|
*
|
|
* @param name
|
|
* @param value
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t aux_read(const char *name, bool *value);
|
|
|
|
/**
|
|
* @brief Write digial output
|
|
*
|
|
* @param name
|
|
* @param value
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t aux_write(const char *name, bool value);
|
|
|
|
/**
|
|
* @brief Read analog input
|
|
*
|
|
* @param name
|
|
* @param value
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t aux_analog_read(const char *name, int *value);
|
|
|
|
#endif /* AUX_IO_H_ */
|
|
// === Fim de: components/peripherals/include/aux_io.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/led.h ===
|
|
#ifndef LED_H_
|
|
#define LED_H_
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
/**
|
|
* @brief Identificadores dos LEDs disponíveis no hardware
|
|
*/
|
|
typedef enum {
|
|
LED_ID_STOP,
|
|
LED_ID_CHARGING,
|
|
LED_ID_ERROR,
|
|
LED_ID_MAX
|
|
} led_id_t;
|
|
|
|
/**
|
|
* @brief Padrões de comportamento possíveis para os LEDs
|
|
*/
|
|
typedef enum {
|
|
LED_PATTERN_OFF, ///< LED sempre desligado
|
|
LED_PATTERN_ON, ///< LED sempre ligado
|
|
LED_PATTERN_BLINK, ///< Pisca com ciclo padrão (500ms on / 500ms off)
|
|
LED_PATTERN_BLINK_FAST, ///< Pisca rápido (200ms / 200ms)
|
|
LED_PATTERN_BLINK_SLOW, ///< Pisca lento (300ms / 1700ms)
|
|
LED_PATTERN_CHARGING_EFFECT ///< Efeito visual para carregamento (2s on / 1s off)
|
|
} led_pattern_t;
|
|
|
|
/**
|
|
* @brief Inicializa os LEDs com base na configuração da placa
|
|
* Deve ser chamada uma única vez na inicialização do sistema.
|
|
*/
|
|
void led_init(void);
|
|
|
|
/**
|
|
* @brief Define diretamente o tempo ligado/desligado de um LED.
|
|
* Pode ser usado para padrões personalizados.
|
|
*
|
|
* @param led_id Identificador do LED (ver enum led_id_t)
|
|
* @param ontime Tempo ligado em milissegundos
|
|
* @param offtime Tempo desligado em milissegundos
|
|
*/
|
|
void led_set_state(led_id_t led_id, uint16_t ontime, uint16_t offtime);
|
|
|
|
/**
|
|
* @brief Aplica um dos padrões de piscar definidos ao LED
|
|
*
|
|
* @param led_id Identificador do LED (ver enum led_id_t)
|
|
* @param pattern Padrão desejado (ver enum led_pattern_t)
|
|
*/
|
|
void led_apply_pattern(led_id_t led_id, led_pattern_t pattern);
|
|
|
|
#endif /* LED_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/led.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/buzzer.h ===
|
|
#ifndef BUZZER_H_
|
|
#define BUZZER_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
/**
|
|
* @brief Inicializa o buzzer e inicia monitoramento automático do estado EVSE.
|
|
*/
|
|
void buzzer_init(void);
|
|
|
|
/**
|
|
* @brief Liga e desliga o buzzer manualmente (uso interno ou testes).
|
|
*/
|
|
void buzzer_on(void);
|
|
void buzzer_off(void);
|
|
|
|
/**
|
|
* @brief Ativa o buzzer por um período fixo (em milissegundos).
|
|
*/
|
|
void buzzer_beep_ms(uint16_t ms);
|
|
|
|
#endif /* BUZZER_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/buzzer.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/ac_relay.h ===
|
|
#ifndef AC_RELAY_H_
|
|
#define AC_RELAY_H_
|
|
|
|
#include <stdbool.h>
|
|
|
|
/**
|
|
* @brief Inicializa o relé de corrente alternada.
|
|
*/
|
|
void ac_relay_init(void);
|
|
|
|
/**
|
|
* @brief Define o estado do relé de corrente alternada.
|
|
*
|
|
* @param state true para ligar, false para desligar.
|
|
*/
|
|
void ac_relay_set_state(bool state);
|
|
|
|
/**
|
|
* @brief Retorna o estado atual do relé de corrente alternada.
|
|
*
|
|
* @return true se estiver ligado, false se desligado.
|
|
*/
|
|
bool ac_relay_get_state(void);
|
|
|
|
#endif /* AC_RELAY_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/ac_relay.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/lm75a.h ===
|
|
#ifndef LM75A_H
|
|
#define LM75A_H
|
|
|
|
#include "esp_err.h" // Para o uso de tipos de erro do ESP-IDF, caso esteja utilizando.
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief Inicializa o sensor LM75A.
|
|
*
|
|
* Configura o sensor para leitura e define os pinos de comunicação.
|
|
*/
|
|
esp_err_t lm75a_init(void);
|
|
|
|
/**
|
|
* @brief Desinicializa o sensor LM75A.
|
|
*
|
|
* Libera os recursos usados pelo sensor.
|
|
*/
|
|
esp_err_t lm75a_deinit(void);
|
|
|
|
/**
|
|
* @brief Lê a temperatura do LM75A.
|
|
*
|
|
* @param show Se for 1, a temperatura será exibida em algum tipo de log ou interface.
|
|
* Se for 0, o valor é apenas retornado sem exibição.
|
|
* @return A temperatura lida em graus Celsius.
|
|
*/
|
|
float lm75a_read_temperature(int show);
|
|
|
|
/**
|
|
* @brief Define o valor do limite de temperatura (T_OS) para o sensor LM75A.
|
|
*
|
|
* @param tos O limite de temperatura de sobrecarga (T_OS) em graus Celsius.
|
|
* @return ESP_OK em caso de sucesso ou código de erro se falhar.
|
|
*/
|
|
esp_err_t lm75a_set_tos(int tos);
|
|
|
|
/**
|
|
* @brief Define o valor do limite de temperatura de histerese (T_HYS) para o sensor LM75A.
|
|
*
|
|
* @param thys O limite de histerese de temperatura (T_HYS) em graus Celsius.
|
|
* @return ESP_OK em caso de sucesso ou código de erro se falhar.
|
|
*/
|
|
esp_err_t lm75a_set_thys(int thys);
|
|
|
|
/**
|
|
* @brief Obtém o limite de temperatura de sobrecarga (T_OS) do sensor LM75A.
|
|
*
|
|
* @return O valor atual de T_OS em graus Celsius.
|
|
*/
|
|
int lm75a_get_tos(void);
|
|
|
|
/**
|
|
* @brief Obtém o limite de temperatura de histerese (T_HYS) do sensor LM75A.
|
|
*
|
|
* @return O valor atual de T_HYS em graus Celsius.
|
|
*/
|
|
int lm75a_get_thys(void);
|
|
|
|
/**
|
|
* @brief Habilita ou desabilita a interrupção do LM75A.
|
|
*
|
|
* @param en 1 para habilitar a interrupção, 0 para desabilitar.
|
|
* @return ESP_OK em caso de sucesso ou código de erro se falhar.
|
|
*/
|
|
esp_err_t lm75a_set_int(int en);
|
|
|
|
/**
|
|
* @brief Obtém o estado do pino OS (Overtemperature Shutdown) do LM75A.
|
|
*
|
|
* @return 1 se o pino OS estiver ativo (indica que a temperatura de sobrecarga foi atingida),
|
|
* 0 caso contrário.
|
|
*/
|
|
int lm75a_get_osio(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* LM75A_H */
|
|
|
|
// === Fim de: components/peripherals/include/lm75a.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/ntc_sensor.h ===
|
|
#ifndef NTC_SENSOR_H_
|
|
#define NTC_SENSOR_H_
|
|
|
|
/**
|
|
* @brief Initialize ntc senso
|
|
*
|
|
*/
|
|
void ntc_sensor_init(void);
|
|
|
|
/**
|
|
* @brief Return temperature after temp_sensor_measure
|
|
*
|
|
* @return float
|
|
*/
|
|
float ntc_temp_sensor(void);
|
|
|
|
#endif /* NTC_SENSOR_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/ntc_sensor.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/proximity.h ===
|
|
#ifndef PROXIMITY_H_
|
|
#define PROXIMITY_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
/**
|
|
* @brief Initialize proximity check
|
|
*
|
|
*/
|
|
void proximity_init(void);
|
|
|
|
/**
|
|
* @brief Return measured value of max current on PP
|
|
*
|
|
* @return current in A
|
|
*/
|
|
uint8_t proximity_get_max_current(void);
|
|
|
|
#endif /* PROXIMITY_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/proximity.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/socket_lock.h ===
|
|
#ifndef SOCKED_LOCK_H_
|
|
#define SOCKED_LOCK_H_
|
|
|
|
#include "esp_err.h"
|
|
|
|
typedef enum
|
|
{
|
|
SOCKED_LOCK_STATUS_IDLE,
|
|
SOCKED_LOCK_STATUS_OPERATING,
|
|
SOCKED_LOCK_STATUS_LOCKING_FAIL,
|
|
SOCKED_LOCK_STATUS_UNLOCKING_FAIL
|
|
} socket_lock_status_t;
|
|
|
|
/**
|
|
* @brief Initialize socket lock
|
|
*
|
|
*/
|
|
void socket_lock_init(void);
|
|
|
|
/**
|
|
* @brief Get socket lock detection on high, stored in NVS
|
|
*
|
|
* @return true when locked has zero resistance
|
|
* @return false when unlocked has zero resistance
|
|
*/
|
|
bool socket_lock_is_detection_high(void);
|
|
|
|
/**
|
|
* @brief Set socket lock detection on high, stored in NVS
|
|
*
|
|
* @param detection_high
|
|
*/
|
|
void socket_lock_set_detection_high(bool detection_high);
|
|
|
|
/**
|
|
* @brief Get socket lock operating time
|
|
*
|
|
* @return time in ms
|
|
*/
|
|
uint16_t socket_lock_get_operating_time(void);
|
|
|
|
/**
|
|
* @brief Set socket lock operating time
|
|
*
|
|
* @param operating_time - time in ms
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t socket_lock_set_operating_time(uint16_t operating_time);
|
|
|
|
/**
|
|
* @brief Get socket lock retry count
|
|
*
|
|
* @return retry count
|
|
*/
|
|
uint8_t socket_lock_get_retry_count(void);
|
|
|
|
/**
|
|
* @brief Set socket lock retry count
|
|
*
|
|
* @param retry_count
|
|
*/
|
|
void socket_lock_set_retry_count(uint8_t retry_count);
|
|
|
|
/**
|
|
* @brief Get socket lock break time
|
|
*
|
|
* @return time in ms
|
|
*/
|
|
uint16_t socket_lock_get_break_time(void);
|
|
|
|
/**
|
|
* @brief Set socket lock break time
|
|
*
|
|
* @param break_time
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t socket_lock_set_break_time(uint16_t break_time);
|
|
|
|
/**
|
|
* @brief Set socke lock to locked / unlocked state
|
|
*
|
|
* @param locked
|
|
*/
|
|
void socket_lock_set_locked(bool locked);
|
|
|
|
/**
|
|
* @brief Get socket lock status
|
|
*
|
|
* @return socket_lock_status_t
|
|
*/
|
|
socket_lock_status_t socket_lock_get_status(void);
|
|
|
|
/**
|
|
* @brief Read the current physical lock state using the detection pin.
|
|
*/
|
|
bool socket_lock_is_locked_state(void);
|
|
|
|
|
|
#endif /* SOCKED_LOCK_H_ */
|
|
|
|
// === Fim de: components/peripherals/include/socket_lock.h ===
|
|
|
|
|
|
// === Início de: components/peripherals/include/adc.h ===
|
|
#ifndef ADC_H_
|
|
#define ADC_H_
|
|
|
|
#include "esp_adc/adc_oneshot.h"
|
|
#include "esp_adc/adc_cali.h"
|
|
#include "esp_adc/adc_cali_scheme.h"
|
|
|
|
extern adc_oneshot_unit_handle_t adc_handle;
|
|
|
|
extern adc_cali_handle_t adc_cali_handle;
|
|
|
|
void adc_init(void);
|
|
|
|
#endif /* ADC_H_ */
|
|
// === Fim de: components/peripherals/include/adc.h ===
|