Help with variable types
I am building a temperature controller for a greenhouse stove so I don't have time to properly search this out for myself, so I ask your help. Why cannot I use "addr = SDEC temp"? how would I go about doing this? everything else works as advertised, but this one last thing... here is the whole code, very messy and big, but so be it for this time. Thank you in advance. ~Lawrence
' ========================================================================= ' ' File....... LCD_AppMod_Demo.BS2 ' Purpose.... Demonstrates the LCD Terminal AppMod ' Author..... Parallax, Inc. (Copyright 2003-04, All Rights Reserved) ' E-mail..... support@parallax.com ' Started.... ' Updated.... 13 JAN 2004 ' ' {$STAMP BS2} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[noparse][[/noparse] Program Description ]--------------------------------------------- ' ' This program demonstrates the use of the Parallax LCD Terminal AppMod ' with any BS2-series microcontroller. This program uses conditional ' compilation techniques which make it completely BS2-agnostic. Custom ' character generation and animation is demonstrated. ' -----[noparse][[/noparse] I/O Definitions ]------------------------------------------------- E PIN 1 ' LCD Enable (1 = enabled) RW PIN 2 ' Read/Write\ RS PIN 3 ' Reg Select (1 = char) LcdDirs VAR DIRB ' dirs for I/O redirection LcdBusOut VAR OUTB LcdBusIn VAR INB ' -----[noparse][[/noparse] Constants ]------------------------------------------------------- #DEFINE _LcdReady = ($STAMP = BS2P) OR ($STAMP = BS2PE) LcdCls CON $01 ' clear the LCD LcdHome CON $02 ' move cursor home LcdCrsrL CON $10 ' move cursor left LcdCrsrR CON $14 ' move cursor right LcdDispL CON $18 ' shift chars left LcdDispR CON $1C ' shift chars right LcdDDRam CON $80 ' Display Data RAM control LcdCGRam CON $40 ' Character Generator RAM LcdLine1 CON $80 ' DDRAM address of line 1 LcdLine2 CON $C0 ' DDRAM address of line 2 LcdScrollTm CON 150 ' LCD scroll timing (ms) ' -----[noparse][[/noparse] Variables ]------------------------------------------------------- addr VAR Word ' address pointer crsrPos VAR Byte ' cursor position char VAR Byte ' character sent to LCD idx VAR Byte ' loop counter scan VAR Byte ' loop counter buttons VAR Nib btnA VAR buttons.BIT0 ' left-most button btnB VAR buttons.BIT1 btnC VAR buttons.BIT2 btnD VAR buttons.BIT3 ' right-most btnDemo VAR Byte ' loop counter set VAR Word ' set temp Msg4t VAR Word onOff VAR Byte servoPos VAR Word sign2 VAR servoPos.BIT15 ' ===================== Define Pins and Variables for DS1620================ DQ CON 15 ' Pin 2 <=> DQ. CLK CON 14 ' Pin 1 => CLK. RST CON 13 ' Pin 0 => RST (high = active). DSdata VAR Word ' Word variable to hold 9-bit data. DSdataC VAR Word ' Word variable to hold 9-bit data. DSdataF VAR Word ' Word variable to hold 9-bit data. Sign VAR DSdata.BIT8 ' Sign bit of raw temperature data. T_sign VAR Bit ' Saved sign bit for converted temperature. ' ===================== Define DS1620 Constants =================== ' >>> Constants for configuring the DS1620 Rconfig CON $AC ' Protocol for 'Read Configuration.' Wconfig CON $0C ' Protocol for 'Write Configuration.' CPU CON %10 ' Config bit: serial thermometer mode. NoCPU CON %00 ' Config bit: standalone thermostat mode. OneShot CON %01 ' Config bit: one conversion per start request. Cont CON %00 ' Config bit: continuous conversions after start. ' >>> Constants for serial thermometer applications. StartC CON $EE ' Protocol for 'Start Conversion.' StopC CON $22 ' Protocol for 'Stop Conversion.' Rtemp CON $AA ' Protocol for 'Read Temperature.' ' >>> Constants for programming thermostat functions. RhiT CON $A1 ' Protocol for 'Read High-Temperature Setting.' WhiT CON $01 ' Protocol for 'Write High-Temperature Setting.' RloT CON $A2 ' Protocol for 'Read Low-Temperature Setting.' WloT CON $02 ' Protocol for 'Write Low-Temperature Setting.' ' -----[noparse][[/noparse] EEPROM Data ]----------------------------------------------------- CC0 DATA $0E, $1F, $1C, $18, $1C, $1F, $0E, $00 ' char 0 CC1 DATA $0E, $1F, $1F, $18, $1F, $1F, $0E, $00 ' char 1 CC2 DATA $0E, $1F, $1F, $1F, $1F, $1F, $0E, $00 ' char 2 Smiley DATA $0E, $0A, $0E, $00, $00, $00, $00, $00 ' smiley Deg DATA $0E, $0A, $0E, $00, $00, $00, $00, $00 ' degree sign Msg1 DATA "Starting" Msg20 DATA "Heat Off" Msg21 DATA "Heat On" Msg3 DATA " Set At " Msg4 DATA 3, "F " ' -----[noparse][[/noparse] Initialization ]-------------------------------------------------- Initialize: NAP 5 ' let LCD self-initialize DIRL = %11111110 ' setup pins for LCD LCD_Init: #IF _LcdReady #THEN LCDCMD E, %00110000 : PAUSE 5 ' 8-bit mode LCDCMD E, %00110000 : PAUSE 0 LCDCMD E, %00110000 : PAUSE 0 LCDCMD E, %00100000 : PAUSE 0 ' 4-bit mode LCDCMD E, %00101000 : PAUSE 0 ' 2-line mode LCDCMD E, %00001100 : PAUSE 0 ' no crsr, no blink LCDCMD E, %00000110 ' inc crsr, no disp shift #ELSE LcdBusOut = %0011 ' 8-bit mode PULSOUT E, 3 : PAUSE 5 PULSOUT E, 3 : PAUSE 0 PULSOUT E, 3 : PAUSE 0 LcdBusOut = %0010 ' 4-bit mode PULSOUT E, 3 char = %00101000 ' 2-line mode GOSUB LCD_Command char = %00001100 ' on, no crsr, no blink GOSUB LCD_Command char = %00000110 ' inc crsr, no disp shift GOSUB LCD_Command #ENDIF Download_Chars: ' download custom chars char = LcdCGRam ' point to CG RAM GOSUB LCD_Command ' prepare to write CG data FOR idx = CC0 TO (Smiley + 7) ' build 4 custom chars READ idx, char ' get byte from EEPROM GOSUB LCD_Write_Char ' put into LCD CG RAM NEXT ' -----[noparse][[/noparse] Program Code ]---------------------------------------------------- Main: set = 74 ' default temp char = LcdCls ' clear the LCD GOSUB LCD_Command PAUSE 500 Write_Splash: addr = Msg1 ' point to message GOSUB LCD_Put_String ' write it PAUSE 1000 Initialize_DS1620: LOW RST ' Deactivate '1620 for now. HIGH CLK ' Put clock in starting state. PAUSE 100 ' Let things settle down a moment. HIGH RST ' Activate the '1620 and set it for continuous.. SHIFTOUT DQ,CLK,LSBFIRST,[noparse][[/noparse]Wconfig,CPU+Cont] ' ..temp conversions. LOW RST ' Done--deactivate. PAUSE 50 ' Wait for the EEPROM to self-program. HIGH RST ' Now activate it again and send the.. SHIFTOUT DQ,CLK,LSBFIRST,[noparse][[/noparse]StartC] ' Send start-conversion protocol. LOW RST ' Done--deactivate. Show_Buttons: char = LcdCls ' clear the LCD GOSUB LCD_Command PAUSE 100 'addr = Msg4 ' write "Buttons:" 'GOSUB LCD_Put_String MainLoop: DO ' Main Loop FOR btnDemo = 1 TO 100 STEP 2 ' read temp once IF btnDemo = 1 THEN GOSUB Get_Temp char = LcdLine1 + 2 GOSUB LCD_Command addr = DSdataF ' write temp in F GOSUB LCD_Put_String ENDIF GOSUB servo char = LcdLine2 + 0 ' show on 2nd line GOSUB LCD_Command IF btnDemo = 1 THEN addr = SDEC set GOSUB LCD_Put_String ELSEIF btnDemo = 61 THEN IF set < DSdataF THEN addr = Msg20 ELSE addr = Msg21 ENDIF ELSEIF btnDemo = 81 THEN addr = Msg3 ENDIF GOSUB LCD_Put_String 'GOSUB LCD_Write_Char GOSUB LCD_Get_Buttons ' read/debounce buttons IF buttons.LOWBIT(3) THEN GOTO MainLoop ' exit loop and refresh if btn pressed NEXT LOOP GOTO Main ' run demo again END ' -----[noparse][[/noparse] Subroutines ]----------------------------------------------------- ' Writes stored (in DATA statement) zero-terminated string to LCD ' -- position LCD cursor ' -- point to 0-terminated string (first location in 'addr') servo: 'DEBUG SDEC set, CR servoPos = 1000 - (set * 100) + (DSdataF * 100) IF sign2 = 1 THEN servoPos = 0 servoPos = servoPos MIN 500 MAX 2800 FOR idx = 1 TO 12 PULSOUT 8, servoPos PAUSE 10 NEXT RETURN Get_Temp: HIGH RST ' Activate the '1620. SHIFTOUT DQ,CLK,LSBFIRST,[noparse][[/noparse]Rtemp] ' Request to read temperature. SHIFTIN DQ,CLK,LSBPRE,[noparse][[/noparse]DSdata\9] ' Get the temperature reading. LOW RST T_sign = Sign ' Save the sign bit of the reading. DSdata = DSdata/2 ' Scale reading to whole degrees C. IF T_sign = 0 THEN no_neg1 DSdata = DSdata | $FF00 ' Extend sign bits for negative temps. no_neg1: 'DEBUG SDEC DSdata," degrees C",CR ' Show signed temperature in C. DSdataC = DSdata DSdata = (DSdata */ $01CC) ' Multiply by 1.8. IF T_sign = 0 THEN no_neg2 ' If negative, extend sign bits. DSdata = DSdata | $FF00 no_neg2: DSdata = DSdata + 32 ' Complete the conversion. 'DEBUG SDEC DSdata," degrees F",CR ' Show signed temperature in F. DSdataF = DSdata - 5 RETURN LCD_Put_String: DO READ addr, char IF (char = 0) THEN EXIT GOSUB LCD_Write_Char addr = addr + 1 LOOP RETURN ' Send command to LCD ' -- put command byte in 'char' LCD_Command: ' write command to LCD #IF _LcdReady #THEN LCDCMD E, char RETURN #ELSE LOW RS GOTO LCD_Write_Char #ENDIF ' Write character to current cursor position ' -- but byte to write in 'char' LCD_Write_Char: ' write character to LCD #IF _LcdReady #THEN LCDOUT E, 0, [noparse][[/noparse]char] #ELSE LcdBusOut = char.HIGHNIB ' output high nibble PULSOUT E, 3 ' strobe the Enable line LcdBusOut = char.LOWNIB ' output low nibble PULSOUT E, 3 HIGH RS ' return to character mode #ENDIF RETURN ' Reads byte from LCD ' -- put byte address in 'addr' ' -- returns byte read in 'char' LCD_Read_Char: ' read character from LCD #IF _LcdReady #THEN LCDIN E, addr, [noparse][[/noparse]char] #ELSE char = addr ' move cursor GOSUB LCD_Command HIGH RS ' data command HIGH RW ' read LcdDirs = %0000 ' make LCD bus inputs HIGH E char.HIGHNIB = LcdBusIn ' get high nibble LOW E HIGH E char.LOWNIB = LcdBusIn ' get low nibble LOW E LcdDirs = %1111 ' return data lines to outputs LOW RW #ENDIF RETURN ' Read and debounce the LCD AppMod buttons LCD_Get_Buttons: LcdDirs = %0000 ' make LCD bus inputs buttons = %1111 ' assume all pressed FOR scan = 1 TO 10 buttons = buttons & LcdBusIn ' make sure button held PAUSE 10 ' debounce 10 x 5 ms NEXT LcdDirs = %1111 ' return bus to outputs IF buttons.LOWBIT(0) THEN set = set - 1 GOTO MainLoop ELSEIF buttons.LOWBIT(1) THEN set = set + 1 GOTO MainLoop ENDIF RETURN
Comments
It's not hard to write a simple output conversion routine. The biggest problem is where to put the result (as a string). With
the limited variable storage in the Stamps (26 bytes of variable space), it's much better to do conversions one character at
a time and send it to the specific device rather than store it. The LCDOUT statement, for example, allows the SDEC formatter.
This routine outputs a sign if the value is negative, suppresses leading zeros, and outputs at least one digit.
The routine sendToLCD sends the character in char to the LCD.
Like the DEC operator, it suppresses leading zeros, so it comes out as two characters "72" instead of "00072".
DSdata might possibly go negative. Maybe not in your application. But I think there is a bug lurking in your get_Temp routine for the DS1620. The */ operator does not work correctly on negatives.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com