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.

Counting pulses from external source PIC16F877a

Status
Not open for further replies.
Hi,

but I don't understand why LED turn on for forever ?
It's already explained in post#17, last sentence.

Klaus

Added:
To debug ... or to find out why things happen, why don't you
* use a simulator, debugger, emulator
* or simply a piece of paper and a pencil. Indeed this is how I do it most of the time.

Klaus
 
I don't understand why LED turn on for forever ?
That's because the processor does exactly what you command it, no what you think it should do. Do you reset MyTrigger any where in your code?

Yes, a mechanical switch must be expected to bounce. You should wait about 20 ms before reenabling the interrupt.
 
simple - you never turn it off!

This is why I queried what you intended to do in an earlier post. There has to be some other condition that exists before you press the button and another condition that happens afterwards. In your code there is nothing to turn 'MyTrigger' off again. To 'UNtrigger' it add this extra line:
Code:
   while (1)
    {
        if(MyTrigger == 1)
        {
            MyTrigger = 0;  // this will prepare it for the next time it is triggered
            // put the code to operate the air jet here
             RD1 = 1;  // Jet ON
             __delay_ms(1000); // 
             RD1 = 0;  // Jet OFF
             __delay_ms(500); // 1 Second Delay
        }
    }

You can also remove the 'return;' line because there is nothing to return to and that line is never reached anyway!

I suspect you have another problem, the bouncing switch contact as you assumed. The ISR counts the number of times the contacts close and open and although you press the switch once, the PIC can respond to very rapid changes as the metal contacts collide and bounce. There is also a gray area where the switch may be partially conducting when the contacts are only just touching. To some extent you can reduce the effect by adding a capacitor (~100nF) across the switch contacts although there are better ways to do it.

What value resistor do you use in series with the LED, if you drop below a few hundred Ohms the PIC pin may be overloaded and it can cause a software crash. I would advise using around 330 Ohms if possible.

Do you have a capacitor (or two) across the VSS and VDD pins and are they mounted close to the PIC. They are not in your schematic but they are essential to reliable operation. Add at least a 100nF ceramic capacitor across VSS and VDD and preferably ALSO add a 10uF electrolytic capacitor across them too.

Brian.
 
Hi,

if(INTF==1)
{
INTF = 0; // Clear interrupt flag
MyCounter++; // add 1 to the MyCounter
if(MyCounter == 10)

MyTrigger = 1;
}
Similar applies to "MyCounter".
In your code it will count 0..up to 10, as you expect it...but then still it goes on with 11,12, 13... until it overflows.

Klaus
 
simple - you never turn it off!

This is why I queried what you intended to do in an earlier post. There has to be some other condition that exists before you press the button and another condition that happens afterwards. In your code there is nothing to turn 'MyTrigger' off again. To 'UNtrigger' it add this extra line:
Code:
   while (1)
    {
        if(MyTrigger == 1)
        {
            MyTrigger = 0;  // this will prepare it for the next time it is triggered
            // put the code to operate the air jet here
             RD1 = 1;  // Jet ON
             __delay_ms(1000); // 
             RD1 = 0;  // Jet OFF
             __delay_ms(500); // 1 Second Delay
        }
    }
Brian.

I added extra line but still LED doesn't turn off
Here is complete code
Code:
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#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)

#define _XTAL_FREQ 20000000 //Specify the XTAL crystal FREQ
#include <xc.h>

volatile unsigned int MyCounter;
char MyTrigger;

void main(void) 
{
    
    TRISB0=1;     // Make RB0 pin as input
    TRISD1= 0;    // Make RD1 pin as output
    OPTION_REG=1;  // Set Rising Edge Trigger 
    INTCON = 1;   // Enable The Global Interrupt
    INTE = 1;     // External Interrupt Enable (not INTF)
    GIE=1;
    MyCounter = 0;  //initial values at start up
    MyTrigger = 0;
    
    while (1)
    {
        if(MyTrigger == 1)
        {
             MyTrigger = 0;  
            // put the code to operate the air jet here
             RD1 = 1;  // Jet ON
             __delay_ms(1000); // 
             RD1 = 0;  // Jet OFF
             __delay_ms(500); // 1 Second Delay
        }
    }
 
}

