PDA

View Full Version : revolution counter



lerameur
- 22nd October 2008, 04:55
Hi,

I want to use the COunter command to count the number of revolution I make on a pulley. The speed is variable, therefore I do not know how count will work. Also the counte command requires a period of time, like 1 second in the manual, but I do not want this, s the wheel might be turning for 5 minutes or longer.
How should I go about calculating the revolution?
I have black and white wheel encoder, with a sensor reading the analog output to digital.

ken

mackrackit
- 22nd October 2008, 06:47
What else will be going on at the same time? Any idea how many times the wheel will turn and how fast?

aratti
- 22nd October 2008, 08:51
You must also tell us how many pulses per turn will generate your encoder.

lerameur
- 22nd October 2008, 12:36
I am making a coiling machine and will be passing the wiring into a small pulley. The pulley will have four sections, two white and two black. The sensor will be reading the encoder , there will be small led lighting the encoder from behind.
Therefore the speed I do not know, and it is not important, it will be going in one direction. I will be counting four changes for one revolution.
Here is a program I just wrote, have not tried it yet,

'Get initil value
ADCON0.2 = 1 'Start Conversion
ADCIN 1, OldOutput_Pot 'analog pin 1 (RA1) get the 8 bit result
pause 50
if OldOutput_Pot > 127 then
OldOutput_Pot =1
endif
if OldOutput_Pot < 128 then
OldOutput_Pot =0
endif

Mainloop:

ADCON0.2 = 1 'Start Conversion
ADCIN 1, Output_Pot 'analog pin 1 (RA1) get the 8 bit result
pause 50

'Calculate the distance
if Output_Pot > 127 then
Output_Pot =1
endif
if Output_Pot < 128 then
Output_Pot =0
endif

if OldOutput_Pot == Output_Pot then
goto Mainloop
endif
if OldOutput_Pot != Output_Pot then
counter = counter +1 'If oldOutput_pot is different then Output_pot
OldOutput_Pot = Output_Pot
if counter =4 then
Revolution = Revolution + 1
counter =0
endif
endif

lcdout $FE,1, "Counter:",dec counter
lcdout $FE,$C0, "Revolution:",dec Revolution
pause 150


GOTO Mainloop
end

Jerson
- 22nd October 2008, 12:58
Ken

What kind of encoder are you using here? Usually an encoder would give out digital pulses. But, you seem to be using the ADC to decode it. I would suggest that you look at the possibility of counting the pulses via an interrupt. This will keep your mainline code free for other tasks. Darrell Taylor has some nice code that can kickstart you in that direction. Just search for it on this site.

Jerson

lerameur
- 22nd October 2008, 13:21
My program is not outputting anything, I think it is a initilizing problem but I do not know what:
I am posting the header:
can some one help me:

' Internal Oscillation program
' A/D testing -RA.1
' LCD

'/////////////////////////
'// Define section //
'/////////////////////////

INCLUDE "modedefs.bas"
@ DEVICE pic16F88 MCLR_ON, INTRC_OSC, WDT_ON, LVP_OFF, BOD_OFF, PWRT_ON, PROTECT_OFF, CCPMX_ON
OSCCON=$60 ' use internal 4MHZ osc

ANSEL = %01000010 ' set AN1 (RA1) as analog, others to digital
ADCON1 = %00000000 ' Left justified results in 8 bits
ADCON0 = %10001001 ' Configure and turn on A/D Module
CMCON = 7 ' Disable analog comparator

'/////////////////////////
'// LCD configuration //
'/////////////////////////

DEFINE LCD_DREG PORTB ' Set LCD Data port
DEFINE LCD_DBIT 4 ' Set starting Data bit (0 or 4) if 4-bit bus

DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 1 ' Set LCD Register Select bit

DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 0 ' Set LCD Enable bit

DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits) '4 therefore put wire at 4, 5, 6 and 7 of LCD

