PIC16F877A - Object Detection and Rejection - Timer Interrupt

Thread Starter

daljeet795

Joined Jul 2, 2018
295
If you are looking to learn C, there is the trial version of MikroC and the instruction manual PDF shows all the examples of code.
I only use assembler, but have used the mikroC manual in order to convert and decipher the different instructions to assembler.
Max.
I am not an expert but I have enough knowledge of c language

I have posted c program in post #17 I am looking help to improve it
 

John P

Joined Oct 14, 2008
1,890
Do you really want to run the timer off an auxiliary crystal? It would be simpler to use the processor's main oscillator. Anyway, the line T1OSCEN = 0; shuts it off, and you never turn it on again.

The 3 lines controlling TRISC don't seem right. You're setting RC0 as an input, then in the while(1) loop you're saying the LED is connected to it. And you're setting TRISC1 twice, once saying it controls RC1 and then again saying it controls RC2.

You're clearing the overflow flag TMR1IF outside the loop, when you should be clearing it inside the loop. And there is no point in setting TMR1H and TMR1L before the loop begins, as that count will be loaded once and then never again. When the loop runs, the count will go from 0 to 65535. But the oscillator isn't running and the overflow flag is always set anyway, so maybe this doesn't matter.

You haven't said what the frequency of the crystal is for the non-functioning auxiliary oscillator, so maybe the repitition rate of TMR1 is reasonable to flash a light, if the output bit were really an output and the overflow flag wasn't always set. If you used the main oscillator, the rate would be about 30Hz, which wouldn't be easy to see, especially with a 100msec delay being 3 times longer than the period. You could fix this by using the prescaler, if you set it to divide by 8. Then you'd have roughly equal on and off times at a 4/sec rate. But why not use a counter in the loop, and turn the LED on when the count is even and off when it's odd?
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
Do you really want to run the timer off an auxiliary crystal? It would be simpler to use the processor's main oscillator.
I have rewritten the code, when I was testing code with encoder, LED should be turn on but It doesn't happen, I was moving shaft of encoder manually
C:
// 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 2000000 //Specify the XTAL crystal FREQ

#include <xc.h>

void main(void)
{
    PORTD = 0;
    TRISC0=1;     // Make RC0 pin as input encoder
    TRISC1= 1;    // Make RC1 pin as input sensor
    TRISD4= 0;    // Make RD4 pin as output

    TMR1ON = 0; // Stops Timer1
    TMR1CS = 1; // Internal clock
    T1SYNC = 1; // Do not synchronize external
    T1OSCEN = 1 ; // Oscillator is enabled
    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)
    {
      RD4 = 1;  // LED on
      __delay_ms(1000);
     RD4 = 0;  // LED off
    }
}
}
 

LesJones

Joined Jan 8, 2017
3,127
Will it be any help if I change my program to use your new preset value of 0x82FF and move the output pulse to PORTD 4 and post the .HEX file to load into your PIC16F877A using a PICKIT 2 or PICKIT3 ? This would prove that your hardware is working.

Les.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
Will it be any help if I change my program to use your new preset value of 0x82FF and move the output pulse to PORTD 4 and post the .HEX file to load into your PIC16F877A using a PICKIT 2 or PICKIT3 ? This would prove that your hardware is working.

Les.
Yes It would be your big help

I did one experiment with conveyor machine. I connected encoder with the motor shaft and I was connecting one LED at the output of encoder

when conveyor was running very slowly LED was blinking continuously. so I think there is no doubt that conveyor is faulty

later I tested following code with PIC controller

Count the 40000 pulses of encoder and then turn on LED 1000ms

I used External interrupt to count 40000 pulses

the conveyor was running and LED was staying turn on for forever but LED should be turn on for 1000 ms as written in program
C:
// 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;

charTrigger;

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

        }
    }
}

void interrupt isr(void)
{
    if(INTF==1)
   {
      INTF =0;// Clear interrupt flag
      Counter++;// add 1 to the Counter
       if(Counter==40000)
           Trigger=1;
    }
}
 
