Quality RTOS & Embedded Software

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


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 ]    [ Privacy ]    [ Sitemap ]    [ ]


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

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

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

Xilinx Microblaze and Zynq partner