DEFINE LCD_LINES 2 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2500
DEFINE LCD_DATAUS 250
DEFINE CHAR_PACING 2000
pause 2000


TRISB = %00000000 ' Set PORTB to all output
TRISA = %11111111 ' Set PORTA to all input


'///////////////////////////////////////////////
'// Variable Declaration and initialization //
'///////////////////////////////////////////////
Output_Pot var byte
OldOutput_Pot var byte
Revolution var word
counter var byte

revolution = 0
Output_Pot = 0
OldOutput_Pot = 0
counter = 0
'Get initil value
ADCON0.2 = 1 'Start Conversion
ADCIN 1, OldOutput_Pot 'analog pin 1 (RA1) get the 8 bit result
pause 50
if OldOutput_Pot > 127 then
OldOutput_Pot =1
endif
if OldOutput_Pot < 128 then
OldOutput_Pot =0
endif

Mainloop:

lerameur
- 22nd October 2008, 13:24
Jerson,

this is very simple encoder. I have light to voltage chip, reading the encoder, the encoder is divided into 4 sections, 2 white and two black, read black show ADC below 127 and white ADC above 127.

ken

mackrackit
- 22nd October 2008, 13:37
Jerson,

this is very simple encoder. I have light to voltage chip, reading the encoder, the encoder is divided into 4 sections, 2 white and two black, read black show ADC below 127 and white ADC above 127.

ken

So black is 0 volts and white is 5 volts?

skimask
- 22nd October 2008, 13:41
I have light to voltage chip,
That's a SOLAR CELL! :)


reading the encoder, the encoder is divided into 4 sections, 2 white and two black, read black show ADC below 127 and white ADC above 127.
I get the feeling you might end up making a small program just to test the ability of your sensor to read the black/white patches in the first place rather than assuming your sensor/PIC will read everything the way you hope it will. Something like this:



........setup.........
ledout var port...some port here
main: adcon0.2=1 'Start Conversion
waitonadc: if adcon0.2 = 1 then waitonadc
oldoutput_pot = adresh *256 + adresl
if oldoutput_pot > 127 then
ledout = 1
else
ledout = 0
endif
goto main

Change the value 127 above to find a 'trip point' for the counter itself.
See what happens with that. If that works for you, then you should be all set.
(Also, you may want to check the manual for your use of the ADCIN command)

Acetronics2
- 22nd October 2008, 14:04
That's a SOLAR CELL! :)



Not compulsory ...

OPB 608/704 / CNY 70 i.e. are reflective Opto-couplers ...

Alain

lerameur
- 22nd October 2008, 14:10
I just want to count the revolution, so even if the trip point is not on the 'dot' it do not matter. What matters here is that I want to be able to calculate the transitions from black to white and white to black. After four transistions I get a revolution .
The problem in my program is that it is not showing anything on the LCD.

ken

lerameur
- 22nd October 2008, 14:19
crap.. I forgot to define my ADC:

Define ADC_BITS 8 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

ken

skimask
- 22nd October 2008, 14:21
I just want to count the revolution, so even if the trip point is not on the 'dot' it do not matter. What matters here is that I want to be able to calculate the transitions from black to white and white to black. After four transistions I get a revolution .
The problem in my program is that it is not showing anything on the LCD.
Right, but if it's not tripping in the first place, you won't get any counts in the last place...
And the ADC, yes, that's part of it. The other part is 'starting' the ADC itself.

mackrackit
- 22nd October 2008, 14:22
crap.. I forgot to define my ADC:

Define ADC_BITS 8 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

ken

So it is working now???

lerameur
- 22nd October 2008, 14:48
I dont know if it works, I m at work now, I will see when I get home tonight

skimask, what do you mean by tripping?
:is this it...

ADCON0.2 = 1 'Start Conversion
ADCIN 1, Output_Pot 'analog pin 1 (RA1) get the 8 bit result

