Using Liberty Basic to Interface a PC (Windows) with a PICAXE

copyright, Peter H Anderson, Baltimore, MD, Jan, '05


Intoduction

This application note discusses Serial RS232 communication between a PC running Windows and a PICAXE. In fact, this could be extended to virtually any processor; NetMedia BX24, Basic Stamp and the like. Typical applications include measurement and perhaps in the case of a thermostat or alarm, acting on the measurement, performing calculations and logging data.

I opted to develop this material using Liberty Basic for Windows. It is relatively inexpensive and appears exceptionally well supported by many dedicated people. It appears well structured and is close enough to C / C++ for me to at least make a good stab at writing simple programs. No knowlege of Windows is required.

However, I will confess that my knowledge is limited and it seems as if each day I make some new discovery. However, if I wait to post material I am proud to post, I fear nothing will ever be posted. So, please take this as a possible starting point for your own creative being.

The Liberty Basic programs were tested using Windows 98SE.


Temperature Measurement using the DS18B20

Consider the following PICAXE program which utilizes a PICAXE-08M with three DS18B20 Dallas 1-W devices. When IN3 on the PICAXE goes to a logic one, a measurement sequence is performed and the data is sent to the PC at 4800 baud. (SerTxD uses 4800). When IN3 is low, the PICAXE idles.

Note that the PCs TxD (term 3 on a DB9 connector) is connected to the PICAXE IN3 using a shunt 10K, series 22K resistor. The PICAXE SerOut (term 7) is connected to the PCs RxD (term 2 on a DB9 connector).

  PC COM Port                                PICAXE-08M

  TxD (term 3) ---------------- 22K -------- IN3 (term 4)
                      |
                      10K
                      |
                      GRD
  RxD (term 2) < ------------------------ SerOut (term 7)

Thus, when any character is sent to the PICAXE, the PICAXE performs the three measurements and sends them to the PC.
' DS18B20_08M_2.Bas - PICAXE-08M
'
' Illustrates an interface with a number of DS18B20 temperature sensors.
'
' Uses the polling interrupt to detect a high on Pin3.
'
' Idles until logic one appears on Pin3.
'
' Performs a single temperature measurement and displays to two significant digits on the
' terminal.  This is repeated for DS18B20 temperature sensors on IN1/OUT1, IN2/OUT2
' and IN4.OUT4.
'
' The unit then again idles until a logic one appears on Pin3.
'
' Note that a 4.7K pullup to +5 VDC is required on each DQ lead.  +5 VDC is required on the
' V+ terminal of the DS18B20.
'
'  08M					DS18B20
'
' IO1 (term 6) ------------------ DQ (term 2)
' IO2 (term 5) ------------------ DQ (term 2)
' IO4 (term 3) ------------------ DQ (term 2)
'
' Uses 140 of 256 bytes.
'
' copyright, Peter H Anderson, Baltimore, MD, Sept, '04, Jan, '05


    Symbol TReading = W0
    Symbol Whole = B2
    Symbol Fract = B3
    Symbol SignBit = B4
    Symbol Dig = B5
    Symbol TempC_100 = W3
    Symbol DevNum = B8
    Symbol IntOccurred = B9

    SetInt %000010000, %000010000	' Pin 3, High
    IntOccurred = 0

Top:
    If IntOccurred = 0 Then Top

    IntOccurred = 0
    For DevNum = 1 to 3	' 1, 2, 3
       Branch DevNum, (Invalid, Dev1, Dev2, Dev3)

Invalid:

Dev1:
       ReadTemp12 1,TReading
       Goto CalcT

Dev2:
       ReadTemp12 2,TReading
       Goto CalcT

Dev3:
       ReadTemp12 4,TReading
       Goto CalcT		' this statement not really necessary

CalcT:
       SignBit = TReading / 256 / 128
       If SignBit = 0 Then Positive
       ' its negative
       TReading = TReading ^ $ffff + 1 ' take twos comp

