PIC16F877A - Object Detection and Rejection - Timer Interrupt

LesJones

Joined Jan 8, 2017
3,172
Hi djs,
I realised that John and yourself would have seen this problem. The way the TS was setting (or clearing.) the right hand bit of the shift register (In the third line of post #326) from the output of the scanner when he should have been setting (or clearing.) the next bit to the left (Assuming that the scanner delay was very small) makes me think he still does not understand the shift register method.

Les.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
I encourage you to work out these examples Once you understand these examples, it will be much simpler to correct your code.
@djsfantasi I understand the bitwise operation

At the sensor bit 0
At the scanner bit 1
At the kicker bit 10

if (SENSOR == 1) // bad object,
ShiftReg |= 0x0001; // set sensor bit 00 0000 0000 0001


if ( ShiftReg |= 0x0002) //'scan request' bit is 0x0002 = 00 0000 0000 0001
Scanner = 1; // set output high
__delay_ms(30); // response time
Scanner = 0; // set output low

if (scan is BAD)
ShiftReg |= 0x0002 // if scan BAD set bit 1

if (scan is GOOD)
(ShiftReg &= ~0x0002) // if scan good clear bit 1

if (ShiftReg & 0x0800) //if the #11 bit after shift is '1', kick it
KICKER = 1; // set output high
__delay_ms(40);
KICKER = 0; // set output low
 

djsfantasi

Joined Apr 11, 2010
7,689
So, most of it looks good. I actually just skimmed the code for obvious problems. I’m not saying (yet) that the code is good.

But there’s one piece that doesn’t make sense, and I’ve quoted it above. I have a question for you. What does the operator |= do? Is it a logical test?

The statement
If(ShiftReg |= 0x0002)​
will always be true! Do you see why?

You need to test if the bit specified by 0x0002 is set or set. Your statement will set that bit; not test it. You do it right later. This is likely what you meant
if(ShiftReg & 0x0002)​

Let me know if you don’t understand why your if statement will always be true.
 
Last edited:

Thread Starter

daljeet795

Joined Jul 2, 2018
295
@djsfantasi @JohnInTX

At the sensor bit 0
At the scanner bit 1
At the kicker bit 11

0000 0000 0000 0000 // 16 bit shift reg

if(ShiftReg & 0x0002) //Test bit 1

ShiftReg |= 0x0002 // set bit 1 to ‘1’

ShiftReg &= (~0x0002) // clear bit 1 to ‘0’


If SENSOR senses an object, put a '1' in the shift register bit that corresponds to the sensor

if (sensor is High)
ShiftReg |= 0x0001 // set bit0 to '1’

When the bit in the shift register specified by 0x0002 is set/ is a 1, perform a scan
if(ShiftReg & 0x0002)

If the SCANNER REPLY says 'bad object' set the bit at the scanner location
if (scan is bad)
ShiftReg |= 0x0002 // set bit 1 to ‘1’

If the SCANNER REPLY says 'good', clear the bit at the scanner location.
if (scan is good)
ShiftReg &= (~0x0002) // clear bit1 to ‘0’

At the KICKER, if the corresponding bit is '1' kick it.
if (ShiftReg & 0x0800)

Hope this would be right logic
 

djsfantasi

Joined Apr 11, 2010
7,689
@djsfantasi @JohnInTX

At the sensor bit 0
At the scanner bit 1
At the kicker bit 11

0000 0000 0000 0000 // 16 bit shift reg

if(ShiftReg & 0x0002) //Test bit 1

ShiftReg |= 0x0002 // set bit 1 to ‘1’

ShiftReg &= (~0x0002) // clear bit 1 to ‘0’


If SENSOR senses an object, put a '1' in the shift register bit that corresponds to the sensor

if (sensor is High)
ShiftReg |= 0x0001 // set bit0 to '1’

When the bit in the shift register specified by 0x0002 is set/ is a 1, perform a scan
if(ShiftReg & 0x0002)

If the SCANNER REPLY says 'bad object' set the bit at the scanner location
if (scan is bad)
ShiftReg |= 0x0002 // set bit 1 to ‘1’

If the SCANNER REPLY says 'good', clear the bit at the scanner location.
if (scan is good)
ShiftReg &= (~0x0002) // clear bit1 to ‘0’

At the KICKER, if the corresponding bit is '1' kick it.
if (ShiftReg & 0x0800)

Hope this would be right logic
The logic is impeccable. That is, good.

The “kicker” used to be at a different bit position. If I missed that change and it’s now at the bit position specified by the mask 0x0800, then I admit the logic is good.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
@djsfantasi @JohnInTX I followed your post #331 I understood the bitwise logic operation but I am not making progress. I am struggling to set, reset and test shift register value according to bad and good object in the queue
 

djsfantasi

Joined Apr 11, 2010
7,689
Ok, basic operations...

Let’s forget actual numbers. Remember that in my examples they represent a position in the shift register. So I’m going to use a variable called “Position” to represent that idea.

To set a bit,
ShiftReg |= Position
This performs the following steps
  • Takes the shift register
  • Ors the value with the (bit specified by) Position
  • Puts the new value into the shift register

To reset a bit

ShiftReg &= ~Position​
  • Takes the (previous value of the) shift register
  • Sets all bits (inverts) except the bit specified by Position
  • ANDs the previous shift register with the inverted Position. Anything in the shift register at the bit specified by Position will be set to ‘0’; all other bits remain unchanged.
  • Puts the new value back into the shift register.
To test if a bit in the shift register is set
if(ShiftReg & Position)​

Position has a single bit set.
  • Take the value in ShiftReg
  • AND it with Position
  • If the SAME bit is set in the shift register, the expression returns a non-zero value and the test will be true.
  • In all other cases, the expression returns all ‘0’s and the test will be false.

The shift register is used to keep track of an object. Each interrupt advances all bits one position. The variable of “Position” in my example will always be a power of two. Hence it takes a value of 1,2,4,8,16,33,64...

Your last post had the code down. It appears as if you’re not sure why. This was my attempt to explain in more detail and I used the variable “Position” to generalize my answer. At the scanner position, you reset the bit if it’s good; set it if it’s bad. As the bits advance, ultimately they will appear at the reject mechanism. Then you test the bit (same as at the scanner) and allow/reject depending on the bit tested.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
Ok, basic operations....
thanks @djsfantasi as I have explained in the post #344. the basic operation is not my problem. I am making mistake to understand the program logic

Please Take a look at this
C:
If (Object detected)
(ShiftReg |= 0x0001)  // set sensor bit 0

If (ShiftReg & 0x0002) // request a scan
Kickit();

if (scan is GOOD)
(ShiftReg &= ~0x0002) // CLEAR the kick bit

if (scan is BAD)
(ShiftReg |0x0002) // set the kick bit,

If (ShiftReg & 0x0800)
Kickit();
Does it make sense

Edit : pseudo code
C:
while(1)
{
if (gotIRQ)
  {
     gotIRQ = 0;  // acknowledge the interrupt ** ALWAYS and before the delay **
     ShiftReg <<= 1;  // shift the integer shift register one bit left. LSbit = 0 after shift

  if (SENSOR == 1)
       ShiftReg |= 0x0001;  // bad object, put 1 in LSbit

  if (ShiftReg & 0x0002)
     Scanner = 1;  // enable
    __delay_ms(30);  // response time
     Scanner = 0;  //  disable

  if (scan is BAD)
   (ShiftReg |0x0002) // set the kick bit,

  if (ShiftReg & 0x0800)
      KICKER = 1;  // set output pulse high
      __delay_ms(40);
      KICKER = 0;  // set output pulse low
   }
}
Note : Code have delay because Every device take time to respond, Here kicker takes a minimum 40s and scanner takes minimum 25 ms

Edited code after post #349
 
Last edited:

djsfantasi

Joined Apr 11, 2010
7,689
thanks @djsfantasi as I have explained in the post #344. the basic operation is not my problem. I am making mistake to understand the program logic

Please Take a look at this
C:
If (Object detected)
(ShiftReg |= 0x0001)  // set sensor bit 0

If (ShiftReg & 0x0002)
Kickit();  // request a scan

If (scan is GOOD)
(ShiftReg &= ~0x0002) // CLEAR the kick bit

If (scan is BAD)
(ShiftReg |0x0002) // set the kick bit,

If (ShiftReg & 0x0800)
Kickit();
Does it make sense
Maybe... you have some typos and hopefully used the wrong function in one place.

But, I hope I can see what you meant.

When do you perform a scan? I’ll answer, when an object is in the scan position. It looks like you understand that, but you call Kickit() instead of scanning. Probably a simple mistake, but is it?

Then you have two similar tests.
if( scan is GOOD )
if( scan is BAD )​
I think you’ve have a typo here.

I’m trying to help. Ive given you some very specific examples. I see you’ve used them in your code. Along with those solutions, I've also suggested some very specific topics for you to research. Also, I’ve provided a real world example. Remember the line of your friends? That was to help you understand the concept of a shift register. Did you understand the example?

It’s TOTALLY understandable if you didn’t understand. But for us to help, we need to know when you don’t understand a point we make. Did you read anything about bit manipulation and bit masking? Did you understand the example with your friends?

I see you properly using suggestions on setting, clearing and testing a bit. But do you understand why it works?

I see you using given values in your code logic. But do you understand why? What does finding out that the bit represented by 0x0002 is either set or reset mean? What does it mean when ShiftReg&2048 is true?

Please answer all of these questions. It’ll help me figure out how to explain the logic to you.

I appreciate the struggles you are going through. You have made incredible progress in your understanding. We’ll get through this. I’m committing to hanging in there. If you make the same commitment, we’ll get there. Just be patient as it may take some time.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
When do you perform a scan? I’ll answer, when an object is in the scan position. It looks like you understand that, but you call Kickit() instead of scanning. Probably a simple mistake, but is it?
the scan will perform if the scanner bit is set bit 1
0x0002 = 0000 0000 0000 0010
if (ShiftReg & 0x0002)
Scanner = 1; // enable
__delay_ms(30); // response time
Scanner = 0; // disable
Then you have two similar tests.
if( scan is GOOD )
if( scan is BAD )​
I think you’ve have a typo here.
okay just need to test BAD
If (scan is BAD)
(ShiftReg |0x0002) // set the kick bit,
I’m trying to help. Ive given you some very specific examples. Did you understand the example?
Did you read anything about bit manipulation and bit masking?
Yes, I understand the given example. whenever I get the trouble to understand the basic I just write simple c program on my laptop see post #133 and #261

I appreciate the struggles you are going through. You have made incredible progress in your understanding. We’ll get through this. I’m committing to hanging in there. If you make the same commitment, we’ll get there. Just be patient as it may take some time.
I am a little bit struggling but I'm enjoying. I have learned a lot about this period. I can understand that it takes some time to solve the problem
 

djsfantasi

Joined Apr 11, 2010
7,689
the scan will perform if the scanner bit is set bit 1
0x0002 = 0000 0000 0000 0010
if (ShiftReg & 0x0002)
Scanner = 1; // enable
__delay_ms(30); // response time
Scanner = 0; // disable

okay just need to test BAD
If (scan is BAD)
(ShiftReg |0x0002) // set the kick bit,

Yes, I understand the given example. whenever I get the trouble to understand the basic I just write simple c program on my laptop see post #133 and #261


I am a little bit struggling but I'm enjoying. I have learned a lot about this period. I can understand that it takes some time to solve the problem
So, what is in the program logic that is confusing you!

By the way, the typo is after the
“if(scan=BAD)”’​
statement, where you set the bit.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
By the way, the typo is after the
“if(scan=BAD)”’​
statement, where you set the bit.
@djsfantasi @JohnInTX
I have tried to convert logic into the program

When bad object detected by sensor, triggre the scanner and the scanner will send data to serial port of PC if controller see the data 'B' set the bit for kicking

Here is my program
C:
#include <xc.h>
#include <stdio.h>
#include <conio.h>

// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

#define ENCODER   RC0
#define SENSOR    RC1
#define Scanner   RD0
#define KICKER    RD1

#define _XTAL_FREQ 20000000

__bit gotIRQ;  // signals main that an interrupt occurred

void putch(char data)
{
    while(!TRMT);
    TXREG = data;
}
  char  getch ()
{
   if(OERR == 1){     // reset UART on overflow error
       CREN = 0;
       CREN = 1;
  }
  while(RCIF==0);   // Wait till the data is received
   return(RCREG);   // Return the received data to calling function
}
void send (char *s)
{
  while (*s != 0)
  putch(*s++);
}

void main(void)
{
  char data;

  unsigned int ShiftReg = 0; //  Init to 0
  INTCON = 0;  // No interrupts

  TRISC = 0b00000011; // RC0 Encoder Pin RC1 Sensor Pin
  TRISD = 0b00000000; // RD0 Kicker pin
  TXSTA = 0b00100100;  // TX enabled, BRGH=1
  RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
  SPBRG = 0x81;  // baud rate 9600
  //CCP1 MODULE INITIALIZATION
  T1CON = 0b00000011;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
  CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value

  //Set CCPR1H and CCPR1L (16 bits) to the number of encoder pulses e
  CCPR1H = 0x03;
  CCPR1L = 0x84;
  CCP1IF = 0;
  CCP1IE = 1;  //Enabled CCP1 interrupt
  INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt

  while (1)
  {
      if  (gotIRQ)
         {
           gotIRQ = 0;  // acknowledge the interrupt ** ALWAYS and before the delay **
     
          ShiftReg <<= 1;  // shift the integer shift register one bit left. LSbit = 0 after shift

           if (SENSOR == 1)
              ShiftReg |= 0x0001;  // bad object, put 1 in LSbit

           if (ShiftReg & 0x0002)
              Scanner = 1;  // enable
              __delay_ms(30);  // response time
             data = getch();
              Scanner = 0;  //  disable
             

           if (data == 'B')
             ShiftReg |0x0002; // set the kick bit,
       
           if ( data == 'G')
               ShiftReg &= ~0x0002 // CLEAR the kick bit

           if (ShiftReg & 0x0800)
              KICKER = 1;  // set output pulse high
               __delay_ms(40);
              KICKER = 0;  // set output pulse low
         }
    }
}

void __interrupt() IRQ(void){
  // CCP1 Interrupt
  if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
  {
    CCP1IF = 0;
    gotIRQ = 1;  // 'Signal' main that an interrupt happened
  }
}
Edit: I am sorry I couldn't test code on hardware I think It would be painful for you to review the whole code

Edit : code has been updated after post #353 and #354
 
Last edited:

djsfantasi

Joined Apr 11, 2010
7,689
@djsfantasi @JohnInTX
I have tried to convert logic into the program

When bad object detected by sensor, triggre the scanner and the scanner will send data to serial port of PC if controller see the data 'B' set the bit for kicking

Here is my program
C:
#include <xc.h>
#include <stdio.h>
#include <conio.h>

// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

#define ENCODER   RC0
#define SENSOR    RC1
#define Scanner   RD0
#define KICKER    RD1

#define _XTAL_FREQ 20000000

__bit gotIRQ;  // signals main that an interrupt occurred

void putch(char data)
{
    while(!TRMT);
    TXREG = data;
}
  char  getch ()
{
   if(OERR == 1){     // reset UART on overflow error
       CREN = 0;
       CREN = 1;
  }
  while(RCIF==0);   // Wait till the data is received
   return(RCREG);   // Return the received data to calling function
}
void send (char *s)
{
  while (*s != 0)
  putch(*s++);
}

void main(void)
{
  char data;

  unsigned int ShiftReg = 0; //  Init to 0
  INTCON = 0;  // No interrupts

  TRISC = 0b00000011; // RC0 Encoder Pin RC1 Sensor Pin
  TRISD = 0b00000000; // RD0 Kicker pin
  TXSTA = 0b00100100;  // TX enabled, BRGH=1
  RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
  SPBRG = 0x81;  // baud rate 9600
  //CCP1 MODULE INITIALIZATION
  T1CON = 0b00000011;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
  CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value

  //Set CCPR1H and CCPR1L (16 bits) to the number of encoder pulses e
  CCPR1H = 0x03;
  CCPR1L = 0x84;
  CCP1IF = 0;
  CCP1IE = 1;  //Enabled CCP1 interrupt
  INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt

  while (1)
  {

    data = getch();

      if  (gotIRQ)
         {
           gotIRQ = 0;  // acknowledge the interrupt ** ALWAYS and before the delay **
        
          ShiftReg <<= 1;  // shift the integer shift register one bit left. LSbit = 0 after shift

           if (SENSOR == 1)
              ShiftReg |= 0x0001;  // bad object, put 1 in LSbit

           if (ShiftReg & 0x0002)
              Scanner = 1;  // enable
              __delay_ms(30);  // response time
              Scanner = 0;  //  disable

           if (data == 'B')
             ShiftReg |0x0002; // set the kick bit,

           if (ShiftReg & 0x0800)
              KICKER = 1;  // set output pulse high
               __delay_ms(40);
              KICKER = 0;  // set output pulse low
         }
    }
}

void __interrupt() IRQ(void){
  // CCP1 Interrupt
  if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
  {
    CCP1IF = 0;
    gotIRQ = 1;  // 'Signal' main that an interrupt happened
  }
}

Edit : I am sorry I couldn't test code on hardware I think It would be painful for you to review the whole code
So, I see two issues...

  1. You read a character before you get a result from the scanner. You need to read the scanner result after you scan. Otherwise, the system won’t be in sync. I suggest that you read the character after the 30ms delay.
  2. Secondly, if the scan was bad you set the bit at 0x0002. If the scan was good, you don’t do anything. But what is the bit value at 0x0002? It’s a ‘1’, because it was set to flag a scan was needed. If the scan was good, you need to clear the bit at 0x0002

I have a question about your send() function but I’m probably wrong. Let me check before I say anything.
 

djsfantasi

Joined Apr 11, 2010
7,689
@djsfantasi @JohnInTX
I have tried to convert logic into the program

When bad object detected by sensor, triggre the scanner and the scanner will send data to serial port of PC if controller see the data 'B' set the bit for kicking

Here is my program
C:
#include <xc.h>
#include <stdio.h>
#include <conio.h>

// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

#define ENCODER   RC0
#define SENSOR    RC1
#define Scanner   RD0
#define KICKER    RD1

#define _XTAL_FREQ 20000000

__bit gotIRQ;  // signals main that an interrupt occurred

void putch(char data)
{
    while(!TRMT);
    TXREG = data;
}
  char  getch ()
{
   if(OERR == 1){     // reset UART on overflow error
       CREN = 0;
       CREN = 1;
  }
  while(RCIF==0);   // Wait till the data is received
   return(RCREG);   // Return the received data to calling function
}
void send (char *s)
{
  while (*s != 0)
  putch(*s++);
}

void main(void)
{
  char data;

  unsigned int ShiftReg = 0; //  Init to 0
  INTCON = 0;  // No interrupts

  TRISC = 0b00000011; // RC0 Encoder Pin RC1 Sensor Pin
  TRISD = 0b00000000; // RD0 Kicker pin
  TXSTA = 0b00100100;  // TX enabled, BRGH=1
  RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
  SPBRG = 0x81;  // baud rate 9600
  //CCP1 MODULE INITIALIZATION
  T1CON = 0b00000011;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
  CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value

  //Set CCPR1H and CCPR1L (16 bits) to the number of encoder pulses e
  CCPR1H = 0x03;
  CCPR1L = 0x84;
  CCP1IF = 0;
  CCP1IE = 1;  //Enabled CCP1 interrupt
  INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt

  while (1)
  {

    data = getch();

      if  (gotIRQ)
         {
           gotIRQ = 0;  // acknowledge the interrupt ** ALWAYS and before the delay **
        
          ShiftReg <<= 1;  // shift the integer shift register one bit left. LSbit = 0 after shift

           if (SENSOR == 1)
              ShiftReg |= 0x0001;  // bad object, put 1 in LSbit

           if (ShiftReg & 0x0002)
              Scanner = 1;  // enable
              __delay_ms(30);  // response time
              Scanner = 0;  //  disable

           if (data == 'B')
             ShiftReg |0x0002; // set the kick bit,

           if (ShiftReg & 0x0800)
              KICKER = 1;  // set output pulse high
               __delay_ms(40);
              KICKER = 0;  // set output pulse low
         }
    }
}

void __interrupt() IRQ(void){
  // CCP1 Interrupt
  if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
  {
    CCP1IF = 0;
    gotIRQ = 1;  // 'Signal' main that an interrupt happened
  }
}

Edit : I am sorry I couldn't test code on hardware I think It would be painful for you to review the whole code
I have a couple of observations.
  1. You read a character, ostensibly the result of a scan, before you do a scan! It looks like you won’t read the result until the object advances in the belt. Ie, the next interrupt. Hence, the object won’t be at the position where you’ll set the bad but. I’d read the character right after the 30ms delay or the next statement which disables the scanner.
  2. If the scan result is bad, you properly set the bit at 0x0002. But you don’t do anything if the scan was good. What happens? The object is marked bad because the bit at 0x0002 was a ‘1’ in order to trigger a scan. We use that bit to mean two things. In positions 1-2, it means an object is here and scan it. In positions 2-11, it means that the associated object is bad. Simply, if the scan returns an object is good, reset (set to ‘0’) the bit at 0x0002.
Got it?
 

JohnInTX

Joined Jun 26, 2012
4,442
@daljeet795 It's a lot easier to make the current code FOLLOW member remarks than refer to edited code. That way, we can follow the corrections and the remarks made after your code make sense time-wise. Here's the latest code you posted, in time order.
C:
#include <xc.h>
#include <stdio.h>
#include <conio.h>

// CONFIG
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
//END CONFIG

#define ENCODER   RC0
#define SENSOR    RC1
#define Scanner   RD0
#define KICKER    RD1

#define _XTAL_FREQ 20000000

__bit gotIRQ;  // signals main that an interrupt occurred

void putch(char data)
{
    while(!TRMT);
    TXREG = data;
}
  char  getch ()
{
   if(OERR == 1){     // reset UART on overflow error
       CREN = 0;
       CREN = 1;
  }
  while(RCIF==0);   // Wait till the data is received
   return(RCREG);   // Return the received data to calling function
}
void send (char *s)
{
  while (*s != 0)
  putch(*s++);
}

void main(void)
{
  char data;

  unsigned int ShiftReg = 0; //  Init to 0
  INTCON = 0;  // No interrupts

  TRISC = 0b00000011; // RC0 Encoder Pin RC1 Sensor Pin
  TRISD = 0b00000000; // RD0 Kicker pin
  TXSTA = 0b00100100;  // TX enabled, BRGH=1
  RCSTA = 0b10010000;  // Serial Port, Continuous Receive enabled
  SPBRG = 0x81;  // baud rate 9600
  //CCP1 MODULE INITIALIZATION
  T1CON = 0b00000011;  // 1:1 prescale, OSC disabled, Input Synchronized, External clock on T1CKI(RC0), Timer ON
  CCP1CON = 0b00001011;  // Compare mode using CCPR1H and CCPR1L as a 16 bit value

  //Set CCPR1H and CCPR1L (16 bits) to the number of encoder pulses e
  CCPR1H = 0x03;
  CCPR1L = 0x84;
  CCP1IF = 0;
  CCP1IE = 1;  //Enabled CCP1 interrupt
  INTCON = 0xc0;  //Enabled Global interrupts & Peripherals interrupt

  while (1)
  {
      if  (gotIRQ)
         {
           gotIRQ = 0;  // acknowledge the interrupt ** ALWAYS and before the delay **
    
          ShiftReg <<= 1;  // shift the integer shift register one bit left. LSbit = 0 after shift

           if (SENSOR == 1)
              ShiftReg |= 0x0001;  // bad object, put 1 in LSbit

           if (ShiftReg & 0x0002)
              Scanner = 1;  // enable
              __delay_ms(30);  // response time
             data = getch();
              Scanner = 0;  //  disable
            

           if (data == 'B')
             ShiftReg |0x0002; // set the kick bit,
      
           if ( data == 'G')
               ShiftReg &= ~0x0002 // CLEAR the kick bit

           if (ShiftReg & 0x0800)
              KICKER = 1;  // set output pulse high
               __delay_ms(40);
              KICKER = 0;  // set output pulse low
         }
    }
}

void __interrupt() IRQ(void){
  // CCP1 Interrupt
  if(CCP1IF == 1)  // if the CCP1 Interrupt flag is set...
  {
    CCP1IF = 0;
    gotIRQ = 1;  // 'Signal' main that an interrupt happened
  }
}
 

djsfantasi

Joined Apr 11, 2010
7,689
@djsfantasi, I have edited code after your post. Please take a look post #352
Now I hope everything is okay
What do you think? Is it ok?

Your tests for if a given bit is set is now correct in all places.

Same thing for the lines of code where you set/reset a bit in all places.

Your sequence of operations is logical. But are there any places where it won’t work?

Remind me... how many milliseconds occur between interrupts? This is important.
 

JohnInTX

Joined Jun 26, 2012
4,442
In #291 we added this to check the PC reply without blocking
C:
// checkPC: checks UART, returns a char received or '\0' if none - does not wait on receive
unsigned char checkPC(void){
  if(OERR == 1){  // reset UART on overflow error
  CREN = 0;
  CREN = 1;
  }
  if(RCIF)  // if a char has been received
  return RCREG;  // return the char
  else
  return ('\0');  // else, return 00
}

unsigned char PCreply;
  if ((PCreply = checkPC()) == '\0')   // is how you check, read the char if it is available but allow other things to happen.  
// If a char is read it will be stored in PCreply.
See line 93 of post #291 to see how it was used in that logic.

You guys are making progress.
 

Thread Starter

daljeet795

Joined Jul 2, 2018
295
What do you think? Is it ok?
are there any places where it won’t work?
Remind me... how many milliseconds occur between interrupts? This is important.
@djsfantasi forgot to add semicolon line 92
ShiftReg &= ~0x0002// CLEAR the kick bit

I do not think there is any other mistake in the code but I have to improve

interrupt time will depend on the belt speed I couldn't find an answer to your question,
 
Last edited:

djsfantasi

Joined Apr 11, 2010
7,689
@djsfantasi
...interrupt time will depend on the belt speed I couldn't find an answer to your question,
Based on everything we’ve discussed thus far, I don’t see any errors in the code.

What belt speeds do you expect? Does the belt vary it’s speed or you don’t know the answer. Maybe you can estimate or know a range... 5-10 cm/sec?

Just for illustration purposes, can you estimate the time or pick a reasonable time between interrupts?
 
Top