void interrupt isr(void)
{  
    if(INTF==1)
    {
        INTF = 0;  // Clear interrupt flag
        MyCounter++;    // add 1 to the MyCounter
        if(MyCounter == 10) 
        MyTrigger = 1;
    } 
}

I suspect you have another problem, the bouncing switch contact as you assumed.

What value resistor do you use in series with the LED, if you drop below a few hundred Ohms the PIC pin may be overloaded and it can cause a software crash. I would advise using around 330 Ohms if possible.Brian.

I am using 560 ohms resistor

I have similear push button board **broken link removed**

Do you have a capacitor (or two) across the VSS and VDD pins and are they mounted close to the PIC. They are not in your schematic but they are essential to reliable operation. Add at least a 100nF ceramic capacitor across VSS and VDD and preferably ALSO add a 10uF electrolytic capacitor across them too.

Brian.
I have single push button, some resitor and capcitor I will try to make it what you suggested
 

Something else you might do:
Add a line (suggest after the 'MyTrigger = 0;' line) that resets the counter, otherwise it just keeps counting upwards. Do not reset it inside the ISR or it will never reach 10.

Brian.
 

Hi,

Do not reset it inside the ISR or it will never reach 10.
I see no reason why it can't be reset within the ISR after the "IF(MyCounter......" line.

Klaus
 

Something else you might do:
Add a line (suggest after the 'MyTrigger = 0;' line) that resets the counter, otherwise it just keeps counting upwards. Do not reset it inside the ISR or it will never reach 10.

Brian.

done already and posted code but the problem is the same

Do you see anything wrong in the code that need to be correct ?

Can you test the code if you do have that microcontroller?
 

done already and posted code but the problem is the same

Are you really paying attention on what you are coding, posting, replying?
No, you did not reset the counter after the 'MyTrigger = 0;' line
 
I see no reason why it can't be reset within the ISR after the "IF(MyCounter......" line.
Trying to keep it simple Klaus, if it goes any earlier in the ISR it wouldn't work. You are quite right though!

Brian.
 

Something else you might do:
Add a line (suggest after the 'MyTrigger = 0;' line) that resets the counter, otherwise it just keeps counting upwards. Do not reset it inside the ISR or it will never reach 10.

Brian.

I am sorry for making mistake but still facing same problem

Code:
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#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)

#define _XTAL_FREQ 20000000 //Specify the XTAL crystal FREQ
#include <xc.h>

volatile unsigned int MyCounter;
char MyTrigger;

void main(void) 
{
    
    TRISB0=1;     // Make RB0 pin as input
    TRISD1= 0;    // Make RD1 pin as output
    OPTION_REG=1;  // Set Rising Edge Trigger 
    INTCON = 1;   // Enable The Global Interrupt
    INTE = 1;     // External Interrupt Enable (not INTF)
    GIE=1;
    MyCounter = 0;  //initial values at start up
    MyTrigger = 0;
    
    while (1)
    {
        if(MyTrigger == 1)
        {
             MyTrigger = 0;
             MyCounter = 0;
            // put the code to operate the air jet here
             RD1 = 1;  // Jet ON
             __delay_ms(1000); // 
             RD1 = 0;  // Jet OFF
             __delay_ms(500); // 1 Second Delay
        }
    }
 
}

void interrupt isr(void)
{  
    if(INTF==1)
    {
        INTF = 0;  // Clear interrupt flag
        MyCounter++;    // add 1 to the MyCounter
        if(MyCounter == 10) 
        MyTrigger = 1;
    } 
}
 

Looking back at post #16, can you confirm it really is a 16F877A you are using and that you are using the correct pins. The 'schematic' drawing of the pinouts is for a 20-pin device but the 16F877A has 40 pins.

Brian.
 


