Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 08:33 07 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Sucking Everything Out of Com buffer.

Author Message
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 10:17pm 31 Aug 2016
Copy link to clipboard 
Print this post

Hi All,

Does this seem a valid approach when I have different sized data frames coming from different devices & want to ensure I suck the Coms buffer dry each time.

Each device is polled by a Master, so only one Slave will reply at a time.

Haven't tried it; thinking while out....

Position & length of pause in the loop?
Beginning or end? Length?

Do While or is Loop Until more appropriate.

Thanks

Phil.

[Code]
Open "Com1:9600,,RecComs,140" as #1


Sub RecComs
Local HdrLoc as integer
Local HdrFnd As String
Local BufLen As Integer

BufLen=0

DO WHILE BufLen<> LOC(#1)
PAUSE 10
BufLen=LOC(#1)
LOOP

Print "Buffer Length=",Loc(#1)

DataStr=INPUT$(LOC(#1),#1) 'then suck everything in the buffer out and stick it in D$....

HdrLoc=Instr(DataStr,"##Data")
If HdrLoc<>0 Then HdrFnd=Mid$(DataStr,HdrLoc,8)

Print "Header Location",HdrLoc ',Instr(DataStr,"##HpData")
Print "Header Found", HdrFnd
Print DataStr 'and print that data on the screen.
Print "==========================================="
..
..
Select Case HdrFnd
..
..
End Select

End if

End Sub
[/code]
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 10:32pm 31 Aug 2016
Copy link to clipboard 
Print this post

[code]
HdrLoc=Instr(DataStr,"##Data")
If HdrLoc<>0 Then HdrFnd=Mid$(DataStr,HdrLoc,8)
[/code]
This could already fail when there is not enough data available.

I think using an interrupt would be easier to use together with a rather large buffer for the com port (depending on how quick data arrives and is processed)

You would then append data to the end of a buffer$ in the interrupt routine.

In the main loop you check the buffer$ if it contains the start of header AND the end of header.
You could then read the complete header and parse its values.
You then chop of the header from the buffer$ with a MID$(buffer$,HeaderPosition+HeaderLength) and retrieve the data with a LEFT$buffers$,DataLength). DataLength would be one of the values in the header. You then chop of the data also to keep the buffer$ as small as possible.

A header could be:
[code]
<SOH><Type><Length><EOH>
[/code]
followed directly by data
[code]
<SOT>This is the data<EOT>
[/code]

Another much easier way is to first make sure there is enough data with LOC() and then use an INPUT$ to read a line of data from the com port. If your data 'records' end with a CR/LF then that is all you need.

Microblocks. Build with logic.
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 12:23am 01 Sep 2016
Copy link to clipboard 
Print this post

Thanks MB,

What I'm using at the moment is working, but the data is sent as frames,
about 140 to 160 bytes from each device.

It's four HC-12's all sitting on the same channel.

The Master Requests the data from a slave & it responds with it's data.

The 2 slaves can't overlap in their transmissions the way the polling is made.

It's the 4th device that has the twist, as it's a receive only monitor.

So it's buffer with contain both the request sent to the slave, as well as the slaves response for the master.

That's why I'm searching for the data header in the string.

At the moment the interrupt is triggered at 140 bytes, but to make sure everything is in the buffer before I read it I have a pause in place of about 50ms to allow extra characters to arrive.

I'd rather not have the pause just fixed; Don't like pauses a lot....

Cheers.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9589
Posted: 12:28am 01 Sep 2016
Copy link to clipboard 
Print this post

[Quote=Phil23]Open "Com1:9600,,RecComs,140" as #1[/Quote]

@ MicroBlocks - the above line of code in Phil's example IS an interrupt - it will loop to RecComs when there is 140 bytes or more in the serial port buffer. Therefore, the code won't fail in the sub, as there will be at least 140 bytes in the buffer at the point the sub is called. Provided of coarse that 140 bytes satisfies the data manipulation routines.....
Smoke makes things work. When the smoke gets out, it stops!
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 01:24am 01 Sep 2016
Copy link to clipboard 
Print this post

Nothing guarantees that the data is exactly what you expect it to be. Well, Murphy's law actually guarantees it is not like you expected. :)

The ##Header could be at the end of the 140 bytes that is read. And the data in the next block of 140 bytes, which will be available later in the next interrupt.
You need to put everything in a buffer and then 'find' the header and make sure there is enough after the header to proceed.



Microblocks. Build with logic.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9589
Posted: 01:30am 01 Sep 2016
Copy link to clipboard 
Print this post

Good point.

I especially like your Murphy's Law comment!
Smoke makes things work. When the smoke gets out, it stops!
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 09:55am 01 Sep 2016
Copy link to clipboard 
Print this post

The ##Data Header is unusual at the beginning of the buffer on the Main unit, but moves to either 11 or 21 on the monitor only MM.

I get a different case if I take one slave off line, as the monitor receives 2 requests on it's buffer, but only one is followed by a response.

Trying to accommodate that situation, units not responding.

That's why I search for the headers position.

The data is all sent in a burst, so since the 140 triggers the routine I want to make sure I've got the whole lot before moving on.

Noticed its less of an issue on the 28 pin than the E64 as the speed of the 100 can have it processing before the last 10 or 20 characters are received.

The processing below the sub ensures the data is valid.

Phil.
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 09:57am 01 Sep 2016
Copy link to clipboard 
Print this post

So back to the primary question,

is the DO WHILE a valid way to check that the buffer is not growing once the Com interrupt is triggered.
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025