Microcontroller-Based Overcurrent Protective Relay

Thread Starter

THE^O/\/E

Joined Jun 1, 2010
3
Hi there,

I'm new to this forum and to the world of pic microcontrollers programming. I have a project I'm working on which is to design a microcontroller based overcurrent protective relay. I'm using pic16f877A chip along with QL200 development board. I'm programming using C and I'm using HI-Tech compiler with MPLab. I've simulated the algorithm I'm using on Matlab and everything went perfect. After that I started writing the C program and when I done with it I wrote it on the microcontroller but unfortunately it didn't work well.

I’m using a method called (Four-Sample) method to identify the signal “basically taking one sample each ¼ of the period (T=1/f=1/60) and using these samples to calculate the RMS value of the current to be monitored”. After getting the RMS value I used another algorithm to implement the relaying decision part of the program. It is required to display the current value in the three lines continuously in the normal condition and then if fault occurs, the program shows a massage on the LCD and the program stop. The LCD I’m using is 128*64 dots LCD.

Note/ I’ve tested the time required to execute the code completely from the beginning to the end and I got 6 seconds!!!. I need to take a one sample every 4.167ms that’s for the three lines!!!

Here is my code. Any help would be appreciated.

Regards,
 

Thread Starter

THE^O/\/E

Joined Jun 1, 2010
3
Rich (BB code):
///////////////
//
// taking analog input for three lines from port E
// and using port A as a control unit for the LCD
//
//
///////////////////// 

#include<pic.h>

#include<math.h> 
__CONFIG(0x1832); 
#define  rs  RA5                    //COMMNAD/DATA SELECT
#define  rw  RA4                    //READ/WRITE SELECT
#define  e   RA3                    //ENABLE SIGNAL
#define  psb RA2                    //PARALLEL/SERIAL SELECT£¨H/L£©
#define  rst RA0                    //RESET SIGNAL
#define  nop()  asm("nop")          //nop func 

unsigned char MM[9];

const unsigned char NNA[ ]={' ',' ','F','A','U','L','T',' ','O','C',' ','L','A'};
const unsigned char NNB[ ]={' ',' ','F','A','U','L','T',' ','O','C',' ','L','B'};
const unsigned char NNC[ ]={' ',' ','F','A','U','L','T',' ','O','C',' ','L','C'}; 

unsigned int lcd_x;                //X address
unsigned int lcd_y;                //Y address

bit busy;                          //busy flag 