MyTrigger should be declared as volatile.
I too question the schematic in post #16. The data sheet does not show any package that has 5V on pin 1 (or 20, or 21, or 40 - i.e.on any pin at the end of the package) with Gnd opposite it. In fact all of the PIC16F877a packages have 2 Vdd and 2 Vss pins that are in the middle of the DIP package sides (similar fot the other packages). If that part of the schematic cannot be right, it makes me doubt the other connections as well. (RD1 (LED) is Pin 20 and RB0/INT is pin 33.)
The LED looks right (series resistor and taking the pin high should turn it on) but the pin with the switch should have a pull-up so that the pin is pulled high when the switch is open. While you are altering the wiring on that pin, I suggest you put a capacitor (~0.1uF) to ground which will help a bit with the debounce.
Do you have the schematic for the board you bought? According the the web page you reference, the board also has an MAX232 on it - you need to make sure that the pins you are using are not connected to anything else on the development board or the additional connections will interfere with what you are trying to do.
I'm getting a little lost on the current input source and actually what is the '...same problem'.
Are you still using a push button as the source?
Is the LED going on and staying on or not going on at all?
Susan
 

MyTrigger should be declared as volatile.
I too question the schematic in post #16. The data sheet does not show any package that has 5V on pin 1 (or 20, or 21, or 40 - i.e.on any pin at the end of the package) with Gnd opposite it. In fact all of the PIC16F877a packages have 2 Vdd and 2 Vss pins that are in the middle of the DIP package sides (similar fot the other packages). If that part of the schematic cannot be right, it makes me doubt the other connections as well. (RD1 (LED) is Pin 20 and RB0/INT is pin 33.)
I see imagae posted in post#16 is used to show LED and Push buton connection

I have posted link of real board that I am using right now

Do you have the schematic for the board you bought? According the the web page you reference, the board also has an MAX232 on it - you need to make sure that the pins you are using are not connected to anything else on the development board or the additional connections will interfere with what you are trying to do.

No I don't have schematic for the board I haven't connected anything other then pickit3

what is the '...same problem'.
Are you still using a push button as the source?
Is the LED going on and staying on or not going on at all?
Susan
yes When I press push button for counts LED goes turn on and It doesn't turn off but In code I have written it for blinking
 

Hi,


This is a good solution if you want the software to count the pulses.

But you may use T1CKI to directly make the hardware to count pulses.
This is the fastest way to count pulses ... and it needs no interrupt, no ISR and no processing power for the counting.

Klaus

okay so I made below code followed link https://exploreembedded.com/wiki/PIC16f877a_Timer

Code:
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON      // 
#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)

#define _XTAL_FREQ 8000000 //Specify the XTAL crystal FREQ
#include <xc.h>

void main(void)
{
   
    TRISC1= 1;    // Make RC1 pin as input sensor
    TRISC1= 0;    // Make RC2 pin as output LED


    TMR1ON = 0; // Stops Timer1
    TMR1CS = 1; // External clock from pin RC0/T1OSO/T1CKI (on the rising edge)
    T1SYNC = 0; // Synchronize external clock input
    T1OSCEN = 0; //Oscillator is shut-off
    T1CKPS1 = T1CKPS0 = 0; // Assigned prescaler rate is 1:1

    TMR1IF = 0; // TMR1 register overflow is cleared
 
    TMR1H=0x82; // initial count values in timer1 register
    TMR1L=0xff;
    TMR1ON = 1;     //Start Timer1

while(1)
{
    if ( TMR1IF==1)
    {
      RC0 = 1;  // LED on 
      __delay_ms(100);
      RC0 = 0;  // LED off
    }
}
}

What's the wrong with this code because the code doesn't work with hardware ?
 

I would anticipate the LED appearing to be on almost all of the time. Forget copying examples from web sites, work out the program flow yourself for your specific needs. I wrote my first computer program in 1973 and I still start out with a proper specification that caters for all situations then a flow chart to help to break the tasks into manageable routines. Programming should be 99% inspiration and 1% perspiration :smile:

