Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PIC 16f877A interrupt

Status
Not open for further replies.

Junaid1996

Newbie level 5
Joined
Jun 4, 2019
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
60
Hi.
I have been working on a project of Over current relay using PIC 16f877A controller in which I have used interrupt signal to generate a exact time delay (trip signal) . For which I have used timer 1 configuration.
It is working all fine when I run its simulation on Protues, it gives accurate result there.
But On hardware sometime it does not gives an interrupt signal, sonetimes it gives on very accuarte time. On tbe otherhand it malfunctions as well.

What could be the reason of this malfunctioning ? Why it does not give an interrupt signal ? Please help.
 

What kind of oscillator are you using, internal RC, external crystal, etc... ?
Anyway, how much inaccurate it is being ?
 

I am using an external oscillator of 20Mhz.
When its inaccurate it never gives an interrupt signal until I reset the circuit 2 or 3 times.
And sometime it gives so accurate result in a single attempt.
 

You seem to be talking about 2 interrupts - one from the outside world to detect the over-current situation, and the other from the internal timer.
I find it hard to see how the internal timer can be 'unreliable' without bad programming. Therefore I assume that you are saying that the signal from the outside world is not always being detected - correct?
Check that you have all of the bypass capacitors correctly installed, that the circuit around the \MCLR\ is not triggering a reset.
Also what is actually generating the external interrupt signal? Could it be noisy/suffering contact bounce/etc.?
Susan
 

When its inaccurate it never gives an interrupt signal until I reset the circuit

In this case there is a misuse of the term inaccuracy, which would imply an operation of timer interruption with incorrect cadence, whereas in the above case it simply stopped to work, and I agree with Susan's remark about the possibility of dealing with bad programming issues. Anyway, just to add, you migh be aware that PIC16F877 has only one interrupt vector for all peripherals, therefore proper care have to be taken to handle all events, which means that once happening an interrupt, all individual interrupt flags should be checked.
 

No, signal from the sensor is correctly read by the controller as I am using LCD as well which shows the value of current. But again the problem is with the interrupt signal it sometimes give and sometimes it does not, quite possible it is due to the bad programming.
 

Thank you for again and agian responding me.
If I share my code with you, would it be possible that you would tell me my mistake in timer 1 configuration ?
 

Yes, zip and post your complete project so that we can tell you what is wrong with it if any and how to fix it.
 

No, signal from the sensor is correctly read by the controller as I am using LCD as well which shows the value of current. But again the problem is with the interrupt signal it sometimes give and sometimes it does not....
How is the interrupt derived from the sensor?
I take it from your descriptor that you are continuously monitoring the sensor output with the MCU (and so displaying the value the LCD). Is there a separate signal from the sensor to the MCU that is acting as the interrupt?
Or are you comparing the value with some threshold value in your code and triggering your 'interrupt' (I would not call it that in this case) that way?
Perhaps a schematic diagram would help.
Susan
 

How is the interrupt derived from the sensor?
I take it from your descriptor that you are continuously monitoring the sensor output with the MCU (and so displaying the value the LCD). Is there a separate signal from the sensor to the MCU that is acting as the interrupt?
Or are you comparing the value with some threshold value in your code and triggering your 'interrupt' (I would not call it that in this case) that way?
Perhaps a schematic diagram would help.
Susan
Exactly, a threshold value has been defined in the code, as the sensor's value reach the threshold value a particular time delay is calculated after which interrupt signal should be generated and the LED must glow at that time.
I am also attaching the zip file of my MP lab Project and the simulation as well.
 

Attachments

  • MPLab Project.rar
    549.3 KB · Views: 70

It is better to use Timer1 interrupt for the delay generation as it gives accurate delays.
What is your required delay range based on your Amps range?
 

It is better to use Timer1 interrupt for the delay generation as it gives accurate delays.
What is your required delay range based on your Amps range?

I am already using timer 1 configuration as I have mentioned above.
It might varies from 1 second to 1 minute no particular range is defined.
 

Explain these so that I can understand the code fully and then debug the code.

What is Ip, PSM, TMS, top, tactual?