mackrackit
- 22nd October 2008, 14:48
The problem in my program is that it is not showing anything on the LCD.

Or is this the problem


DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits) '4 therefore put wire at 4, 5, 6 and 7 of LCD

skimask
- 22nd October 2008, 15:26
Ok, I see there's 2 places where I could be 'tripping' ! :D

1st tripping - by that I mean the point where the ADCIN routine distinguishes between the light and dark area of the disc.

2nd tripping - Do you see this phrase anywhere in the manual?


ADCON0.2 = 1 'Start Conversion

I.E. YOU don't need to start the A/D conversion, ADCIN does that for you.

Jerson
- 22nd October 2008, 15:59
Jerson,

this is very simple encoder. I have light to voltage chip, reading the encoder, the encoder is divided into 4 sections, 2 white and two black, read black show ADC below 127 and white ADC above 127.

ken

Precisely. Depending on the way you've wired the sensor, you could see a logic 1 for black or a logic 0 for black. You can just read the digital input after configuring the pins tris register for input mode. Easier than reading the ADC and all its associated overhead. This overhead would eventually cause you to lose counts. I will still prod you into looking at the interrupt option.

What you've done will work, but at speeds relatively slower than the speed at which you read the ADC.

A simple routine could have an interrupt set up possibly on RB0. And the interrupt code would do something as simple as this



CounterISR:
dummyread = PortB ' clear the cause of the interrupt
Counter = Counter+1
return ' from interrupt


This code will ensure that you catch each and every pulse that comes its way irrespective of the Pauses in your mainline code.

This code is just a guide, please dont hold me to it.

JF

lerameur
- 22nd October 2008, 16:18
OOo I get the digital part now, no need for ADC.
I have never used interrupt, can you explain the code snippet you provided above?


should this work?

Mainloop:

'Calculate the distance
Output_Pot = PortB.3

if OldOutput_Pot == Output_Pot then
goto Mainloop
endif
if OldOutput_Pot != Output_Pot then
counter = counter +1 'If oldOutput_pot is different then Output_pot
OldOutput_Pot = Output_Pot
if counter =4 then
Revolution = Revolution + 1
counter =0
endif
endif

lcdout $FE,1, "Counter:",dec counter
lcdout $FE,$C0, "Revolution:",dec Revolution
pause 150

GOTO Mainloop
end

ken

lerameur
- 22nd October 2008, 23:51
still nothing showing on the lcd...

k

skimask
- 23rd October 2008, 00:10
Well, then get rid of the digital inputs and make sure the LCD is working in the first place...

And besides, in the beginning of the program, OldOutput_Pot = 0 and Output_Pot = 0 therefore, they're both equal and Mainloop keeps executing! Unless you've preset one or the other to a different value...

lerameur
- 23rd October 2008, 00:42
I got the circuit working now without the ADC, thats the one I will use.
BUT,I also tried the ADC, it only works in 10 bit mode when I try the 8 bit mode, nothing appears on the LCD. Here the progrm, but before here is the two lines I changed for the 8 bit mode:

ADCON1 = %10000010
Define ADC_BITS 8 ' Set number of bits in result

why is this happening?

INCLUDE "modedefs.bas" 'Includes supoprt for PicBasic language
@ DEVICE pic16F88, INTRC_OSC, CCPMX_ON
OSCCON=$60 ' use internal 4MHZ osc

ANSEL = 0
CMCON = 7 ' Turn OFF the comparators so pins can be used as digital I/O-pins
ADCON1 = %00000010 ' Analog to digital configuration register (ADCON)
' Set PORTA to digital

' Define ADCIN parameters
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

ADCON1 = %10000010 ' Analog to digital configuration register (ADCON)
' Set PORTA to digital

'/////////////////////////
'// LCD configuration //
'/////////////////////////

