Com port communication

Please use this Board for QBasic related requests ( file research, programming, etc.)

Moderators:Administrator, Global Moderator

Post Reply
Guest
Com port communication

Post by Guest » Fri Jun 20, 2003 8:32 pm

I'm working to interface Qbasic with several machines in the lab, and I was wondering if it would be possible for me to save or view signals that come through the Com port from an outside source. Any help would be appreciated.  

User avatar
frankiebaby
Global Moderator
Posts:95
Joined:Tue Apr 30, 2002 1:38 am
Location:Pennsylvania
Contact:

Re: Com port communication

Post by frankiebaby » Sat Jun 21, 2003 8:50 am

yes, it is possible. I have created a unit that controls 8 AC outlets via parallel port for the purpose of controled lighting.

The statement your are looking for is:

OPEN "COMn: optlist1 optlist2" [FOR mode] AS [#]filenum [LEN=reclen]

 _ n is either 1 or 2, and identifies the communications port to be opened
 _ optlist1 has the following syntax
     [speed][,[parity][,[data][,[stop]]]]
   where the defaults are set for the transmission of text (rather than
   numeric) data. See Details if you are transmitting numeric data.

this was taken from the basic online help. if the data you are recieveing is text, 1 bit per character (LEN = reclen = 1) for integers 2 bits and for doubles i believe is 4. if you are using mixed characters and numbers i would probably use characters. Its seems your purpose would be to save or display output, so 1 bit should do the trick. You use the com port just like a file ie:

INPUT #1, variable

Guest

Re: Com port communication

Post by Guest » Sat Jun 21, 2003 11:46 pm

I've tried what you're suggesting, but the program seems to stall on that INPUT command. You see, since the COM ports open up either as output, input, or random, I have to switch between them after I send the message that causes the hardware to respond. I don't know if that completely messes it up or what, but I'll try your suggestion again. Thanks for the tip!

Lukes52
Newbie
Posts:4
Joined:Sat Dec 16, 2017 7:36 pm

Re: Com port communication

Post by Lukes52 » Sat Dec 16, 2017 8:05 pm

I have an A/D converter that has placed the following characters in Com Port #3: Voltage = 1.2, *
I am using the following QB64 code to read the serial data:

‘ ** Wipe out old messages
Z$ = ""

OPEN "Com3:9600,n,8,1,ds0,cs0,rs" FOR INPUT AS #2
_DELAY .25 ' Delay to let Com Port settle

PRINT "EOF="; EOF(2), "LOC="; LOC(2), "LOF="; LOF(2) ' Debug line showing why the following error; EOF=-1 LOF and LOC both =0 even though info is there

DO UNTIL INSTR(Z$, "*") > 0
Z$ = INPUT$(12, # 2) '-----------------ERROR INPUT PAST END OF FILE
PRINT "EOF(2)="; EOF(2)
LOOP

PRINT "instr="; INSTR(Z$, "*")' When I get the error I get a dialog box asking if I want to continue anyway I press YES and get instr= 9

PRINT "Z$="; Z$ ,” lenZ$= “; LEN(Z$) , I also get Z$=Vlae=12,* That is every other character in the buffer.

First question why do I get EOF=-1 as soon as I open the port? How can I change that or not show EOF for the INPUT statement?

Lukes52
Newbie
Posts:4
Joined:Sat Dec 16, 2017 7:36 pm

Re: Com port communication

Post by Lukes52 » Sun Dec 17, 2017 12:29 am

I have since added the following lines after the _Delay .25 line.

getdata:
bytes% = LOC(2) ' Check receive buffer for data
IF bytes% = 0 THEN GOTO getdata ' After more than 300 thousand of getdata cycles it continues

Now EOF is still -1 but LOC is 17 and LOF still shows 0
How can LOF be 0 if there are 17 characters?
I tried changing to Open for Random and using Get #2, , Z$ but since LOF=0 it gives ERROR bad file length
When opening as random EOF =0 until the first Get statement, but LOF=0 still causes the above error.

HOW DO YOU READ A SERIAL BUFFER?

Lukes52
Newbie
Posts:4
Joined:Sat Dec 16, 2017 7:36 pm

Re: Com port communication

Post by Lukes52 » Wed Jan 03, 2018 7:00 pm

SOLUTIONS USED:
I used the OPEN FOR INPUT command and Z$=INPUT(LOC(2),#2) which I knew would result in an INPUT PAST END OF FILE error. I had to use LOC instead of LOF b/c LOF was always =0 and my routine returned LOC = a valid number. just before the Z$= INPUT command I added the line ON ERROR GOTO EHANDLER. Then at the end of the Code I added"
EHandler:
errfile$ = _INCLERRORFILE$
RESUME NEXT
The program steps over the error and keeps running.

As for the every other character in the buffer read error. I altered the output of my A/D sending code with spaces between the letters. I could then read the correct message with QB64 with the exception of the missing decimal in the voltage value. Then using LSTR$, RSTR$, and CVI commands I was able to get my voltage reading. of course it was wrong having no decimal, but knowing where it belonged I divided by 10,000 to put the decimal where it belonged. Seems like a nasty bunch of work arounds but I am continuing with my project now.

Lukes52
Newbie
Posts:4
Joined:Sat Dec 16, 2017 7:36 pm

Re: Com port communication

Post by Lukes52 » Fri Jan 19, 2018 10:31 pm

This program reads a com port and plots a voltage reading sent to the com port via an A/D
QB64 always causes an Input Past End of File error when reading a com port but the included ON ERROR / Error handling sub takes care of it.

Code: Select all

CLS
LOCATE 2, 20, , 0, 7
PRINT "COLLECTING DATA"
_DELAY 1
j = 0 '                                 Counter for counting samples to average
SCREEN 12 '                              Set screen to Graph Mode
GOSUB AxisPrint
seconds1 = TIMER

again: '                              This is where it starts again and again for each sample
CLOSE #2 '                            Close COM ports
'_DELAY 1
OPEN "Com3:9600,n,8,1,ds0,cs0,cd0,rs" FOR RANDOM AS #1 ' Open COM port to output command
_DELAY 1.25 '                                             delay to let com settle
FIELD #1, 35 AS m$
'                                          Form Message to send to External Device
Command = 2: pin = 4: argument = 0 '          Code to Get analog voltage reading(0-5Vdc)
msg$ = STR$(Command) + "," + STR$(pin) + "," + STR$(argument) + "*"
LSET m$ = msg$ '                               Prepare message for sending code
PUT #1, , m$ '                                Send message to the external device
_DELAY 1 '                                     Let it settle

CLOSE #1 '                                       Finish sending request
m$ = "": msg$ = "" '                                Wipe out old messages
bytes% = 0: Z$ = ""

OPEN "Com3:9600,n,8,1,ds0,cs0,cd0,rs" FOR INPUT AS #2 ' Open to get Voltage reading

getdata: '                                    Loop until data present
_DELAY 2.5 '                                  Delay to let Com Port settle and data arrives
bytes% = LOC(2) '                             Check receive buffer for data
IF bytes% < 2 THEN GOTO getdata 'DELAY above was increased until first pass has data: Loop if not ready
ON ERROR GOTO EHandler '              Input past end of file occurs in next line b/c LOF=0
Z$ = INPUT$(12, # 2) '               Error but gets data in buffer Goes to EHandler to clear Error Message
'
j = j + 1 '                                       Counts number to average
endofdata = INSTR(Z$, "*"): '                     PRINT "EOD= "; endofdata: PRINT " len(Z$)= "; LEN(Z$)
Z$ = LEFT$(Z$, endofdata - 1) '                 gets data left of End of File trash
Z$ = RIGHT$(Z$, 2) '                            plucks voltage reading out of Buffer
V = VAL(Z$) '                                   Converts voltage text to number
V = V / 10 '                                   Decimal point not read restore decimal point
IF V > .01 THEN Vb = V '                     If valid voltage reading save as Vb
Va = Va + Vb '                                Add for average
IF j = 4 THEN Va = Va / 4 ELSE GOTO again '   Average this many samples or go get another sample
j = 0 '                                      Clear number to average counter

seconds2 = TIMER '                          Get finish time
DeltaT = seconds2 - seconds1 '              Calculate time to end of average sample for plotting
IF DeltaT > 3500 THEN DeltaT = 1 '          Wrap data points on graph if X axis max is reached
'                        *******************Calculate and scale data TO GRAPH **********
X = DeltaT
X = 50 + DeltaT * 600 / 3600 ' SCALE TIME to X AXIS FOR the Time point
tmp$ = "                             ####,.## Seconds" ' Format for printing Time
PRINT ; USING tmp$; DeltaT
tmp$ = "                             #####.## Volts" ' Format for printing voltage
PRINT ; USING tmp$; Va

Va = 400 - (Va * 80) '                       SCALE Va TO GRAPH Y for the voltage point
Y = Va
Va = 0 '                                     reset to zero for next round

AxisPrint: '                  ********** Subroutine to draw graph axis and labels *********
LINE (50, 0)-(50, 400), 10 '                Draw Y axis
LINE (50, 400)-(600, 400), 10 '             DRAW X AXIS
LINE (350, 395)-(350, 405), 10 '            Draw X axis Tic
LOCATE 12, 3, , 0, 7 '                      Y AXIS LABEL POSITION
PRINT "V" '                                 Y AXIS LABEL
LOCATE 27, 43, 1, 0, 7 '                    X AXIS LABEL POSITION
PRINT "TIME" '                              X AXIS LABEL
FOR i = 1 TO 390 STEP 20 '                  Y AXIS TIC MARKS
    LINE (45, i)-(55, i), 7
NEXT i
LOCATE 21, 4, , 7 '                         Y AXIS LABEL POINT
PRINT "1"
FOR i = 50 TO 600 STEP 25: k = i + 5 '      Voltage line
    LINE (i, 81)-(k, 81), 10
NEXT i
LOCATE 16, 4, , 10
PRINT "2"
FOR i = 50 TO 600 STEP 25: k = i + 5 '      Voltage line
    LINE (i, 161)-(k, 161), 10
NEXT i
LOCATE 11, 4, , 10
PRINT "3"
FOR i = 50 TO 600 STEP 25: k = i + 5 '      Voltage line
    LINE (i, 241)-(k, 241), 10
NEXT i
LOCATE 6, 4, 0, 10
PRINT "4"
FOR i = 50 TO 600 STEP 25: k = i + 5 '      Voltage line
    LINE (i, 321)-(k, 321), 10
NEXT i
LOCATE 1, 4, 0, 10
PRINT "5"
FOR i = 50 TO 600 STEP 25: k = i + 5 '      Voltage line
    LINE (i, 1)-(k, 1), 10
NEXT i
RETURN '                                    End of subroutine to print graph

CIRCLE (X, Y), 2%, 7 '                      DRAW VOLTAGE POINT
GOTO again '                                Go get next voltage reading

END

EHandler: '                     ********* Subroutine to clear End of File error message ********
errfile$ = _INCLERRORFILE$
RESUME NEXT

Post Reply