Code:
Amps = 0.007;
        float Ip = 0.005 * 1 ;
       
        if(Amps>Ip)
        {
         float   PSM;
         float   top ;
         float   TMS = 1.0 ;   
         float  tactual =0.0 ;
         PSM = Amps/Ip ; // 1.4
         top = TMS * (0.14 / (pow(PSM,0.02)-1))  ; // 20.73

         //tactual = top * TMS ;
         delayy(top);

Are you sure XC8 compiler's __delay_ms() function accepts float values are arguments?
 

Explain these so that I can understand the code fully and then debug the code.

What is Ip, PSM, TMS, top, tactual?

Code:
Amps = 0.007;
        float Ip = 0.005 * 1 ;
       
        if(Amps>Ip)
        {
         float   PSM;
         float   top ;
         float   TMS = 1.0 ;   
         float  tactual =0.0 ;
         PSM = Amps/Ip ; // 1.4
         top = TMS * (0.14 / (pow(PSM,0.02)-1))  ; // 20.73

         //tactual = top * TMS ;
         delayy(top);

Are you sure XC8 compiler's __delay_ms() function accepts float values are arguments?

No, __delay_ms() does not accept float value that is the only reason why I chose interrupt function.
 

Code:
#include <xc.h>
#include "LCD.h"
#include <math.h>
#define _XTAL_FREQ 20000000
// CONFIG
// CONFIG1H
 
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
int count;
int k;

//**ADC FUnctions***//
void ADC_Initialize()
{
  ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
  ADCON1 = 0b11000000; // Internal reference voltage is selecte
}
 
unsigned int ADC_Read(unsigned char channel)
{
  ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits
  ADCON0 |= channel<<3; //Setting the required Bits
  __delay_ms(2); //Acquisition time to charge hold capacitor
  GO_nDONE = 1; //Initializes A/D Conversion
  while(GO_nDONE); //Wait for A/D Conversion to complete
  return ((ADRESH<<8)+ADRESL); //Returns Result
}
//***End of ADC Functions***//
 
void main(void) 
{
    int adc=0; //Variable to read ADC value
    float Voltage1; //Variable to store voltage
    float Amps; //Variable to store Amps value
    int Am1,Am2,Am3; //Variable to split Amps value into char
    float top;
    float PSM;
    TRISA4 =1; //AN4 declared as input
    TRISB = 0x00;
    TRISD0 = 0;
    TRISD1 = 0;
    char bool = 1;
    TRISC0 =1;
    TRISC1 =1;
    TRISC2 =1;
    
    ADC_Initialize();
	InitLCD();
    RD0=0;
    RD1=0;
    
while(1)
{   
    /***Current Calculation*****/
        for (int i=0; i<20;i++) //Read value for 20 Times
    {       
        adc=0;// Initialize the LCD
        adc=ADC_Read(4); //Read ADC
        Voltage1 = (adc*4.8828); //Calculate the Voltage
        if( Voltage1>=2500)
        {
        //If the current is positive
          Amps += ((Voltage1-2500)/18.5);
        }
        else if (Voltage1<=2500) //If the current is negative
        {
            Amps += ((2500-Voltage1)/18.5);
        }
    }
        Amps/=20;  //Average the value that was read for 20 times
         if (bool) //during the normal operating condition
         {
        RD0 = 1;  // LED ON
        RD1 = 0;  // LED ON   
        }

        GotoYXPositionOnLCD(LCD_LINE1, 0);
        Am1 = fmod((Amps/100) , 10) ;
        Am2 = fmod((Amps/10 ) ,10) ;
        Am3 = fmod(Amps,10);
        //Am4 = fmod(Amps *10,10);
        WriteStringToLCD("CURRENT ="); // displaying the value of current sensed by the ACS 712
        WriteDataToLCD(Am1+'0');
        WriteDataToLCD(Am2+'0');
        WriteDataToLCD('.');
        WriteDataToLCD(Am3+'0');
        //WriteDataToLCD(Am4+'0');
        WriteDataToLCD('A'); 
        
        float Ip = 30.0; // giving a threshold value for tripping
        float Is = 80.0; // giving a threshold value for instantaneous tripping
            if(Amps > Is )
            {
              RD0 = 0;  // LED ON
              RD1 = 1;
              while (1){
              GotoYXPositionOnLCD(LCD_LINE1, 0);
              WriteStringToLCD(" SHORT CIRCUIT"); 
              GotoYXPositionOnLCD(LCD_LINE2, 0);
              WriteStringToLCD("     ALERT"); 
            }
            }
        else if( Amps> Ip)
        {
            // timer 1 config starting
        TMR1=0;
        TMR1CS=0;
        T1CKPS0=0;
        T1CKPS1=0;
        TMR1ON=1;
        TMR1IE=1;
        TMR1IF=0;
        GIE=1;
        PEIE=1;
        // timer 1 config ending
        PSM = Amps/Ip ;
        top = (13.5 / (PSM-1))  ; // time delay calculation after which the interrupt signal should be generated 
        k = (top * 20000000)/(4*65536); // overflow counter calculation
        bool= 0 ;
        }
        }    
}
__interrupt() void timer_isr()
{
    if  (TMR1IF)
    {
        count++;
        if (count == k)
        {
        RD0 = 0;  // LED ON
        RD1 = 1; 
        count=0;
        }
        TMR1IF=0;
    }//interrupt service routine 
}

Your Ip = 30 Amps and Is = 80 Amps but your sensor is 5 Amps type.
Did you change the ACS712 sensor to 100A or 200A type?
I see you use 20 MHz Oscillator but with 20 MHz you can't get 1 sec timer interrupt. Even if you use 4 MHz Crystal then you can get around 500ms timer interrupt max.
Why not create a 1ms timer interrupt and then find out value for k and test if ++count >= k in ISR?
 

kindly help me.

Hi Junaid1996!

For what it's worth, I had the same issue not long ago on an 16F device i.e. external interrupt + TIMER1 interrupt. In the end I dropped the external interrupt and did some polling in main loop in stead. The main reason for this was that regardless of IOCBP/IOCBN settings the external interrupt triggered on both edges.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top