DEFINE LCD_DREG PORTB ' Set LCD Data port
DEFINE LCD_DBIT 4 ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 1 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 0 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits) '4 therefore put wire at 4, 5, 6 and 7 of LCD
DEFINE LCD_LINES 2 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2500
DEFINE LCD_DATAUS 250
DEFINE CHAR_PACING 2000
pause 1000


'/////////////////////////
'// PIN configuration //
'/////////////////////////

TRISA = %11100111 ' Set PORTA to all input
TRISB = %00001100 ' Set PORTB to all output
PortA = 0

'///////////////////////////////////////////////
'// Variable Declaration and initialization //
'///////////////////////////////////////////////
Output_Pot var byte
OldOutput_Pot var byte
Revolution var word
counter var byte

revolution = 0
Output_Pot = 0
OldOutput_Pot = 0
counter = 0

'Get initial value
'ADCON0.2 = 1 'Start Conversion
ADCIN 1, OldOutput_Pot 'analog pin 1 (RA1) get the 8 bit result
pause 50
if OldOutput_Pot > 512 then
OldOutput_Pot =1
else
OldOutput_Pot =0
endif

Mainloop:

'ADCON0.2 = 1 'Start Conversion
ADCIN 1, Output_Pot 'analog pin 1 (RA1) get the 8 bit result
pause 50

'Calculate the distance
if Output_Pot > 512 then
Output_Pot =1
else
Output_Pot =0
endif

if OldOutput_Pot == Output_Pot then
goto Mainloop
endif
if OldOutput_Pot != Output_Pot then
counter = counter +1 'If oldOutput_pot is different then Output_pot
OldOutput_Pot = Output_Pot
if counter =4 then
Revolution = Revolution + 1
counter =0
endif
endif

lcdout $FE,1, "Counter:",dec counter
lcdout $FE,$C0, "Revolution:",dec Revolution
pause 150


GOTO Mainloop
end

skimask
- 23rd October 2008, 00:55
BUT,I also tried the ADC, it only works in 10 bit mode when I try the 8 bit mode, nothing appears on the LCD. Here the progrm, but before here is the two lines I changed for the 8 bit mode:
Did you set it for left justify or right justify? Makes a difference...

lerameur
- 23rd October 2008, 01:41
it is in the code above:

with this it works:
ADCON1 = %00000010
Define ADC_BITS 10 ' Set number of bits in result


but not:

ADCON1 = %10000010
Define ADC_BITS 8 ' Set number of bits in result

skimask
- 23rd October 2008, 03:12
Right, with one you're putting the 10 bit value (justified left) into a byte, with the other, you're putting the 10 bit value (justified right) into a byte, trying to stuff 10 bits into a spot for 8 bits.
So, with one, you get the lower 8 bits of the 10 bits, with the other you get the upper 8 bits of the 10 bits.
Which one is it? That's for you to figure out....(hint: if you use a word variable for reading, you'll figure it out quickly if you also use the LCD to display that value)

lerameur
- 23rd October 2008, 14:32
I am using the same config as the sample program on melabs:
http://www.melabs.com/resources/samples/pbp/adcin8.bas

as you can see mine is not working.

k

skimask
- 23rd October 2008, 14:35
I am using the same config as the sample program on melabs:
http://www.melabs.com/resources/samples/pbp/adcin8.bas
as you can see mine is not working.
k

Except that they're using 8 bits and a byte, and you tried using 10 bits and a byte.
(hint: see the hint above about the hint in post #25)

lerameur
- 23rd October 2008, 15:42
oups, ok i was sleepy last night,


thanks for your help

ken

skimask
- 23rd October 2008, 16:00
oups, ok i was sleepy last night,
thanks for your help
ken

All good then?

lerameur
- 23rd October 2008, 19:01
Yep its good,

I am just working on reset, so many options, I just want to put zero my values in a push of a button, I think I will just use a pin low pin high, and a loop in my program that verifies this pin.
I read about power on reset, but I never used it and it is unclear in the documentation I read so far.

k