geezer88
Senior Member
I've posted this in code snippets because this is working, but not finished, and won't be. However, parts may be useful to folks. The LCD code supports four bit interface. The retro-reflective photo proximity sensor uses a one transistor amplifier and a photo diode and LED from a junk inkjet printer. My MPU is a 18M2.
RPM is one of several rate related calculations that typically drives the need to divide a 16 or 32 bit word by a 16 word. Jeremy Leach, a poster in this forum, wrote a math routine set, and this division was stolen from his work. See the listing remarks for more about his work, and where to get it from this forum.
Leading zero suppression is another need for a project like this, and for this I used the routine from inglewoodpete. Again, see the listing for more info.
tom
RPM is one of several rate related calculations that typically drives the need to divide a 16 or 32 bit word by a 16 word. Jeremy Leach, a poster in this forum, wrote a math routine set, and this division was stolen from his work. See the listing remarks for more about his work, and where to get it from this forum.
Leading zero suppression is another need for a project like this, and for this I used the routine from inglewoodpete. Again, see the listing for more info.
tom
Code:
#rem
TACHOMETER WITH PHOTO DIODE REFLECTIVE PROXIMITY INPUT Tom 5/26/2011
This program implements a simple photo tachometer using a photo diode and LED from scrounged
from a dead printer. Ambient light makes an imact on operation, so a variable resistor is
used to adjust for stable operation.
#endrem
'* Pin Assignments **************************************
'LCD pin 6 = SE = c.6 = pin 15 CPU
'LCD pin 4 = RS = c.7 = pin 16 CPU
'LCD pin 11 = D4 = b.4 = pin 10 CPU
'LCD pin 12 = D5 = b.5 = pin 11 CPU
'LCD pin 13 = D6 = b.6 = pin 12 CPU
'LCD pin 14 = D7 = b.7 = pin 13 CPU
'phototransistor input = b.0
'* Symbols ************************************************
symbol LcdSE = c.6 'strobe data pin
symbol LcdRS = c.7 'data direction pin (read/write)
symbol LcdByte = b0 'data byte sent to LCD
symbol tthous = b5 'result of bintoascii command
symbol thous = b4 'result of bintoascii command
symbol huns = b3 'result of bintoascii command
symbol tens = b2 'result of bintoascii command
symbol ones = b1 'result of bintoascii command
symbol j = b6 'scratch variable
symbol i = b5 'scratch variable *SHARED WITH tthous*
symbol scratchword = w5 'scratch word variable *SHARED WITH WORDB*
symbol WordA = w4 'one of two word multiplied to create a 32 bit numerator
symbol WordB = w5 'second word to be multiplied
symbol WordC = w6 'denominator word in my case the pulsein value
symbol LSW = w7 'least significant word of the numerator
symbol MSW = w8 'most significant work of the numerator
symbol wholew = w9 'whole word part of some calculations
symbol remain = w10 'remainder of some calculations
symbol Fwhole = w11 'final whole word part of the finished calculation
symbol Fremain = w12 'final remainder word of the finished calc. I don't use
symbol scratch = w13 'scratch variable I don't understand
' ****Set Up LCD ****
EEPROM 0, ("RPM = ") 'load static text
gosub LCD_Init 'get lcd ready
For j = 0 to 5
read j, LcdByte
gosub LCD_WrChr 'write the message
next j
do ' ****Main Loop****
'****Get preliminary rotation period to allow calculation of average without overflow
WordC = 0 'zero variable for rotation period
pulsin b.0, 0, scratchword 'get reflected light part of rotation
pause 2
pulsin b.0, 1, WordC 'get dark part of rotation
pause 2
WordC = WordC + scratchword 'add to get total time of revolution in 10 usecs
i = 60000 / WordC max 10 'i will be number of samples to average without overflow
'****Now begin getting data to display
WordC = 0 'zero variable for rotation period
for j = 1 to i 'begin collecting rotation times
pulsin b.0,1,scratchword 'get reflected light part of rotation
pause 2
pulsin b.0,0,scratchword 'get dark part of rotation
pause 2
WordC = WordC + scratchword 'add to get total time of revolution in 10 usecs
next j
WordC = WordC / i 'calculate average of "i" readings
'****Initialize a few variables
Fwhole = 0
Fremain = 0
WordA = 6000
WordB = 1000
'****Loop to get RPM = 6000000 / WordC
#rem
This routine was stolen from Jeremy Leach via a posting he made on the PicAxe Forum.
It was a modularized routine from a larger collection of math functions that he wrote.
I have modified it to run as part a simpler program. I confess to not understanding
all that goes on in the routine, but I have checked it for accuracy in one specialized
application for a tachometer. In this special case, the RPM of a rotating shaft is
related to the time of rotation using pulsein, measured in units of 10 usec. The
resulting equation is: RPM = 6000000 / pulsein word. So for this case, I used
6000 for WordA, 1000 for WordB which multiplied make 6 million. WordC is the 16 bit word
resulting from pulsein. For 12000 RPM pulsein is 500. For 100 RPM pulsein is
60048; nearly up to the 65535 limit of a word varible.
For the whole enchalada see: http://www.picaxeforum.co.uk/showpost.php?p=75560&postcount=1
#endrem
do
MSW = WordA ** WordB
LSW = WordA * WordB
wholew = 65535 / WordC * MSW
remain = 0
gosub Update
wholew = LSW / WordC
remain = LSW // WordC
gosub Update
WordA = 65535 // WordC + 1
WordB = MSW
loop until WordB = 0 'calculation is finished
'****This neat leading zero procedure came from inglewoodpete of PicAxe forum fame
'****See this post: http://www.picaxeforum.co.uk/showpost.php?p=154989&postcount=16
bintoascii Fwhole, tthous, thous, huns, tens, ones
if tthous = "0" then
tthous = " "
if thous = "0" then
thous = " "
if huns = "0" then
huns = " "
if tens = "0" then
tens = " "
endif
endIf
endIf
endIf
LcdByte = $86 'move cursor two spaces past equal sign
gosub LCD_WrIns
LcdByte = tthous 'print tenthousands
gosub LCD_WrChr
LcdByte = thous 'print thousands
gosub LCD_WrChr
LcdByte = huns 'print hundreds
gosub LCD_WrChr
LcdByte = tens 'print tens
gosub LCD_WrChr
LcdByte = ones 'print ones
gosub LCD_WrChr
loop 'return to beginning of main loop
end
'* Initialise LCD *****************************************
LCD_Init:
'set relevant pins to output
dirsb = %11110000
dirsc = %11000000
low LcdRS
low LcdSE
'wait for LCD to stabilise (>40ms after Vcc > 2.7V)
pause 100
'send 00110000 three times to initialise LCD by instruction
outpinsb = %00110000
pause 1
pulsout c.6,1000
pause 1
pulsout c.6,1000
pause 1
pulsout c.6,1000
pause 1
outpinsb = %00100000 'set to 4 bit mode
pause 1
pulsout c.6,1000
LcdByte = %00101000 'set interface
pause 1
gosub LCD_WrIns
LcdByte = %00001100 'enable display, no cursor
pause 1
gosub LCD_WrIns
LcdByte = %00000001 'clear and home cursor
pause 1
gosub LCD_WrIns
LcdByte = %00000110 'set cursor direction
pause 1
gosub LCD_WrIns
return
'* Display Character On LCD *******************************
LCD_WrChr:
high LcdRS 'set RS high (write data)
pause 1
outpinsb = LcdByte and %11110000
pause 2
pulsout LcdSE,1
outpinsb = LcdByte * 16
pause 2
pulsout LcdSE,1
return
'* Send Instruction to LCD ********************************
LCD_WrIns:
low LcdRS 'set RS low (write instruction)
pause 1
outpinsb = LcdByte and %11110000
pause 1
pulsout LcdSE,1
outpinsb = LcdByte * 16
pause 1
pulsout LcdSE,1
return
'* Clear LCD **********************************************
LCD_Clear:
LcdByte = 1
pause 1
gosub LCD_WrIns
return
'* Home Cursor *******************************************
LCD_Home:
LcdByte = 2
pause 1
gosub LCD_WrIns
return
'* Move To Line 1 *****************************************
LCD_Line1:
LcdByte = 128
pause 1
gosub LCD_WrIns
return
'* Move To Line 2 *****************************************
LCD_Line2:
LcdByte = 192
pause 1
gosub LCD_WrIns
return
'* Move To Line 3 *****************************************
LCD_Line3:
LcdByte = 148
pause 1
gosub LCD_WrIns
return
'* Move To Line 4 *****************************************
LCD_Line4:
LcdByte = 212
pause 1
gosub LCD_WrIns
return
'*Update the divide function; read Jeremy Leach document for how it works
Update:
scratch = WordC - Fremain
Fremain = Fremain + remain
if remain >= scratch then
Fremain = Fremain - WordC
inc wholew
endif
Fwhole = Fwhole + wholew
return
Attachments
-
38.8 KB Views: 169
-
86.5 KB Views: 168
Last edited: