Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Tick rate + serial comm.

Posted by pedrovt on November 27, 2007
Hi,

I'm using freeRTOS in a control project. I have to sample a sensor with a frequency of at least 1kHz and feed that measure into the PI-controller algorithm. The problem is that this will have to be done for two sensors and two controllers (a PI and a PID). The problem is: what tick rate should I use? I've been using 100000, but from what I've read so far this seems to be at least exaggerated. What would you reccomend? The rtos is running on an ATmega32.

I would also like to ask for your help on the following piece of code, which is part of a task:

> xSerialPutChar( xPort, light/4, 1000);
> if( (xSerialGetChar( xPort, rc, 10)==pdPASS) && (rc!=0x00) );
> {
> vChangeOCPWM0(0xFF - light/4);
> xSerialPutChar( xPort, rc, 10);
> }

When I send a byte through the serial port, the microcontroller stops responding completely. Could you please tell me what's wrong?

Thanks

RE: Tick rate + serial comm.

Posted by sotd on November 27, 2007
100KHz seems very fast for a tick on an AVR. If you need to run your algorithms at 1KHz then why not write a tick hook function and set the tick to 1KHz? http://www.freertos.org/a00016.html

> xSerialPutChar( xPort, light/4, 1000);

This might be better -

xSerialPutChar(xPort, light>>2, 1000);

> if( (xSerialGetChar( xPort, rc, 10)==pdPASS) && (rc!=0x00) );

Are you assuming left to right evaluation here? So rc is set by the call to xSerialGetChar(), then tested as the second && operand?

What type is rc? Is it a pointer? If not then should it be -

> if( (xSerialGetChar( xPort, &rc, 10)==pdPASS) && (rc!=0x00) );



RE: Tick rate + serial comm.

Posted by pedrovt on December 4, 2007
First of all, sorry for not answering faster.

I do not want to write a tick hook function since i have to run two controllers in parallel, both at 1kHz. I've changed the tick rate to 10000.

Yes, I am assuming left-to-right evaluation, is it incorrect? rc is a portSHORT. I've tried your suggestions with the following

if( (xSerialGetChar( xPort, &rc, 10)==pdPASS) && (rc!=0x00) );
{
vChangeOCPWM0(0xFF - light/4);
xSerialPutChar( xPort, rc, 10);
xSerialPutChar( xPort, light/4, 1000);
}

What happens is that the program keeps sending rc and light/4 way after I send it a byte, when I just want it to send when it *really* receives a byte.

RE: Tick rate + serial comm.

