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.
It is unlikely that the switch is the problem (and easy to check, preferably with a DSO but also a DMM).
However changing things on a whim is NOT a good idea. If you *know* that the switch is faulty then replace the switch with a known good switch; don't introduce another complication such as an encoder.
Can you flash the LED as I suggested?
If you have then move to turning it on when the button is down and off when the button is up?
Have you added the delay after you turn off the LED as suggested by Betwixt in Post #37?
All of these are MUCH simpler to test than making random changes and MUCH more likely to lead to success.
Susan
 

I would anticipate the LED appearing to be on almost all of the time.

Brian.

I am responding on this thread very lately because there is reason and the reason is compiler

When I reinstalled MPLABX IDE the same code is working with same hardware

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 
 
volatile unsigned int Counter;
char Trigger;
 
void main(void) 
{
    
    TRISB0=1;     // encoder as input
	
    TRISB1=1;     // Sensor as input
    TRISD1= 0;    // LED as output
    OPTION_REG=1;  // Set Rising Edge Trigger 
    INTCON = 1;   // Enable The Global Interrupt
    INTE = 1;     // External Interrupt Enable (not INTF)
    GIE=1;
    Counter = 0;  //initial values at start up
    Trigger = 0;
    
    while (1)
    {
        if(Trigger == 1)
        {
             Trigger = 0;
             Counter = 0;
            
             RD1 = 1;  // LED ON
             __delay_ms(1000); // 
             RD1 = 0;  // LED OFF
             __delay_ms(500); 
        }
    }
 
}
 
void interrupt isr(void)
{  
    if(INTF==1)
    {
        INTF = 0;  // Clear interrupt flag
        Counter++;    // add 1 to the Counter
        if(Counter == 30) 
        Trigger = 1;
    } 
}

my another thread is running https://www.edaboard.com/showthread.php?383921-How-to-start-counter-when-sensor-is-activate/page2&p=1648206#post1648206 but I thought It's good to inform here

Thanks a lot for helpful response

- - - Updated - - -

Tidied up a little and with the counting and checking added:

Brian.
so the programming is workin now I am trying to add sensor triggre

The sensor is connected to RB1, an encoder is connected to RB0 and LED is connected to RD1

When the sensor is low stop counting . when a sensor trigger, starts count pulse coming on RB0 pin. after 600 counts from the encoder, LED will turn ON for 500 mSec. If the SENSOR triggers again, the process will repeat.

I made this program

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 Counter;
char Trigger;
 
void interrupt isr(void)
{  
    if(INTF==1)
    {
        INTF = 0;  // Clear interrupt flag
        Counter++;    // add 1 to the Counter
        if(Counter == 600) 
        Trigger = 1;
    } 
}

void main(void) 
{
    
    TRISB0=1;      // encoder as input
	
    TRISB1=1;      // Sensor as input
	
    TRISD1= 0;     // LED as output
	
    OPTION_REG=1;  // Set Rising Edge Trigger 
    INTCON = 1;    // Enable The Global Interrupt
    INTE = 1;      // External Interrupt Enable (not INTF)
    GIE=1;
   
    Counter = 0;   //initial values at start up
    Trigger = 0;
    
    while (1)
    {
      if (RB1 == 0)
	   
	   {

	     if(Trigger == 1)
      
    	  {
             Trigger = 0;
             Counter = 0;            
          }
		  
		  INTE = 0; //Disables the RB0/INT external interrupt
       }
	   
      else if (RB1 == 1)
	   
	   {

	     if(Trigger == 1)
      
    	  {
             Trigger = 0;
             Counter = 0;
            
             RD1 = 1;  // LED ON
             __delay_ms(500); 
             RD1 = 0;  // LED OFF
            
          }
		  
		  INTE = 1; //Enables the RB0/INT external interrupt
       } 
	   
 
    }
}

Note : This code is untested would test when will have time
 

That is poorly structured, do the check for Trigger==1 once then check the RB1 state, it makes the code much simpler. Why do you change the INTE bit?

Brian.
 

Try if this works. For me, it is only working the first time that is it flashes the LED once after 10 counts but the second time when it is triggered it flashed the LED at 8 counts itself. Need to see if it is due to bug created by XC8 Compiler optimization. Will investigate it later when I get more time.

A better way is to use triggerDetect flag set when Trigger is received and then use this flag in ISR to increment the pulseCount and keep the INTE enabled all the time before entering while(1). Try it and let me know what happens.

MPLAB X 5.10, XC8 2.05


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* 
 * File:   main.c
 * Author: Jayanth D
 *
 * Created on 30 April, 2019, 5:58 AM
 */
 
#define _XTAL_FREQ 20000000
 
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
 
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON       // 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)
 
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
 
#define Use_External_Interrupt
 
#ifndef Use_External_Interrupt
    #define Use_Timer_Counter
#endif
 
#define Trigger_Value  1
#define Pulse_Count   10
 
#define Trigger PORTBbits.RB1
#define LED     PORTDbits.RD1
 
#define LED_On  1
#define LED_Off 0
 
typedef struct {
    unsigned char B0:1;
    unsigned char B1:1;
    unsigned char B2:1;
    unsigned char B3:1;
    unsigned char B4:1;
    unsigned char B5:1;
    unsigned char B6:1;
    unsigned char B7:1;    
}BIT_FIELDS_TYPE;
 
BIT_FIELDS_TYPE flags;
 
//#define triggerDetect flags.B0
#define toggleLed       flags.B1
 
unsigned int pulseCount = 0;
 
void __interrupt () _isr_routine (void) {
    #ifdef Use_External_Interrupt        
        if((INTCONbits.INTE) && (INTCONbits.INTF) /*&& (triggerDetect)*/) {
            INTCONbits.INTF = 0;            
            if(++pulseCount >= Pulse_Count) { INTCONbits.INTE = 0; toggleLed = 1; pulseCount = 0; }
        }
    #endif 
        
    #ifdef Use_Timer_Counter
 
    #endif
}
 
int main(int argc, char** argv) {
    
    TRISB = 0x03;
    TRISD = 0x00;
    
    PORTB = 0x00;
    PORTD = 0x00;
    
    __delay_ms(100);
    
    toggleLed = 0;
    
    OPTION_REGbits.INTEDG = 0;
    INTCONbits.INTF = 0;    
    
    INTCONbits.PEIE = 1;
    INTCONbits.GIE = 1;
    
    while(1) {        
        if(Trigger == Trigger_Value) {
            __delay_ms(30);
            if(Trigger == Trigger_Value) {
                //triggerDetect = 1;
                INTCONbits.INTE = 1;                
            }
        }
        
        if(toggleLed) {
            toggleLed = 0;
 
            LED = LED_On;
            __delay_ms(500);
            LED = LED_Off;
        }        
    }            
    
    return (EXIT_SUCCESS);
}

 

Attachments

  • Project1.rar
    104 KB · Views: 53
Last edited:

If you use my code then you can make a little improvement to it that is,

Just turn On the LED in ISR that is in

Code:
if(++pulseCount >= Pulse_Count)

above condition and turn it off in while(1) loop.
 

If you use my code then you can make a little improvement to it that is,

Just turn On the LED in ISR that is in

Code:
if(++pulseCount >= Pulse_Count)
above condition and turn it off in while(1) loop.

Hi Jayanth

I used your code but LED triggered doesn't depend on the sensor output. If a sensor enabled / disabled LED flash continuously
 

Can't help more without knowing what exactly is your sensor? Also, need to know what encoder you are using to help better.
 

Can't help more without knowing what exactly is your sensor? Also, need to know what encoder you are using to help better.

encoder link **broken link removed**

sensor **broken link removed**

- - - Updated - - -

