Question on program slowness?
I am working on a simple program to read a RPM input then display it on a serial LCD and also toggle a pin depending on the RPM set point , it works but its slow to update the reading on the lcd and also slow to toggle the output pin i have this setup on the PDB and im using the pulse generator to input a pulse to the sx for a RPM signal, you can watch in the debug window for RPM when it goes from one Hz output to the next its slow to update in the debug screen also.
Am i doing something wrong im my program or what?
Here is my code so far some i got from searching the forum and it works, just kinda slow.
[noparse][[/noparse]code]' =========================================================================
'
' File...... TEMPLATE.SXB
' Purpose... SX/B Programming Template
' Author....
' E-mail....
' Started...
' Updated...
'
' =========================================================================
'
' Program Description
'
'
' Device Settings
'
DEVICE SX28, OSCHS2, TURBO,OPTIONX,STACKX,BOR42
FREQ 20_000_000
'
' IO Pins
'
LcdTx VAR RA.1
SpeedIn PIN RB.0 INPUT SCHMITT
led PIN RB.2 output
dip pin RB.5 input pullup
DIP2 PIN RB.6 INPUT PULLUP
DIP3 PIN RB.7 INPUT PULLUP
'
' Constants
'
LcdBaud CON "T19200" ' or T2400, or T9600
LcdBkSpc CON $08 ' move cursor left
LcdRt CON $09 ' move cursor right
LcdLF CON $0A ' move cursor down 1 line
LcdCls CON $0C ' clear LCD (need 5 ms delay)
LcdCR CON $0D ' move pos 0 of next line
LcdBLon CON $11 ' backlight on
LcdBLoff CON $12 ' backlight off
LcdOff CON $15 ' LCD off
LcdOn1 CON $16 ' LCD on; no crsr, no blink
LcdOn2 CON $17 ' LCD on; no crsr, blink on
LcdOn3 CON $18 ' LCD on; crsr on, no blink
LcdOn4 CON $19 ' LCD on; crsr on, blink on
LcdLine1 CON $80 ' move to line 1, column 0
LcdLine2 CON $94 ' move to line 2, column 0
LcdCC0 CON $F8 ' define custom char 0
LcdCC1 CON $F9 ' define custom char 1
LcdCC2 CON $FA ' define custom char 2
LcdCC3 CON $FB ' define custom char 3
LcdCC4 CON $FC ' define custom char 4
LcdCC5 CON $FD ' define custom char 5
LcdCC6 CON $FE ' define custom char 6
LcdCC7 CON $FF ' define custom char 7
'
' Variables
'
idx VAR Byte
digits VAR Byte (5)
value VAR Word
tmpW1 VAR Word
RPM VAR WORD
RPS VAR Byte
idx1 VAR Byte ' loop control
char VAR Byte
'newChar VAR Byte
'pos VAR Byte ' position
SETTING VAR WORD
SETTING2 VAR WORD
'SETTING3 VAR WORD
'SETTING4 VAR WORD
temp1 VAR Byte ' subroutine work vars
temp2 VAR Byte
temp3 VAR Byte
temp4 VAR Byte
temp5 VAR Byte
'
INTERRUPT
'
' =========================================================================
PROGRAM Start
' =========================================================================
'
' Subroutines / Jump Table
'
LCD_5_DIGITS SUB 1, 2
DELAY SUB 1, 2 ' delay in milliseconds
DELAY_US SUB 1, 2 ' delay in microseconds
WAIT_MS SUB 1, 2 ' delay in milliseconds
LCD_OUT SUB 1, 2 ' send byte {+ count} to LCD
LCD_STR SUB 2 ' send string to LCD
LCD_CCHAR SUB 2 ' define custom character
'
' Program Code
'
Start:
HIGH LcdTx
WAIT_MS 100 ' let LCD initialize
LCD_STR " BOOST BY SMITH / GSXTURBO"
PAUSE 1000
LCD_OUT LcdCls
LCD_STR " GPS INTERCEPTER"
PAUSE 1000
LCD_OUT LcdCls
PAUSE 10
' 100 ms Delay for the sub LCD_OUT
Main:
LCD_OUT LcdBLon
lcd_OUT LcdOn1
lcd_OUT LcdLine1
FOR idx = 5 to 7 ' First Lable at line 1, pos 0
READ Label_1 + idx, char ' Divides it into bytes and passes the byte to the variable char
LCD_OUT char ' Sends each byte (char) to the lcd
NEXT ' Loops until the top statement is no longer true
Rpms:
' Identifies the next variable location for the cursor
Count SpeedIn, 1000, RPS ' Counts how many revolutions occured in 1 second
RPM = RPS * 60 ' Multiplying by 60 to get RPM
LCD_5_DIGITS RPM ' Sends the data to a subroutine that divides the RPM
' into individual byte #'s and then converts them to
' ASCII (the subs, LCD_5 & 3_Digits were written by Terry
' Hitt (Bean))
IF DIP2 = 0 THEN
SETTING = $170C
ELSE
IF DIP2 = 1 THEN
SETTING = $3E8
ENDIF
ENDIF
IF RPM < SETTING THEN
RB.2 = 1
ELSE
ENDIF
IF RPM > SETTING THEN
RB.2 = 0
ELSE
ENDIF
GOTO MAIN
'
' Subroutines
'
'
LCD_5_DIGITS:
IF __PARAMCNT = 1 THEN
value = __PARAM1 ' save byte value
ELSE
value = __WPARAM12
ENDIF
'Init digits to all zeros
PUT digits, "00000"
'Convert value to ascii digits
DO WHILE value >= 10000
INC digits(0)
value = value - 10000
LOOP
DO WHILE value >= 1000
INC digits(1)
value = value - 1000
LOOP
DO WHILE value >= 100
INC digits(2)
value = value - 100
LOOP
DO WHILE value >= 10
INC digits(3)
value = value - 10
LOOP
DO UNTIL value = 0
INC digits(4)
value = value - 1
LOOP
idx = 0
DO WHILE idx < 4
IF digits(idx) = "0" THEN ' IF digit is Zero...
digits(idx) = " " ' make it Blank
ELSE
idx = 4 ' Set counter to done value
ENDIF
INC idx
LOOP
' Send digits to LCD
FOR idx = 0 TO 4
char = digits(idx)
LCD_OUT char
NEXT
BREAK
WATCH RPM
RETURN
'
' Use: WAIT_MS milliseconds {, multiplier }
' -- multiplier is optional
WAIT_MS:
temp1 = __PARAM1 ' get milliseconds
IF __PARAMCNT = 1 THEN ' if no multiplier
temp2 = 1 ' set to 1
ELSE ' else
temp2 = __PARAM2 ' get multiplier
ENDIF
IF temp1 > 0 THEN ' no delay if either 0
IF temp2 > 0 THEN
PAUSE temp1 * temp2 ' do the delay
ENDIF
ENDIF
RETURN
'
' Use: DELAY ms
' -- 'ms' is delay in milliseconds, 1 - 65535
DELAY:
IF __PARAMCNT = 1 THEN
tmpW1 = __PARAM1 ' save byte value
ELSE
tmpW1 = __WPARAM12 ' save word value
ENDIF
PAUSE tmpW1
RETURN
'
' Use: DELAY us
' -- 'us' is delay in microseconds, 1 - 65535
DELAY_US:
IF __PARAMCNT = 1 THEN
tmpW1 = __PARAM1 ' save byte value
ELSE
tmpW1 = __WPARAM12 ' save word value
ENDIF
PAUSEUS tmpW1
RETURN
'
' Use: LCD_OUT theByte {, count }
' -- sends "theByte" to LCD [noparse][[/noparse]optional] "count" times
' -- "count" defaults to 1 if not specified
LCD_OUT:
temp1 = __PARAM1 ' save the byte
IF __PARAMCNT = 2 THEN ' "count" specified?
temp2 = __PARAM2 ' yes, save
ELSE
temp2 = 1 ' no, set to 1
ENDIF
DO WHILE temp2 > 0
SEROUT LcdTx, LcdBaud, temp1 ' transmit to LCD
DEC temp2
LOOP
RETURN
'
' Use: LCD_STR [noparse][[/noparse] string | label ]
' -- "string" is an embedded literal string
' -- "label" is DATA statement label for stored z-String
LCD_STR:
temp3 = __PARAM1 ' get string offset
temp4 = __PARAM2 ' get string base
DO
READ temp4 + temp3, temp5 ' read a character
IF temp5 = 0 THEN EXIT ' if 0, string complete
LCD_OUT temp5 ' send the byte
INC temp3 ' point to next character
temp4 = temp4 + Z ' update base on overflow
LOOP
RETURN
'
' Use: LCD_CCHAR CharDef
' -- loads custom character definition into serial LCD
' -- "CharDef" is DATA table that holds character number and definition
' bytes
LCD_CCHAR:
temp1 = __PARAM1 ' get definition offset
temp4 = __PARAM2 ' get definition base
FOR idx = 0 TO 8
READ temp4 + temp3, temp5 ' read a byte
LCD_OUT temp5 ' send the byte
INC temp3 ' point to next
temp4 = temp4 + Z ' update base on overflow
NEXT
RETURN
' =========================================================================
' Program Data
' =========================================================================
'
Label_1:
DATA "RPM"
Label_2:
DATA "SERP"
Label_3:
DATA "MHT1"
Label_4:
DATA "CHT2"
'
Pgm_ID:
DATA "SX/B Template", 0
Am i doing something wrong im my program or what?
Here is my code so far some i got from searching the forum and it works, just kinda slow.
[noparse][[/noparse]code]' =========================================================================
'
' File...... TEMPLATE.SXB
' Purpose... SX/B Programming Template
' Author....
' E-mail....
' Started...
' Updated...
'
' =========================================================================
'
' Program Description
'
'
' Device Settings
'
DEVICE SX28, OSCHS2, TURBO,OPTIONX,STACKX,BOR42
FREQ 20_000_000
'
' IO Pins
'
LcdTx VAR RA.1
SpeedIn PIN RB.0 INPUT SCHMITT
led PIN RB.2 output
dip pin RB.5 input pullup
DIP2 PIN RB.6 INPUT PULLUP
DIP3 PIN RB.7 INPUT PULLUP
'
' Constants
'
LcdBaud CON "T19200" ' or T2400, or T9600
LcdBkSpc CON $08 ' move cursor left
LcdRt CON $09 ' move cursor right
LcdLF CON $0A ' move cursor down 1 line
LcdCls CON $0C ' clear LCD (need 5 ms delay)
LcdCR CON $0D ' move pos 0 of next line
LcdBLon CON $11 ' backlight on
LcdBLoff CON $12 ' backlight off
LcdOff CON $15 ' LCD off
LcdOn1 CON $16 ' LCD on; no crsr, no blink
LcdOn2 CON $17 ' LCD on; no crsr, blink on
LcdOn3 CON $18 ' LCD on; crsr on, no blink
LcdOn4 CON $19 ' LCD on; crsr on, blink on
LcdLine1 CON $80 ' move to line 1, column 0
LcdLine2 CON $94 ' move to line 2, column 0
LcdCC0 CON $F8 ' define custom char 0
LcdCC1 CON $F9 ' define custom char 1
LcdCC2 CON $FA ' define custom char 2
LcdCC3 CON $FB ' define custom char 3
LcdCC4 CON $FC ' define custom char 4
LcdCC5 CON $FD ' define custom char 5
LcdCC6 CON $FE ' define custom char 6
LcdCC7 CON $FF ' define custom char 7
'
' Variables
'
idx VAR Byte
digits VAR Byte (5)
value VAR Word
tmpW1 VAR Word
RPM VAR WORD
RPS VAR Byte
idx1 VAR Byte ' loop control
char VAR Byte
'newChar VAR Byte
'pos VAR Byte ' position
SETTING VAR WORD
SETTING2 VAR WORD
'SETTING3 VAR WORD
'SETTING4 VAR WORD
temp1 VAR Byte ' subroutine work vars
temp2 VAR Byte
temp3 VAR Byte
temp4 VAR Byte
temp5 VAR Byte
'
INTERRUPT
'
' =========================================================================
PROGRAM Start
' =========================================================================
'
' Subroutines / Jump Table
'
LCD_5_DIGITS SUB 1, 2
DELAY SUB 1, 2 ' delay in milliseconds
DELAY_US SUB 1, 2 ' delay in microseconds
WAIT_MS SUB 1, 2 ' delay in milliseconds
LCD_OUT SUB 1, 2 ' send byte {+ count} to LCD
LCD_STR SUB 2 ' send string to LCD
LCD_CCHAR SUB 2 ' define custom character
'
' Program Code
'
Start:
HIGH LcdTx
WAIT_MS 100 ' let LCD initialize
LCD_STR " BOOST BY SMITH / GSXTURBO"
PAUSE 1000
LCD_OUT LcdCls
LCD_STR " GPS INTERCEPTER"
PAUSE 1000
LCD_OUT LcdCls
PAUSE 10
' 100 ms Delay for the sub LCD_OUT
Main:
LCD_OUT LcdBLon
lcd_OUT LcdOn1
lcd_OUT LcdLine1
FOR idx = 5 to 7 ' First Lable at line 1, pos 0
READ Label_1 + idx, char ' Divides it into bytes and passes the byte to the variable char
LCD_OUT char ' Sends each byte (char) to the lcd
NEXT ' Loops until the top statement is no longer true
Rpms:
' Identifies the next variable location for the cursor
Count SpeedIn, 1000, RPS ' Counts how many revolutions occured in 1 second
RPM = RPS * 60 ' Multiplying by 60 to get RPM
LCD_5_DIGITS RPM ' Sends the data to a subroutine that divides the RPM
' into individual byte #'s and then converts them to
' ASCII (the subs, LCD_5 & 3_Digits were written by Terry
' Hitt (Bean))
IF DIP2 = 0 THEN
SETTING = $170C
ELSE
IF DIP2 = 1 THEN
SETTING = $3E8
ENDIF
ENDIF
IF RPM < SETTING THEN
RB.2 = 1
ELSE
ENDIF
IF RPM > SETTING THEN
RB.2 = 0
ELSE
ENDIF
GOTO MAIN
'
' Subroutines
'
'
LCD_5_DIGITS:
IF __PARAMCNT = 1 THEN
value = __PARAM1 ' save byte value
ELSE
value = __WPARAM12
ENDIF
'Init digits to all zeros
PUT digits, "00000"
'Convert value to ascii digits
DO WHILE value >= 10000
INC digits(0)
value = value - 10000
LOOP
DO WHILE value >= 1000
INC digits(1)
value = value - 1000
LOOP
DO WHILE value >= 100
INC digits(2)
value = value - 100
LOOP
DO WHILE value >= 10
INC digits(3)
value = value - 10
LOOP
DO UNTIL value = 0
INC digits(4)
value = value - 1
LOOP
idx = 0
DO WHILE idx < 4
IF digits(idx) = "0" THEN ' IF digit is Zero...
digits(idx) = " " ' make it Blank
ELSE
idx = 4 ' Set counter to done value
ENDIF
INC idx
LOOP
' Send digits to LCD
FOR idx = 0 TO 4
char = digits(idx)
LCD_OUT char
NEXT
BREAK
WATCH RPM
RETURN
'
' Use: WAIT_MS milliseconds {, multiplier }
' -- multiplier is optional
WAIT_MS:
temp1 = __PARAM1 ' get milliseconds
IF __PARAMCNT = 1 THEN ' if no multiplier
temp2 = 1 ' set to 1
ELSE ' else
temp2 = __PARAM2 ' get multiplier
ENDIF
IF temp1 > 0 THEN ' no delay if either 0
IF temp2 > 0 THEN
PAUSE temp1 * temp2 ' do the delay
ENDIF
ENDIF
RETURN
'
' Use: DELAY ms
' -- 'ms' is delay in milliseconds, 1 - 65535
DELAY:
IF __PARAMCNT = 1 THEN
tmpW1 = __PARAM1 ' save byte value
ELSE
tmpW1 = __WPARAM12 ' save word value
ENDIF
PAUSE tmpW1
RETURN
'
' Use: DELAY us
' -- 'us' is delay in microseconds, 1 - 65535
DELAY_US:
IF __PARAMCNT = 1 THEN
tmpW1 = __PARAM1 ' save byte value
ELSE
tmpW1 = __WPARAM12 ' save word value
ENDIF
PAUSEUS tmpW1
RETURN
'
' Use: LCD_OUT theByte {, count }
' -- sends "theByte" to LCD [noparse][[/noparse]optional] "count" times
' -- "count" defaults to 1 if not specified
LCD_OUT:
temp1 = __PARAM1 ' save the byte
IF __PARAMCNT = 2 THEN ' "count" specified?
temp2 = __PARAM2 ' yes, save
ELSE
temp2 = 1 ' no, set to 1
ENDIF
DO WHILE temp2 > 0
SEROUT LcdTx, LcdBaud, temp1 ' transmit to LCD
DEC temp2
LOOP
RETURN
'
' Use: LCD_STR [noparse][[/noparse] string | label ]
' -- "string" is an embedded literal string
' -- "label" is DATA statement label for stored z-String
LCD_STR:
temp3 = __PARAM1 ' get string offset
temp4 = __PARAM2 ' get string base
DO
READ temp4 + temp3, temp5 ' read a character
IF temp5 = 0 THEN EXIT ' if 0, string complete
LCD_OUT temp5 ' send the byte
INC temp3 ' point to next character
temp4 = temp4 + Z ' update base on overflow
LOOP
RETURN
'
' Use: LCD_CCHAR CharDef
' -- loads custom character definition into serial LCD
' -- "CharDef" is DATA table that holds character number and definition
' bytes
LCD_CCHAR:
temp1 = __PARAM1 ' get definition offset
temp4 = __PARAM2 ' get definition base
FOR idx = 0 TO 8
READ temp4 + temp3, temp5 ' read a byte
LCD_OUT temp5 ' send the byte
INC temp3 ' point to next
temp4 = temp4 + Z ' update base on overflow
NEXT
RETURN
' =========================================================================
' Program Data
' =========================================================================
'
Label_1:
DATA "RPM"
Label_2:
DATA "SERP"
Label_3:
DATA "MHT1"
Label_4:
DATA "CHT2"
'
Pgm_ID:
DATA "SX/B Template", 0
Comments
I think that you may want to try and move some of the code into an Interrupt routine so that some of the tasks can be done in the background. JonnyMac has written some excellent ISR based serial RX/TX routines and you could use that to send out the data to the serial LCD in the background while your main code can do the calculations to determine what to display and when to toggle the output. For best performance you may want to try and move the counting to the ISR as well.
As it stands now there are a few places where your program will slow down (counting pulses, and sending data to LCD) that will cause the program to act as you describe.
Hope this gives you a few ideas on what could be done.
Robert
You could try using:
Count SpeedIn, 100, RPS ' Counts how many revolutions occured in 0.1 second
RPM = RPS * 600 ' Multiplying by 600 to get RPM
This will make the program 10 times faster, but the resolution will be 600 RPM instead of 60 RPM.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
·The next time you need a hero don't look up in the sky...Look in the mirror.
·
Im sure i will be back for more questions.LOL