Positive:
       TempC_100 =  TReading * 6		' TC = value * 0.0625
       TReading = TReading * 25 / 100
       TempC_100 = TempC_100 + TReading

       GoSub DisplayTemp
    Next

    GoTo Top

DisplayTemp:

   SerTxD (#DevNum, " ") ' note this is at 4800 baud
   Whole = TempC_100 / 100
   Fract = TempC_100 % 100
   If SignBit = 0 Then DisplayTemp_1
   SerTxD ("-")

DisplayTemp_1:

   SerTxD (#Whole, ".")
  ' be sure the fractional is two digits
   Dig = Fract / 10
   SerTxD (#Dig)
   Dig = Fract % 10
   SerTxD (#Dig, 13, 10)
   Return

Interrupt:
   Pause 100
   If Pin3 = 1 then Interrupt
   IntOccurred = 1
   SetInt %000010000, %000010000
   Return

Program DS18B20_1.Bas is the program which is run on the interfacing PC. It periodically sends a character to the PICAXE causing the PICAXE-08M to perform three temperature measurements using the DS18B20. The data is then sent to the PC is of the form;

1 23.73
2 14.53
3 -3.72
These three strings are fetched using function GetLine$ and displayed on the terminal.

Notes.

The comm port is opened at 4800 baud, 8 data bits, no parity using;

    open "com2:4800,n,8,1, cs0, ds0" for random as #commhandle
I spent a considerable amount of time trying to deal with Com Port errors, using the command oncommerror. In my case, I was repeatedly running the program again and again and quite often the programmed failed to open the port as it was already open from a previous run. Thus, my intent was to close the comm port if it encountered an error. I don't think I was successful in doing so, but decided to keep it in the code as my feeble stab may be of use to someone else.

A "!" character is sent to the PICAXE which causing IN3 on the PICAXE to go momentarily high. Note that the character which is sent could be any character.

    print #commhandle, "!"  ' send any character
The program then calls GetLine$. Note that the variable NumChars is passed by reference such that any change within the function will be present in the calling function when the function is completed. The actual string is returned by the function.

Inside function GetLine$, the function continually loops (while x=0). If lof(#commhandle) is zero, no character has been received by the PC Comm Port and the current date and time is read off the PC system clock using the date$ and time$ functions and if a specified period of time has elapsed, the function is exited with the StatusFlag (known as NumChars in the calling routine) set to -30000.

If, however, there is a character in the serial buffer (lof(#commhandle) <> 0), the character is read. If it is ASCII 13, (carriage return), I assume the string has been completed and the function is exited with StatusFlag equal to the number of the number of characters which have been received. If the character is ASCII 10 (line feed), it is ignored and if it is any other character, it is appended to the DataLine$. Note that the loop is exited only when ASCII 13 is received or when a timeout occurs.

On entering the function, the time (in milliseconds since midnight) and the date (in days since Jan 1, 1901) is fetched off the system clock. The timing interval in this example is 3000 milliseconds.

Note that time$("milliseconds") returns a number in the range of 0 to 86,400,000 -1 (24 * 60 * 60 * 1000). If, on adding this timing interval, the result is greater or equal to the number of seconds in a day, the timeout occurs in the next day (TimeOutDate = TimeOutDate + 1) at the time (TimeOutTime = TimeOutTime - 86400000).

Again, if no character is in the serial buffer, the CurrentTime is tested as to whether it is greater or equal to TimeOutTime and the CurrentDate is greater or equal to the DateTimeOut. If so, a "timeout" has occurred. If not, the program contiues to loop, looking for received characters.

function GetLine$(ByRef StatusFlag)

    TimeOutTime = time$("milliseconds") + 3000
    TimeOutDate = date$("days")

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if


     DataLine$ = ""
     StatusFlag = 0
     NumChars = 0
     x=0
     while x=0
        if lof(#commhandle) <>0 then
           c$ = input$(#commhandle, 1)
           if c$ = chr$(13) then
              StatusFlag = NumChars ' probably a valid line
              exit while
           end if

           if c$ = chr$(10) then   ' ignore it

           else
              DataLine$ = DataLine$ + c$
              NumChars = NumChars + 1
           end if
        else
           CurrentDate = date$("days")
           CurrentTime = time$("milliseconds")
           If (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate) Then
              StatusFlag = -30000
              exit while
           end if
        end if
     wend
     GetLine$ = DataLine$

Throughout the program I also used a pause subroutine (call pause 500). I was able to handle the Cinderela effect a bit this a bit diffently in implementing the pause routine;

sub pause mil
    tcurrent = time$("milliseconds")
    timeout = tcurrent + mil
    if timeout >= 86400000 then  ' roll over at midnight
       timeout = timeout - 86400000
       do
          tcurrent = time$("milliseconds")
       loop until (86400000 - tcurrent > 1000000)    ' wait for clock to roll over
    end if

    do
          tcurrent = time$("milliseconds")
    loop until (tcurrent >= timeout)

    end sub
The delay in ms is passed in mil. In calculating timeout, if the timeout is less than the number of ms in a day, the program simply loops until the tcurrent is greater than or equal to the timeout. Otherwise, the timout value is adjusted by subtracting 86400000. The delay is then implemented using two series loops. The first loops until midnight is crossed and the second then loops until the tcurrent is greater than the adjusted timeout.

When a vaild string is fetched, it is displayed using subroutine DisplayVals which is implemented using the Mid$ function. In this example, there really is not much utility in using this subroutine as opposed to simply printing the string (print DataLine$). However, I wanted to develop the subroutine as a stepping stone to extracting a specified field from a string.

DS18B20_1.Bas - The Complete Program.

' DS18B20_1.Bas (Liberty Basic)
'
' Use with PICAXE-08M programmed with DS18B20_08M_2.Bas.
'
' Periodically sends a character to the PICAXE, causing the PICAXE to perfrom
' temperature measurements on each of the three DS18B20 devices.  This program
' fetches each string from the PICAXE using function GetLine$.
'
' Note that the GetLine$ function passes back a negative number in NumChars to
' indicate there was a timeout in fetching the string.
'
' Uses Com2, 4800 baud.
'
' copyright, Peter H Anderson, Baltimore, MD, Jan, '05

    Com = 16384     ' size of serial buffer

[top]
    oncomerror [closecomm]  ' not sure if this works
    open "com2:4800,n,8,1, cs0, ds0" for random as #commhandle

    call pause 500  ' wait for unit to settle

[again]
    print #commhandle, "!"  ' send any character

    x = 0
    while x = 0       ' loop until either a string is received or timeout
       DataLine$ = GetLine$(NumChars) ' NuChars is passed by reference

       If NumChars = -30000 Then  ' timeout
          print "timeout"
          exit while
       End If

       If NumChars > 2 Then       ' probably a vaild string
          Call DisplayVals DataLine$
       Else
          print "Unknown error"   ' only one or two characters
          exit while
       End If
    wend
    call pause 5000
    goto [again]


[closecomm]
     print "Error code: ";ComErrorNumber
     close #commhandle
     goto [top]

function GetLine$(ByRef StatusFlag)

    TimeOutTime = time$("milliseconds")
    TimeOutDate = date$("days")

    TimeOutTime = TimeOutTime + 3000 ' three seconds

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if


     DataLine$ = ""
     StatusFlag = 0
     NumChars = 0

     x=0
     while x=0
        if lof(#commhandle) <>0 then
           c$ = input$(#commhandle, 1)
           if c$ = chr$(13) then
              StatusFlag = NumChars ' probably a valid line
              exit while
           end if

           if c$ = chr$(10) then   ' ignore it

           else
              DataLine$ = DataLine$ + c$
              NumChars = NumChars + 1
           end if
        else
           CurrentDate = date$("days")
           CurrentTime = time$("milliseconds")
           If (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate) Then
              StatusFlag = -30000
              exit while
           end if
        end if
     wend
     GetLine$ = DataLine$
End Function


Sub DisplayVals DtLn$

   DevNum$ = Mid$(DtLn$, 1, 1)
   TC$ = Mid$(DtLn$, 3)
   print DevNum$ + "  " + TC$

end sub


sub pause mil
    tcurrent = time$("milliseconds")
    timeout = tcurrent + mil
    if timeout >= 86400000 then  ' roll over at midnight
       timeout = timeout - 86400000
       do
          tcurrent = time$("milliseconds")
       loop until (tcurrent >=86400000)    ' wait for clock to roll over
    end if

    do
          tcurrent = time$("milliseconds")
    loop until (tcurrent >= timeout)

    end sub

    end


Program DS18B20_2.Bas - Liberty Basic

This program interfaces with the same PICAXE-08M with three DS18B20 devices as discussed above.

The program differs in that the time$ and date$ functions are used to implement a measurement sequence every sixty seconds. In addition, the channel and temperature strings are extracted from the data string and are converted from strings to numeric values. These are evaluated in subroutine Thermostat to determine if the temperature is above or below a high and low trip point. In this routine, all that is done is to print a message. More practically, one might send serial data to a PICAXE to operate a relay.

The fields of the dataline$ string are extracted using function ExtractField$;

function ExtractField$(Var$, NumField)

    for Num = 1 to NumField
       Index = FindWhiteSpace(Var$)
       LeftStr$ = Left$(Var$, Index - 1) ' everything to the left of the space
       Var$ = Mid$(Var$, Index+1)        ' to the right of the space
       If Num = NumField Then
          exit for
       End If
    next

    ExtractField$ = LeftStr$

end function

Note that the index of the first occurance of a space " " is determined using function FindWhiteSpace(Var$) and the string is split, all that is left of the white space and all that is to the right. The index of the next is found by passing the trimmed string; i.e, that which was to the right and passing it to function FindWhiteSpace(Var$). This is repated until the nth occurance of white space is found, and all that is the the left is the nth field.

' DS18B20_2.Bas (Liberty Basic)
'
' Use with PICAXE-08M programmed with DS18B20_08M_2.Bas.
'
' Every minute sends a character to the PICAXE, causing the PICAXE to perfrom
' temperature measurements on each of the three DS18B20 devices.  This program
' fetches each string from the PICAXE using function GetLine$.
'
' Converts channel and temperature to numbers and uses subroutine Thermostat to
' detrmine if a temperature is below or above a trip point.
'
' Illustrates extracting a substring from a string, conversion of a string to a number
' and the use of the PCs timer to periodically execute the task.
'
' Uses Com2, 4800 baud.
'
' copyright, Peter H Anderson, Baltimore, MD, Jan, '05


    Com = 16384     ' size of buffer

[top]
    oncomerror [closecomm]  ' not sure if this works
    open "com2:4800,n,8,1, cs0, ds0" for random as #commhandle

    call pause 500  ' wait for unit to settle

    TimeOutTime = time$("seconds")
    TimeOutDate = date$("days")

[again]
    TimeOutTime = TimeOutTime + 60 ' every minute

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if

    print #commhandle, "!"  ' send any character

    x = 0
    while x = 0       ' loop until either a string is received or timeout
       DataLine$ = GetLine$(NumChars) ' NuChars is passed by reference

       If NumChars = -30000 Then  ' timeout
          print "timeout"
          exit while
       End If

       If NumChars > 2 Then       ' probably a vaild string
           Field$ = ExtractField$(DataLine$, 1)
           Channel = Val(Field$)
           Field$ = ExtractField$(DataLine$, 2)
           Temperature = Val(Field$)
           Print Channel; " "; Temperature
           Call Thermostat Channel, Temperature
       Else
          print "Unknown error"   ' only one or two characters
          exit while
       End If
    wend
    do
       CurrentDate = date$("days")
       CurrentTime = time$("seconds")
    loop until (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate)
    goto [again]


[closecomm]
     print "Error code: ";ComErrorNumber
     close #commhandle
     goto [top]

Sub Thermostat Ch, Tc

   Select Case Ch

      Case 1
          If Tc < 10.0 Then
             Print "Alarm on Channel "; Ch; "  "; Tc; "  Less than Low Trip"
          End If
          If Tc > 23.0 Then
             Print "Alarm on Channe; "; Ch; "  "; Tc; "  Higher than High Trip"
          End If
      Case 2
          If Tc < -5.0 Then
             Print "Alarm on Channel "; Ch; "  "; Tc; "  Less than Low Trip"
          End If
          If Tc > 23.0 Then
             Print "Alarm on Channe; "; Ch; "  "; Tc; "  Higher than High Trip"
          End If
      Case 3
          If Tc < 22.0 Then
             Print "Alarm on Channel "; Ch; "  "; Tc; "  Less than Low Trip"
          End If
          If Tc > 25.0 Then
             Print "Alarm on Channe; "; Ch; "  "; Tc; "  Higher than High Trip"
          End If

      End Select

end sub

function GetLine$(ByRef StatusFlag)

    TimeOutTime = time$("milliseconds")
    TimeOutDate = date$("days")

    TimeOutTime = TimeOutTime + 3000 ' three seconds

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if


     DataLine$ = ""
     StatusFlag = 0
     NumChars = 0

     x=0
     while x=0
        if lof(#commhandle) <>0 then
           c$ = input$(#commhandle, 1)
           if c$ = chr$(13) then
              StatusFlag = NumChars ' probably a valid line
              exit while
           end if

           if c$ = chr$(10) then   ' ignore it

           else
              DataLine$ = DataLine$ + c$
              NumChars = NumChars + 1
           end if
        else
           CurrentDate = date$("days")
           CurrentTime = time$("milliseconds")
           If (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate) Then
              StatusFlag = -30000
              exit while
           end if
        end if
     wend
     GetLine$ = DataLine$
End Function

function ExtractField$(Var$, NumField)

    for Num = 1 to NumField
       Index = FindWhiteSpace(Var$)
       LeftStr$ = Left$(Var$, Index - 1) ' everything to the left of the space
       Var$ = Mid$(Var$, Index+1)        ' to the right of the space
       If Num = NumField Then
          exit for
       End If
    next

    ExtractField$ = LeftStr$

end function

function FindWhiteSpace(Var$)

    for n = 1 to len(Var$)
       ch$ = Mid$(Var$, n, 1)
       If ch$ = " " then
          exit for
       End If
       If ch$ = Chr$(13) then
          exit for
       End If
       If ch$ = Chr$(10) then
          exit for
       End If
    next
    FindWhiteSpace = n

end function

sub pause mil
    tcurrent = time$("milliseconds")
    timeout = tcurrent + mil
    if timeout > 86400000 then  ' roll over at midnight
       timeout = timeout - 86400000
       do
             tcurrent = time$("milliseconds")
       loop until (86400000 - tcurrent) > 1000000
    end if

    do
            tcurrent = time$("milliseconds")
    loop until (tcurrent >= timeout)

    end sub

    end


Program DS18B20_3.Bas - Liberty Basic

' DS18B20_3.Bas (Liberty Basic)
'
' Use with PICAXE-08M programmed with DS18B20_08M_2.Bas.
'
' Opens a file d:\data.txt
'
' For ten times, every minute sends a character to the PICAXE, causing the PICAXE to perfrom
' temperature measurements on each of the three DS18B20 devices.  This program fetches each
' string from the PICAXE using function GetLine$.
'
' The string is then displayed on the terminal.  In addition, the file is briefly opened, the
' string is written to the file and the file is closed.
'
' After ten samples, the file is opened and the results are displayed on the terminal.
'
' Illustrates opening a file for output, for appending and for input.
'
' All of this is useful for developing data logger applications.
'
' Uses Com2, 4800 baud.
'
' copyright, Peter H Anderson, Baltimore, MD, Jan, '05


    Com = 16384     ' size of buffer

[top]
    oncomerror [closecomm]  ' not sure if this works
    open "com2:4800,n,8,1, cs0, ds0" for random as #commhandle

    call pause 500  ' wait for unit to settle

    open "d:\data.txt" for output as #log ' open the file
    close #log

    TimeOutTime = time$("seconds")
    TimeOutDate = date$("days")

    For N = 1 to 10
       TimeOutTime = TimeOutTime + 60 ' every minute

       if (TimeOutTime >= 86400000) then
           TimeOutDate = TimeOutDate + 1
           TimeOutTime = TimeOutTime - 86400000
       end if

       print #commhandle, "!"  ' send any character

       x = 0
       while x = 0       ' loop until either a string is received or timeout
          DataLine$ = GetLine$(NumChars) ' NuChars is passed by reference

          If NumChars = -30000 Then  ' timeout
             print "timeout"
             exit while
          End If

          If NumChars > 2 Then       ' probably a vaild string
              print DataLine$

              open "d:\data.txt" for append as #log
          print #log, DataLine$
              close #log

          Else
              print "Unknown error"   ' only one or two characters
              exit while
          End If
       wend
       do
           CurrentDate = date$("days")
           CurrentTime = time$("seconds")
       loop until (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate)
    Next

    ' now open the file display the data
    open "d:\data.txt" for input as #log

    while eof(#log) = 0
       line input #log, datain$
       print datain$
    wend

    close #log

[Done]
    Goto [Done]

[closecomm]
     print "Error code: ";ComErrorNumber
     close #commhandle
     goto [top]


function GetLine$(ByRef StatusFlag)

    TimeOutTime = time$("milliseconds")
    TimeOutDate = date$("days")

    TimeOutTime = TimeOutTime + 3000 ' three seconds

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if


     DataLine$ = ""
     StatusFlag = 0
     NumChars = 0

     x=0
     while x=0
        if lof(#commhandle) <>0 then
           c$ = input$(#commhandle, 1)
           if c$ = chr$(13) then
              StatusFlag = NumChars ' probably a valid line
              exit while
           end if

           if c$ = chr$(10) then   ' ignore it

           else
              DataLine$ = DataLine$ + c$
              NumChars = NumChars + 1
           end if
        else
           CurrentDate = date$("days")
           CurrentTime = time$("milliseconds")
           If (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate) Then
              StatusFlag = -30000
              exit while
           end if
        end if
     wend
     GetLine$ = DataLine$
End Function

sub pause mil
    tcurrent = time$("milliseconds")
    timeout = tcurrent + mil
    if timeout > 86400000 then  ' roll over at midnight
       timeout = timeout - 86400000
       do
          tcurrent = time$("milliseconds")
       loop until (86400000 - tcurrent) > 1000000
    end if

    do
        tcurrent = time$("milliseconds")
    loop until (tcurrent >= timeout)

    end sub

    end


Program DS18B20_4.Bas - Liberty Basic

' DS18B20_4.Bas (Liberty Basic)
'
' Use with PICAXE-08M programmed with DS18B20_08M_2.Bas.
'
' Opens a text box.  Opens a file d:\data.txt
'
' Every minute sends a character to the PICAXE, causing the PICAXE to perfrom
' temperature measurements on each of the three DS18B20 devices.  This program fetches each
' string from the PICAXE using function GetLine$.
'
' The string is then displayed on the terminal.  In addition, the file is briefly opened, the
' string is written to the file and the file is closed.
'
' This continues indefinitely, until any character is entered from the terminal.  The file is
' then opened and diplsyaed to the terminal.
'
' Illustrates developing a text box, and the use of scan to read a charcter from the keyboard.
'
' Useful for developing data logger applications.
'
' Uses Com2, 4800 baud.
'
' copyright, Peter H Anderson, Baltimore, MD, Jan, '05


    Com = 16384     ' size of buffer

    nomainwin

    WindowWidth = 400
    WindowHeight = 300
    texteditor #window.te, 0, 0, 391, 254     'The handle for our texteditor is #window.te
    graphicbox #window.gb, 800, 1, 10, 10
    open "kb" for window as #window           'The handle for our window is #window
    print #window.gb, "when characterInput [getChar]"   'When the user presses a key go to [getChar]
    print #window, "trapclose [quit]"    'When the user closes our terminal window, go to [quit]
    print #window.te, "!autoresize";   'Tell the texteditor to resize with the terminal window
    print #window, "font courier_new 9";

[top]
    oncomerror [closecomm]  ' not sure if this works
    open "com2:4800,n,8,1, cs0, ds0" for random as #commhandle

    call pause 500  ' wait for unit to settle

    open "d:\data.txt" for output as #log ' open the file
    close #log

    TimeOutTime = time$("seconds")
    TimeOutDate = date$("days")

[again]

    TimeOutTime = TimeOutTime + 60 ' every minute

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if

    print #commhandle, "!"  ' send any character

    x = 0
    while x = 0       ' loop until either a string is received or timeout
       DataLine$ = GetLine$(NumChars) ' NuChars is passed by reference

       If NumChars = -30000 Then  ' timeout
          print "timeout"
          exit while
       End If

       If NumChars > 2 Then       ' probably a vaild string
          print DataLine$

          open "d:\data.txt" for append as #log
          print #window.te, DataLine$ ' display the string
          print #log, DataLine$       ' and write it to the file
          close #log

       Else
          print "Unknown error"   ' only one or two characters
          exit while
       End If
    wend
    do
        print #window.gb, "setfocus"
        scan ' used for check if activity from the keyboard
        CurrentDate = date$("days")
        CurrentTime = time$("seconds")
    loop until (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate)

    goto [again]

[display]
    ' now open the file display the data
    open "d:\data.txt" for input as #log

    while eof(#log) = 0
       line input #log, datain$
       print #window.te, datain$
    wend

    close #log

[Done]
    Goto [Done]

[getChar]

    'Whenever the user presses a key, we go here to process it.
    c$ = Inkey$
    ' print #window.te, "at getChar"
    goto [display]

[closecomm]
     print "Error code: ";ComErrorNumber
     close #commhandle
     goto [top]

function GetLine$(ByRef StatusFlag)

    TimeOutTime = time$("milliseconds")
    TimeOutDate = date$("days")

    TimeOutTime = TimeOutTime + 3000 ' three seconds

    if (TimeOutTime >= 86400000) then
        TimeOutDate = TimeOutDate + 1
        TimeOutTime = TimeOutTime - 86400000
    end if


     DataLine$ = ""
     StatusFlag = 0
     NumChars = 0

     x=0
     while x=0
        if lof(#commhandle) <>0 then
           c$ = input$(#commhandle, 1)
           if c$ = chr$(13) then
              StatusFlag = NumChars ' probably a valid line
              exit while
           end if

           if c$ = chr$(10) then   ' ignore it

           else
              DataLine$ = DataLine$ + c$
              NumChars = NumChars + 1
           end if
        else
           CurrentDate = date$("days")
           CurrentTime = time$("milliseconds")
           If (CurrentTime >= TimeOutTime) AND (CurrentDate >= TimeOutDate) Then
              StatusFlag = -30000
              exit while
           end if
        end if
     wend
     GetLine$ = DataLine$
End Function

sub pause mil
    tcurrent = time$("milliseconds")
    timeout = tcurrent + mil
    if timeout > 86400000 then  ' roll over at midnight
       timeout = timeout - 86400000
       do
           tcurrent = time$("milliseconds")
       loop until (86400000 - tcurrent) > 1000000
    end if

    do
       tcurrent = time$("milliseconds")
    loop until (tcurrent >= timeout)

    end sub

    end


In the future.

Later in Jan, '05, I will be adding routines to interface with a PICAXE-08M;