That is poorly structured, do the check for Trigger==1 once then check the RB1 state, it makes the code much simpler. Why do you change the INTE bit?

Brian.

I tried with polling method
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 Counter;
char Trigger;
 
void main(void) 
{
    
    TRISB= 0b00000001;           // encoder as input
    TRISD= 0b00000000;           // LED as output
    
    OPTION_REG = 0b01000000;     // Set Rising Edge Trigger
    INTCON = 1;                  // Enable The Global Interrupt
    
    while (1)
    {
        if(INTF==1)
        {
            
             RD4 = 1;  // LED ON
             __delay_ms(1000); // 
             RD4 = 0;  // LED OFF
             
             INTF = 0;  // Clear interrupt flag
             
        }
    }
        
}

This code work for me when sensor detect object LED get triggres

- - - Updated - - -

That is poorly structured, do the check for Trigger==1 once then check the RB1 state, it makes the code much simpler. Why do you change the INTE bit?

Brian.

What's wrong in following code because LED doesn't flash when 30 counts happen

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 Counter;

char Trigger;
 
void main(void) 
{
    
    TRISB= 0b00000001;     // encoder as input
    TRISD= 0b00000000;    // LED as output
     
    OPTION_REG = 0b01000000; // Set Rising Edge Trigger
    
    INTCON = 1;   // Enable The Global Interrupt
    
    Counter = 0;  //initial values at start up
    Trigger = 0;
    
    while (1)
    {
        if(INTF == 1)
        {
            
            Counter++;    // add 1 to the Counter      
            
             if(Counter == 100) 
                Trigger = 1;
            
            INTF = 0;  // Clear interrupt flag
        }
        
        if(Trigger == 1)
            
        {            
             RD4 = 1;  // LED ON
             __delay_ms(1000); // 
             RD4 = 0;  // LED OFF
             
             Trigger = 0;
             Counter = 0;
             
        }
    }
}
 

Hi,

What's wrong in following code because LED doesn't flash when 30 counts happen
if(Counter == 100)
If this isn´t obvious, then I recommend to start with simpler projects.

Be thankful to all those, who do your job with great patience.

Klaus
 

Hi,
If this isn´t obvious, then I recommend to start with simpler projects.

Be thankful to all those, who do your job with great patience.

Klaus

sorry Made mistake I Apologize

I did copy & paste program from compiler to fotum while testing code

actually value was if(Counter == 30) in program
 

because LED doesn't flash when 30 counts happen

At the following snippet:

Code:
RD4 = 1;  // LED ON
__delay_ms(1000); // 
RD4 = 0;  // LED OFF

It is missing an additional delay:

Code:
__delay_ms(1000); //
 

At the following snippet:

Code:
RD4 = 1;  // LED ON
__delay_ms(1000); // 
RD4 = 0;  // LED OFF

It is missing an additional delay:

Code:
__delay_ms(1000); //

correct but I don't think it's issue of additional delay

Do you see anything wrong in code other then additional delay ?
 

I don't think it's issue of additional delay

I DO think you will not see any LED blinking with the above code unless you have an exceptional vision able to perceive the slightest flicker. Did you at least tried to fix it as suggested ?
 

Go back to the basics - for the moment forget about the sensor or counting pulses etc and just make the LED flash on for (say) 1 second and off for 1 second.
When you know that you have that part working, then start adding back in the rest of the code, starting with have the LED flash when you press a button once, then increase that to needing 5 presses, then change the button for the sensor and so on.
At the moment I'm sensing that you are trying to do everything at once and have no idea what is going wrong. Start with something very basic and then build up from a 'known good' working base.
Susan
 

Okay, I have fixed my previous XC8 code which I posted and now it is working fine. It was not an issue with my code because the same code ported to mikroC works fine (tested on Proteus). The issue is a bug I suspect in XC8 v2.05 and the bug is I guess the INTE bit not turning Off inside the ISR (in my code).

I added

Code:
pulseCount = 0;

