Add message framing (start, end, escape bytes) to UART
Same functionality as previous commit. But way more stable and clean. Previous proof of concept approach had issues with random partial or too large messages due to time based method Rework send and receive functions to work more stable - send: encode data with frame (start, end byte) - receive: read each byte one after the other, assemble message, handle actual data in handle function - add semaphore to write operation to prevent parallel write of different data when called from other tasks
This commit is contained in:
@@ -26,7 +26,7 @@ extern "C"
|
||||
//=========================
|
||||
//only run uart test code at the end
|
||||
//disables other functionality
|
||||
#define UART_TEST_ONLY
|
||||
//#define UART_TEST_ONLY
|
||||
|
||||
|
||||
//tag for logging
|
||||
@@ -35,7 +35,6 @@ static const char * TAG = "main";
|
||||
|
||||
|
||||
#ifndef UART_TEST_ONLY
|
||||
#include "control.hpp"
|
||||
//====================================
|
||||
//========== motorctl task ===========
|
||||
//====================================
|
||||
|
||||
@@ -1,49 +1,58 @@
|
||||
#include "uart.hpp"
|
||||
#include "config.hpp"
|
||||
#include "types.hpp"
|
||||
#include "uart_common.hpp"
|
||||
//===== uart board MOTORCTL =====
|
||||
|
||||
static const char * TAG = "uart";
|
||||
|
||||
|
||||
|
||||
//handle received payload from uart
|
||||
void handleMessage(uint8_t *receivedData, int len) {
|
||||
ESP_LOGI(TAG, "complete message received len=%d", len);
|
||||
//local variables
|
||||
uartData_test_t dataTest;
|
||||
motorCommands_t dataMotorCommands;
|
||||
//assign data to struct
|
||||
switch (len){
|
||||
case sizeof(uartData_test_t):
|
||||
dataTest = serialData2Struct<uartData_test_t>(receivedData);
|
||||
ESP_LOGW(TAG, "received uartDataStruct len=%d DATA: timestamp=%d, id=%d, value=%.1f", len, dataTest.timestamp, dataTest.id, dataTest.value);
|
||||
break;
|
||||
|
||||
case sizeof(motorCommands_t):
|
||||
dataMotorCommands = serialData2Struct<motorCommands_t>(receivedData);
|
||||
ESP_LOGI(TAG, "received motorCommands struct len=%d left=%.2f%% right=%.2f%%, update target...", len, dataMotorCommands.left.duty, dataMotorCommands.right.duty);
|
||||
//update target motor state and duty
|
||||
motorLeft.setTarget(dataMotorCommands.left.state,
|
||||
dataMotorCommands.left.duty);
|
||||
motorRight.setTarget(dataMotorCommands.right.state,
|
||||
dataMotorCommands.right.duty);
|
||||
break;
|
||||
|
||||
//TODO add other received structs here
|
||||
default:
|
||||
ESP_LOGE(TAG, "received data len=%d cant be associated with configures struct", len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==============================
|
||||
//====== task_uartReceive ======
|
||||
//==============================
|
||||
//TODO duplicate code, same task in both boards, only handleMessage function has to be passed -> move to uart_common
|
||||
void task_uartReceive(void *arg){
|
||||
ESP_LOGW(TAG, "receive task started");
|
||||
//receive data from uart, detect associated struct and copy/handle the data
|
||||
//TODO use queue instead of check interval?
|
||||
uartData_test_t dataTest;
|
||||
motorCommands_t dataMotorCommands;
|
||||
uint8_t receivedData[1024-1];
|
||||
while(1){
|
||||
//note: check has to be more frequent than pause time between sending
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
//read bytes (max 1023) until 20ms pause is happening
|
||||
int len = uart_read_bytes(UART_NUM_1, receivedData, sizeof(receivedData), 20 / portTICK_PERIOD_MS);
|
||||
uart_flush_input(UART_NUM_1);
|
||||
if (len < 1) continue;
|
||||
switch (len){
|
||||
|
||||
case sizeof(uartData_test_t):
|
||||
dataTest = serialData2Struct<uartData_test_t>(receivedData);
|
||||
ESP_LOGW(TAG, "received uartDataStruct len=%d DATA: timestamp=%d, id=%d, value=%.1f", len, dataTest.timestamp, dataTest.id, dataTest.value);
|
||||
break;
|
||||
|
||||
case sizeof(motorCommands_t):
|
||||
dataMotorCommands = serialData2Struct<motorCommands_t>(receivedData);
|
||||
ESP_LOGI(TAG, "received motorCommands struct len=%d left=%.2f%% right=%.2f%%, update target...", len, dataMotorCommands.left.duty, dataMotorCommands.right.duty);
|
||||
//update target motor state and duty
|
||||
motorLeft.setTarget(dataMotorCommands.left.state,
|
||||
dataMotorCommands.left.duty);
|
||||
motorRight.setTarget(dataMotorCommands.right.state,
|
||||
dataMotorCommands.right.duty);
|
||||
break;
|
||||
|
||||
//TODO add other received structs here
|
||||
default:
|
||||
ESP_LOGE(TAG, "received data len=%d cant be associated with configures struct", len);
|
||||
break;
|
||||
while (1) {
|
||||
uint8_t byte;
|
||||
//read 1 byte TODO: use uart queue here? data might get lost when below function takes longer than data arrives
|
||||
int len = uart_read_bytes(UART_NUM_1, &byte, 1, portMAX_DELAY);
|
||||
if (len > 0) {
|
||||
//process received byte
|
||||
uart_processReceivedByte(byte, handleMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "uart_common.hpp"
|
||||
|
||||
|
||||
//===== uart board MOTORCTL =====
|
||||
|
||||
void task_uartReceive(void *arg);
|
||||
|
||||
Reference in New Issue
Block a user