Lets break your program down into small sections to see where it goes wrong:
Code:
    TRISC1= 1;    // Make RC1 pin as input sensor
    TRISC1= 0;    // Make RC2 pin as output LED
Does that really make any sense or actually do anything?
Code:
TMR1ON = 0; // Stops Timer1
not really necessary but it does no harm.
Code:
TMR1CS = 1; // External clock from pin RC0/T1OSO/T1CKI (on the rising edge)
Good! but check RC0 is an input and the switch is connected to it.
Code:
T1SYNC = 0; // Synchronize external clock input
again, not really necessary but does no harm.
Code:
T1OSCEN = 0; //Oscillator is shut-off
only necessary if RC0 and RC1 have a crystal or resonator between them but does no harm.
Code:
T1CKPS1 = T1CKPS0 = 0; // Assigned prescaler rate is 1:1
Good, you count every input pulse individually.
Code:
TMR1IF = 0; // TMR1 register overflow is cleared
Good, it makes sure you start with the interrupt bit cleared.
Code:
TMR1H=0x82; // initial count values in timer1 register, TMR1L=0xff;
Very suspicious, you are loading decimal 65410 into the counter so you have to press the button 126 times before it overflows and sets the TMR1IF bit.
Code:
while(1)
{
    if ( TMR1IF==1)
    {
      RC0 = 1;  // LED on 
      __delay_ms(100);
      RC0 = 0;  // LED off
    }
}
this waits until TMR1IF is set then goes into a strange loop. Look at the timing, LED on for 100mS, LED off for a few uS then on again in a loop. You would never see the off periods, they are too short.

Brian.
 

I see imagae posted in post#16 is used to show LED and Push buton connection
I have posted link of real board that I am using right now
I will say it again - the schematic in port #16 is totally useless. It does not show pin numbers and if you try to apply the 'standard' pin numbering then you cannot get anything that agrees with the package descriptions in the data sheet.
As for a schematic - let me help you with that: **broken link removed** (Actually I got that link from the advertisement for the board that you posted. However you should ALWAYS get documentation on the boards you use.) That schematic shows RC0 and RC1 (which I assume are the pins you are trying to use) have no other connections. However it also shows that the boards built-in push button and LED are on RD3 and RD4 respectively.
Another thing: you have told the device to use the external crystal as the clock source. According to the schematic, the board has a 20MHz crystal. However you have told the __delay_ms() function that you have an 8MHz clock (in the XTAL_FREQ preprocessor macro). Therefore you are telling the delay function that you clock is going 2.5 times slower than it really is and so the delays will be 2.5 times shorter than you expect.
I really do suggest that you take a step back and simply get the board to flash the LED on and off with a delay of (say) 1 second between each transition and then time how long the flashes really take. When you can get the LED to flash at the rate you specify THEN you know you have the oscillator and associated preprocessor macros set up correctly.
Susan
 

Hi,

What's the wrong with this code because the code doesn't work with hardware ?
Is it asking too much for an error description?

Klaus
 

I will say it again - the schematic in port #16 is totally useless. It does not show pin numbers and if you try to apply the 'standard' pin numbering then you cannot get anything that agrees with the package descriptions in the data sheet.
Note : My mistake I used wrong image I should not have done that, the picture posted in post#16 to show the connection of push button and LED

I have sent e mail for documention of board to seller and just waiting for his reply

- - - Updated - - -

Hi,


Is it asking too much for an error description?

Klaus
you gave one idea to count pulses in post #13

I followed advice and wrote program post #36.

I tried to write complete program but I was struggling so I posted my code for the suggestion

- - - Updated - - -

I would anticipate the LED appearing to be on almost all of the time. Forget copying examples from web sites, work out the program flow yourself for your specific needs. I wrote my first computer program in 1973 and I still start out with a proper specification that caters for all situations then a flow chart to help to break the tasks into manageable routines. Programming should be 99% inspiration and 1% perspiration :smile:

Lets break your program down into small sections to see where it goes wrong:


Brian.

I think the problem with push button so I have decided it to test with encoder (external interrupt)

I will test code in post #31 with encoder and update you result
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top