Tick rate + serial comm.
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
Tick rate + serial comm.
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) );
Tick rate + serial comm.
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.
Tick rate + serial comm.
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
Tick rate + serial comm.
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[i] != ‘