No announcement yet.

Simple Serial Port Programming

  • Filter
  • Time
  • Show
Clear All
new posts

  • Simple Serial Port Programming


    I have plugged my little Garmin 12X GPS receiver into my serial port (COM1).

    I can read anything coming into the port, and do whatever I need to with it.

    This is done by simply opening the port, and inputting from it.
    (See Code Below)

    What I want to know is: How can I tell if my GPS is connected before I do an input there?

    If my GPS has shut itself down for no battery or no GPS coverage, it hangs up.

    I'm hoping that someone can show me how to do this with 10 lines of code or less -- I can't always follow explanations, but could really appreciate seeing a "Simplest Common Solution" for this.



    Code Follows:

    t = FreeFile
    open "Com1" for input as #t

    10 Rem
    input #t, k$
    print k$

    G$ = Ucase$(Inkey$)
    IF G$ <> "Q" then GoTo 10


    Close #t


    Ken S. Elvehjem
    [email protected]

  • #2
    Check the documentation of the GPS. If it has serial communication
    capability (obviously it does), there should be a simple command
    you can send it from your computer and your program will expect a
    response back. The command doesn't have to actually do anything,
    just send one that the GPS will send a response back to.

    If the response happens with a specific period of time, the GPS
    is probably connected. If it doesn't.....


    print #t,AreYouConnected$ + crlf$;

    delay (sleep) 5

    if lof(t) = 0 then
    do something. it's not connected.
    do something else. it is connected.
    end if

    Basically, what's happening on your example is the program is
    hanging up on "input #t". It's staying there, waiting until the
    comm buffer has something in it.


    Rereading your post, another way would be:

    if lof(t) > 0 then
    ' get the info and do something with it
    end if

    [This message has been edited by Mel Bishop (edited November 22, 2002).]
    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.


    • #3

      Thanks for the response! I assume LOF(t) checks how much good stuff is in the buffer.

      I will have to stand closer to my reference manual next time.

      Thanks Again,


      Ken S. Elvehjem
      [email protected]


      • #4
        Ken ..

        Be careful if you are using this in a multi-tasking operating system
        to make sure that if you do get the port open and do get the thing
        initialized. Do everything you can to keep the device from falling
        off line or the cable from getting unplugged while the port is in use.

        Even with OS/2 which is darned good about things, even OS/2 does not take
        kindly at all to yanking a serial port connection away after it has
        been established! It will lock a session bigger than Dallas and you'll
        have to go through special pains to get that session closed down if it happens!

        This is sort of like unloading cows from a trailer into the pen with a chute!
        You have a buffer load of communications cows in that trailer .. 1, 2 .. 16
        of them, whatever. You back the trailer up to the chute. You lock the chute
        in place and open the gates. Out comes the cattle prod and presto! Cows come
        down the chute!

        But .. if the chute just disappears with cows still coming down the trailer
        and they fall on the ground .. cows with broken legs and damaged beef!

        Plus the trailer has a life of its own in re cows here too! This is a crazy
        trailer that has a way of getting 1, 2 .. 16 cows in it over and over
        again. And you don't prod the load with a hot stick to empty the trailer
        until you have a set number of cows ready to run down the chute.

        PowerBASIC, from my experience at using it in DOS-VDM's in OS/2 seems
        to have an issue where if you send it a small one or two bytes, and expect
        it to give you a one byte answer back for initialization and response ..
        may get interesting! PowerBASIC does do what the routines say it is
        supposed to do with the example code for comm ports and buffering and so
        on. But that doesn't mean that the operating system will cooperate with
        one or two byte buffer operations!

        For example, a two byte probe and a one byte response to initialize the
        IRMAN infra red devices works just fine on OS/2 native. I have a port
        analysis program called Poor Man's Line Monitor that can be used in OS/2
        to display and log each and every byte that goes both ways on a given
        port. But if I try this exact same port I/O code in a DOS-VDM in OS/2,
        written in PowerBASIC and compiled as a DOS application, then I never
        see the one or two byte return from the buffer that should be in LOF(1) ...
        until more than two bytes has been entered into the buffer.

        Thus my LOF(1), like you are going to be looking for, is missing for
        the critical initiation proof like you are looking for as well! That, at
        least with the standard setup for Ray Gwinn's SIO or SIO2k comm port
        drivers for OS/2 here. You too will have comm port drivers as well,
        regardless of what operating system you engage!

        Actually, what is going on, I think, based on what I have learned, I
        think, about all this is .. that comm port routines are great for passing
        data .. AFTER .. they have been initialized! But if your devices are
        intended to use only a ONE byte or a TWO byte at first initialization
        string, and get back only ONE or TWO bytes for the response that says,
        "Chute's in place and locked, Mikey!", then there never is a clean response
        and into what-if-land we go.

        Point to make.

        There are a number of programs like Ray Gwinn's PMLM for OS/2 which can
        be found for DOS or WIN or whatver. I have lost touch of what the names
        of these tools are in DOS, but someone here can point you in this
        direction or I'll go digging in my BBS SysOp game of old Fidoland for
        you as needed.

        Your ability to really get all this working and timed correctly and being
        able to set and use just the right buffer sizes and flush modes will likely
        turn on your ability to see just one or two bytes marching up and down the
        chute during the developing and debugging of this!

        Mike Luther
        [email protected]
        Mike Luther
        [email protected]


        • #5
          In addition to those comments, be sure to test ERR/ERRCLEAR after all I/O statements to watch for run-time errors... they might also offer a good clue that the remote unit has shut down, etc.

          PowerBASIC Support
          mailto:[email protected][email protected]</A>
          mailto:[email protected]


          • #6
            Oh yes Lance!

            You are so right. And while you are talking about run time errors
            we might as well note that the use of IN and OUT can be a real stinky
            problem .. at times.

            Mother Skunk had two kits, IN and OUT. Both were underfoot in the kitchen
            and she got real mad hollering, "Go Play! Go Play!" So play they did
            in the fenced in buffer zone between the house and the alley!

            Suddenly, Out appeared back in the kitchen! Mother Skunk moaned, "I
            thought I told you to play!"

            Out said, "But Mother, I can't!"

            Mother said, "Why not?"

            Out said, "Because of In stinked!"

            Yes, Lance is right; don't go trusting your hunches about what that
            satellite gwine send you in due time. Especially when something can
            raise a stink by just pre-empting your nice cookin' session. Catch
            the errors before they get in the kitchen where you can't clean up
            the stink!

            Mike Luther
            [email protected]

            [This message has been edited by Mike Luther (edited November 23, 2002).]
            Mike Luther
            [email protected]


            • #7
              Well, I really appreciate all the input.

              I have discovered that once I get my port opened up, the incoming data is pretty regular, and it reads just fine.

              It really hates it when the GPS shuts off or the cable is disconnected in mid stream, tho.

              A thing that puzzles me:

              When I did this same idea with VB, I would "INPUT #t, K$" and I'd get every jolly thing in the buffer, including commas, CRLF's (or whatever the EOL character is, and stray subatomic particles to boot.

              When I do it from PB DOS, K$ *ALWAYS* is only the next field from the record. I'll have to snoop my code on this other program, but I had to jump through a lot of hoops to parse the data.

              I wonder what the difference could be?


              Ken S. Elvehjem
              [email protected]


              • #8

                You might try using:

                IF LOC(t) THEN
                S$ = INPUT$(LOC(t), #t)
                END IF

                Note that that is "LOC", not "LOF"!

                I do not know for a fact that this will make a difference, but
                I have not had any problems with it in the comm stuff I've


                [This message has been edited by Clay Clear (edited November 23, 2002).]


                • #9
                  Here's a code snippet I use to read a laser distance meter. This is a 'triggered' device, but the input loop might be instructive for you. It displays a running time and watches for key presses too. I have added extra comments to this post (me bad, few comments in original).

                    'read a distance
                    LOCATE 1, 1: PRINT TIME$; " Waiting for distance meter.                 ";
                    IF LOC(5) THEN a$ = a$ + INPUT$(LOC(5), #5) 'empty the com buffer first
                    a$ = "": jtime! = TIMER + 3! 'jtime! is a timeout value 3s later than now
                    PRINT #5, "M"; 'trigger the instrument
                      IF LOC(5) THEN a$ = a$ + INPUT$(LOC(5), #5)
                      GOSUB Chechey 'check for and record any keypresses in ke$
                      LOCATE 1, 1: PRINT TIME$;
                    LOOP UNTIL RIGHT$(a$, 1) = CHR$(10) OR ke$ <> "" OR TIMER > jtime!
                    LOCATE 1, 1: PRINT TIME$; "                                               ";
                  ' keys pressed take prescedence over any half read distance
                    IF RIGHT$(a$, 1) <> CHR$(10) AND ke$ <> "" THEN GOSUB DoKeyPress: GOTO begin
                    tim! = (timer / 3600!) 'record the time in decimal hours hh.hhhhh
                    d# = VAL(LEFT$(a$, 9)) 'grab the distance from the input string
                  What can go wrong will go wrong.
                  Anything can go wrong.
                  What hasn't?!?!
                  What can go wrong will go wrong.
                  Anything can go wrong.
                  What hasn't?!?!


                  • #10
                    Now here's a lengthier code bit that shows how I cope with the digital sounder. It is an ON COM() driven routine that run's fine on our 50MHz 486DX machine, without bogging down the rest of the program very much. This sounder outputs six 11 character depth strings each second, ending with LF (chr$(10)). I read the input, display it, and stream it out to a simple text file with time stamps. I will end up using a similar system for GPS capture sometime in the future when we start using it. Hope this helps.

                    A few notes:
                    - In ReadSounder, I use lots of hxxx variables, the h denotes hydro, as in hydrographic / sounder. This helps me keep my variables vaugely distinct from the rest of the program.
                    - last% points to the chr$(10)/LF that ends each depth, and I work backwards from there.
                    - if len(hd$) > 22... chops down hd$, in case the program somehow missed reading for a while.
                    - if last% < 11... chucks out any too-short depth strings (unlikely, but we don't want errors from dropped chars).
                    - hd$ acts as a running input buffer, so hd$ = MID$(hd$, (last% + 1)) dumps the part we just processed, keeps anything that came in later, until IF INSTR(hd$, CHR$(10)) finds another whole depth some later pass through.

                    ' here's the setup bits assembled in one place.
                    ' this code forces use of com2, could be made more flexible
                    ' note that I mask out all comm erreors with the 'ME, FE' options.
                    PRINT "The sounder MUST be attached to COM2 to work."
                    hcomm$ = "COM2:9600,N,8,1,RS,CS,DS,CD,ME,FE"
                    on com(2) gosub ReadSounder  'this sets up the event routine
                    com(2) on                    'before it's needed
                    OPEN hcomm$ FOR RANDOM AS #6 'this 'turns on' the sounder stream
                    '... much later in the code we find...
                    ' on-com event handler for sounder
                    ht! = TIMER  'grab the time right away
                    IF NOT EOF(6) THEN hd$ = hd$ + INPUT$(LOC(6), 6)
                    if len(hd$) > 22 then hd$ = right$(hd$, 13)
                    IF INSTR(hd$, CHR$(10)) THEN
                      last% = INSTR(hd$, CHR$(10))
                      IF last% < 11 THEN hd$ = MID$(hd$, (last% + 1)): return
                      hd! = (hsos! * (VAL(MID$(hd$, (last% - 10), 5)) / 100)) + hdraft! 'extract the depth
                      hd$ = MID$(hd$, (last% + 1))
                      htb% = csrlin : hta% = pos
                      print #7, using"##.#####, ###.##"; (ht! / 3600!), hd!
                      BigPrintNumber 27%, 55%, 0%, using$("+##.##", hd!)
                      locate htb%, hta%
                    END IF
                    Sorry about the MIXED case IN here, it's hurried port from a QB3.5 jobbie, and QB force formats your code

                    What can go wrong will go wrong.
                    Anything can go wrong.
                    What hasn't?!?!
                    What can go wrong will go wrong.
                    Anything can go wrong.
                    What hasn't?!?!