Data Visualization-FreeRTOS

This article is the last one in the data visualization series. The previous three focus on peripheral configuration and algorithms. I will talk about the program structure this time.

The program consists of two key tasks that need to be executed periodically: the I2C data reading and CAN message broadcasting. Data reading is running at 500Hz, and CAN message broadcasting is 100Hz. Meanwhile, the zero calibration function should only be executed once at the very beginning.

Part 1 FreeRTOS configuration

1) It's always better to implement the malloc failure and stack overflow hook functions, also set the configCHECK_FOR_STACK_OVERFLOW macro to an overflow checking method you need. These settings can save a ton of debugging time when your project becomes large and involves complex scheduling. And you use non-static functions to create tasks, queues, semaphores, event groups, and so on.

2) Use preemption, time slicing, and idle should yield

3) Enable vTaskDlay() and vTaskDelayUntil() for the angle reading and CAN broadcasting tasks.

Part 2 Coding part

//AS5600 data reading task
void as5600Task(void *pvParameters)
{
    const TickType_t xDelay =pdMS_TO_TICKS(2);

    struct canBroadData data;
    for(;;)
    {
        while(!currentSensor->flag_dataRdy)
        {
            HAL_i2cRead(currentSensor);
        }
        mechanicalAngleDeg(currentSensor);
        //Angular speed observer
        speedObserverRun(AOHandler,currentSensor->angleRad);
        data.angleDeg=currentSensor->angleDeg;
        data.angularSpeed=AOHandler->out;
        xQueueOverwrite(gCANPhysiqueue,&data);
        currentSensor->flag_dataRdy=0;
        vTaskDelay(xDelay);
    }
}        

The queue in this project is special because the reading function (500Hz) is faster than the CAN broadcasting function(100Hz), but we want the latest data to be transmitted. So there is only one element in the queue, thus, we use a xQueueOverwrite() to fill the gCANPhysicqueue. Meanwhile, to get a good estimation of angular velocity, the function is executed in the same reading cycle.

void canMessageTask(void * pvParameters)
{
    canMsg_t *obj=(canMsg_t *)pvParameters;
    struct canBroadData data;
    uint16_t temp;
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = obj->tRate;
    xLastWakeTime=xTaskGetTickCount();
    for(;;)
    {
        xTaskDelayUntil(&xLastWakeTime, xFrequency);
        xQueueReceive(gCANPhysiqueue, &data, 0);
        //angle data packaging
        if(data.angleDeg>=0)
        {
            temp= data.angleDeg/ANGLEFACTOR;
        }
        else
        {
            temp=~((uint16_t)((0-data.angleDeg)/ANGLEFACTOR))+1;
        }
        obj->data[0]=temp&0xFF;
        obj->data[1]=(temp>>8)&0xFF;
        temp=(data.angularSpeed*RADS2RPM+10000U)*RPMFACTOR;
        obj->data[2]=temp&0xFF;
        obj->data[3]=(temp>>8)&0xFF;
        HAL_sendCAN(obj);
    }
}        

To reach a restricted 10ms transmission rate, I use a vTaskDelayUntil() function. In bare metal projects, an update of the xLastWakeTime is required. However, xTaskDelayUntil() will update it internally in FreeRTOS, so we do not need it here. After reading the queue, we use different packaging methods for the positive and negative numbers. Then, put the angle data into bytes 0 and 1 in a little-endian order, and the angular velocity is in bytes 2 and 3. After that, we call the HAL_senCAN() to start the transmission.

void rtosInit(void)
{   //create queue
    gCANPhysiqueue=xQueueCreateStatic(1,sizeof(struct canBroadData),gflQueueBuf,&gQueueStaticStruct);
    //create tasks
    xTaskCreate(as5600Task, "encoderTask", 128, NULL, 2, NULL);
    xTaskCreate(canMessageTask, "CANtask", 128, &angle, 1, NULL);
    vTaskStartScheduler();
}        

The init function is straightforward; we declared the gCANPhysiqueue with a static method, and created two tasks. The as5600Task has no input arguments, but the canMessageTask has a canMsg_t type argument.

The bare metal and FreeRTOS versions had been completed and uploaded to the following repository.

https://github.com/ElonYao/CAN_project

The actual FreeRTOS applications are far complex than this. This example is just a demonstration of a simple FreeRTOS structure. It also wraps up the whole series of articles on data visualization.

To view or add a comment, sign in

Others also viewed

Explore content categories