Posted by Jay on December 4, 2007
You issue is you tick rate it too fast. What is the frequency of your crystal? Maybe 8MHz? At 100Khz you are telling an ISR to execute every 10us. If you only have a prescaler rate of 8us (prescaler is set to Fcpu/64 in the port.c) then all you can ever do is call that routine. However, that routine pushes and pops 32 registers + the PC, and the SREG ... think it can do that in 2us and still send serial? Nope, as soon as it's done, the flag is already set and it jumps back into the ISR. At 8Mhz the Fcpu tick time is 125ns (at 16MHz it's 62.5ns). Each instruction (and I don't know the actual values) can translate to 2 or more clock ticks. Let's say each push and pop takes only 2 clock ticks ... 10us/250ns = 40 instructions in 10us.

100KHz seems so out of whack with how fast serial can be sent anyway. 115200Baud = 9bits in 78.1us or 1 byte in 625us. Don't go over 1000 for your clock tick rate and think about something even less. I use 400 and can service a PID and trig function fast enough to keep locked on target all the while generating motor speed commands based on the trig while the PID locks the speeds of two motors tot he commanded values all while sending a stream of serial (115200baud) at 10Hz (100ms).

How many times per second you you really need to update your PID loop? Does the feedback signal change appreciably during that time? I'm using 50Hz on mine and it's working fine. Does your system react faster than 50Hz (20ms)?

FWIW,
Jay

RE: Tick rate + serial comm.

Posted by pedrovt on December 5, 2007
I've followed your suggestions, but ran into another problem. One of the tasks sends the ADC's first channel value through the serial port. What happens is that after sending around 100 values, the OS stops responding. Here is the code:



portSHORT main()
{
...
xPort=xSerialPortInitMinimal(serialBAUD_RATE,20);
xSerialPutChar(xPort,'M',10);
xTaskCreate(vUpdateLight,"Light",configMINIMAL_STACK_SIZE,NULL,mainUpdateLight_TASK_PRIORITY,NULL);
xTaskCreate(vUpdateOutput,"Out",configMINIMAL_STACK_SIZE,NULL,mainUpdateOutput_TASK_PRIORITY,NULL);
xTaskCreate(vSend,"Send",configMINIMAL_STACK_SIZE,NULL,mainSend_TASK_PRIORITY,NULL);
...
}

...

static void vSend ( void *pvParameters)
{
( void ) pvParameters;

portTickType xLastWake=xTaskGetTickCount();
const portTickType xSendPeriod=1000;

for(;;)
{
char *value;
itos(light,value);
int i=0;

while(value != '\0')
{
xSerialPutChar(xPort,value,1000);
i++;
}
xSerialPutChar(xPort,',',10000);

xLastWake=xTaskGetTickCount();
vTaskDelayUntil(&xLastWake,xSendPeriod);
}

}

Can you please help me?

Thanks

RE: Tick rate + serial comm.

Posted by Jay on December 5, 2007
My comments after the // on each line. Is there a quote function on this system?

Jay


//---------------------------------------
const portTickType xSendPeriod=1000; // this is 1000 ticks of the clock not the FCPU
// If you have clock rate at 1000, this means 1 second ... this is what you want, to send something (if available) every second?

for(;;)
{
char *value; // Why not put this above the loop ?
itos(light,value); // Every sub function you call requires stack space. Does this function call another function? Think about it, the task stack you configured for minimal (see FreeRTOSconfig.h for the actual size specified for your port) may not be enough for the task stack, and multiple sub function stacks too.
int i=0; // Declare the var above the loop but initialize it to 0

while(value != '\0')
{
xSerialPutChar(xPort,value,1000); // Same here, how many subfunctions does this call?
i++;
}
xSerialPutChar(xPort,',',10000); // You are telling it to put the char on the queue and to block for a rather long time. Better to use comNO_BLOCK like comtest.c does. You didn't include your code to initialize the serial and the serial queues so I can only assume you used the example from comtest.c???

xLastWake=xTaskGetTickCount();
vTaskDelayUntil(&xLastWake,xSendPeriod); // wait 1 second (1hz) if clocktickrate = 1000
}

RE: Tick rate + serial comm.

Posted by pedrovt on December 5, 2007
Yes, that was the problem... value (char*) was filling the processor's memory. I'm not using the example from comtest.c...this is what i use to initialize the serial port:

xPort=xSerialPortInitMinimal(serialBAUD_RATE,5);

Using NO_BLOCK wouldn't stop the task from blocking when necessary?

Thanks for your support,

Pedro

RE: Tick rate + serial comm.

Posted by Jay on December 5, 2007
xPort=xSerialPortInitMinimal(serialBAUD_RATE,5);

So you only allow 5 bytes on your transmit buffer?

Why would the Tx need to block? It is reading data from the TX queue (of size 5) and sending the chars out when the TX flag is set. No need to block unless you are overflowing your TX buffer. Of course I suppose ti doesn't hurt to set a block timeout in this case either but I wanted to know why you would need/want that?

//-----------------------
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar, portTickType xBlockTime )
{
volatile avr32_usart_t *usart = serialPORT_USART;

/* Place the character in the queue of characters to be transmitted. */
if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )
{
return pdFAIL;
}

/* Turn on the Tx interrupt so the ISR will remove the character from the
queue and send it. This does not need to be in a critical section as
if the interrupt has already removed the character the next interrupt
will simply turn off the Tx interrupt again. */
usart->ier = (1 << AVR32_USART_IER_TXRDY_OFFSET);

return pdPASS;
}

RE: Tick rate + serial comm.

Posted by pedrovt on December 5, 2007
The 5 bytes shouldn't be there. I was working with 20. The reason for the timeout is that the processor will send info to a datalogging system, in other words, just to prevent data from being lost. But i guess 1 second is a lot of time...now i have to deal with some problems in the PI task, i'm getting some abnormal values from the PI equation...

Thanks again,

Pedro :)

RE: Tick rate + serial comm.

Posted by Jay on December 5, 2007
/**
* queue. h
portBASE_TYPE xQueueSend(
xQueueHandle xQueue,
const void * pvItemToQueue,
portTickType xTicksToWait
);

* @param xTicksToWait The maximum amount of time the task should block
* waiting for space to become available on the queue, should it already
* be full. The call will return immediately if this is set to 0. The
* time is defined in tick periods so the constant portTICK_RATE_MS
* should be used to convert to real time if this is required.

FYI. This is good information for me too as serial input is my issue. I want 2-way comm but I'm at TX only right now until I understand all the mechanics at work.

Jay


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS