Below is a complete working freeRTOS program that I am using, instead of a few code snips. If, after looking it over you got questions, I'll do my best to provide answers.
Code: Select all
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include <CAN_config.h>
#include <ESP32CAN.h>
#include "esp32-hal-ledc.h"
////////////////////////////////////////////////////////////////////////
#define evtCAN_Bus ( 1 << 1 ) // 1
#define evtServo_Test ( 1 << 2 ) // 10
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
/* create a hardware timer */
hw_timer_t * timer = NULL;
///////////////////////////////////////////////////////////////////////
/* create event group */
EventGroupHandle_t eg;
///////////////////////////////////////////////////////////////////////
#define TimerDivider 80
#define TaskCore1 1
#define TaskCore0 0
#define OneK 1000
#define TaskStack10K 10000
#define TaskStack10K5 10500
#define TaskStack15K 15000
#define Priority5 5
#define SerialDataBits 115200
#define TIMER_FOUR 3
#define TIMER_WIDTH 16
#define REFRESH_USEC 20000
#define TIMER_FREQUENCY 50
#define InitialServoPositionA 1500
#define Channel_Zero 0
#define Channel_One 1
#define Channel_Two 2
#define Channel_Three 3
#define Channel_Four 4
#define Channel_Five 5
#define Channel_Six 6
#define Channel_Seven 7
#define Channel_Eight 8
#define Channel_Nine 9
#define Channel_Ten 10
#define Channel_Eleven 11
#define Channel_Twleve 12
#define Channel_ZeroPin 23
#define Channel_OnePin 4
#define Channel_TwoPin 12
#define Channel_ThreePin 13
#define Channel_FourPin 14
#define Channel_FivePin 15
#define Channel_SixPin 16
#define Channel_SevenPin 17
#define Channel_EightPin 18
#define Channel_NinePin 19
#define Channel_TenPin 21
#define Channel_ElevenPin 22
#define Channel_12Pin 2
///////////////////////////////////////////////////////////////////////
TickType_t xTicksToWait0 = 0;
TickType_t xTicksToWait3ms = pdMS_TO_TICKS( 3 );
TickType_t QueueReceiveDelayTime = 20;
TickType_t xTicksToWait20 = 20;
TickType_t xSemaphoreTicksToWait30 = 30;
TickType_t xSemaphoreTicksToWait10 = 10;
///////////////////////////////////////////////////////////////////////
CAN_device_t CAN_cfg;
///////////////////////////////////////////////////////////////////////
QueueHandle_t xQ_ServoTorqueInfo;
struct stu_ServoTorqueInfo
{
int sServo = 0;
int d1 = 0;
int d2 = 0;
int d3 = 0;
int d4 = 0;
} x_SERVO_INFO;
const int asciiA = 65;
const int asciiB = 66;
const int asciiC = 67;
const int asciiD = 68;
const int asciiE = 69;
const int asciiF = 70;
const int asciiG = 71;
const int asciiH = 72;
const int asciiI = 73;
const int asciiJ = 74;
const int asciiK = 75;
const int asciiL = 76;
bool EOT = true;
struct stuSERVO_ACK
{
int MsgID = 2;
int DLC = 8;
char Servo_ACK = '6';
char p4 = '0';
} xServo_ACK;
///////////////////////////////////////////////////////////////////////
float timer_width_ticks = pow( 2, TIMER_WIDTH );
///////////////////////////////////////////////////////////////////////
SemaphoreHandle_t sema_CAN_Bus;
SemaphoreHandle_t sema_SERVO_Info;
///////////////////////////////////////////////////////////////////////
////// Recommended servo pins include 2,4,12-19,21-23,25-27,32-33
/*
** ledc: 0 => Group: 0, Channel: 0, Timer: 0
** ledc: 1 => Group: 0, Channel: 1, Timer: 0
** ledc: 2 => Group: 0, Channel: 2, Timer: 1
** ledc: 3 => Group: 0, Channel: 3, Timer: 1
** ledc: 4 => Group: 0, Channel: 4, Timer: 2
** ledc: 5 => Group: 0, Channel: 5, Timer: 2
** ledc: 6 => Group: 0, Channel: 6, Timer: 3
** ledc: 7 => Group: 0, Channel: 7, Timer: 3
** ledc: 8 => Group: 1, Channel: 8, Timer: 0
** ledc: 9 => Group: 1, Channel: 9, Timer: 0
** ledc: 10 => Group: 1, Channel: 10, Timer: 1
** ledc: 11 => Group: 1, Channel: 11, Timer: 1
** ledc: 12 => Group: 1, Channel: 12, Timer: 2
** ledc: 13 => Group: 1, Channel: 13, Timer: 2
** ledc: 14 => Group: 1, Channel: 14, Timer: 3
** ledc: 15 => Group: 1, Channel: 15, Timer: 3
*/
///////////////////////////////////////////////////////////////////////
// timer ISR callback set at 1000X a second
void IRAM_ATTR onTimer()
{
BaseType_t xHigherPriorityTaskWoken;
// iTicCount++;
xEventGroupSetBitsFromISR(eg, evtCAN_Bus, &xHigherPriorityTaskWoken); //
} // void IRAM_ATTR onTimer()
///////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin( SerialDataBits );
eg = xEventGroupCreate();
/* set CAN pins, baudrate start can module */
CAN_cfg.speed = CAN_SPEED_1000KBPS;
CAN_cfg.tx_pin_id = GPIO_NUM_5; // green wire
CAN_cfg.rx_pin_id = GPIO_NUM_34; // white wire
CAN_cfg.rx_queue = xQueueCreate(3, sizeof(CAN_frame_t));
ESP32Can.CANInit();
ledcSetup ( Channel_Zero, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_ZeroPin, Channel_Zero ); //
ledcWrite (Channel_Zero, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_One, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_OnePin, Channel_One ); //
ledcWrite (Channel_One, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Two, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_TwoPin, Channel_Two ); //
ledcWrite (Channel_Two, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Three, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_ThreePin, Channel_Three ); //
ledcWrite (Channel_Three, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Four, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_FourPin, Channel_Four ); //
ledcWrite (Channel_Four, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Five, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_FivePin, Channel_Five ); //
ledcWrite (Channel_Five, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Six, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_SixPin, Channel_Six ); //
ledcWrite (Channel_Six, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Seven, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_SevenPin, Channel_Seven ); //
ledcWrite (Channel_Seven, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Eight, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_EightPin, Channel_Eight ); //
ledcWrite (Channel_Eight, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Nine, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_NinePin, Channel_Nine ); //
ledcWrite (Channel_Nine, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Ten, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_TenPin, Channel_Ten ); //
ledcWrite (Channel_Ten, usToTicks ( 0 ) ); //
///////////////
ledcSetup ( Channel_Eleven, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_ElevenPin, Channel_Eleven ); //
ledcWrite (Channel_Eleven, usToTicks ( 0 ) ); //
////////////////////////////////////////////////////////
ledcSetup ( Channel_Twleve, TIMER_FREQUENCY, TIMER_WIDTH ); //
ledcAttachPin ( Channel_12Pin, Channel_Twleve ); //
ledcWrite ( 12, usToTicks ( 0 ) );
////////////////////////////////////////////////////////
xQ_ServoTorqueInfo = xQueueCreate ( 1 , sizeof(stu_ServoTorqueInfo) );
/////////////////////////// TASK CORE 0
xTaskCreatePinnedToCore ( Servo_Test, "Servo_Test", TaskStack10K5, NULL, Priority5, NULL, TaskCore0 ); // assigned to core
sema_SERVO_Info = xSemaphoreCreateBinary();
xSemaphoreGive ( sema_SERVO_Info );
//////////////////////////////// TASK CORE 1 ///////////////////////////////////////////////////////////////////////////////////////////////////
xTaskCreatePinnedToCore ( fCAN_Receive, "fCAN_Receive", TaskStack15K, NULL, Priority5, NULL, TaskCore1 ); // assigned to core
sema_CAN_Bus = xSemaphoreCreateBinary();
xSemaphoreGive ( sema_CAN_Bus );
/////////////////////////////////////////////////////
timer = timerBegin( TIMER_FOUR, TimerDivider, true );
timerAttachInterrupt( timer, &onTimer, true );
timerAlarmWrite(timer, OneK, true);
timerAlarmEnable(timer);
////////////////////////////////////////
} // void setup()
///////////////////////////////////////////////////////////////////////
void loop() {}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
void fLED_off ()
{
ledcWrite (Channel_Zero, 0 );
ledcWrite (Channel_One, 0 );
ledcWrite (Channel_Two, 0 );
ledcWrite (Channel_Three, 0 );
ledcWrite (Channel_Four, 0 );
ledcWrite (Channel_Five, 0 );
ledcWrite (Channel_Six, 0 );
ledcWrite (Channel_Seven, 0 );
ledcWrite (Channel_Eight, 0 );
ledcWrite (Channel_Nine, 0 );
ledcWrite (Channel_Ten, 0 );
ledcWrite (Channel_Eleven, 0 );
}
///////////////////////////////////////////////////////////////////////
void Servo_Test ( void *pvParameters )
{
stu_ServoTorqueInfo pxServo_Info;
for ( ;;)
{
xEventGroupWaitBits ( eg, evtServo_Test, pdTRUE, pdTRUE, portMAX_DELAY ) ;
if ( xSemaphoreTake( sema_SERVO_Info, xSemaphoreTicksToWait30 ) == pdTRUE ) // grab semaphore wait
{
xQueueReceive( xQ_ServoTorqueInfo, &pxServo_Info, QueueReceiveDelayTime );
ledcWrite ( Channel_Twleve, usToTicks ( 2500 ) );
int t = pxServo_Info.d4;
t = t + (pxServo_Info.d3 * 10);
t = t + (pxServo_Info.d2 * 100);
t = t + (pxServo_Info.d1 * 1000);
// Serial.print ( pxServo_Info.sServo );
// Serial.print ( " , " );
// Serial.print ( t );
// Serial.print ( " , " );
// Serial.print ( t );
// Serial.println();
if ( t != 0 )
{
t = usToTicks ( t );
switch ( pxServo_Info.sServo )
{
case asciiA:
ledcWrite (Channel_Zero, t );
// Serial.println ( " asciiA " );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
break;
case asciiB:
ledcWrite (Channel_One, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiB " );
break;
case asciiC:
ledcWrite (Channel_Two, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiC " );
break;
case asciiD:
ledcWrite (Channel_Three, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiD " );
break;
case asciiE:
ledcWrite (Channel_Four, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiE " );
break;
case asciiF:
ledcWrite (Channel_Five, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiF " );
break;
case asciiG:
ledcWrite (Channel_Six, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiG " );
break;
case asciiH:
ledcWrite (Channel_Seven, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiH " );
break;
case asciiI:
ledcWrite (Channel_Eight, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiI " );
break;
case asciiJ:
ledcWrite (Channel_Nine, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiJ " );
break;
case asciiK:
ledcWrite (Channel_Ten, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiK " );
break;
case asciiL:
ledcWrite (Channel_Eleven, t );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
// Serial.println ( " asciiL " );
break;
}
vTaskDelay( pdMS_TO_TICKS( 20 ) );
}
ledcWrite ( Channel_Twleve, usToTicks ( 0 ) );
xSemaphoreGive ( sema_SERVO_Info );
}
}
vTaskDelete ( NULL );
}
///////////////////////////////////////////////////////////////////////
int usToTicks(int usec)
{
return (int)((float)usec / ((float)REFRESH_USEC / (float)timer_width_ticks) * (((float)TIMER_FREQUENCY) / 50.0));
} // int usToTicks(int usec)
///////////////////////////////////////////////////////////////////////
void fCAN_Receive ( void *pvParameters )
{
CAN_frame_t rx_frame;
char Current_RCVD[9];
char Past_RCVD[9];
for ( ;; )
{
xEventGroupWaitBits (eg, evtCAN_Bus, pdTRUE, pdTRUE, portMAX_DELAY) ;
//Serial.println ( "fCAN_Receive" );
if ( xSemaphoreTake( sema_CAN_Bus, xTicksToWait0 ) == pdTRUE ) // grab semaphore no wait
{
ledcWrite ( Channel_Twleve, usToTicks ( 2500 ) );
// Serial.println ( "fCAN_Receive 2" );
// if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
if ( (CAN_cfg.rx_queue != NULL) && (uxQueueMessagesWaiting(CAN_cfg.rx_queue)) ) // if queue not null and something is waiting in queue
{
Serial.println ( "fCAN_Receive 3" );
while ( uxQueueMessagesWaiting(CAN_cfg.rx_queue) > 0 )
{
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, xTicksToWait0) == pdTRUE)
{
ledcWrite ( Channel_Twleve, usToTicks ( 0 ) );
// Serial.println ( " received queue" );
// ledcWrite (Channel_Ten, usToTicks ( InitialServoPositionA ) );
if ( rx_frame.MsgID == 1 )
{
ledcWrite ( Channel_Twleve, usToTicks ( 2500 ) );
// Serial.println ( " MsgId OK");
// ledcWrite (Channel_Nine, usToTicks ( InitialServoPositionA ) );
if ( rx_frame.data.u8[0] != '6' )
{
// Serial.println ( "not 6" );
if ( rx_frame.data.u8[0] != '3')
{
// Serial.println ( "not 3 ");
if ( EOT == false )
{
ledcWrite ( Channel_Twleve, usToTicks ( 0 ) );
x_SERVO_INFO.sServo = rx_frame.data.u8[0];
x_SERVO_INFO.d1 = String(char(rx_frame.data.u8[1])).toInt();
x_SERVO_INFO.d2 = String(char(rx_frame.data.u8[2])).toInt();
x_SERVO_INFO.d3 = String(char(rx_frame.data.u8[3])).toInt();
x_SERVO_INFO.d4 = String(char(rx_frame.data.u8[4])).toInt();
Current_RCVD[0] = (char)x_SERVO_INFO.sServo;
Current_RCVD[1] = (char)x_SERVO_INFO.d1;
Current_RCVD[2] = (char)x_SERVO_INFO.d2;
Current_RCVD[3] = (char)x_SERVO_INFO.d3;
Current_RCVD[4] = (char)x_SERVO_INFO.d4;
// comapre with last received and process if different
if ( strcmp ( Current_RCVD, Past_RCVD ) != 0 )
{
// Serial.print ( "message begin" );
// Serial.print ( ", " );
// Serial.print ( rx_frame.data.u8[0] );
// Serial.print ( ", " );
// Serial.print ( rx_frame.data.u8[1] );
// Serial.print ( ", " );
// Serial.print ( rx_frame.data.u8[2] );
// Serial.print ( ", " );
// Serial.print ( rx_frame.data.u8[3] );
// Serial.print ( ", " );
// Serial.print ( rx_frame.data.u8[4] );
// Serial.println ( " message end" );
xQueueSend( xQ_ServoTorqueInfo, (void *) &x_SERVO_INFO, xTicksToWait20 );
xEventGroupSetBits( eg, evtServo_Test );
}
strcpy ( Past_RCVD, Current_RCVD );
}
} //
}
if (rx_frame.data.u8[0] = '3')
{
// fLED_off();
// got a 51 initiate a ACK acknoledge
EOT = true;
// Serial.println ( "got EOT!" );
ledcWrite ( Channel_Twleve, usToTicks ( 2500 ) );
vTaskDelay( pdMS_TO_TICKS( 15 ) );
ledcWrite ( Channel_Twleve, usToTicks ( 0 ) );
// Serial.println ( "EOT ready" );
// let control know servo_control is ready
rx_frame.FIR.B.FF = CAN_frame_std;
rx_frame.MsgID = xServo_ACK.MsgID;
rx_frame.FIR.B.DLC = xServo_ACK.DLC;
rx_frame.data.u8[0] = xServo_ACK.Servo_ACK; // 54
rx_frame.data.u8[1] = xServo_ACK.p4;
rx_frame.data.u8[2] = xServo_ACK.p4;
rx_frame.data.u8[3] = xServo_ACK.p4;
rx_frame.data.u8[4] = xServo_ACK.p4;
rx_frame.data.u8[5] = xServo_ACK.p4;
rx_frame.data.u8[6] = xServo_ACK.p4;
rx_frame.data.u8[7] = xServo_ACK.p4;
ESP32Can.CANWriteFrame(&rx_frame);
// Serial.println ( "sent eot ack" );
}
if (rx_frame.data.u8[0] = '6')
{
// got a 54 a ACK
EOT = false;
// Serial.println ( "got ack!" );
ledcWrite ( Channel_Twleve, usToTicks ( 2500 ) );
vTaskDelay( pdMS_TO_TICKS( 15 ) );
ledcWrite ( Channel_Twleve, usToTicks ( 0 ) );
// Serial.println ( "ready" );
// let control know servo_control is ready
rx_frame.FIR.B.FF = CAN_frame_std;
rx_frame.MsgID = xServo_ACK.MsgID;
rx_frame.FIR.B.DLC = xServo_ACK.DLC;
rx_frame.data.u8[0] = xServo_ACK.Servo_ACK; // 54
rx_frame.data.u8[1] = xServo_ACK.p4;
rx_frame.data.u8[2] = xServo_ACK.p4;
rx_frame.data.u8[3] = xServo_ACK.p4;
rx_frame.data.u8[4] = xServo_ACK.p4;
rx_frame.data.u8[5] = xServo_ACK.p4;
rx_frame.data.u8[6] = xServo_ACK.p4;
rx_frame.data.u8[7] = xServo_ACK.p4;
ESP32Can.CANWriteFrame(&rx_frame);
// Serial.println ( "sent ack" );
} // else
} // if ( rx_frame.MsgID == 1 )
} // if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, xTicksToWait0) == pdTRUE)
} // while ( uxQueueMessagesWaiting(CAN_cfg.rx_queue) > 0 )
} // if ( (CAN_cfg.rx_queue != NULL) && (uxQueueMessagesWaiting(CAN_cfg.rx_queue)) )
xSemaphoreGive ( sema_CAN_Bus );
//
// Serial.print( "fCAN_Receive " );
// Serial.print(uxTaskGetStackHighWaterMark( NULL ));
// Serial.println();
// Serial.flush();
} // if ( xSemaphoreTake( sema_CAN_Bus, xTicksToWait0 ) == pdTRUE ) // grab semaphore no wait
} // for ( ;; )
vTaskDelete ( NULL );
} // void fCAN_Receive ( void *pvParameters )
///////////////////////////////////////////////////////////////////////