PIC16F877A Timer Interrupt - Object Detection and Rejection

Discussion in 'Embedded Systems and Microcontrollers' started by daljeet795, Mar 24, 2019.

  1. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    Well, you are coding before you have decided on the design (shift register, counter, etc.) How can that possibly work? If you are to be successful with this thing, you need to step back, add to what you have shown in #156 to indicate how you will track bad objects as they move along the belt. The code you show here only implements the encoder divider. What then?

    But you probably want to see something -anything!- work at this point so here we go.
    First, your code doesn't compile. If you have C syntax errors, hit the books. Fix that stuff first. That includes compiler warnings too. Warnings are errors that don't happen until run-time.
    Initialize ALL of your I/O pins, not just the ones you are using. Set any unconnected pins to output 0. Leaving uninitialized pins leaves you open to all kinds of problems.
    Next, you have a delay inside your interrupt routine. That can't work. While you are merrily burning CPU cycles to show your LED, you will miss all of the encoder counts during that time. Interrupt routines in a PIC must be kept short and avoid doing I/O inside an interrupt routine. I show one way to beat that below.
    You don't say what the code is supposed to do. How are we to know when it does or doesn't do it?

    The code below actually compiles (XC8 Ver 2.00) and toggles the LED on each interrupt. Says me, I haven't tested it. Of interest is how I used a flag - gotIRQ - to indicate when an interrupt happens. The 'while' loop in main waits for this signal then complements the LED to flash it at 1/2 the interrupt rate. That's enough to prove out the timer/compare stuff. You also can experiment with different settings for the compare registers.

    A final concern. I see that you have BOTH encoder inputs connected in this one. That's different. If what you really need is quadrature encoding (both directions of the belt) then this implementation won't work.

    Good luck!
    Code (C):
    1.  
    2. // Daljeet: always describe what a program is supposed to do.  That way,
    3. // when it doesn't, you at least know what to look at
    4.  
    5. // This program uses TIMER1/CCP1 as a period counter that counts
    6. // encoder pulses on T1CKI.  When the count is equal to the value in CCP1RH/L,
    7. // it toggles the LED on RD4
    8.  
    9. // PIC16F877A Configuration Bit Settings
    10. // 'C' source line config statements
    11. // CONFIG
    12. #pragma config FOSC = XT  // Oscillator Selection bits (XT oscillator)
    13. #pragma config WDTE = OFF  // Watchdog Timer Enable bit (WDT disabled)
    14. #pragma config PWRTE = ON  // Power-up Timer Enable bit (PWRT enabled)
    15. #pragma config BOREN = OFF  // Brown-out Reset Enable bit (BOR disabled)
    16. #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)
    17. #pragma config CPD = OFF  // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
    18. #pragma config WRT = OFF  // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
    19. #pragma config CP = OFF  // Flash Program Memory Code Protection bit (Code protection off)
    20. // #pragma config statements should precede project file includes.
    21. // Use project enums instead of #define for ON and OFF.
    22. #include <xc.h>
    23. __bit gotIRQ;  // signals main that an interrupt
    24.  
    25. void main(void)
    26. {
    27.   //Make all PORTD pins low  <- No, it doesn't
    28.   PORTA = 0b00000000;
    29.   PORTB = 0b00000000;
    30.   PORTC = 0b00000000;
    31.   PORTD = 0b00000000;
    32. // Configured PORTD as Output
    33.   TRISD4 = 0;
    34. // Connect the encoder to RC0 &  RC1 sensor inputs
    35.   TRISC = 3;
    36.    
    37. // How about the REST of the IO pins??????  
    38.    
    39.   RD4 = 0;  // init LED
    40. //CCP1 MODULE INITIALIZATION
    41.   T1CON = 0b00000011 ;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
    42.   CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value
    43.   CCPR1H = 0x03;
    44.   CCPR1L = 0x1B;
    45.   CCP1IF = 0;
    46.  
    47.   INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt
    48.   CCP1IE = 1;  //Enabled CCP1 interrupt
    49.   while(1){
    50.   if (gotIRQ)
    51.   RD4 = ~RD4;  // toggle LED each interrupt
    52.   gotIRQ=0;  // acknowledge the interrupt
    53.   }
    54. }
    55. void __interrupt() IRQ(void){
    56.   // CCP1 Interrupt
    57.   if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
    58.   {
    59.   CCP1IF = 0;
    60.   gotIRQ = 1;  // 'Signal' main that an interrupt happened
    61.   // NEVER delay inside an interrupt routine  
    62.   }
    63. }
    64.  
    65.  
     
  2. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    @JohnInTX so we are doing rejection based on the distance. This diagram shows the 10 slot's with pulses and distance.
    upload_2019-5-13_15-40-11.png

    I want to know how rejection will done with shift register logic.

    Manually I have everything pulses distance, and 10 slot's But still I don't understand how to implement logic into the program?
     
    Last edited: May 13, 2019 at 7:17 AM
  3. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    All of that has been pretty thoroughly covered already.

    The PLC example demonstrates the concept. In #102, I show another way to think about the shift register solution and show how to use a C integer to implement the shift register itself and how to add bits at the sensor and detect ‘1’ bits at the kicker.

    Just above I show how to divide your encoder down to generate one interrupt per segment on the belt to control when you sample the sensor and look at the output of the shift register to control the kicker.

    What, specifically, are you having trouble with?

    EDIT:
    You really have all of the pieces:
    • A belt divided into segments, one object per segment
    • An interrupt that indicates when the belt has traveled one segment length and that it is time to make some decisions.
    • A 'signal' from interrupt to main to let main know when each segment has passed
    • A shift register that assigns one bit to each belt segment. That bit indicates whether or not the object in that segment is GOOD or BAD.
    • A sensor at the beginning that indicates GOOD/BAD i.e. whether the current segment under the belt should actuate the kicker when that segment has moved to the end.
    • A kicker at the end that can remove an object when it is actuated.
    Now it's time to put them together.

    If you haven't yet done it, make a simple sketch on paper of everything and run it in your head. Write some pseudo-code (simplified C that doesn't care about syntax):
    Code (C):
    1. unsigned long int ShiftRegister;  // a 32 bit integer will handle up to 32 belt segments.  Should be enough.
    2.  
    3. interrupt(){
    4. signal_one_segment_has_passed();
    5. }
    6.  
    7. main()
    8. {
    9.   initialize();
    10.  
    11.   while(1){
    12.   wait_for_interrupt_signal();
    13.   clear_interrupt_signal();  // acknowledge signal for next time
    14.  
    15. // sample object at sensor
    16.   if(sensor == BAD)
    17.     put_1_in_shift_register_input();
    18.   else
    19.    put_0_in_shift_register_input();
    20.  
    21. // The end of the shift register shows if the object that WAS under the sensor N interrupts ago is good or bad
    22.   if(end_of_shift_register_bit == 1)
    23.    actuate_kicker();
    24.  
    25. // this belt segment is done, store new sensor reading, discard used kicker bit
    26. shift_one_bit();
    27.  
    28.   }//while
    29. }//main
    That's pretty much the whole thing.. or IS it? There is no START/STOP function to turn it on and off. But from our pseudo-code, we see that we are just waiting between interrupts so that would be a good time to look at that.

    You haven't really defined how the sensor operates or how to actuate the kicker so give that some thought, too.

    Most important is to have all of the big pieces we know about hooked up and be able to trace the basic operation on paper. As you do that, questions about details like start/stop, kicker etc. will arise. Drill down into each of those until you have them figured out. Add those details to your pseudo-code until you don't have any more questions about the details.

    Then, and ONLY then, does it make sense to start coding it. That's really how it's done.

    Have fun!
     
    Last edited: May 13, 2019 at 9:39 AM
    daljeet795 likes this.
  4. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    hi @JohnInTX

    Your approach depends on the spacing I can't find solutions on the paper for rejection that doesn't depend on spacing.

    My main problem is the spacing between each object what will happen if the gap between two objects will vary?

    upload_2019-5-13_19-55-41.png
     
    Last edited: May 13, 2019 at 11:04 AM
  5. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    Try increasing the resolution of the system by using smaller segments on the belt and increasing the number of bits in the shift register by a corresponding amount. You may find that your objects span more than one segment meaning more than one consecutive bits per object but that doesn’t matter. As an exercise, consider what it would do with an infinite number of segments and bits. You would have an exact linear image of the objects on the belt. But that would be overkill considering that things like the kicker and sensor have limited resolution e.g. if the kicker blows everything within 2” off the belt, it’s probably pointless to have much more resolution in the system.
     
  6. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    @JohnInTX
    Perhaps I am missing shift register understanding
    Code (C):
    1. #include<stdio.h>
    2.  
    3. int main(void)
    4. {
    5.        int a = 0000 0000 0001;
    6.        printf("\nNumber is Shifted By 1 Bit : %d",a << 1);
    7.  
    8.        printf("\nNumber is Shifted By 2 Bits : %d",a << 2);
    9.  
    10.        printf("\nNumber is Shifted By 3 Bits : %d",a << 3);
    11.  
    12.        printf("\nNumber is Shifted By 4 Bits : %d",a << 4);
    13.  
    14.        printf("\nNumber is Shifted By 5 Bits : %d",a << 5);
    15.  
    16.        printf("\nNumber is Shifted By 6 Bits : %d",a << 6);
    17.  
    18.        printf("\nNumber is Shifted By 7 Bits : %d",a << 7);
    19.  
    20.        printf("\nNumber is Shifted By 8 Bits : %d",a << 8);
    21.    
    22.        printf("\nNumber is Shifted By 9 Bits : %d",a << 9);
    23.  
    24.        printf("\nNumber is Shifted By 10 Bits : %d",a << 10);
    25.  
    26.        return(0);
    27. }
    Number is Shifted By 1 Bit : 2 gives 0000 0000 0000 0010

    Number is Shifted By 2 Bits : 4 gives 0000 0000 0000 0100

    Number is Shifted By 3 Bits : 8 gives 0000 0000 0000 1000

    Number is Shifted By 4 Bits : 16 gives 0000 0000 0001 0000

    Number is Shifted By 5 Bits : 32 gives 0000 0000 00100000

    Number is Shifted By 6 Bits : 64 gives 0000 0000 0100 0000

    Number is Shifted By 7 Bits : 128 gives 0000 0000 1000 0000

    Number is Shifted By 8 Bits : 256 gives 0000 0001 0000 0000

    Number is Shifted By 9 Bits : 512 gives 0000 0010 0000 0000

    Number is Shifted By 10 Bits : 1024 gives 0000 0100 0000 0000

    How to set input zero if object is good and how to set input one if object is good ?
     
  7. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    In the code I posted in #102, for the sensor, I show how to use a bit wise OR in line 8 to set the LSbit in the shift register when the object is bad. In line 9 I show how to use a bit wise AND to test any bit within the shift register for a ‘1’. That’s for the kicker.
     
    Last edited: May 14, 2019 at 9:02 AM
    daljeet795 likes this.
  8. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    @JohnInTX I am understanding something now
    Code (C):
    1. unsigned int ShiftReg = 0; //  Init to 0
    2. if (3600 pulses)
    3. {
    4.   reload_timer(3600);
    5.   ShiftReg << 1;  // shift the integer shift register one bit left. LSbit = 0 after shift
    6.   if (object_is_bad)
    7.      ShiftReg |= 0x0001;  // bad object, put 1 in LSbit
    8.   if(ShiftReg & 0x0400) // and if the #10 bit after shift is '1', kick it
    9.     kick_the_object();
    10. }
    11.  
    I didn't understand following statment you are performing AND logic
    Code (C):
    1.  
    2. if(ShiftReg & 0x0400) // and if the #10 bit after shift is '1', kick it
    3.     kick_the_object();
    4.  
    assume ShiftReg value is 0000 0001 0000 0000
    0000 0001 0000 0000 = ShiftReg
    0000 0100 0000 0000 = 0x 0400

    0000 0101 0000 0000 = result

    What's the logic behind that statement. Are you just checking 11 bit only if it's high kick object?
     
    Last edited: May 14, 2019 at 2:48 PM
  9. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    Last edited: May 14, 2019 at 2:53 PM
  10. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    4,489
    1,664
    First, that’s the idea. That is exactly what JohnInTx had in mind.

    Second, how did you get that results? The operation is a bit wise AND (&), which results in a 1 if both corresponding bits in the operands are 1. In your example, here are no bit positions that have a 1 in the corresponding bit positions of the two operands. The result of your example is 0x0!

    You performed a bit wise OR between the two operands. A bit wise or results in a 1 if any bit in either of the corresponding operands is a 1.
     
    daljeet795 and JohnInTX like this.
  11. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    You are using the OR function. For AND, both bits in a corresponding position must be 1 for the value to be non-zero:

    0000 0001 0000 0000 = ShiftReg AND
    0000 0100 0000 0000 = 0x 0400
    --------------------------------
    0000 0000 0000 0000 = 0 (FALSE)

    0000 0101 0000 0000 = ShiftReg AND
    0000 0100 0000 0000 = 0x 0400
    --------------------------------
    0000 0100 0000 0000 = not 0 (TRUE)

    So you set your mask (the 0x4000) with one (and only one) bit set. When the shift register shifts left enough times to bring the 'BAD' bit (1) under the mask, the result of the AND is TRUE and you turn on the kicker. GOOD/BAD bits (0/1) are entered on the right end of the shift register. The shift register is shifted left one time per belt segment.

    Using the AND mask as shown allows you to select which bit in the shift register operates the kicker. Set that mask value to match the length of the belt i.e. if there are 24 segments defined on the belt (by the encoder / divider) you set the mask to select the 24th bit in the shift register.

    Why are you thinking about changing PICs? Personally, I don't like the 16F877 (or any midrange PIC) so I'm OK with it. But as long as you are thinking about a change, look up one that has the quadrature encoder module built in.

    dangit.. @djsfantasi beat me to it again..:p

    EDIT: You can experiment with the shift register stuff using the MPLABX simulator. Write your routines and check them out there. No hardware, no muss no fuss.
     
    daljeet795 likes this.
  12. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    I think The PIC16f877A is not enough fast to catch all the valid encoder states, If I use PIC16F877A, I do not get a rejection at the full-speed on the conveyor.
    Rejection only happen at the 1/3 speed of conveyor belt
     
    Last edited: May 15, 2019 at 5:14 AM
  13. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    @JohnInTX This was your idea
    Code (Text):
    1. unsigned int ShiftReg = 0; //  Init to 0
    2. if (3600 pulses)
    3. {
    4.   reload_timer(3600);
    5.   ShiftReg << 1;  // shift the integer shift register one bit left. LSbit = 0 after shift
    6.   if (object_is_bad)
    7.      ShiftReg |= 0x0001;  // bad object, put 1 in LSbit
    8.   if(ShiftReg & 0x0400) // and if the #10 bit after shift is '1', kick it
    9.     kick_the_object();
    10. }
    I understand the idea now but having a problem to write code. I have written following code to follow the idea
    Code (C):
    1. #include <xc.h>
    2.  
    3. #define _XTAL_FREQ 20000000
    4.  
    5. #pragma config FOSC = HS
    6. #pragma config WDTE = OFF
    7. #pragma config PWRTE = OFF
    8. #pragma config BOREN = ON
    9. #pragma config LVP = OFF
    10. #pragma config CPD = OFF
    11. #pragma config WRT = OFF
    12. #pragma config CP = OFF
    13.  
    14. #define ENCODER RC0
    15. #define SENSOR RB1
    16. #define KICKER RD4
    17.  
    18. void main(void)
    19. {
    20.  
    21.     unsigned int ShiftReg = 0; //  Init to 0
    22.  
    23.     INTCON = 0; // No interrupts
    24.     PORTC = 0b00000000; //Set all Pin to Low
    25.  
    26.     TRISC0 = 1; // RC0 Eencoder Pin
    27.     TRISC1 = 1; // RC1 Sensor Pin
    28.     TRISD0 = 0; // RD0 Kicker Pin
    29.     TMR1H = 0xF7;        // 65536- 2165 = 63,371 is eual to 0xF78B
    30.     TMR1L = 0x8B;
    31.  
    32.     TMR1ON  =  0;   // Stops Timer1
    33.     TMR1CS =  1;   // Internal clock
    34.     T1SYNC =  0;   // Synchronize external clock input
    35.     T1OSCEN =  0;   // Oscillator is shut-off
    36.     T1CKPS0 =  0;   //  1:1 prescale value
    37.     T1CKPS1 =  0;
    38.  
    39.     TMR1IE = 1;      //Enable timer interrupt bit
    40.     GIE =  1;         //Enable Global Interrupt
    41.     PEIE = 1;        //Enable the Peripheral Interrupt
    42.  
    43.     TMR1ON = 1; //Start Timer1
    44.     while(1)
    45.    {
    46.         ShiftReg << 1;         // shift the integer shift register one bit left. LSbit = 0 after shift
    47.         if (SENSOR == 1)
    48.         ShiftReg |= 0x0001;    // bad object, put 1 in LSbit
    49.  
    50.         if(ShiftReg & 0x0400)  // and if the #10 bit after shift is '1', kick it
    51.             KICKER = 1;        // KICKER ON
    52.             __delay_ms(200);
    53.             KICKER = 0;        // KICKER OFF
    54.  
    55.     }
    56. }
    57.  
    58. void interrupt timer_isr()
    59. {
    60.   if(TMR1IF == 1)
    61.   {
    62.     TMR1IF  =  0;            // Clear timer interrupt flag
    63.     TMR1ON = 0;            // stop timer
    64.     TMR1H  = 0xF7 ;        // High byte F7
    65.     TMR1L  = 0x8B;         // Low Byte 8B
    66.   }
    67. }
    Does it follow your logic?
     
    Last edited: May 15, 2019 at 5:08 AM
  14. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    First, congratulations on the success so far. That's progress.
    Operating the 10 bit shift register looks OK. The rest not so much.
    The timer isn't what I was thinking. In #150 and #159 I introduce the idea of using TIMER1/CCP1 to prescale your encoder and automatically reset the timer. I said you will lose counts on the encoder if you stop and reload the timer. Use the COMPARE function like we discussed.

    Well, the first place I'd look is that 200msec delay in your interrupt routine. In #161 I said
    and yet there is a delay in the interrupt routine. Blocking delays like that will cripple your program. And never, EVER put any kind of delay inside an interrupt routine, especially when you only have one. Interrupt service routines must be short and tight. Look at the code in #161 to see how to coordinate interrupts and main routines.

    Logically, you don't want to control the kicker with any kind of fixed time, right? We all agreed that this was a distance-based system that kept track of everything based on the position of objects on the belt. Using time to determine when to kick an object was rejected because of the difficulty of keeping up with different belt speeds, yes? Even without the delay issue if you turn on the kicker for a fixed time, that doesn't work well for different belt speeds. A timed puff that works at low speeds may blow off multiple objects at high speeds. As a first order solution, just run the air-jet while there is a '1' output from the shift register and turn it off when there is a '0'. That will handle varying belt speeds and the cases where you have differently spaced objects.

    You mentioned a faster processor. In #150, I examined some of that. A better processor may be a good thing but it won't help here. A 120MHz PIC32 will also fail to keep up with the system when it hits that same 200ms delay. Get rid of that first.
     
    Last edited: May 15, 2019 at 9:04 AM
    daljeet795 likes this.
  15. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    @JohnInTX Thank's Thanks a lot, everybody for your contribution
    I have modified the previous program. I hope it would better than previous
    Code (C):
    1.  
    2. #include <xc.h>
    3.  
    4. #pragma config FOSC = XT  // Oscillator Selection bits (XT oscillator)
    5. #pragma config WDTE = OFF  // Watchdog Timer Enable bit (WDT disabled)
    6. #pragma config PWRTE = ON  // Power-up Timer Enable bit (PWRT enabled)
    7. #pragma config BOREN = OFF  // Brown-out Reset Enable bit (BOR disabled)
    8. #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)
    9. #pragma config CPD = OFF  // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
    10. #pragma config WRT = OFF  // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
    11. #pragma config CP = OFF  // Flash Program Memory Code Protection bit (Code protection off)
    12. // #pragma config statements should precede project file includes.
    13. // Use project enums instead of #define for ON and OFF.
    14.  
    15. #define ENCODER RC0
    16. #define SENSOR  RC1
    17. #define KICKER  RD0
    18. void main(void)
    19. {
    20.  
    21.     unsigned int ShiftReg = 0; //  Init to 0
    22.     INTCON = 0; // No interrupts
    23.  
    24.     PORTC = 0b00000000; //Set all Pin to Low
    25.     TRISC0 = 1; // RC0 Eencoder Pin
    26.     TRISC1 = 1; // RC1 Sensor Pin
    27.     TRISD0 = 0; // RD0 Kicker Pin
    28.  
    29.  
    30.     //CCP1 MODULE INITIALIZATION
    31.     T1CON = 0b00000011 ;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
    32.     CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value
    33.  
    34.     // 65536- 2165 = 63,371 is eual to 0xF78B
    35.     CCPR1H = 0xF7;
    36.     CCPR1L = 0x8B;
    37.     CCP1IF = 0;
    38.     INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt
    39.     CCP1IE = 1;  //Enabled CCP1 interrupt
    40.  
    41.   while(1)
    42.   {
    43.         ShiftReg << 1;         // shift the integer shift register one bit left. LSbit = 0 after shift
    44.         if (SENSOR == 1)
    45.         ShiftReg |= 0x0001;    // bad object, put 1 in LSbit
    46.         if(ShiftReg & 0x0400)  // and if the #10 bit after shift is '1', kick it
    47.             KICKER =~ KICKER ;    
    48.   }
    49. }
    50.  
    51. void __interrupt() IRQ(void){
    52.   // CCP1 Interrupt
    53.   if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
    54.   {
    55.   CCP1IF = 0;
    56.  
    57.   }
    58. }
    Okay, I will find the solution that doesn't need time.

    EDIT: I haven't tested code on the board
     
  16. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    4,489
    1,664
    Your code ALWAYS shifts the register to the left one bit. I think you only should shift it when the belt has moved one position. "while (1)" will excecute many times while the belt only moves a little bit. The problem here should be obvious. When the actual object has moved one position, you will have shifted its corresponding bit out of the shift register.

    I've lost where you are actually, but when reading the encoder, you only want to shift the register when the belt has moved one position. I am ASSUMING your interrupt routine is what detects the condition of moving one position. In the interrupt routine, you would set a flag (and you may be doing that) when objects have moved one position.

    You need an additional test in your main loop, to ONLY shift ther bits when this flag has been set.
     
    daljeet795 and JohnInTX like this.
  17. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    Good catch! The interrupt signal was what I was trying to show in the pseudo-code in #163. Hmmm..
     
    daljeet795 likes this.
  18. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    @djsfantasi @JohnInTX I have done some changes
    Code (C):
    1. #include <xc.h>
    2.  
    3. #pragma config FOSC = XT  // Oscillator Selection bits (XT oscillator)
    4. #pragma config WDTE = OFF  // Watchdog Timer Enable bit (WDT disabled)
    5. #pragma config PWRTE = ON  // Power-up Timer Enable bit (PWRT enabled)
    6. #pragma config BOREN = OFF  // Brown-out Reset Enable bit (BOR disabled)
    7. #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)
    8. #pragma config CPD = OFF  // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
    9. #pragma config WRT = OFF  // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
    10. #pragma config CP = OFF  // Flash Program Memory Code Protection bit (Code protection off)
    11. // #pragma config statements should precede project file includes.
    12. // Use project enums instead of #define for ON and OFF.
    13.  
    14. #define ENCODER RC0
    15. #define SENSOR  RC1
    16. #define KICKER  RD0
    17.  
    18. __bit gotIRQ;  // signals main that an interrupt
    19.  
    20. void main(void)
    21. {
    22.     unsigned int ShiftReg = 0; //  Init to 0
    23.  
    24.     INTCON = 0; // No interrupts
    25.  
    26.     PORTC = 0b00000000; //Set all Pin to Low
    27.  
    28.     TRISC0 = 1; // RC0 Eencoder Pin
    29.     TRISC1 = 1; // RC1 Sensor Pin
    30.     TRISD0 = 0; // RD0 Kicker Pin
    31.  
    32.     //CCP1 MODULE INITIALIZATION
    33.     T1CON = 0b00000011 ;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
    34.     CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value
    35.  
    36.     // 65536- 2165 = 63,371 is eual to 0xF78B
    37.     CCPR1H = 0xF7;
    38.     CCPR1L = 0x8B;
    39.  
    40.     CCP1IF = 0;
    41.  
    42.     INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt
    43.  
    44.     CCP1IE = 1;  //Enabled CCP1 interrupt
    45.  
    46.   while(1)
    47.   {
    48.         ShiftReg << 1;         // shift the integer shift register one bit left. LSbit = 0 after shift
    49.         if (SENSOR == 1)
    50.         ShiftReg |= 0x0001;    // bad object, put 1 in LSbit
    51.         if(ShiftReg & 0x0400)  // and if the #10 bit after shift is '1', kick it    
    52.         if (gotIRQ)
    53.         KICKER =~ KICKER ;
    54.         gotIRQ = 0;  // acknowledge the interrupt
    55.   }
    56. }
    57. void __interrupt() IRQ(void){
    58.   // CCP1 Interrupt
    59.   if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
    60.   {
    61.      CCP1IF = 0;
    62.      gotIRQ = 1;  // 'Signal' main that an interrupt happened
    63.   }
    64. }
     
    Last edited: May 15, 2019 at 7:05 PM
  19. JohnInTX

    Moderator

    Jun 26, 2012
    3,541
    1,818
    You are not waiting for 'gotIRQ' from the interrupt routine.
     
  20. daljeet795

    Thread Starter Member

    Jul 2, 2018
    170
    1
    so @JohnInTX I think first need to check the flag
    Code (C):
    1.   while(1)
    2.   {
    3.         if (gotIRQ)
    4.         ShiftReg << 1;         // shift the integer shift register one bit left. LSbit = 0 after shift
    5.         if (SENSOR == 1)
    6.         ShiftReg |= 0x0001;    // bad object, put 1 in LSbit
    7.         if(ShiftReg & 0x0400)  // and if the #10 bit after shift is '1', kick it        
    8.         KICKER =~ KICKER ;
    9.         gotIRQ = 0;  // acknowledge the interrupt
    10.   }
     
Loading...