PIC16F877A - Object Detection and Rejection - Timer Interrupt

Ian Rogers

Joined Dec 12, 2012
884
• ShiftReg &= ~0x0002 // CLEAR the kick bit
That would not compile..Your compiler would have winged.... As I said before the external clock ( provided it's clean enough ) can be as high as 50Mhz.. The counter is independent of clock speed.... Reading Timer1 at that speed brings it's own problems...If you read the high byte the low byte is still changing... rapidly.. A read is almost impossible at high speed.. The datasheet has a recommendation, but there is always going to be a difference.

But as you are using the CCP module it should be okay...

daljeet795

Joined Jul 2, 2018
295
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?
VFD is used to control the speed of the motor. We can set at any speed

The conveyor has 1400 RPM motor and roller diameter 72 mm, a circumference of 72 x 3.14159 is 226.19448.

I think Conveyor speed = 1400rpm * 226.2= 316680 mm/s

That would not compile..Your compiler would have winged......
are you talking about missing semicolons?

then you missed a post #359 if I add semicolons It does compiles

Last edited:

JohnInTX

Joined Jun 26, 2012
4,433
That would not compile..Your compiler would have winged.... As I said before the external clock ( provided it's clean enough ) can be as high as 50Mhz.. The counter is independent of clock speed.... Reading Timer1 at that speed brings it's own problems...If you read the high byte the low byte is still changing... rapidly.. A read is almost impossible at high speed.. The datasheet has a recommendation, but there is always going to be a difference.

But as you are using the CCP module it should be okay...
Semicolon, OK.
The counting speed and using TIMER1 with external clocking and COMPARE with automatic reset to divide the belt into segments that map to a shift register as well as max speed calculations were shown in detail way back in #150 here and detailed in subsequent posts.

We're not reading TIMER1 at all.

djsfantasi

Joined Apr 11, 2010
7,689
That would not compile..Your compiler would have winged.... As I said before the external clock ( provided it's clean enough ) can be as high as 50Mhz.. The counter is independent of clock speed.... Reading Timer1 at that speed brings it's own problems...If you read the high byte the low byte is still changing... rapidly.. A read is almost impossible at high speed.. The datasheet has a recommendation, but there is always going to be a difference.

But as you are using the CCP module it should be okay...
So, if it moves at 316680 mm/sec or 3,166 cm/sec, how far will it move in 30 ms?

3,166.8 cm/s * 0.03s
95.04 cm​

And at 3,168.8 cm/sec, how far will the belt move between interrupts. You should be able to calculate that figure with the information you’ve supplied me.

It’s important to verify that your program will work in the real world. We know it works in the theoretical world.

* NOTE: I didn’t verify the belt speed calculations, yet. But for purposes of this discussion, the result is acceptable.

Ian Rogers

Joined Dec 12, 2012
884
We're not reading TIMER1 at all.
Yes.. I'm confusing the OP... I'll carry on just watching.... Doing a great job by the way...

LesJones

Joined Jan 8, 2017
3,168
There is an error in the calculation in post #362. The result should 316680 mm/minute. ( NOT 316680 mm/s)

Les.

djsfantasi

Joined Apr 11, 2010
7,689
There is an error in the calculation in post #362. The result should 316680 mm/minute. ( NOT 316680 mm/s)
Thanks for catching that, Les!

That’s why I added a disclaimer to my reply. I wasn’t near the resources I’d use to check the calculation.

My question to the TS stands. What is the time between interrupts.

djsfantasi

Joined Apr 11, 2010
7,689
With the information provided by @LesJones , my calculations change to

316,680 mm/minute =
3,166.8 cm/minute =
52.78 cm/sec
So, in the 30ms delay for the scan, the object will move
52.78 cm/sec * 30ms =
52.78 cm/sec * 0.03 sec =
1.58 cm​
So, if an interrupt occurs in less than every 30ms and the object keeps on moving,
Where will the object be at the end of the scan delay?

LesJones

Joined Jan 8, 2017
3,168
Hi djs,
Here is a text file I created some time back to save having to search through the thread for the values being used. I don't know if these values are being used at the moment. (It gets confusing when the specifications and the values keep changing.)
Start of text file.
5000 line encoder

1.2 metres from fail detector to reject point.
16500 pulses per 1.2 metres. (13750 pulses per metre.)
Conveyor speed 5.3 metres per second . So counts per second = 5.3 x 13750 = 72875 (13.7 uS) (Conveyor moves (5300 x 13.7)/1000000 = 0.073 mm)

Object length 190mm (so object will take 190/5300 seconds to pass a point = 0.0358 seconds (36 mS)

Object spacing. 20 mm

In 30 mS conveyor moves 5300 x 30/1000mm = 5.3 x 30mm = 159mm
In 30 mS there will have been 30000/13.7 (30 mS divided by 13.7 uS.) steps of the shift register = 2189.8 steps
End of text file,
The speed of 5.3 metres per second in the above table is close to the (corrected. ) calculation of 5.278 metres per second in post #362

Les.

JohnInTX

Joined Jun 26, 2012
4,433
Hi djs,
Here is a text file I created some time back to save having to search through the thread for the values being used. I don't know if these values are being used at the moment. (It gets confusing when the specifications and the values keep changing.)
Start of text file.
5000 line encoder

1.2 metres from fail detector to reject point.
16500 pulses per 1.2 metres. (13750 pulses per metre.)
Conveyor speed 5.3 metres per second . So counts per second = 5.3 x 13750 = 72875 (13.7 uS) (Conveyor moves (5300 x 13.7)/1000000 = 0.073 mm)

Object length 190mm (so object will take 190/5300 seconds to pass a point = 0.0358 seconds (36 mS)

Object spacing. 20 mm

In 30 mS conveyor moves 5300 x 30/1000mm = 5.3 x 30mm = 159mm
In 30 mS there will have been 30000/13.7 (30 mS divided by 13.7 uS.) steps of the shift register = 2189.8 steps
End of text file,
The speed of 5.3 metres per second in the above table is close to the (corrected. ) calculation of 5.278 metres per second in post #362

Les.
Thanks, Les, but don't forget that we are using TIMER1/COMPARE to prescale the encoder so that the belt is divided into larger segments. Currently, it's 900 encoder counts per interrupt i.e. 900 encoder counts per belt segment - based on the code in #356. That allows the shift register to be much smaller - it currently fits into about 11bits of a 16 bit integer IIRC, with the distance between sensor and kicker divided into the corresponding 11 equal-length segments. The effective length of each belt segment can be adjusted by varying the value of the COMPARE register in the PIC. When that happens, the effective shift register length must change also so that each belt segment has one corresponding bit in the shift register.

So far, at least

Last edited:

djsfantasi

Joined Apr 11, 2010
7,689
Hi djs,
Here is a text file I created some time back to save having to search through the thread for the values being used. I don't know if these values are being used at the moment. (It gets confusing when the specifications and the values keep changing.)
Start of text file.
5000 line encoder

1.2 metres from fail detector to reject point.
16500 pulses per 1.2 metres. (13750 pulses per metre.)
Conveyor speed 5.3 metres per second . So counts per second = 5.3 x 13750 = 72875 (13.7 uS) (Conveyor moves (5300 x 13.7)/1000000 = 0.073 mm)

Object length 190mm (so object will take 190/5300 seconds to pass a point = 0.0358 seconds (36 mS)

Object spacing. 20 mm

In 30 mS conveyor moves 5300 x 30/1000mm = 5.3 x 30mm = 159mm
In 30 mS there will have been 30000/13.7 (30 mS divided by 13.7 uS.) steps of the shift register = 2189.8 steps
End of text file,
The speed of 5.3 metres per second in the above table is close to the (corrected. ) calculation of 5.278 metres per second in post #362

Les.
Thanks for the summary. After 18 pages, I know somethings there but it’s a pain to search through all the posts on my mobile phone.

daljeet795

Joined Jul 2, 2018
295
There is an error in the calculation in post #362. The result should 316680 mm/minute. ( NOT 316680 mm/s)

Les.
Thanks, @LesJones for catching that error,

Here is a text file I created some time back to save having to search through the thread for the values being used. I don't know if these values are being used at the moment. (It gets confusing when the specifications and the values keep changing.)Les.
I fully agree with you. This is also a big pain for me. I do not want to do this but I have to do it. whatever I have available at the movement I have to work with that

daljeet795

Joined Jul 2, 2018
295
.It’s important to verify that your program will work in the real world. We know it works in the theoretical world..
@djsfantasi I'm very curious to see the test result. I would test the program today I hope the program will work

djsfantasi

Joined Apr 11, 2010
7,689
@djsfantasi I'm very curious to see the test result. I would test the program today I hope the program will work
Great! Let me know how it works out...

LesJones

Joined Jan 8, 2017
3,168
Hi John,
I think I have lost track of more than the pre scaling of the encoder output by a factor of 900. I will stay out of the discussion until I have worked out the current configuration.

Les.

JohnInTX

Joined Jun 26, 2012
4,433
Hi John,
I think I have lost track of more than the pre scaling of the encoder output by a factor of 900. I will stay out of the discussion until I have worked out the current configuration.

Les.
No worries, Les. It has been through a lot of iterations. Good input is always welcome

daljeet795

Joined Jul 2, 2018
295
Great! Let me know how it works out...
Hi John,
I think I have lost track of more than the pre-scaling of the encoder output by a factor of 900. I will stay out of the discussion until I have worked out the current configuration.Les.
I have tested code but It was not working as it supposes to do. I saw the scanner doesn't trigger an accurate position. I think there may be one reason that the interrupt time is less than the scanning time

.@LesJonse I can understand that this is a little difficult to remember the specification. I am sorry because again I am posting a new calculation. I thought I should share real calculation so you can give better advice.

Now I will keep this specification until I get success
• The distance between the sensor and kicker is 400 mm long
• Object length is 40 mm
• 400 mm distance is equal to 10000 pulses of the encoder
• The distance between the sensor and scanner is 50 mm long
• let's say 7 objects fit between the sensor and the kicker
• one segment is equal to 1428 pulses
• Conveyor speed = 1400rpm * 226.2= 316680 mm/minute
• Scanner response time is 30 ms
• Kicker response time is 40 ms
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 = 0x01;
CCPR1L = 0x2C;
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 & 0x100)
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
}
}
Note: I have changed the timer register value in the program such as 700, 800, 500, 1428 1228

Last edited:

JohnInTX

Joined Jun 26, 2012
4,433
Line 87: you need the = with the logical operators. |=

Edit: only that one

Last edited:

LesJones

Joined Jan 8, 2017
3,168
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

Joined Jan 8, 2017
3,168
If I understand you code correctly you are setting / clearing bit 1 of the shift register with the scanner result but in the 30 mS the object an the shift register bit representing the object have moved on in during that time.
Here are the values you gave in post #377 plus calculations for division ratios of 1428 and 300.

Now I will keep this specification until I get success

The distance between the sensor and kicker is 400 mm long
Object length is 40 mm
400 mm distance is equal to 10000 pulses of the encoder
The distance between the sensor and scanner is 50 mm long
let's say 7 objects fit between the sensor and the kicker
one segment is equal to 1428 pulses
Conveyor speed = 1400rpm * 226.2= 316680 mm/minute ( = 5278 mm / Sec. )
Scanner response time is 30 ms
Kicker response time is 40 ms

-----------------------------------

With prescale of 1428

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

In 30 mS object moves (5278 x 30)/1000 =158.24mm So the bit in the shift register representing the object will be in bit position 4 of the shift register. (1 + 30/10.8 = ~1 +3)

-----------------------------------
With prescale of 300

1 segment = (400 x 300 )/10000 = 12.00mm (Or 12.0/5278 seconds = 0.00227 seconds = 2.27 mS)

In 30 mS object moves (5278 x 30)/1000 =158.24mm So the bit in the shift register representing the object will be in bit position 14 of the shift register (1 + 30/2.27 = ~ 1 + 13)

Les.