in Trigger detect code to reset the pulseCount when a new trigger is received and now the code works fine.

Here is the latest code which I have tested on Proteus. test it and reply.
Check the Schematic PDF inside. Your Trigger and Encoder connections should be similar that is with the pull-ups and pull-downs.

Also find the complete project attached (Proteus SImulation Video included).

Are you trying to flash the LED once when the rpm or rps of the motor connected to encoder exceeds a certain value?


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* 
 * File:   main.c
 * Author: Jayanth D
 *
 * Created on 30 April, 2019, 5:58 AM
 */
 
#define _XTAL_FREQ 20000000
 
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
 
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON       // 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)
 
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
 
#define Use_External_Interrupt
 
#ifndef Use_External_Interrupt
    #define Use_Timer_Counter
#endif
 
#define Trigger_Value  1
#define Pulse_Count   10
 
#define Trigger PORTBbits.RB1
#define LED     PORTDbits.RD1
 
#define LED_On  1
#define LED_Off 0
 
typedef struct {
    unsigned char B0:1;
    unsigned char B1:1;
    unsigned char B2:1;
    unsigned char B3:1;
    unsigned char B4:1;
    unsigned char B5:1;
    unsigned char B6:1;
    unsigned char B7:1;    
}BIT_FIELDS_TYPE;
 
BIT_FIELDS_TYPE flags;
 
#define turnOffLED flags.B1
 
unsigned int pulseCount = 0;
 
void __interrupt () _isr_routine (void) {
    #ifdef Use_External_Interrupt        
        if((INTCONbits.INTE) && (INTCONbits.INTF)) {
            INTCONbits.INTF = 0;            
            if(++pulseCount >= Pulse_Count) { INTCONbits.INTE = 0; turnOffLED = 1; pulseCount = 0; LED = LED_On; }
        }
    #endif 
        
    #ifdef Use_Timer_Counter
 
    #endif
}
 
int main(int argc, char** argv) {
    
    TRISB = 0x03;
    TRISD = 0x00;
    
    PORTB = 0x00;
    PORTD = 0x00;
    
    __delay_ms(100);
    
    turnOffLED = 0;
    
    OPTION_REGbits.INTEDG = 0;
    INTCONbits.INTF = 0;
    INTCONbits.INTE = 0;    
    
    INTCONbits.PEIE = 1;
    INTCONbits.GIE = 1;
    
    while(1) {        
        if(Trigger == Trigger_Value) {
            __delay_ms(30);
            if(Trigger == Trigger_Value) {                
                pulseCount = 0;
                
                if(INTCONbits.INTE == 0)
                    INTCONbits.INTE = 1;                                
            }
        }
        
        if(turnOffLED) {            
            __delay_ms(500);
            turnOffLED = 0;
            LED = LED_Off;
        }        
    }            
    
    return (EXIT_SUCCESS);
}

 

Attachments

  • Project1_Rev_1.1.rar
    1.8 MB · Views: 51
Last edited:

Most honestly

your comments from post #48
What's wrong in following code because LED doesn't flash when 30 counts happen


I didn't see any reason not to work the code you posted on #48 and it must LED flash once a time every 30 switch press

Code:
if(Counter == 30) 
                Trigger = 1;

If it isn't work something wrong with your connection so check around RB0 and micro switch

However i would suggest you to change the crystal to 4MHz and load capacitor since Honorable PIC16F877A working very relabel at 4MHz for beginners

and following code at 4MHz crystal

Code:
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)

Code:
#define _XTAL_FREQ 4000000 //Specify the XTAL crystal FREQ

if you do not use debouching solution that others are pointed out then you can use at least software debouching solution

I would suggest to use few delay


Code:
 while (1)
    {
        if(INTF == 1)
        {
[COLOR=#ff0000]             __delay_ms(10); // [/COLOR]
            Counter++;    // add 1 to the Counter      
            
             if(Counter == 10) 
                Trigger = 1;
 
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top