Quality RTOS & Embedded Software

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




Loading

Three tasks bug

Posted by Breno Pinheiro on March 13, 2008
Hi all, I'm posting a huge code that I'm using to control an cc motor and adjust the positions of wheels in a car. The bug occurs when I start 3 threads to run. It works fine on pairs (ex. control_velocity and other) but it completely stuck when a got 3 tasks created.
I'm not sure if it's a memory issue or processor capacity problem.
I'm using Atmega128 my configTOTAL_HEAP_SIZE is 4*1024.
To sum up, I have three tasks, one to run the velocity control law, another one to adjust the direction of the wheels and another one to catch the value of AD converter. I used some mechanism to synchronization with tasks and interruptions
I hope find someone patient to take a look.

// * Definitions


/* Includes */
#include <stdio.h>
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <math.h>

#ifdef GCC_MEGA_AVR
/* EEPROM routines used only with the WinAVR compiler. */
#include <avr/eeprom.h>
#endif

/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>
/* Demo file headers. */
#include "serial.h"


float get_velocity(void);

/* Priority definitions for most of the tasks in the demo application. Some
tasks just use the idle priority. */


/* Baud rate used by the serial port*/
#define mainCOM_TEST_BAUD_RATE( ( unsigned portLONG ) 38400 )

#define TwoTasks
//#define OneTask
#define VelocidadeCFiltro
#define filtroRef
//#define ContagemTicks
#define adc


//void transmit_value (float var);
//void transmit_value (float var,float ref);

float get_velocity( void );
void adjust_PH_vel(char direction);
void adjust_DutyPWM_vel(float duty);
void vApplicationIdleHook( void );
void control_velocity( void );
#ifdef TwoTasks
static void adjust_DirPos(void);

#endif
#ifdef OneTask
void adjust_DirPos(float pos);
#endif

#ifdef adc
static void getDistanciaObstaculo();
#endif

/*
* Global variables
*/

int pulse;
float ref_pos = 6.7;
float ref_vel = 80;
int iterations = 0;
unsigned char ccc=0;
char ini[] = "Programa Iniciado!!!\n\r";
unsigned char buffer[5];

#ifdef adc
xSemaphoreHandle semaforoADC = NULL;

#endif


int main( void )
{
DDRA = 0xFF;
xSerialPortInitMinimal( mainCOM_TEST_BAUD_RATE, 1 );


/********************** CONFIG INT*************************/
DDRB = 0xFF;
DDRC = 0xFF;
DDRE |= 0b00001000;
MCUCR = 0x03;

/*************************PWM's*************************/
//Configuracao da saida de PWM A, B e C do Timer1(PB5) e 3(PE3)

//Configs Velo - PWM0, POS - PWM1
TCCR0 = 0b01101010;
TCCR3A = 0b10000010;
TCCR3B = 0b00010010;

//Configs Velo - PWM3, Pos - PWM0
//TCCR0 = 0b01100110;
//TCCR3A = 0b10000010;
//TCCR3B = 0b00011010;

/*********************Set Freq PWM1 to 2khz and PWM3 6khz************/

OCR0 = 0x00;
//configs para velocidade a 4 khz
ICR3 = 0x2710;
//configs para velocidade a 6khz
//ICR3 = 0xA5; //==165 -> 166 cont's
// ******************ADC CONFIG.*********************************/
ADMUX = 0x00;
////Habilita ADC
ADCSRA = 0x88;
// ******************

/*****************Interruptions*************************/
SREG = 0x80;
EICRA = 0x03; // 3 - 0
EICRB = 0x00; // 7 - 4
EIMSK = 0x01;
/****************************** END of conf.*************************/
string_transmit(ini);

#ifdef adc
vSemaphoreCreateBinary( semaforoADC );
#endif

ref_vel = 80;
adjust_PH_vel(0);

xTaskCreate ( control_velocity, "Vel", configMINIMAL_STACK_SIZE, NULL, 2, NULL );

#ifdef TwoTasks
xTaskCreate (adjust_DirPos, "Dir", 30, NULL, 2 , NULL);
#endif

#ifdef adc
// xTaskCreate (getDistanciaObstaculo,"obs", 30, NULL,2,NULL);
#endif

vTaskStartScheduler();
return 0;
}