void display(int x,unsigned int y);
void fault(int r);
void init();                        //system init.
void lcd_init();                    //LCD init
void clear_p();                    //clear screen
void flash();
void wr_zb();                       //display setting mode.
void qushu(int counts,const unsigned char *ps);       //search table.
void send_d(unsigned char x);       //send data
void send_i(unsigned char x);       //send command.
void chk_busy();                    //check busy sub.
void delay();                       //delay func, decide the speed of display.
void delay1();                      //delay func, decide the speed of blink.
void delay2();                      //delay func, to insure saving sample.
void delayad();                     //delay func, to insure the 4 samples per cycle. 
void main()
{
      int i=0x0;
      int j=0x0;
    
      unsigned int A[4];
      unsigned int B[4];
      unsigned int Q[4];
      unsigned int a1=0x0;
      unsigned int b1=0x0;
      unsigned int q1=0x0;
      unsigned int ip1=0x0;
      unsigned int ip2=0x0;
      unsigned int ip3=0x0;
      unsigned int pp=0x0;
      unsigned int s=0x0;
      unsigned int c=0x0;
      unsigned int ipick=0x0231;

        //-------

      ADRESH=0x0;
      ADRESL=0x0;

      //-------

      TRISA=0xFF;
      PORTA=0X00;
      TRISE=0x07;
      PORTC=0X00; 

      ADCON1=0x80; 
      for(i=0;i<4;)
                  { 
                  /////////////////////////
                   ADRESH=0x0;
                   ADRESL=0x0; 
                   ADCON0=0x41;      // teke analog from RE0 >> line A 
                   ADGO=0X1;             //start convert

                   while(ADGO);
                   delay2();   // i<0x5 

                   A= ADRESH << 8 | ADRESL; 

                   ///////////////////////// 

                   /////////////////////////

                  ADRESH=0x0;
                  ADRESL=0x0; 
                  ADCON0=0x71;     // take analog input from RE1 >> line B 
                  ADGO=0X1;             //start convert

                  while(ADGO);

                  delay2();   // i<0x5 

                  B= ADRESH << 8 | ADRESL; 

                  ///////////////////////// 

                  ADRESH=0x0;
                  ADRESL=0x0; 
                  ADCON0=0x79;     // take analog input from RE2 >> line C 
                  ADGO=0X1;             //start convert

                  while(ADGO);

                  delay2();   // i<0x5 

                  Q= ADRESH << 8 | ADRESL; 

                  ///////////////////////// 

                  delayad(); 
      i++;

      }

      while(1)

      {
              //-------

              ADRESH=0x0;
              ADRESL=0x0;
              //-------
              TRISA=0xFF;
              PORTA=0X00;
              TRISE=0x07;
              PORTC=0X00;
              TRISB=0x0;
              PORTB=0x01;

              //-------

              ADCON1=0x80;

              //-------
 
               ADRESH=0x0;
               ADRESL=0x0; 
               ADCON0=0x69;      // teke analog from RE0 >> line A 
               ADGO=0X1;             //start convert

               while(ADGO);

               delay2();   // i<0x5 

               a1= ADRESH << 8 | ADRESL; 

               /////////////////////////

              ADRESH=0x0;
              ADRESL=0x0; 
              ADCON0=0x71;     // take analog input from RE1 >> line B 
              ADGO=0X1;             //start convert

              while(ADGO);

              delay2();   // i<0x5 

              b1= ADRESH << 8 | ADRESL; 

              ///////////////////////// 

              ADRESH=0x0;
              ADRESL=0x0; 
              ADCON0=0x79;     // take analog input from RE2 >> line C 
              ADGO=0X1;             //start convert

              while(ADGO);

              delay2();   // i<0x5 

              q1= ADRESH << 8 | ADRESL; 

              ///////////////////////// 

              for(i=0;i<3;)      // shift the samples in the arrays to make room for

              {                  // the new sample

              A=A[i+1];
              B=B[i+1];
              Q=Q[i+1]; 

              i++;

              } 

              A[3]=a1;
              B[3]=b1;
              Q[3]=q1; 

              //---------
              s=0x0;
              c=0x0;
     
              s=A[0]+A[1]-A[2]-A[3];
              c=A[0]-A[1]-A[2]+A[3];

              ip1=(sqrt((s*s)+(c*c)));
              ip1=ip1>>2; // ip1/4

              //---------
              s=0x0;
              c=0x0; 
              s=B[0]+B[1]-B[2]-B[3];
              c=B[0]-B[1]-B[2]+B[3]; 

              ip2=sqrt(((s*s)+(c*c)));
              ip2=ip2>>2; 

              //----------
              s=0x0;
              c=0x0; 
              s=Q[0]+Q[1]-Q[2]-Q[3];
              c=Q[0]-Q[1]-Q[2]+Q[3]; 

              ip3=sqrt(((s*s)+(c*c)));
              ip3=ip3>>2;

               //-----------------------

               // scale the voltage level here to the value of the current before

               // the conditioning circuit.

               //-----------------------
               //ip3=0x0275; 

              init();                 //initiate the ports for the LCD display

          lcd_init();    //LCD initiation.      

                        clear_p();    //LCD clear 

                     //pp=(A[0]+A[1]+A[2]+A[3])/4;

               display(0x1,pp);

               display(0x2,ip2);

               display(0x3,ip3); 

               //-------

               // disicion

               //-------

              if(ip1>ipick)

              {

                fault(0x1);

              }

              //else

              //{ display(0x1,ip1); }

              
              if(ip2>ipick)

              {

                fault(0x2);

              }

              //else

              //{ display(0x2,ip2); }

              if(ip3>ipick)

              {

                fault(0x3);

              }

             // else

             // { display(0x3,ip3); }

         PORTB=0x0;

             delay1();   

        } // end of the while(1) loop 

 
}  // end of main function 
///------------------------------------- 
void display(int x,unsigned int y)

