Page 1 of 1

PIC16F877A problem with Routine too Large

Posted: 13 Oct 2010 00:01
by Killing Tank
Hi everyone, i am programming a controller for a Piezoelectric Transducer Actuator and have come up with the error Routine too large. I have tried many methods of overcoming it but still have not found the solution. Please help me in way you can.
I have commented out Case 7 since it runs perfectly without it, but the problem is when you delete the comments, this is relevant also if you uncomment some of the other cases.

Thank you.

Here is the code:

Code: Select all


    char kp, kp2, kp3, kp4, kp5, kp6, Emergency, Resume, State, Cancel, Check;
    float StepSize, Resol, kv, kv2, kv3, kv4, kv5, kv6, See, Voltage, Frequency, Amplitude;

    char Text[15];
    
    const char *Intro = "Step:1 Cont:2";
    const char *StepSet = "Step Mode Set";
    const char *ContSet = "Cont Mode Set";
    const char *Size = "Enter Step Size";
    const char *Displacement = "Enter Displ mm";
    const char *UpDown = "Incr:1  Decr:2";
    const char *Freq = "Enter Freq kHz";


    const char lookup[] = {'U','1','2','3','U','4','5','6','U','7','8','9','U','*'
                          ,'0','#','U'};


    void strConstCpy (char *dest, const char *source) {
    while(*source)
    *dest++ = *source++ ;

    *dest = 0 ;
                                                     }


    void main()
    {
    //Pwm_Init(1000);
    //Pwm_Start();
    State = 0;
    CMCON = 7;   //Comparators off
    TRISA = 0b000001;    // ,Set Bit 0 as Input
    TRISB = 0b11111111;    //Set all Bits as Inputs for the Keypad
    TRISC = 0b00011100;     // Bit 7 (Sound) as an output, Bits 4 to 2
    //Cancel, Emergency Stop, Resume) as Inputs, Bit 0 (Actuator) as an output
    TRISD = 0b00000000; // Set Port D as Outputs for the LCD

    ADCON0 = 0b00000001;     //Set Fosc/8 and turn Convertor on
    ADCON1 = 0b00000000;     // Set PORTA.F0 as an Analog Input

    LCD_Config(&PORTD,7,6,5,3,2,1,0);
    LCD_Cmd(LCD_CLEAR);
    LCD_Cmd(LCD_CURSOR_OFF);
    
    strConstCpy(Text,Intro);
    LCD_OUT(1,1,Text);

    Keypad_Init(&PORTB) ;

    while(1){

    switch (State){

    case 0:
    PORTA.F0 = 0; //  Set Actuator Position to Initial 0 Volts
    State = 1;
    break;


    case 1:
    while(!keypad_Read()){}
    kp = Keypad_Released();
    kv = lookup[kp];
    LCD_Chr(2,1,kv);

    if(kv == '1')    //Step mode selected
    {
    State = 2;
    strConstCpy(Text,StepSet);
    LCD_OUT(1,1,Text);
    }
    else
        {
    State = 3;
    strConstCpy(Text,ContSet);
    LCD_OUT(1,1,Text);
        }
    break;



    case 2:
    Delay_ms(100);
    LCD_Cmd(LCD_CLEAR);
    strConstCpy(Text,Size);
    LCD_OUT(1,1,Text);

    while(!keypad_Read()){}
    kp2 = Keypad_Released();
    Delay_ms(10);
    kv2 = lookup[kp2];
    //Delay_ms(1);
    if (kv2=='#')
    {
    kv2=0;
    StepSize = kv2;
    State = 4;
    break;
    }
    else
         {
    LCD_Chr(2,1,kv2);
    LCD_OUT(2,2,".");
         }

    while(!keypad_Read()){}
    kp3 = Keypad_Released();
    Delay_ms(10);
    kv3 = lookup[kp3];
    //Delay_ms(1);
    if (kv3=='#')
    {
    StepSize = kv2;
    State = 4;
    break;
    }
    else
           {
    LCD_Chr(2,3,kv3);
           }

    while(!keypad_Read()){}
    kp4 = Keypad_Released();
    Delay_ms(10);
    kv4 = lookup[kp4];
    //Delay_ms(1);
    if (kv4=='#')
    {
    StepSize = kv2 + (0.1 * kv3);
    State = 4;
    break;
    }
    else
        {
    LCD_Chr(2,4,kv4);
        }

    while(!keypad_Read()){}
    kp5 = Keypad_Released();
    Delay_ms(10);
    kv5 = lookup[kp5];
    Delay_ms(1);
    if (kv5=='#')
    {
    StepSize = kv2 + (0.1 * kv3) + (0.01 * kv4);
    State = 4;
    break;
    }
    else
        {
    LCD_Cmd(LCD_CLEAR);
    Delay_ms(100);
    State = 2;
        }

    break;

    case 3:
    Delay_ms(100);
    LCD_Cmd(LCD_CLEAR);
    strConstCpy(Text,Displacement);
    LCD_OUT(1,1,Text);

    while(!keypad_Read()){}
    kp2 = Keypad_Released();
    Delay_ms(10);
    kv2 = lookup[kp2];
    if (kv2=='#')
    {
    kv2=0;
    State = 7;
    break;
    }
    else
         {
    LCD_Chr(2,1,kv2);
         }

    while(!keypad_Read()){}
    kp3 = Keypad_Released();
    Delay_ms(10);
    kv3 = lookup[kp3];
    if (kv3=='#')
    {
    Amplitude = kv2;
    State = 7;
    break;
    }
    else
           {
    LCD_Chr(2,2,kv3);
    LCD_OUT(2,3,".");
           }

    while(!keypad_Read()){}
    kp4 = Keypad_Released();
    Delay_ms(10);
    kv4 = lookup[kp4];
    if (kv4=='#')
    {
    Amplitude = kv2 + (0.1 * kv3);
    State = 7;
    break;
    }
    else
        {
    LCD_Chr(2,4,kv4);
        }

    while(!keypad_Read()){}
    kp5 = Keypad_Released();
    Delay_ms(10);
    kv5 = lookup[kp5];
    if (kv5=='#')
    {
    Amplitude = kv2 + (0.1 * kv3) + (0.01 * kv4);
    State = 7;
    break;
    }
    else
        {
    State = 3;
        }
    break;

    case 4:
    Resol = StepSize * (0.0000167);
    State = 5;
    break;

    case 5:
    LCD_Cmd(LCD_CLEAR);
    strConstCpy(Text,UpDown);
    LCD_OUT (1,1,Text);

    while(!keypad_Read()){}
    Check = Keypad_Released();         //Checks to see if the Increase or Decrease
    Delay_ms(10);                      //Button was pressed
    See = lookup[Check];
    Delay_ms(1);
    if(See == '1')
    {
    State = 6;
    LCD_Cmd(LCD_CLEAR);                                //Increase
    break;
    }
    else
        {
        LCD_Cmd(LCD_CLEAR);
        Voltage = PORTA.F0;
        Delay_ms(1);                      //Decrease
        if(Voltage = 0)
          {
          State = 10;
          }
    else
            {
            State = 9;
            }
         }
    break;

    case 6:
    Voltage = PORTA.F0 + Resol;             //Increase PZT piston length


    if(Voltage > 0.02)                    //check if Maximum reached
    {
    State = 10;                           //goes to state 10 for the sound to be played
    }
    else
        {
        State = 6;
        }
    break;

//    case 7:
//    Delay_ms(100);
//    LCD_Cmd(LCD_CLEAR);
//    strConstCpy(Text,Freq);
//    LCD_OUT(1,1,Text);

//    while(!keypad_Read()){}
//    kp2 = Keypad_Released();
//    Delay_ms(10);
//    kv2 = lookup[kp2];
//    if (kv2=='#')
//    {
//    kv2=0;
//    State = 8;
//    break;
//    }
//    else
//         {
//    LCD_Chr(2,1,kv2);
//    LCD_OUT(2,2,".");
//         }

//    while(!keypad_Read()){}
//    kp3 = Keypad_Released();
//    Delay_ms(10);
//    kv3 = lookup[kp3];
//    if (kv3=='#')
//    {
//    Frequency = kv2;
//    State = 8;
//    break;
//    }
//    else
//           {
//    LCD_Chr(2,3,kv3);
//           }

//    while(!keypad_Read()){}
//    kp4 = Keypad_Released();
//    Delay_ms(10);
//    kv4 = lookup[kp4];
//    if (kv4=='#')
//    {
//    Frequency = kv2 + (0.01 * kv3);
//    State = 8;
//    break;
//    }
//    else
//           {
//    State = 7;
//           }

    break;

//    case 8:
//    Voltage =  Amplitude * SinE3(2* 3.14 * Frequency * (1/Frequency));
//    State = 11;                                //Calculate Sine Wave
//    break;
//
    case 9:
    Voltage = PORTA.F0 - Resol;
    if(Voltage = 0)
    {
    Sound_Init(&PORTC, 7);
    Sound_Play(1000, 100);
    State = 5;
    break;
    }
    else
      {
      State = 9;
      }
    break;

    case 10:
    Sound_Init(&PORTC, 7);
    Sound_Play(1000, 100);
    State = 5;
    break;

//    case 11:
//    Pwm_Change_Duty(Voltage);
//    State = 12;   //how do you generate it and send?
//    break;
//
//    case 12:
//    while(!keypad_Read()){}
//    kp6 = Keypad_Released();
//    Delay_ms(10);                            //check for Stop button
//    kv6 = lookup[kp6];
//
//    if(kv6 == '*')
//    {
//    State = 3;                                //Stop Button pressed
//    break;
//    }
//    else
//      {
//      State = 11;
//      }
//    break;

    default:
    State = 0;
    break;
                }//End Swtich State
          }//End While Ever
    }//End Void Main






