# PIC16F877A - Object Detection and Rejection - Timer Interrupt

#### daljeet795

Joined Jul 2, 2018
295
Can you explain the reasoning (And calculations) for changing the division ratio from 900 to the values 700, 800, 500, 1428 1228 ?
Also why do you use the value of 300 (0x12C) in the code in post #377 ?

Les.
@LesJones thanks
The distance between sensor and scanner is 50mm long. When I set at 1428 prescale scanner doesn't scan the object. So I was trying with different prescale values

segment = (400 x 1424 )/10000 = 57.12mm (Or 57.12/5278 second = 0.0108 seconds = 10.8 mS)

So belt cover 57.12 mm distance within 10.8 ms

That is less time for scanner to respond. Scanner take minimum 30 ms to scan

This is all calculations at full speed
Assume belt running at 1/3 speed aprox 400;rpm than I think it may take long time more then 30ms to cover 52.12 mm distance

How to set the accurate position of object in front of the scanner?

Last edited:

#### djsfantasi

Joined Apr 11, 2010
7,695
@LesJones thanks
The distance between sensor and scanner is 50mm long. When I set at 1428 prescale scanner doesn't scan the object. So I was trying with different prescale values

segment = (400 x 1424 )/10000 = 57.12mm (Or 57.12/5278 second = 0.0108 seconds = 10.8 mS)

That is less time for scanner to respond. Scanner take minimum 30 ms to scan

How to set the accurate position of object in front of the scanner?
First, I believe you said you are using 30ms because it is longer then the scan time. The actual scan time is shorter than 30ms. The rest of this post will assume 30ms, but reconsider using the actual time.

Secondly, the object has never stopped moving while you were scanning. So perhaps, the scan is successful while it’s moving.

Third, staying with the 30ms value, the object will move 1.71 cm (0.67”) during that time. That is 3*57.12mm. 3 interrupts will occur in that time.

Fourth, if 3 interrupts have occurred, which bit in your shift register corresponds to the object’s location? The scan starts at bit position 2. It moves 3 bit positions of the shift register during the scan. Hence, you need to set/reset bit position 5 in the shift register. (Not 0x0002) The bit mask for bit position 5 is 0x0010.

#### daljeet795

Joined Jul 2, 2018
295
Great! Let me know how it works out...
@djsfantasi @JohnInTX
the code was not working as it supposes to do so I tried to find a problem in the code
there is problem in line 70. the scanner doesn't give result if I uncomment this line // data = getch();

if I remove line 70. scanner give Good/Bad signal
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 = 0x04;
CCPR1L = 0x44;
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

}
}
}

void __interrupt() IRQ(void){
// CCP1 Interrupt
if(CCP1IF == 1)
{
CCP1IF = 0;
gotIRQ = 1;
}
}
What's wrong with this "data = getch(); " ?

Last edited:

#### JohnInTX

Joined Jun 26, 2012
4,448
Maybe you have to set Scanner=0 to get the reply from the PC? As written, it will wait forever until it gets a character while Scanner = 1.
If so, interchange lines 82 and 83.

#### daljeet795

Joined Jul 2, 2018
295
Maybe you have to set Scanner=0 to get the reply from the PC? As written, it will wait forever until it gets a character while Scanner = 1.
If so, interchange lines 82 and 83.
@@JohnInTX I did that but doesn't give result
Code:
if (ShiftReg & 0x0002)
Scanner = 1;  // enable
__delay_ms(30);  // response time
Scanner = 0;  //  disable
data = getch();
I also did it also doesn't give result

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

#### JohnInTX

Joined Jun 26, 2012
4,448
What precisely is it not doing?

#### daljeet795

Joined Jul 2, 2018
295
What precisely is it not doing?
@JohnInTX I don't understand why it doesn't give result when I add line 70? That line is necessary because we are getting a response from port

#### JohnInTX

Joined Jun 26, 2012
4,448
You need brackets around this part to execute ALL of the lines when the 0x0002 bit is set.

C:
 if (ShiftReg & 0x0002) { //<<<<<-------------
Scanner = 1;  // enable
__delay_ms(30);  // response time
Scanner = 0;  //  disable
data = getch();
}//<------------------

#### djsfantasi

Joined Apr 11, 2010
7,695
You need brackets around this part to execute ALL of the lines when the 0x0002 bit is set.