Last edited:

spinnaker

Joined Oct 29, 2009
7,835
Yes It would be your big help

I did one experiment with conveyor machine. I connected encoder with the motor shaft and I was connecting one LED at the output of encoder

when conveyor was running very slowly LED was blinking continuously. so I think there is no doubt that conveyor is faulty

later I tested following code with PIC controller

Count the 40000 pulses of encoder and then turn on LED 1000ms

I used External interrupt to count 40000 pulses
C:
// 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;

charTrigger;

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

        }
    }
}

void interrupt isr(void)
{
    if(INTF==1)
   {
      INTF =0;// Clear interrupt flag
      Counter++;// add 1 to the Counter
       if(Counter==40000)
           Trigger=1;
    }
}
the conveyor was running and LED was staying turn on for forever
Staying on? Or continuing to blink? Trigger never gets set to zero once it is set initially so the LED will continue to blink once the external interrupt occurs 40000 times.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
Staying on? Or continuing to blink? Trigger never gets set to zero once it is set initially so the LED will continue to blink once the external interrupt occurs 40000 times.
LED was staying ON It was not blinking continuously I don't understand what's wrong happening
 

spinnaker

Joined Oct 29, 2009
7,835
LED was staying ON It was not blinking continuously I don't understand what's wrong happening

Do you have test equipment? Use your debugger and figure it out.


Remove the if statement block for if(Trigger == 1). Just get the LED to do nothing but blink.

You have to have something wired wrong unless on that chip RD1 is on by default. You could also get RD1=0 right after you set it as an output to eliminate the possibility of that.
 

LesJones

Joined Jan 8, 2017
3,127
Here are two versions of the hex file. TM1divide03.hex uses port C bit 0 as the encoder input and port C bit 1 as the sensor input. Port C bit 1 has a 10K pullup resistor to +5 volts and a push button to ground to simulate the sensor input. TM1divide03a.hex is the same except it runs continuously without the push button. The pulse output is on port D bit 4 The preload value is 0x82FF the same as your program which counts 32001 pulses. I have just noticed that you have used port B bit 0 as the encoder input. If is is difficult for you to wire the encoder input to port C bit 0 instead of port B bit 0 I can modify the program. Let me know if you would like this modified version creating. The zip file contains both .hex files.
EDIT. I've just realised that PORTC,0 is the direct input to TM1 counter so it can't just be swapped over. I was confused by you making PORTB,0 as an input.

Les.
 

Attachments

Last edited:

LesJones

Joined Jan 8, 2017
3,127
There are problems with the schematic in post #32.
1. You are feeding a 24 volt signal from the encoder directly into pin 15 of the PIC16F877A. You will have probably destroyed the PIC.
2 You have a push button shorting out the output of the sensor. Pressing the push button may damage the output sensor unit. Can you give some details of the sensor unit ?

The schematic in post #33 should work. (R4 and R8 do not serve any purpose bus should not stop it working.) Verify that the inputs signals to pins 15 and 16 swing between 0 volts and about +4.5 volts. (They will not reach + 5 volts due to R4 and R8)

I suggest using the 3a code first as this does not need the sensor input signal. It will be counting input pulses as soon as the citcuit is powered on. When the counter overflows PORTD 4 will go high for 100 mS. At the end of the pulse it will start counting again. (I was testing it by feeding a 100 Khz signal in from a signal generator to simulate the encoder input. This displayed a 100 mS pulse followed by a gap of 320 mS on my oscilloscope.) You could just drive the encoder with an electric drill. NOTE the output from the encoder could be the specified value or half of that value or a quarter of that value.(I think from memory your encoder was specified as 5000 pulses per rev so you may get 2500 or 1250 pulses per rev.)

Les.
 
Last edited:

Thread Starter

daljeet795

