' A PID controller using the Hitachi HD44780 LCD controller chip in 4-bit mode ' 4-button interface Const INPUT_MODE As Byte = 5 'to Pin 5 Const INPUT_UP As Byte = 6 'to Pin 6 Const INPUT_DOWN As Byte = 7 'to Pin 7 Const INPUT_COMMIT As Byte = 8 'to Pin 8 ' HD44780 4-bit Data lines Const HD44780_DB3 As Byte = 9 'Most significant bit Const HD44780_DB2 As Byte = 10 Const HD44780_DB1 As Byte = 11 Const HD44780_DB0 As Byte = 12 'Least significant bit ' HD44780 Control lines Const HD44780_ENABLE As Byte = 13 'to pin 6 'Const HD44780_READWRITE As Byte = 14 '1=Read 0=Write, unused so tied to ground Const HD44780_REGSELECT As Byte = 15 '1=Data 0=Instruction, to pin 4 Const PID_TEMPERATURE_IN As Byte = 20 'to Pin 20 Const PID_HEAT_OUT As Byte = 19 'to Pin 19 Const PID_COLD_OUT As Byte = 18 'to Pin 18 Const PID_PERIODIC_1_OUT As Byte = 17 'to Pin 17 Const PID_PERIODIC_2_OUT As Byte = 16 'to Pin 16 Const LCDREAD As Byte = 1 Const LCDWRITE As Byte = 0 Const LCDDATA As Byte = 1 Const LCDINSTRUCTION As Byte = 0 Dim sTemperatureActual As Single Dim sTemperatureActualLast As Single Dim sTemperatureSetpoint As Single Dim sHeatProportion As Single Dim sHeatIntegral As Single Dim sHeatDerivative As Single Dim sCoolProportion As Single Dim sCoolIntegral As Single Dim sCoolDerivative As Single Dim sPeriodic1ON As Single Dim sPeriodic1OFF As Single Dim sPeriodic1ONTimeOut As Single Dim sPeriodic1OFFTimeOut As Single Dim sPeriodic2ON As Single Dim sPeriodic2OFF As Single Dim sPeriodic2ONTimeOut As Single Dim sPeriodic2OFFTimeOut As Single Dim sTemperatureMin As Single Dim sTemperatureMax As Single Dim sTmpMin As Single Dim sTmpMax As Single Dim bWorkingDisplay As Boolean Dim bNewTemperature As Boolean ' global temporary variables used by string functions Dim sTmpString As String 'used for LCDPrintString Dim bCount As Byte Dim bMask As Byte Dim bByte As Byte Dim bLength As Byte Dim bCharPos As Byte Dim sChar As String * 1 Dim sTmp As String Dim bInput As Byte Dim bField As Byte Dim sTmpValue As Single Dim sComposeSingle As Single Dim bComposeDecimal As Boolean Dim bComposeWidth As Byte Dim TaskStack(0 To 90) As Byte '80 bytes is too small Dim sTaskInputVolts As Single Dim sTaskTemp As Single Dim sTaskSecs As Single Dim bTaskCount As Byte Sub Main() Delay (0.5) 'in case of rescue Call PutPin(26,0) ' green led on Call LCDInit() Call PIDInit() CallTask "MyTask", TaskStack WorkingDisplayLoop: bComposeDecimal = True ' both active fields share these same settings bComposeWidth = 6 ' both active fields share these same settings Call LCDClearDisplay() Call LCDGotoRowCol(0,1) sTmpString = "Actual Temp:" Call LCDPrintString () Call LCDGotoRowCol(0,13) sComposeSingle = sTemperatureActual Call PIDComposeValue() Call LCDPrintString () Call LCDSendCharacter (bx11011111) 'degrees sign Call LCDGotoRowCol(1,4) sTmpString = "Setpoint:" Call LCDPrintString () Call LCDGotoRowCol(1,13) sComposeSingle = sTemperatureSetpoint Call PIDComposeValue() Call LCDPrintString () sTmpValue = sTemperatureSetpoint Do While (True) Sleep (0.0) If sTemperatureActual <> sTemperatureActualLast Then Call LCDGotoRowCol(0,13) sComposeSingle = sTemperatureActual bComposeDecimal = True bComposeWidth = 6 Call PIDComposeValue() Call LCDPrintString () bNewTemperature = False Call LCDGotoRowCol(1, 19) ' Go back to setpoint field End If bInput = PIDGetButton() Select Case bInput Case INPUT_UP sTmpValue = sTmpValue + 0.1 If sTmpValue > 9999.9 Then sTmpValue = 9999.9 End If Case INPUT_DOWN sTmpValue = sTmpValue - 0.1 If sTmpValue < -999.9 Then sTmpValue = -999.9 End If Case INPUT_COMMIT sTemperatureSetpoint = sTmpValue Call Sleep (0.2) ' pause for lazy-finger Case INPUT_MODE GoTo HeatSettingsLoop End Select 'bInput If (bInput = INPUT_UP) Or (bInput = INPUT_DOWN) Then Call LCDGotoRowCol(1, 13) sComposeSingle = sTmpValue Call PIDComposeValue() Call LCDPrintString () End If Loop ' Working Display HeatSettingsLoop: bComposeDecimal = False bComposeWidth = 4 Call LCDClearDisplay() Call LCDGotoRowCol(0,0) sTmpString = "[Heat PID]" Call LCDPrintString () Call LCDGotoRowCol(0,14) sTmpString = "Prop:" Call LCDPrintString () Call LCDGotoRowCol(0,19) sComposeSingle = sHeatProportion Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,1) sTmpString = "Int:" Call LCDPrintString () Call LCDGotoRowCol(1,5) sComposeSingle = sHeatIntegral Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,13) sTmpString = "Deriv:" Call LCDPrintString () Call LCDGotoRowCol(1,19) sComposeSingle = sHeatDerivative Call PIDComposeValue() Call LCDPrintString () bField = 0 sTmpValue = sHeatProportion Call LCDGotoRowCol(0, 23) Do While (True) Sleep (0.0) bInput = PIDGetButton() Select Case bInput Case INPUT_UP sTmpValue = sTmpValue + 1.0 If sTmpValue > 9999.0 Then sTmpValue = 9999.0 End If Case INPUT_DOWN sTmpValue = sTmpValue - 1.0 If sTmpValue < 0.0 Then sTmpValue = 0.0 End If Case INPUT_COMMIT Call Sleep (0.2) ' pause for lazy-finger Select Case bField Case 0 sHeatProportion = sTmpValue bField = 1 sTmpValue = sHeatIntegral Call LCDGotoRowCol(1, 9) Case 1 sHeatIntegral = sTmpValue bField = 2 sTmpValue = sHeatDerivative Call LCDGotoRowCol(1, 23) Case 2 sHeatDerivative = sTmpValue bField = 0 sTmpValue = sHeatProportion Call LCDGotoRowCol(0, 23) End Select Case INPUT_MODE GoTo CoolSettingsLoop End Select 'bInput If (bInput = INPUT_UP) Or (bInput = INPUT_DOWN) Then Select Case bField Case 0 Call LCDGotoRowCol(0, 19) Case 1 Call LCDGotoRowCol(1, 5) Case 2 Call LCDGotoRowCol(1, 19) End Select sComposeSingle = sTmpValue Call PIDComposeValue() Call LCDPrintString () End If Loop ' Heating PID Settings CoolSettingsLoop: bComposeDecimal = False bComposeWidth = 4 Call LCDClearDisplay() Call LCDGotoRowCol(0,0) sTmpString = "[Cool PID]" Call LCDPrintString () Call LCDGotoRowCol(0,14) sTmpString = "Prop:" Call LCDPrintString () Call LCDGotoRowCol(0,19) sComposeSingle = sCoolProportion Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,1) sTmpString = "Int:" Call LCDPrintString () Call LCDGotoRowCol(1,5) sComposeSingle = sCoolIntegral Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,13) sTmpString = "Deriv:" Call LCDPrintString () Call LCDGotoRowCol(1,19) sComposeSingle = sCoolDerivative Call PIDComposeValue() Call LCDPrintString () bField = 0 sTmpValue = sCoolProportion Call LCDGotoRowCol(0, 23) Do While (True) Sleep (0.0) bInput = PIDGetButton() Select Case bInput Case INPUT_UP sTmpValue = sTmpValue + 1.0 If sTmpValue > 9999.0 Then sTmpValue = 9999.0 End If Case INPUT_DOWN sTmpValue = sTmpValue - 1.0 If sTmpValue < 0.0 Then sTmpValue = 0.0 End If Case INPUT_COMMIT Call Sleep (0.2) ' pause for lazy-finger Select Case bField Case 0 sCoolProportion = sTmpValue bField = 1 sTmpValue = sCoolIntegral Call LCDGotoRowCol(1, 9) Case 1 sCoolIntegral = sTmpValue bField = 2 sTmpValue = sCoolDerivative Call LCDGotoRowCol(1, 23) Case 2 sCoolDerivative = sTmpValue bField = 0 sTmpValue = sCoolProportion Call LCDGotoRowCol(0, 23) End Select Case INPUT_MODE GoTo Periodic1SettingsLoop End Select 'bInput If (bInput = INPUT_UP) Or (bInput = INPUT_DOWN) Then Select Case bField Case 0 Call LCDGotoRowCol(0, 19) Case 1 Call LCDGotoRowCol(1, 5) Case 2 Call LCDGotoRowCol(1, 19) End Select sComposeSingle = sTmpValue Call PIDComposeValue() Call LCDPrintString () End If Loop ' Cooling PID Settings Periodic1SettingsLoop: bComposeDecimal = True bComposeWidth = 6 Call LCDClearDisplay() Call LCDGotoRowCol(0,0) sTmpString = "[Periodic 1]" Call LCDPrintString () Call LCDGotoRowCol(1,0) sTmpString = "[in Minutes]" Call LCDPrintString () Call LCDGotoRowCol(0,14) sTmpString = "ON:" Call LCDPrintString () Call LCDGotoRowCol(0,17) sComposeSingle = sPeriodic1ON Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,13) sTmpString = "OFF:" Call LCDPrintString () Call LCDGotoRowCol(1,17) sComposeSingle = sPeriodic1OFF Call PIDComposeValue() Call LCDPrintString () bField = 0 sTmpValue = sPeriodic1ON Call LCDGotoRowCol(0, 23) Do While (True) Sleep (0.0) bInput = PIDGetButton() Select Case bInput Case INPUT_UP sTmpValue = sTmpValue + 0.1 If sTmpValue > 9999.9 Then sTmpValue = 9999.9 End If Case INPUT_DOWN sTmpValue = sTmpValue - 0.1 If sTmpValue < 0.0 Then sTmpValue = 0.0 End If Case INPUT_COMMIT Call Sleep (0.2) ' pause for lazy-finger Select Case bField Case 0 sPeriodic1ON = sTmpValue sPeriodic1ONTimeOut = Timer() + (sPeriodic1ON * 60.0) If sPeriodic1ONTimeOut > 86400.0 Then sPeriodic1ONTimeOut = sPeriodic1ONTimeOut - 86400.0 End If bField = 1 sTmpValue = sPeriodic1OFF Call LCDGotoRowCol(1, 23) Case 1 sPeriodic1OFF = sTmpValue sPeriodic1OFFTimeOut = Timer() + (sPeriodic1OFF * 60.0) If sPeriodic1OFFTimeOut > 86400.0 Then sPeriodic1OFFTimeOut = sPeriodic1OFFTimeOut - 86400.0 End If bField = 0 sTmpValue = sPeriodic1ON Call LCDGotoRowCol(0, 23) End Select Case INPUT_MODE GoTo Periodic2SettingsLoop End Select 'bInput If (bInput = INPUT_UP) Or (bInput = INPUT_DOWN) Then Select Case bField Case 0 Call LCDGotoRowCol(0, 17) Case 1 Call LCDGotoRowCol(1, 17) End Select sComposeSingle = sTmpValue Call PIDComposeValue() Call LCDPrintString () End If Loop ' Periodic 1 Settings Periodic2SettingsLoop: bComposeDecimal = True bComposeWidth = 6 Call LCDClearDisplay() Call LCDGotoRowCol(0,0) sTmpString = "[Periodic 2]" Call LCDPrintString () Call LCDGotoRowCol(1,0) sTmpString = "[in Minutes]" Call LCDPrintString () Call LCDGotoRowCol(0,14) sTmpString = "ON:" Call LCDPrintString () Call LCDGotoRowCol(0,17) sComposeSingle = sPeriodic2ON Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,13) sTmpString = "OFF:" Call LCDPrintString () Call LCDGotoRowCol(1,17) sComposeSingle = sPeriodic2OFF Call PIDComposeValue() Call LCDPrintString () bField = 0 sTmpValue = sPeriodic2ON Call LCDGotoRowCol(0, 23) Do While (True) Sleep (0.0) bInput = PIDGetButton() Select Case bInput Case INPUT_UP sTmpValue = sTmpValue + 0.1 If sTmpValue > 9999.9 Then sTmpValue = 9999.9 End If Case INPUT_DOWN sTmpValue = sTmpValue - 0.1 If sTmpValue < 0.0 Then sTmpValue = 0.0 End If Case INPUT_COMMIT Call Sleep (0.2) ' pause for lazy-finger Select Case bField Case 0 sPeriodic2ON = sTmpValue bField = 1 sTmpValue = sPeriodic2OFF Call LCDGotoRowCol(1, 23) Case 1 sPeriodic2OFF = sTmpValue bField = 0 sTmpValue = sPeriodic2ON Call LCDGotoRowCol(0, 23) End Select Case INPUT_MODE GoTo MinMAxTempLoop End Select 'bInput Loop ' Periodic2SettingsLoop MinMAxTempLoop: sTmpMin = sTemperatureMin sTmpMax = sTemperatureMax bComposeDecimal = True bComposeWidth = 6 Call LCDClearDisplay() Call LCDGotoRowCol(0,0) sTmpString = "[Min Max]" Call LCDPrintString () Call LCDGotoRowCol(1,0) sTmpString = "[Reset ]" Call LCDPrintString () Call LCDGotoRowCol(0,12) sTmpString = "Min:" Call LCDPrintString () Call LCDGotoRowCol(0,16) sComposeSingle = sTemperatureMin Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,12) sTmpString = "Max:" Call LCDPrintString () Call LCDGotoRowCol(1,16) sComposeSingle = sTemperatureMax Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1, 7) Do While (True) Sleep (0.0) bInput = PIDGetButton() Select Case bInput Case INPUT_UP Sleep (0.0) Case INPUT_DOWN Sleep (0.0) Case INPUT_COMMIT ' reset min max values to current temperature Call Sleep (0.2) ' pause for lazy-finger sTemperatureMin = sTemperatureActual sTemperatureMax = sTemperatureMin Call LCDGotoRowCol(0,16) sComposeSingle = sTemperatureMin Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1,16) sComposeSingle = sTemperatureMax Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1, 7) Case INPUT_MODE GoTo WorkingDisplayLoop End Select 'bInput If sTemperatureMin < sTmpMin Then sTmpMin = sTemperatureMin Call LCDGotoRowCol(0,16) sComposeSingle = sTemperatureMin Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1, 7) ' reset prompt End If If sTemperatureMax > sTmpMax Then sTmpMax = sTemperatureMax Call LCDGotoRowCol(1,16) sComposeSingle = sTemperatureMax Call PIDComposeValue() Call LCDPrintString () Call LCDGotoRowCol(1, 7) ' reset prompt End If Loop ' Min Max Report Call PutPin(26,1) ' green led off End Sub 'Main Sub MyTask () Dim bToggleLED As Byte ' Remove finally, just an 'alive' signal bToggleLED = 0 Do While (True) ' forever Call PutPin(25, bToggleLED) sTaskTemp = sTemperatureActual / 500.0 For bTaskCount = 1 to 10 Call GetADC(PID_TEMPERATURE_IN, sTaskInputVolts) sTaskTemp = sTaskTemp + ((sTaskInputVolts - sTaskTemp)/100.0) 'smoothes value jumps Call Sleep (0.01) Next sTemperatureActualLast = sTemperatureActual sTemperatureActual = sTaskTemp * 500.0 sTemperatureActual = CSng(CLng(sTemperatureActual * 10.0))/10.0 'trunc to 0.1 ' --- Set Min Max temperatures If sTemperatureActual > sTemperatureMax Then sTemperatureMax = sTemperatureActual End If If sTemperatureActual < sTemperatureMin Then sTemperatureMin = sTemperatureActual End If ' --- Adjust warming/cooling ' If too warm.. ' -- Stub If ((sTemperatureActual - sTemperatureSetpoint) > 1.0) Then ' hysteresis 'turn on cool-out End If ' If too cool.. If ((sTemperatureSetpoint - sTemperatureActual) < 1.0) Then ' hysteresis 'turn off warm-out End If ' pulse warm output according to proportional band ' -- Stub ' -- Adjust periodic1/periodic2 output ' -- Stub 'sPeriodic1ON 'sPeriodic1ONTimeOut 'sPeriodic1OFF 'sPeriodic1OFFTimeOut 'sPeriodic2ON 'sPeriodic2OFF 'sPeriodic2ONTimeOut 'sPeriodic2OFFTimeOut ' -- Remove finally, just an 'alive' signal if bToggleLED = 1 Then bToggleLED = 0 Else bToggleLED = 1 End If Call Sleep (0.5) Loop End Sub Function PIDGetButton () As Byte If GetPin(INPUT_UP) = 0 Then Call Sleep (0.1) 'debounce PIDGetButton = INPUT_UP Exit Function ElseIf GetPin(INPUT_DOWN) = 0 Then Call Sleep (0.1) 'debounce PIDGetButton = INPUT_DOWN Exit Function ElseIf GetPin(INPUT_COMMIT) = 0 Then Call Sleep (0.1) 'debounce PIDGetButton = INPUT_COMMIT Exit Function ElseIf GetPin(INPUT_MODE) = 0 Then Call Sleep (0.1) 'debounce PIDGetButton = INPUT_MODE Exit Function Else PIDGetButton = 0 Exit Function End If End Function ' Left-pads string with spaces. Sub PIDComposeValue() If bComposeDecimal = True Then sTmp = CStr(CLng(sComposeSingle * 10.0)) Else sTmp = CStr(CLng(sComposeSingle)) End If bLength = CByte(Len(sTmp)) bCount = bLength If bComposeDecimal = True Then bCount = bCount + 1 ' for the decimal point If Abs(sComposeSingle) < 1.0 Then bCount = bCount + 1 ' for the leading zero End If End If sTmpString = "" Do While (bComposeWidth - bCount > 0) sTmpString = sTmpString & " " bCount = bCount + 1 Loop sTmpString = sTmpString & Mid(sTmp, 1, CInt(bLength-1)) If bComposeDecimal = True Then If Abs(sComposeSingle) < 1.0 Then sTmpString = sTmpString & "0" End If sTmpString = sTmpString & "." End If sTmpString = sTmpString & Mid(sTmp, CInt(bLength), 1) End Sub 'Prints the global string sTmpString Sub LCDPrintString () Call PutPin(HD44780_REGSELECT, LCDDATA) For bCharPos = 1 To CByte(Len(sTmpString)) sChar = Mid(sTmpString, CInt(bCharPos), 1) bByte = Asc(sChar) bMask = bx10000000 For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) For bCount = 0 to 3 'Put next 4 bits Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.0005) Next End Sub ' LCDPrintString Sub PIDInit () Call PutPin(INPUT_MODE, bxInputPullup) ' Pull-up Call PutPin(INPUT_UP, bxInputPullup) ' Pull-up Call PutPin(INPUT_DOWN, bxInputPullup) ' Pull-up Call PutPin(INPUT_COMMIT, bxInputPullup) ' Pull-up bWorkingDisplay = False bNewTemperature = False Call GetADC(PID_TEMPERATURE_IN, sTemperatureActual) sTemperatureActual = sTemperatureActual * 500.0 sTemperatureActualLast = sTemperatureActual sTemperatureSetpoint = 68.0 sHeatProportion = 40.0 sHeatIntegral = 10.0 sHeatDerivative = 0.0 sCoolProportion = 40.0 sCoolIntegral = 10.0 sCoolDerivative = 0.0 sPeriodic1ON = 0.1 sPeriodic1OFF = 59.9 sPeriodic1ONTimeOut = 0.0 sPeriodic1OFFTimeOut = 0.0 sPeriodic2ON = 720.0 sPeriodic2OFF = 720.0 sPeriodic2ONTimeOut = 0.0 sPeriodic2OFFTimeOut = 0.0 End Sub Sub LCDInit() Call PutPin(HD44780_ENABLE, bxOutputLow) Call PutPin(HD44780_REGSELECT, bxOutputLow) Call Sleep(0.050) 'for LCD chip startup Call LCDPut4Bits ( bx00110000 ) 'function set (assumes 8-bit at startup) Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.005) Call LCDPut4Bits ( bx00110000 ) 'function set (assumes 8-bit at startup) Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.00015) Call LCDPut4Bits ( bx00110000 ) 'function set (assumes 8-bit at startup) Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call LCDPut4Bits ( bx00100000 ) 'Now actually sets to 4-bit mode Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call LCDFunctionSet () 'sets the complete function set Call LCDDisplayOFF () Call LCDClearDisplay () Call LCDEntryModeSet () Call LCDDisplayON () End Sub Sub LCDFunctionSet8 () '8-bit, 2 lines, no-scroll, blinking cursor Call LCDSendCommand ( bx00111000 ) End Sub Sub LCDFunctionSet () '4-bit, 2 lines, no-scroll, blinking cursor Call LCDSendCommand ( bx00101000 ) End Sub Sub LCDDisplayON () Call LCDSendCommand ( bx00001111 ) End Sub Sub LCDDisplayOFF () Call LCDSendCommand ( bx00001000 ) End Sub Sub LCDEntryModeSet () Call LCDSendCommand ( bx00000110 ) End Sub Sub LCDClearDisplay () Call PutPin(HD44780_ENABLE, bxOutputLow) Call PutPin(HD44780_REGSELECT, LCDINSTRUCTION) Call PutPin(HD44780_DB3,0) Call PutPin(HD44780_DB2,0) Call PutPin(HD44780_DB1,0) Call PutPin(HD44780_DB0,0) Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call PutPin(HD44780_DB3,0) Call PutPin(HD44780_DB2,0) Call PutPin(HD44780_DB1,0) Call PutPin(HD44780_DB0,1) Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.0016) 'Clear Display needs more time End Sub Sub LCDReturnHome () Call LCDSendCommand ( bx00000010 ) Call Sleep(0.0016) End Sub Sub LCDGotoRowCol (ByVal bRow As Byte, ByVal bCol As Byte) Call PutPin(HD44780_REGSELECT, LCDINSTRUCTION) Call PutPin(HD44780_ENABLE, bxOutputLow) bByte = bx10000000 Or (bRow * 64 + bCol) bMask = bx10000000 For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) For bCount = 0 to 3 'Put next 4 bits Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.00005) End Sub 'Sub LCDSetDDRAMAddr (ByVal bAddr As Byte) ' Call LCDSendCommand ( bx10000000 Or bAddr) 'bAddr is 7-bits 'End Sub Sub LCDSendCommand (ByVal bByte As Byte) Call PutPin(HD44780_REGSELECT, LCDINSTRUCTION) Call PutPin(HD44780_ENABLE, bxOutputLow) bMask = bx10000000 For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.00005) End Sub Sub LCDSendCharacter (ByVal bByte As Byte) Call PutPin(HD44780_REGSELECT, LCDDATA) Call PutPin(HD44780_ENABLE, bxOutputLow) bMask = bx10000000 For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) For bCount = 0 to 3 'Put next 4 bits Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) Call Sleep(0.00005) End Sub ' 4-bit interface - ENABLE pulse expects WRITE mode Sub LCDPutByte (ByVal bByte As Byte) bMask = bx10000000 For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next Call PulseOut(HD44780_ENABLE, 0.00005, bxOutputHigh) For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next End Sub Sub LCDPut4Bits (ByVal bByte As Byte) 'msb's only bMask = bx10000000 For bCount = 0 to 3 'Put most significant bits first Call PutPin(HD44780_DB3 + bCount, ((bByte And bMask)\bMask)) bMask = bMask \ 2 Next End Sub