Re: PIC16F877A problem with Routine too Large

Posted: 18 Oct 2010 00:13
by Killing Tank
Bump

Re: PIC16F877A problem with Routine too Large

Posted: 02 Nov 2010 11:17
by filip
Hi,

In applications targeted at PIC16, no single routine should exceed one page (2,000 instructions). If routine does not fit within one page, linker will report an error.
When confront with this problem, maybe you should rethink the design of your application – try breaking the particular routine into several chunks, etc.

Regards,
Filip.

Re: PIC16F877A problem with Routine too Large

Posted: 07 Nov 2010 15:19
by netos
use pic18f452 instead of pic16f877a. it has almost the same price and more powerful :)

Re: PIC16F877A problem with Routine too Large

Posted: 08 Nov 2010 05:10
by Killing Tank
Yes I have come to the conclusion that the PIC was the problem, now that problem has been solved but a new obstacle has shown up... How do you use Digital to Analog Conversion in a PIC18F452?

Re: PIC16F877A problem with Routine too Large

Posted: 08 Nov 2010 16:58
by netos
just same as pic16 devices.
read the device datasheet about configuring ADCONx registers and TRISx registers.
some devices olso have analog comparators sharing the analog pins. So you may configure CMCON registers if you don't use them

Re: PIC16F877A problem with Routine too Large

Posted: 16 Nov 2010 02:12
by Killing Tank
netos wrote:just same as pic16 devices.
read the device datasheet about configuring ADCONx registers and TRISx registers.
some devices olso have analog comparators sharing the analog pins. So you may configure CMCON registers if you don't use them

you misread my post i said "Digital to Analog" i want to send Analog signals to my PZT (Piezoelectric Transducer) i am familiar with the Analog to Digital Conversion Module, but what about the reverse?

Re: PIC16F877A problem with Routine too Large

Posted: 12 Dec 2010 21:42
by netos
oh i'm so sorry about this.

if your transducers does not need fast settling time of digital-to-analog converter, mcu's pwm outputs are good for you. otherwise you need external DACs