Adicionar primeiro
This commit is contained in:
443
components/serial_sync/src/sync_master.c
Executable file
443
components/serial_sync/src/sync_master.c
Executable file
@@ -0,0 +1,443 @@
|
||||
|
||||
/* UART asynchronous example, that uses separate RX and TX tasks
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "driver/uart.h"
|
||||
#include "string.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "nanopb/pb_decode.h"
|
||||
#include "nanopb/pb_encode.h"
|
||||
#include "nanopb/pb_common.h"
|
||||
|
||||
#include "LoToHi.pb.h"
|
||||
#include "HiToLo.pb.h"
|
||||
// #include "inc/version_autogen.h"
|
||||
#include "sync_master.h"
|
||||
#include "evse_api.h"
|
||||
|
||||
#define VERSION_STRING "2.2"
|
||||
|
||||
static const int RX_BUF_SIZE = 1024;
|
||||
|
||||
#define TXD_PIN (GPIO_NUM_27)
|
||||
#define RXD_PIN (GPIO_NUM_26)
|
||||
|
||||
static uint8_t msg[2048];
|
||||
static uint8_t code;
|
||||
static uint8_t block;
|
||||
static uint8_t *decode;
|
||||
|
||||
static const char *TAG = "MASTER_TASK";
|
||||
|
||||
void cobsDecodeReset()
|
||||
{
|
||||
code = 0xff;
|
||||
block = 0;
|
||||
decode = msg;
|
||||
}
|
||||
|
||||
void handlePacket(uint8_t *buf, int len);
|
||||
|
||||
void init(void)
|
||||
{
|
||||
const uart_config_t uart_config = {
|
||||
.baud_rate = 115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
// We won't use a buffer for sending data.
|
||||
uart_driver_install(UART_NUM_2, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
|
||||
uart_param_config(UART_NUM_2, &uart_config);
|
||||
uart_set_pin(UART_NUM_2, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
|
||||
cobsDecodeReset();
|
||||
}
|
||||
|
||||
uint32_t crc32(uint8_t *buf, int len)
|
||||
{
|
||||
int i, j;
|
||||
uint32_t b, crc, msk;
|
||||
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
while (i < len)
|
||||
{
|
||||
b = buf[i];
|
||||
crc = crc ^ b;
|
||||
for (j = 7; j >= 0; j--)
|
||||
{
|
||||
msk = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & msk);
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
// printf("%X",crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
void cobsDecodeByte(uint8_t byte)
|
||||
{
|
||||
|
||||
// ESP_LOGI("RX_TASK", "init cobsDecodeByte");
|
||||
// ESP_LOGI("RX_TASK", "Read bytes: '%02X'", byte);
|
||||
|
||||
// check max length
|
||||
if ((decode - msg == 2048 - 1) && byte != 0x00)
|
||||
{
|
||||
ESP_LOGI(TAG, "cobsDecode: Buffer overflow");
|
||||
cobsDecodeReset();
|
||||
}
|
||||
|
||||
if (block)
|
||||
{
|
||||
// ESP_LOGI("RX_TASK", "block");
|
||||
// we're currently decoding and should not get a 0
|
||||
if (byte == 0x00)
|
||||
{
|
||||
// probably found some garbage -> reset
|
||||
ESP_LOGI("RX_TASK", "cobsDecode: Garbage detected");
|
||||
cobsDecodeReset();
|
||||
return;
|
||||
}
|
||||
*decode++ = byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ESP_LOGI("RX_TASK", "not block");
|
||||
if (code != 0xff)
|
||||
{
|
||||
*decode++ = 0;
|
||||
}
|
||||
block = code = byte;
|
||||
if (code == 0x00)
|
||||
{
|
||||
// we're finished, reset everything and commit
|
||||
if (decode == msg)
|
||||
{
|
||||
// we received nothing, just a 0x00
|
||||
ESP_LOGI("RX_TASK", "cobsDecode: Received nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
// set back decode with one, as it gets post-incremented
|
||||
handlePacket(msg, decode - 1 - msg);
|
||||
}
|
||||
cobsDecodeReset();
|
||||
return; // need to return here, because of block--
|
||||
}
|
||||
}
|
||||
block--;
|
||||
}
|
||||
|
||||
void cobsDecode(uint8_t *buf, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
cobsDecodeByte(buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
size_t cobsEncode(const void *data, size_t length, uint8_t *buffer)
|
||||
{
|
||||
uint8_t *encode = buffer; // Encoded byte pointer
|
||||
uint8_t *codep = encode++; // Output code pointer
|
||||
uint8_t code = 1; // Code value
|
||||
|
||||
for (const uint8_t *byte = (const uint8_t *)data; length--; ++byte)
|
||||
{
|
||||
if (*byte) // Byte not zero, write it
|
||||
*encode++ = *byte, ++code;
|
||||
|
||||
if (!*byte || code == 0xff) // Input is zero or block completed, restart
|
||||
{
|
||||
*codep = code, code = 1, codep = encode;
|
||||
if (!*byte || length)
|
||||
++encode;
|
||||
}
|
||||
}
|
||||
*codep = code; // Write final code value
|
||||
|
||||
// add final 0
|
||||
*encode++ = 0x00;
|
||||
|
||||
return encode - buffer;
|
||||
}
|
||||
|
||||
int linkWrite(HiToLo *m)
|
||||
{
|
||||
|
||||
ESP_LOGI(TAG, "linkWrite");
|
||||
uint8_t tx_packet_buf[200];
|
||||
uint8_t encode_buf[208];
|
||||
pb_ostream_t ostream = pb_ostream_from_buffer(tx_packet_buf, sizeof(tx_packet_buf) - 4);
|
||||
bool status = pb_encode(&ostream, HiToLo_fields, m);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
// couldn't encode
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t tx_payload_len = ostream.bytes_written;
|
||||
|
||||
// add crc32 (CRC-32/JAMCRC)
|
||||
uint32_t crc = crc32(tx_packet_buf, tx_payload_len);
|
||||
|
||||
for (int byte_pos = 0; byte_pos < 4; ++byte_pos)
|
||||
{
|
||||
tx_packet_buf[tx_payload_len] = (uint8_t)crc & 0xFF;
|
||||
crc = crc >> 8;
|
||||
tx_payload_len++;
|
||||
}
|
||||
size_t tx_encode_len = cobsEncode(tx_packet_buf, tx_payload_len, encode_buf);
|
||||
const int txBytes = uart_write_bytes(UART_NUM_2, encode_buf, tx_encode_len);
|
||||
return txBytes;
|
||||
}
|
||||
|
||||
void send_time_stamp()
|
||||
{
|
||||
ESP_LOGI(TAG, "send_time_stamp");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_time_stamp_tag;
|
||||
msg_out.payload.time_stamp = esp_timer_get_time() / 1000;
|
||||
linkWrite(&msg_out);
|
||||
printf("time stamp sent %i.\n", (int)msg_out.payload.time_stamp);
|
||||
}
|
||||
|
||||
void send_connector_lock(bool on)
|
||||
{
|
||||
ESP_LOGI(TAG, "connector_lock");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_connector_lock_tag;
|
||||
msg_out.payload.connector_lock = on;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void send_max_charging_current(uint32_t max_charging_current)
|
||||
{
|
||||
ESP_LOGI(TAG, "send_max_charging_current");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_max_charging_current_tag;
|
||||
msg_out.payload.max_charging_current = max_charging_current;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void send_allow_power_on(bool allow_power_on)
|
||||
{
|
||||
ESP_LOGI(TAG, "allow_power_on");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_allow_power_on_tag;
|
||||
msg_out.payload.allow_power_on = allow_power_on;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void send_reset(bool reset)
|
||||
{
|
||||
ESP_LOGI(TAG, "reset");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_reset_tag;
|
||||
msg_out.payload.reset = reset;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void send_grid_current(uint32_t grid_current)
|
||||
{
|
||||
ESP_LOGI(TAG, "send_grid_current");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_grid_current_tag;
|
||||
msg_out.payload.grid_current = grid_current;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void send_max_grid_current(uint32_t max_grid_current)
|
||||
{
|
||||
ESP_LOGI(TAG, "send_max_grid_current");
|
||||
HiToLo msg_out = HiToLo_init_default;
|
||||
msg_out.which_payload = HiToLo_max_grid_current_tag;
|
||||
msg_out.payload.max_grid_current = max_grid_current;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
/*
|
||||
const evse_state_t cp_state_to_evse_state(CpState cp_state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case CpState_EVSE_STATE_A:
|
||||
return EVSE_STATE_A;
|
||||
case CpState_EVSE_STATE_B1:
|
||||
return EVSE_STATE_B1;
|
||||
case CpState_EVSE_STATE_B2:
|
||||
return EVSE_STATE_B2;
|
||||
case CpState_EVSE_STATE_C1:
|
||||
return EVSE_STATE_C1;
|
||||
case CpState_EVSE_STATE_C2:
|
||||
return EVSE_STATE_C2;
|
||||
case CpState_EVSE_STATE_D1:
|
||||
return EVSE_STATE_D1;
|
||||
case CpState_EVSE_STATE_D2:
|
||||
return EVSE_STATE_D2;
|
||||
case CpState_EVSE_STATE_E:
|
||||
return EVSE_STATE_E;
|
||||
case CpState_EVSE_STATE_F:
|
||||
return EVSE_STATE_F;
|
||||
default:
|
||||
return EVSE_STATE_F;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void handlePacket(uint8_t *buf, int len)
|
||||
{
|
||||
// printf ("packet received len %u\n", len);
|
||||
|
||||
// Check CRC32 (last 4 bytes)
|
||||
// uint32_t crc = calculateCrc(rx_packet_buf, rx_packet_len);
|
||||
if (crc32(buf, len))
|
||||
{
|
||||
printf("CRC mismatch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
|
||||
LoToHi msg_in;
|
||||
|
||||
pb_istream_t istream = pb_istream_from_buffer(buf, len);
|
||||
|
||||
if (pb_decode(&istream, LoToHi_fields, &msg_in))
|
||||
{
|
||||
//printf("LoToHi recvd %i \n", msg_in.which_payload);
|
||||
|
||||
switch (msg_in.which_payload)
|
||||
{
|
||||
case LoToHi_time_stamp_tag:
|
||||
printf("Received time stamp %i\n", (int)msg_in.payload.time_stamp);
|
||||
break;
|
||||
case LoToHi_relais_state_tag:
|
||||
printf("Received relais_state %i\n", (int)msg_in.payload.relais_state);
|
||||
break;
|
||||
case LoToHi_error_flags_tag:
|
||||
// printf("Received error_flags %i\n", (int)msg_in.payload.error_flags);
|
||||
break;
|
||||
case LoToHi_cp_state_tag:
|
||||
printf("Received cp_state %i\n", (int)msg_in.payload.cp_state);
|
||||
// state = cp_state_to_evse_state(msg_in.payload.cp_state);
|
||||
break;
|
||||
case LoToHi_pp_state_tag:
|
||||
printf("Received cp_state %i\n", (int)msg_in.payload.pp_state);
|
||||
break;
|
||||
case LoToHi_max_charging_current_tag:
|
||||
printf("Received max_charging_current %i\n", (int)msg_in.payload.max_charging_current);
|
||||
|
||||
int max_charging_current = (int)msg_in.payload.max_charging_current;
|
||||
|
||||
if (max_charging_current != evse_get_max_charging_current())
|
||||
{
|
||||
send_max_charging_current(evse_get_max_charging_current());
|
||||
}
|
||||
break;
|
||||
|
||||
case LoToHi_max_grid_current_tag:
|
||||
printf("Received max_grid_current %i\n", (int)msg_in.payload.max_grid_current);
|
||||
|
||||
int max_grid_current = (int)msg_in.payload.max_grid_current;
|
||||
|
||||
if (max_grid_current != grid_get_max_current())
|
||||
{
|
||||
send_max_grid_current(grid_get_max_current());
|
||||
}
|
||||
break;
|
||||
|
||||
case LoToHi_lock_state_tag:
|
||||
printf("Received lock_state %i\n", (int)msg_in.payload.lock_state);
|
||||
break;
|
||||
case LoToHi_power_meter_tag:
|
||||
printf("Received power_meter %i\n", (int)msg_in.payload.power_meter.time_stamp);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Not Found Sync Master recvd %i \n", msg_in.which_payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tx_task(void *arg)
|
||||
{
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
// send_time_stamp();
|
||||
// vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
// send_connector_lock(true);
|
||||
// vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
send_max_charging_current(32);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
// send_allow_power_on(true);
|
||||
// vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
// send_reset(true);
|
||||
// vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void rx_task(void *arg)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)malloc(RX_BUF_SIZE + 1);
|
||||
while (1)
|
||||
{
|
||||
|
||||
const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 1000 / portTICK_PERIOD_MS);
|
||||
if (rxBytes > 0)
|
||||
{
|
||||
data[rxBytes] = 0;
|
||||
// ESP_LOGI(TAG, "Read %d bytes: '%s'", rxBytes, data);
|
||||
// ESP_LOG_BUFFER_HEXDUMP(TAG, data, rxBytes, ESP_LOG_INFO);
|
||||
cobsDecode(data, rxBytes);
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
void master_sync_start()
|
||||
{
|
||||
ESP_LOGI(TAG, "Master SYNC Serial");
|
||||
|
||||
init();
|
||||
xTaskCreate(rx_task, "uart_rx_task", 1024 * 5, NULL, 5, NULL);
|
||||
//xTaskCreate(tx_task, "uart_tx_task", 1024 * 5, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
void master_sync_stop(void)
|
||||
{
|
||||
/*
|
||||
ESP_LOGI(TAG, "Stopping");
|
||||
|
||||
if (rx_task)
|
||||
{
|
||||
vTaskDelete(rx_task);
|
||||
rx_task = NULL;
|
||||
}
|
||||
|
||||
if (tx_task)
|
||||
{
|
||||
vTaskDelete(tx_task);
|
||||
tx_task = NULL;
|
||||
}
|
||||
|
||||
if (port != -1)
|
||||
{
|
||||
uart_driver_delete(port);
|
||||
port = -1;
|
||||
}*/
|
||||
}
|
||||
Reference in New Issue
Block a user