{
        if(x==0x1)

         {

          MM[0]=76;                // L
          MM[1]=45;                // -
          MM[2]=49;                // 1
          MM[3]=61;                // =
          MM[4]=(5*y/1024)+48;     // first digit
          MM[5]=46;                // point (.)
          MM[6]=((50*y/1024)%10)+48; // second digit
          MM[7]=((20*y/41)%10)+48;   // third digit
          MM[8]=65;                 //  A for Amp 

          send_i(0x80);  /// search what is the thing 
          qushu(0x9,MM);

         } 

         if(x==0x2)

         {

          MM[0]=76;                 // L
          MM[1]=45;                 // -
          MM[2]=50;                 // 2
          MM[3]=61;                 // =
          MM[4]=(5*y/1024)+48;      // first digit
          MM[5]=46;                 // point (.)
          MM[6]=((50*y/1024)%10)+48; // second digit
          MM[7]=((20*y/41)%10)+48;  // third digit
          MM[8]=65;                 // A for Amp 
 
         send_i(0x90); 
          qushu(0x9,MM);

         } 

         if(x==0x3)

         {

          MM[0]=76;               // L
          MM[1]=45;              // -
          MM[2]=51;               // 3
          MM[3]=61;               // =
          MM[4]=(5*y/1024)+48;    // first digit
          MM[5]=46;               // point (.)
          MM[6]=((50*y/1024)%10)+48; // second digit
          MM[7]=((20*y/41)%10)+48;  // third digit
          MM[8]=65;                // A for Amp 

          send_i(0x88); 
          qushu(0x9,MM); 

         } 

        delay1();                     //

        //clear_p();                   // 
}
 

Thread Starter

THE^O/\/E

Joined Jun 1, 2010
3
//----------------
void fault(int r)

{

init(); //system init.
lcd_init(); //
clear_p(); //
send_i(0x90);

if(r==0x1)

{

qushu(0xd,NNA);

}

if(r==0x2)

{

qushu(0xd,NNB);

}



if(r==0x3)

{

qushu(0xd,NNC);

}
delay1(); //
flash();
clear_p();

}

//----------

void flash()

{

send_i(0x08); //off display.
delay1(); //delay
send_i(0x0c); //on display
delay1();
delay1(); //delay
send_i(0x08); //off
delay1();
send_i(0x0c); //on
delay1();
delay1();
send_i(0x08); //off
delay1();
send_i(0x0c); //on
delay1();
delay1();
}

//------------

void init()

{

TRISA=0X00; //A port as output
TRISD=0X00; //d port as output
ADCON1=0X06; //A port as ordinary i/o
}

/////

void lcd_init()

{

rst=0; //reset LCD
delay();
rst=1; //LCD normal work.
nop();
psb=1; //8 bit as parrallel.
send_i(0x30); //basic operation instruction
send_i(0x01); //off display
send_i(0x06); //set the cursor's moving direction.
send_i(0x0c); //on display,off cursor,off blink
}

////

void wr_zb()

{

send_i(lcd_y);
send_i(lcd_x);

}

/////

void clear_p()

{

send_i(0x1); //clear all
send_i(0x34); //extend.
send_i(0x30); //basic

}

////

void qushu(int counts,const unsigned char *ps)

{

int i; //define loop count.

for(i=counts;i>0;i--) //

{

send_d(*ps); //
delay(); //
ps++; //get next.

}

}

////

void send_d(unsigned char x)

{

chk_busy(); //check busy.
rs=1; //data not commnad.
rw=0; //write not read.
PORTD=x; //data to bus.
e=1; //enable.
nop();
nop();
nop();
e=0; //disable.
}

////

void send_i(unsigned char x)

{

chk_busy(); //check lcd if busy.
rs=0; //data not commnad.
rw=0; //write not read.
PORTD=x; //data to bus.
e=1; //enable.
nop();
nop();
nop();
e=0; //disable.

}

////

void chk_busy()

{

busy=1; //set busy signal
TRISD=0XFF; //change the bus to input.
rs=0; //command not data.
rw=1; //read not write.
while(busy)
{

nop();
nop();
nop();
e=1; //enable.
nop();
nop();
nop();
if(!RD7) busy=0; //
nop();
nop();
nop();
e=0; //DISABLE.
}
e=0; //DISABLE.
TRISD=0X00; //bus as output.
}

////

void delayad()

{

int i;

for(i=0;i<0x100;i++)

{;}
}

////

void delay()

{

int i;

for(i=0;i<5000;i++)

{;}

}

//-------------------------------------------

//delay1

void delay1()

{

int i;

for(i=0;i<10;i++)

{

delay(); //call delay.

}

}

////

void delay2()

{

int i;

for(i=0;i<0x5;i++)

{;}

}
[/code]
 
Top