why so slow?? (again)

17 Aug 2010

Dear guys,

I found another bad news during my prototyping comparing the mbed with my atmega128 16MHz. After the mbed cannot handle too many interrupt activated whereas atmega128 can handle the same tasks (reading PPM signal, IMU, adn others) with the same structure code. (http://mbed.org/forum/mbed/topic/983/) Now, when on my mbed  I write down my PID function the same way as on my atmega, other processes result gone wrong.

This is one of my PID function:

float YAW_pid_P_func()
{             
    return (float)YAW_error * yaw_gain.p;        
}              

float YAW_pid_I_func()
{
    yaw_gain.error_i += YAW_error;
    if(yaw_gain.error_i >= YAW_PID_WINDUP_MAX) yaw_gain.error_i = YAW_PID_WINDUP_MAX;
    if(yaw_gain.error_i <= YAW_PID_WINDUP_MIN) yaw_gain.error_i = YAW_PID_WINDUP_MIN;

    return  (float)yaw_gain.error_i * yaw_gain.i;
}                             
                                                    

float YAW_pid_D_func()
{
    return (float)(YAW_error - YAW_prev_error) * yaw_gain.d;
}


unsigned char YAW_pid_func()
{
    float result;
    
    YAW_error = yaw_gain.goal - (int)fcc.azimuth;
    
    if(YAW_error >YAW_MAX / 2 || YAW_error < -YAW_MAX / 2)
    {       
        if(YAW_error <= 0) YAW_error = (YAW_MAX + YAW_error);        
        else                YAW_error = -(YAW_MAX - YAW_error);
    }

    result = YAW_pid_P_func() + YAW_pid_I_func() + YAW_pid_D_func(); 
     
    if(result > YAW_PID_MAX) result = YAW_PID_MAX;
    if(result < YAW_PID_MIN) result = YAW_PID_MIN;  

    YAW_prev_error = YAW_error;  
    
    return (unsigned char)result + YAW_MIDDLE;
} 
And the solution is to write it down in one function as like this:

unsigned char YAW_pid_func()
{
    float result;
    
    YAW_error = yaw_gain.goal - (int)fcc.azimuth;
    
    if(YAW_error >YAW_MAX / 2 || YAW_error < -YAW_MAX / 2)
    {       
        if(YAW_error <= 0) YAW_error = (YAW_MAX + YAW_error);        
        else                YAW_error = -(YAW_MAX - YAW_error);
    }

    result = YAW_error * yaw_gain.p;    
    
    yaw_gain.error_i += YAW_error;
    if(yaw_gain.error_i >= YAW_PID_WINDUP_MAX) yaw_gain.error_i = YAW_PID_WINDUP_MAX;
    if(yaw_gain.error_i <= YAW_PID_WINDUP_MIN) yaw_gain.error_i = YAW_PID_WINDUP_MIN;
    
    result += yaw_gain.error_i * yaw_gain.i;  
    result += (YAW_error - YAW_prev_error) * yaw_gain.d;
     
    if(result > YAW_PID_MAX) result = YAW_PID_MAX;
    if(result < YAW_PID_MIN) result = YAW_PID_MIN;  

    YAW_prev_error = YAW_error;  
    
    return (unsigned char)result + YAW_MIDDLE;
} 
Yes, I am new beginner in firmware coding but why atmega can do but mbed not?

 

17 Aug 2010

Hi Raharja,

This problem doesn't really look related to speed; inlining code like that when you are doing so many floating point operations really shouldn't make any difference. It is not clear to me in what way it was broken in the first case, but I suspect it is something to do with type casting, global variables, knock on effects of inlining or something unrelated. Certainly the function call overhead is not your problem, so i'd perhaps look a bit more closely at the symptoms of it being broken.

For reference, i've put up a full explanation of the behaviour you were seeing related to interrupts at:

Again, this shows it is not related to speed, but simply what we are instructing the microcontroller to do (it just follows orders after all!). The mbed is certainly not slower than a 16MHz part, and the post should show you a good example of how you can get the behaviour you want.

Simon