C:
 if (ShiftReg & 0x0002) { //<<<<<-------------
Scanner = 1;  // enable
__delay_ms(30);  // response time
Scanner = 0;  //  disable
data = getch();
}//<------------------
Nice catch!

#### JohnInTX

Joined Jun 26, 2012
4,448
Thinking out loud for a moment.. There has been discussion about how far the belt moves in the 30ms scan time and whether to adjust the location of the scan result bit in the shift register. Good thoughts but since the scanner takes a certain time to scan (30ms) doesn't that define the minimum segment size? Indeed if the belt moves 2 segments in that 30ms, the scan result would be put 2 bits further into the shift register. But that also means that the system is 'blind' for those 3 segments (original one plus 2 following) and there can't be any objects in those segments. If that is the constraint, doesn't that indicate that you might as well use bigger segments - that size being constrained by the object size AND how far the belt travels during the fixed scan time?
It also indicates that the sensor and scanner trigger should define the leading edge of a segment with the the requirement that all processing be done by the time that the leading edge of the next segment arrives.
Sorry for barging in.

Last edited:

#### LesJones

Joined Jan 8, 2017
3,193
Hi John,
I agree with the above comments. (post #390) The 30 mS time taken for the scan was only mentioned very late in the thread. If we assume that the TS still wants the system to cope with varying conveyor speed (Which was the reason for using the encoder in the first place rather than just using timing which would work with a fixed conveyor speed.) we would need to save the scanner output and use it after the maximum number of conveyor segments that could occur in a little more than the 30 mS scan time. (This would be calculated for the maximum conveyor speed that the system could use.) I think one we are sure that the TS understands the shift register concept it would be worth using mot than one shift register bit per conveyor segment so we could identify the approximate centre of the object both for the scanner and the kicker. (Possibly 3 shift register bits per conveyor segment.) It would be interesting to know how the scanner works and what property is being detected to decide pass or fail.

Les.

#### JohnInTX

Joined Jun 26, 2012
4,448
Hi John,
I agree with the above comments. (post #390) The 30 mS time taken for the scan was only mentioned very late in the thread. If we assume that the TS still wants the system to cope with varying conveyor speed (Which was the reason for using the encoder in the first place rather than just using timing which would work with a fixed conveyor speed.) we would need to save the scanner output and use it after the maximum number of conveyor segments that could occur in a little more than the 30 mS scan time. (This would be calculated for the maximum conveyor speed that the system could use.) I think one we are sure that the TS understands the shift register concept it would be worth using mot than one shift register bit per conveyor segment so we could identify the approximate centre of the object both for the scanner and the kicker. (Possibly 3 shift register bits per conveyor segment.) It would be interesting to know how the scanner works and what property is being detected to decide pass or fail.

Les.
I'd like some detailed info on the scanner, too.
But I think what's driving many of our thoughts is that variable 0ms - 70ms blocking delay time per loop as well as blocking while waiting on the scan result. That will be a killer as the belt speed increases.
I showed a way to sample the UART without blocking here:
and a way to wait on the PC reply while watching for interrupts in line 135 here:
but both are ad-hoc solutions-of-the-day; The code keeps changing.

Still, I think you, @djsfantasi have well noted the central issue that has to be resolved, namely the delays that are being built into the system. It's not particularly hard to do that but it will require a more involved approach than what we have so far.

Good luck!

#### daljeet795

Joined Jul 2, 2018
295
@djsfantasi @JohnInTX

Thank you all. I do not have a conveyor belt machine available Those who gave me the machine have sold their all machine so I can not make progress on this project. I will try to arrange a machine for the project

#### JohnInTX

Joined Jun 26, 2012
4,448
@djsfantasi @JohnInTX

Thank you all. I do not have a conveyor belt machine available Those who gave me the machine have sold their all machine so I can not make progress on this project. I will try to arrange a machine for the project
Bummer!
But you can still work on the project. As all of us have said, the biggest part of an embedded project is the planning, design and flowing out a solution to the problem at hand. Somewhere back in the thread, I (and maybe others, too) posted code that worked to the then current spec without even seeing your machine. How did we do that?? By doing just what we told you to do. Maybe you need to revise the current approach or move into that 18F. Now's the time to do it.

While you are waiting, why not sit down and drill into a solution? You can test much of the code in MPSIM. When you get the machine again, you can apply what you have developed.

Hope you get another shot at it.