THE^O/\/E
Newbie level 1
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 **broken link removed**. 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,
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 **broken link removed**. 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,
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[i]= 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[i]= 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[i]= 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[i]=A[i+1];
B[i]=B[i+1];
Q[i]=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(); //
}
//----------------
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++)
{;}
}