Joined Jul 2, 2018
295
There are problems with the schematic in post #32.
1. You are feeding a 24 volt signal from the encoder directly into pin 15 of the PIC16F877A. You will have probably destroyed the PIC.
2 You have a push button shorting out the output of the sensor. Pressing the push button may damage the output sensor unit. Can you give some details of the sensor unit ?

The schematic in post #33 should work. (R4 and R8 do not serve any purpose bus should not stop it working.) Verify that the inputs signals to pins 15 and 16 swing between 0 volts and about +4.5 volts. (They will not reach + 5 volts due to R4 and R8)Les.
I am doing connection according to the schematic in post #33 and I have removed 1K resistor

I suggest using the 3a code first as this does not need the sensor input signal. It will be counting input pulses as soon as the citcuit is powered on.
Les.
I don't understand connection in post #31. I don't know exactly which you pins are using for input/output devices

can you give some information of pins used in your program
 

LesJones

Joined Jan 8, 2017
3,127
This is the schematic of my test circuit.
TM1divide.png
The transistor Q2 just converts the signal generator output to 5 volt square wave. This simulates the encoder output. It goes to pin 15 of the PIC which is the input clock to TM1 counter/timer. The push button simulates the signal from the sensor and this goes to pin 16 of the PIC (PORTC bit 1) The output pulse comes out of the PIC on pin 27 (PORTD bit 4). This is connected to an LED via a 270 ohm current limiting resistor. You would also connect your oscilloscope to that pin for testing. If you are using version 3 of the code the counting starts when the button is released. (The low to high transition.) Version 3a of the code does not use the pulse from the push button. It just counts from the end of the output pulse.
The programming connector connects to a PICKIT 2 or 3 so the PIC16F877 can be programmed without removing it from the board.
Les.
 

LesJones

Joined Jan 8, 2017
3,127
With version 3a of the code this is the output signal on pin 27 of the PIC with the simulated encoder signal was set to 100 Khz

SDS00001.png

If your encoder is giving 5000 pulses per rev then it would need 6.4 revolutions to produce 32000 pulses.

Les.
 

MaxHeadRoom

Joined Jul 18, 2013
22,823
In light of what you have told me off line, the fact that there can be up to 10 products on the conveyor between reject sensor and reject actuator, means that any qty up to 10 could be candidates for rejection, based on your present program I believe that this only works at present for one item to be tracked from detect to reject, if so, another method is required to record the each and every rejected items.
Max.
 

LesJones

Joined Jan 8, 2017
3,127
My schematic in post #36 is functionally identical to the one in your post #33. the only difference is the source of the signals.
From Max's comments in post #39 the simple requirement you described will not do what you want. (It will only work with one object between sensor and the ejection point.) You would need to be running 10 counters. This would have to be done in software and I suspect the PIC16F877A would not be fast enough as you want to use an encoder with excessively high resolution. It is better when requesting help to give the FULL story of what you are trying to do from the start rather than letting us solve the wrong problem. We still don't know how fast you conveyor is running so we don't know how much time there is to do the calculations.

Les.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
In light of what you have told me off line, the fact that there can be up to 10 products on the conveyor between reject sensor and reject actuator, means that any qty up to 10 could be candidates for rejection, based on your present program I believe that this only works at present for one item to be tracked from detect to reject, if so, another method is required to record the each and every rejected items.
Max.
The present program is based on the encoder pulses and I asked you program logic based on sensor because you said it's possible with two sensor's if detection and rejection have fixed distance

if one product reject on the conveyor then we can think about the more
 
Last edited:

Thread Starter

daljeet795

Joined Jul 2, 2018
295
My schematic in post #36 is functionally identical to the one in your post #33. the only difference is the source of the signals.
From Max's comments in post #39 the simple requirement you described will not do what you want.

Les.
my first priority to count the pulses of the encoder when it completes count then triggered led

I was trying to make test a program where MCU count 40000 pulses and then triggered led

Just tested code in #24 with conveyor led doesn't work according to program It was staying on

I just wanted your program to test encoder on a conveyor because mine is not working
 
Last edited:
Top