void control_velocity( void )
{

char firstTime = 1;

float control[2],control2;
float error[2],new_velocity[4],final_velocity[4];
#ifdef filtroRef
float referencia[2];
#endif

#ifdef ContagemTicks
char tick;
#endif

while(1)
{
/******************************* Initializations********************************/
if(firstTime ==1)
{
new_velocity[0]=get_velocity();
error[0]=ref_vel-new_velocity[0];

control[0]= 0;
control[1] = 0;
error[1]=error[0];
new_velocity[1]=new_velocity[0];
new_velocity[2]=new_velocity[0];
new_velocity[3]=new_velocity[0];

#ifdef VelocidadeCFiltro
final_velocity[1]=new_velocity[0];
final_velocity[2]=new_velocity[0];
final_velocity[3]=new_velocity[0];
#endif
#ifdef filtroRef
referencia[0] = 0;
referencia[1] = 0;
#endif

firstTime = 0;
}

/****************************** Control Law*******************************/



new_velocity[3]=new_velocity[2];
new_velocity[2]=new_velocity[1];
new_velocity[1]=new_velocity[0];

//GET Velocity
new_velocity[0]=get_velocity();

#ifdef ContagemTicks
// tick = xTaskGetTickCount ();
tick = TCNT1;
#endif


#ifdef VelocidadeCFiltro
final_velocity[3]=final_velocity[2];
final_velocity[2]=final_velocity[1];
final_velocity[1]=final_velocity[0];

//Filtro de terceira ordem na leitura
//final_velocity[0]=0.332*new_velocity[0]+0.995*new_velocity[1]+0.995*new_velocity[2]+0.332*new_velocity[3]-1.15*final_velocity[1]-0.44*final_velocity[2]-0.057*final_velocity[3];
final_velocity[0]=0.4*new_velocity[0]+0.6*final_velocity[1];

#endif
//Calculo do Erro
error[1] = error[0];

#ifdef VelocidadeCFiltro
#ifndef filtroRef
error[0]=ref_vel-final_velocity[0];
#endif
#ifdef filtroRef
referencia[1] = referencia[0];
referencia[0] = 0.2*ref_vel+0.8*referencia[1];
error[0]=referencia[0]-final_velocity[0];
#endif
#endif
#ifndef VelocidadeCFiltro
error[0]=ref_vel-new_velocity[0];
#endif
control[1] = control[0];
//Calculo do Controle (PI discreto)
control[0]=(2.25*error[0])-(1.95*error[1])+control[1];

//Aproximacao da Look-up Table (tensao por velocidade)
control2=0.015*control[0]+5.013;


control2=control2*13.88;

if(abs(control2)>100)

adjust_DutyPWM_vel(100);
else

adjust_DutyPWM_vel(abs(control2));

#ifdef ContagemTicks
// tick = xTaskGetTickCount() -tick;
tick = TCNT1 - tick;
// transmit_value((float)tick);
itoa((int)tick,buffer,10);
string_transmit(buffer);
#endif

PORTA = ~0x01;

}
}

#ifdef TwoTasks
static void adjust_DirPos(void)
{
while(1)
{



OCR3A = 100*ref_pos;
vTaskDelay(50);


}

}
#endif
#ifdef OneTask
void adjust_DirPos (float pos)
{

if(pos<6.7)
{OCR3A = 670;}
else
{
if(pos>7.9)
{OCR3A = 790;}
else
{OCR3A = 100*pos;}
}

}
#endif

float get_velocity()
{
pulse =0;
EIMSK = 0x01;
vTaskDelay(( portTickType ) 300/ portTICK_RATE_MS);
EIMSK = 0x00;

return (pulse*3.78);
}


void adjust_DutyPWM_vel(float duty)
{

//config to velocity at 4khz
OCR0 = 2.55*duty;
//config to velocity at 6khz
//OCR3A = 1.65*duty;

}

void adjust_PH_vel(char direction)
{
//1 - backward
//0 - forward

if(direction==1)
PORTB = (PORTB&(0b11111100))|(0b10);
else
PORTB = (PORTB&(0b11111100))|(0b01);

}
#ifdef adc
static void getDistanciaObstaculo()
{

static int adcValue = 0;
static float distancia = 0;

while(1){

ADCSRA = 1<<6|ADCSRA;


if( xSemaphoreTake( semaforoADC, 10 ) == pdTRUE ){

adcValue = ADCL;
adcValue |= ADCH<<8;
distancia = (adcValue/204.8);

if(distancia <0.7){
PORTA = ~0x01;
}else{
PORTA = ~0x80;
}
}

}
}
#endif


/***********Tratadores de Interrupcao************************/
#ifdef adc
ISR(ADC_vect)
{
xSemaphoreGiveFromISR( semaforoADC, pdFALSE );

}

#endif

ISR(INT0_vect)
{

pulse++;
}

ISR(USART0_RX_vect)
{
ccc = UDR0;

switch(ccc)
{
case 'a':
ref_vel = 100;
break;
case 'b':
ref_vel = 70;
break;
case 'c':
ref_vel = 120;
break;
case 'A':
#ifdef OneTask
adjust_DirPos(7);
#endif
#ifdef TwoTasks
ref_pos = 7;
// xTaskResumeFromISR(dirHandle);
#endif
break;
case 'B':
#ifdef OneTask
adjust_DirPos(6.7);
#endif
#ifdef TwoTasks
ref_pos = 6.7;
// xTaskResumeFromISR(dirHandle);
#endif
break;
case 'C':
#ifdef OneTask
adjust_DirPos(7.9);
#endif
#ifdef TwoTasks

ref_pos = 7.9;
// xTaskResumeFromISR(dirHandle);
#endif
break;
default:
break;

}


}

/*************** USART***********************************/
void string_transmit(unsigned char str[])
{
int counter = 0;

while(str[counter]!='\0')
{
/* Wait for empty transmit buffer */
while ( !(UCSR0A & (1<<UDRE0)) )
;
/* Start transmittion */
UDR0 = str[counter];
counter++;
}

}
/******************TRANSMISSÃO DE DADOS**************
void transmit_value (float var,float ref)
{
static char buffer[5];

// itoa((int)ref_vel,buffer,10);
itoa((int)ref,buffer,10);
string_transmit(buffer);
string_transmit("\t");

itoa((int)var,buffer,10);
string_transmit(buffer);
string_transmit("\n\r");


}

/******************IDLE TASK************************************/
void vApplicationIdleHook( void )
{
vCoRoutineSchedule();
}

RE: Three tasks bug

Posted by PICmeup on March 13, 2008
I think that is a big ask for someone to look through that. I suppose you have checked you are not overflowing the stack though.

RE: Three tasks bug

Posted by JMR on March 13, 2008
Hi,
A huge bit of code!!! It's generaly a good idea to try and create a minimal program that demonstrates the problem.
As you pointed out you have a memory problem.
You defined the heap to be 4kB which is OK. The RTOS will allocate memory from this when creating tasks or queues.
When you're creating your tasks however you are only giving a stack of 30 bytes. Way less than required. Try giving each task at east 100bytes. That should cure the problem.

RE: Three tasks bug

Posted by Breno Pinheiro on March 16, 2008
Thank you guys!!! I had to set less heap size (about 1000 bytes) to get it working.

Now I'm running it with four threads without any problem until now.


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




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists