Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 06:49 13 May 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 : Newie got a few questions

     Page 4 of 25    
Author Message
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 02:33am 15 Aug 2016
Copy link to clipboard 
Print this post

Thanks, I'll be able to sort it out with that help
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 03:08am 15 Aug 2016
Copy link to clipboard 
Print this post

I spoke too soon

What I want to do is this

[code]
Open "COM1:19200" As #2 'Open port for HC-12 TX/RX
'OPEN "COM3:9200" AS #3
If LOC(#2) <> 0 then SERIALFLUSH 'If COM1 serial port buffer is NOT empty....
if LOC(#3) <> 0 then SERIALFLUSH1
DO
clock routine and other bits go here
LOOP
End
Sub SERIALFLUSH
Local D$ 'Define D$ only for use by this subroutine(ignores any D$ in main code)
D$ = Input$(40, #2) 'Suck everything in buffer out
Print D$;
End Sub

Sub SERIALFLUSH1
Local F$ 'Define D$ only for use by this subroutine(ignores any D$ in main code)
D$ = Input$(80, #3) 'Suck everything in buffer out
Print F$;
End Sub


The only way I've got part of it working is this
[quote]
Open "COM1:19200" As #2 'Open port for HC-12 TX/RX
'OPEN "COM3:9200" AS #3
If LOC(#2)<>0 then LOOP 'If COM1 serial port buffer is NOT empty....
DO
IF LOC(#2)>1 THEN SERIALFLUSH
SERIALFLUSH
pause 500
LOOP
End

Sub SERIALFLUSH
Local D$ 'Define D$ only for use by this subroutine(ignores any D$ in main code)
D$ = Input$(40, #2) 'Suck everything in buffer out
Print D$;
End Sub [/quote]
 
Zonker

Guru

Joined: 18/08/2012
Location: United States
Posts: 767
Posted: 02:47pm 16 Aug 2016
Copy link to clipboard 
Print this post

Lew..

Sub SERIALFLUSH1
Local F$ 'Define D$ only for use by this subroutine(ignores any D$ in main code)
D$ = Input$(80, #3) 'Suck everything in buffer out
Print F$;
End Sub


This one has the data going back into D$ (not F$)

Prints nothing...

This is easy to do, and I have done it many times...

Easy fix...

Also, you open #3 at 9200 baud...? not 9600...

I notice also, you hit the action subs if ANY amount of data is collected...

Usually, you would wait for a small number of characters to build up first. If you know how many are expected, then set the LOC on a few less...
If you know what the termination character is (like cr/lf) then you can also check for this... Data is usually collected from the RX buffer one character at a time, and then "added" to the D$ or F$ holding variable... While doing this with a simple DO loop, you can also be checking for the termination character... Edited by Zonker 2016-08-18
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9493
Posted: 03:07pm 16 Aug 2016
Copy link to clipboard 
Print this post

Yes, as Zonker says....

Note my examples are just examples, and I have not tried it with an HC-12 module.

However, it should work as commented.

In your subs, you are sucking 40 bytes out of the buffer in SERIALFLUSH and 80 bytes in SERIALFLUSH1.

Please note that if there is NOT 40 or 80 bytes in there to suck out, you will get that "Error: Number out of bounds." error again, as you would be trying to read what is not there.

Writing code is fun, eh?!

I also agree with Zonker on the CR or LF idea.
This is how I detect all my serial coms, but that is in MY case, which is specific to my serial devices and needs.
Smoke makes things work. When the smoke gets out, it stops!
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 07:08am 28 Aug 2016
Copy link to clipboard 
Print this post

Now I#'m back in the country again I can start working on this again

I'm "slightly" (very) confused over input$ and character length

If I use D$ = Input$(80, #3) 'Suck everything in buffer out
That assumes there are 80 characters coming in via the com port

However does characters mean each letter and space, or each comma seperated item?

for instance

how many characters are there in this string send to the serial port?
[quote]{"city":{"id":2651357,"name":"Denton","coord":{"lon":-2.11822,"lat":53.456779},"country":"GB","population":0},"cod":"200 ","message":0.0092,"cnt":7,"list":[{"dt":1472385600,"temp":{"day":20.82,"min":15.1,"max":20.82,"night":15.1,"eve":18.07,"morn":20.82},"pressure":1000.23,"humidity":91,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}] ,"speed":2.01,"deg":7,"clouds":92,"rain":2.54},{"dt":1472472000,"temp":{"day":18.7,"min":11.34,"max":19.24,"night":11.34 ,"eve":17.68,"morn":14.1},"pressure":1009.58,"humidity":77,"weather": [{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}] ,"speed":4.82,"deg":284,"clouds":0},{"dt":1472558400,"temp":{"day":22.25,"min":8.84,"max":23.07,"night":14.47,"eve":21.2 2,"morn":8.84},"pressure":1010.56,"humidity":67,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}] ,"speed":3.61,"deg":218,"clouds":0},{"dt":1472644800,"temp":{"day":20.04,"min":11.67,"max":20.04,"night":13.12,"eve":18. 19,"morn":11.67},"pressure":1003.72,"humidity":70,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}] ,"speed":4.41,"deg":226,"clouds":0,"rain":1.44},{"dt":1472731200,"temp":{"day":16.42,"min":8.1,"max":18.15,"night":8.1," eve":16.97,"morn":11.79},"pressure":1010.7,"humidity":75,"weather": [{"id":500,"main":"Rain","description":"light rain","icon":"10d"}] ,"speed":2.62,"deg":293,"clouds":8,"rain":0.22},{"dt":1472817600,"temp":{"day":20.17,"min":11.54,"max":20.17,"night":11. 54,"eve":18.96,"morn":16.62},"pressure":1012.65,"humidity":0,"weather": [{"id":500,"main":"Rain","description":"light rain","icon":"10d"}] ,"speed":5.94,"deg":239,"clouds":61,"rain":0.87},{"dt":1472904000,"temp":{"day":23.21,"min":10.51,"max":23.5,"night":14. 51,"eve":23.5,"morn":10.51},"pressure":1013.14,"humidity":0,"weather": [{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"speed":3.89,"deg":140,"clouds":0}]}[/quote]

Edit:
or if thats too many to count
How many are in this string?[quote]{"coord":{"lon":-2.12,"lat":53.46},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}] ,"base":"stations","main":{"temp":17.99,"pressure":1013,"humidity":68,"temp_min":16,"temp_max":20},"visibility":10000,"w ind":{"speed":5.1,"deg":300},"clouds":{"all":40},"dt":1472403905,"sys":{"type":1,"id":5060,"message":0.0305,"country":"G B","sunrise":1472361153,"sunset":1472411099},"id":2651357,"name":"Denton","cod":200} [/quote]

And am I right in assuming that If I use D$ = Input$(80, #3)
If there are less than 80 characters the string is still received correctly and will work, but if there are more than 80 characters then the string received will be ignored by the program and it would appear on first glance the com port isn't working?
Edited by lew247 2016-08-29
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3999
Posted: 07:54am 28 Aug 2016
Copy link to clipboard 
Print this post

I think it's:

Fewer than 80 and it will wait until there are 80. Forever, if needs be. So, if you expect 80 but there is a tiny chance one will be corrupted your program may hang forever. (It may be wise to assume this can happen and program differently.)

It counts each char (byte), so any commas are not special just more char(s).

More than 80 and you get the 80 you asked for with the rest still in the buffer.

JohnEdited by JohnS 2016-08-29
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 05:40pm 28 Aug 2016
Copy link to clipboard 
Print this post

Yes,

Every Single ASCII chatacter counts.

[Code]{"This is",50 Characters:of text, etc, etc, "etc".[/code]

If it was Printed Without a semi colon,

Ie

[Code]Data$="{"This is",15 Characters:of text, etc, etc, "etc"."

Print#1, Data$

Vs

Print#1, Data$;[/code]

It would be 52 characters long as the string would have a CR & LF at the end.

The two strings you show above are 1928 & 446 characters long according to Excel.


Phil.
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 09:23pm 28 Aug 2016
Copy link to clipboard 
Print this post

Thanks you Phil and JohnS
I understand it fine now

However what do I use IF the serial port is going to have 2 different sets of data coming in, one set is 1928 characters, and the other set is 446 characters?


If I want to pick out words that are comma seperated like this
[quote]mmrain "," , mmrain2 "," , hightemp "," , hightemp2 "," ,[/quote]
Would I be correct in assuming that I use arg$
ie arg$(0) would select mmrain and arg$(3) would select hightemp?
Edited by lew247 2016-08-30
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2927
Posted: 10:07pm 28 Aug 2016
Copy link to clipboard 
Print this post

I don't believe ARG$ is a function (or at least its not in the manual!).

You may want to use INSTR to search for the position of the words (if the words are known), and then read the subsequent data with MID$

WW
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6221
Posted: 10:13pm 28 Aug 2016
Copy link to clipboard 
Print this post

Before you get too carried away, strings in MMBasic are limited to 255 characters.
The com buffer can be configured to hold more so I would read the port in bite sized chunks and search them for your keywords before getting the next chunk.

Someone here did a program for scraping weather data.

Jim
VK7JH
MMedit
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 10:14pm 28 Aug 2016
Copy link to clipboard 
Print this post

Thanks Phil
I can see a problem so, while I know what "words" will be sent the actual character length can vary, for instance the pressure might at one time be 948.34 another time it might be 1024.87 for example
That's why it would be better to be able to select specific "words" which are a number of comma's apart, that way I wouldn't need to know the exact character length or what the actual "word" will be

an example of what I mean
The serial port will be receiving these "words?"
"Today," & desc & "," & icon & "," & temp & "," & press &"," & speed & "," & dir & "," & humid
BUT the actual words received will vary each time
for example desc one time might be "light clouds" but another time might be "sunny"
dir could be 1 or it could be 360 and so on
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 10:27pm 28 Aug 2016
Copy link to clipboard 
Print this post

Thanks TassyJim
I actualy made an error above
It's the ESP8266 that will be receiving all those characters and parsing them, then it will be transmitting only the data I actually want on it's serial port to the Micromite

But as a result I won't know the exact number of characters coming into the serial port at any one time (but it will be less than 255) and each item of data will have a comma separating themEdited by lew247 2016-08-30
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6221
Posted: 10:38pm 28 Aug 2016
Copy link to clipboard 
Print this post

If the data is being sent in one burst,
1. read the data
2. add it onto the end of a bugger string
3. wait a brief while
4. go back and get the next chunk and add it onto the end of your buffer string.
If there is no data available after a suitable length wait, you can assume that the sending has finished and you have all the data to play with.

Another option.
You know the maximum amount of data that gets send in one event so you can work out the time it takes to send (depends on the baud rate and number of characters.
When you get the interrupt signalling the data has started to arrive, wait the maximum time before retrieving the data.
That way you know you have got it all in one chunk.

If you know the number of fields arriving, you know the number of commas so you can count them.

If you have control over the sending, add a CR to the end so you know you have it all.

And there are lots of other ways to do the task. AS long as the sending system and the receiving system know what the other is doing.

Jim
VK7JH
MMedit
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2927
Posted: 10:56pm 28 Aug 2016
Copy link to clipboard 
Print this post

From the data samples you send, the 'word' is always in speech marks, then there is a colon, then there is the 'data'. Any more 'chunks' of information are separated by a comma; but they follow the same pattern above.

Note the 'data' can be numeric (not in speech marks), or wording (in speech marks).

So an example from your data:

"id":800,"main":"Clear","description":"clear sky"

Are you trying to read the data 'between' commas (i.e. "id":800) or are you trying to read the 'word headings' (i.e. ID) so you can then 'extract' the data (800)?
Edited by WhiteWizzard 2016-08-30
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 11:03pm 28 Aug 2016
Copy link to clipboard 
Print this post

Basically I'm going to get the ESP to send the data as follows
"Start", data1,data2, data3 and so on then "end"
That way there will be a start and an end to pick out valid data
EACH item will be seperated by a comma

what I need to do is check there is a start and end being received by the micromite
THEN once there is valid data in the Serial buffer be able to pick out sections of data
for example I might want to PRINT data1 but I might want to do something different Data3
Hope that made senseEdited by lew247 2016-08-30
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10071
Posted: 11:09pm 28 Aug 2016
Copy link to clipboard 
Print this post

The data is in JSON format, see wikipedia

I can't find a full JSON parser written in Basic although MikeO has done some great work on this
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3999
Posted: 11:14pm 28 Aug 2016
Copy link to clipboard 
Print this post

I'd work on the basis that you need to build up a string char by char from the serial buffer (LOC will tell you if there's at least one) because you have functions that can work on a string.

Then you need to allow for errors such as inserted/corrupted chars.

So you need to allow for things such as a start but no end, two starts etc.

If each item has a trailing comma you can separate the items using that (INSTR can find a comma, for example). If it's something else then use that.

Then you need to allow for each item possibly being corrupted.

And so on. Just think logically. (You can't program anything robust otherwise.)

It might be simpler to write the code if you don't care if it crashes / hangs / is unreliable from time to time. The code itself may be about the same length if you make it robust but may well need harder thought...

JohnEdited by JohnS 2016-08-30
 
jman

Guru

Joined: 12/06/2011
Location: New Zealand
Posts: 711
Posted: 11:43pm 28 Aug 2016
Copy link to clipboard 
Print this post

Hi
Looks like you are trying parse some weather information.
Not sure if this helps but they way I do it is use a web server running PHP
(Most Web Servers can do this)
This downloads and does a parse on the json and then sends the results in nice
linefeed delimited format to the MM. As I know none of the lines are more than
255 characters and I know how many lines to expect reading the data from the com port via the ESP8266 is easy


Do
Line Input #1, C$
If echo Then Print c$
Loop While C$ <> "START"

Print "Start found ";C$

Do
I=I+1
Line Input #1, WData$(I)
Print WData$(I)
Loop While WData$(I) <> "END"

Print "End Found ";WData$(I)

End Sub


Below is the output from the PHP script of course you can customize
it to suit your needs and taste


START
Mon
Time 21:40:06 29-08-2016
Temperature 08
Humidity 76
Pressure 1008
Mon
29-08-2016
Max : 19
Min : 07
mostlycloudy
Sunrise : 07:01
Sunset : 17:59
Wind SPD : 4
Mostly cloudy. Low 7C.
Tue
30-08-2016
Max : 14
Min : 03
partlycloudy
Sunrise : 06:59
Sunset : 18:01
Wind SPD : 13
Some clouds in the morning will give way to mainly sunny skies for the afternoon. High 14C. Winds ESE at 10 to 15 km/h.
Wed
31-08-2016
Max : 13
Min : 02
clear
Sunrise : 06:58
Sunset : 18:02
Wind SPD : 23
Sunny. High 13C. Winds ENE at 15 to 30 km/h.
Thu
01-09-2016
Max : 16
Min : 07
mostlycloudy
Sunrise : 06:56
Sunset : 18:03
Wind SPD : 23
Partly cloudy. High 16C. Winds NNW at 15 to 30 km/h.
Fri
02-09-2016
Max : 19
Min : 06
clear
Sunrise : 06:54
Sunset : 18:04
Wind SPD : 19
Sunshine. High 19C. Winds NNW at 15 to 25 km/h.
Sat
03-09-2016
Max : 13
Min : 06
partlycloudy
Sunrise : 06:52
Sunset : 18:05
Wind SPD : 14
Partly cloudy. High 14C. Winds SE at 10 to 15 km/h.
Christchurch
END



To use the PHP use the following format
http://your-url-here/test.php?Key=xxxxxx&Location=NZCH
This uses https://www.wunderground.com/ to obtain the weather data you will
need to get an API key from them (There are free).

2016-08-29_093449_Weather.zip

Please note I am no PHP expert so the PHP is not very pretty but it does work
Hope this helps

Regards
Jman

 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2927
Posted: 11:57pm 28 Aug 2016
Copy link to clipboard 
Print this post

  lew247 said   . . . be able to pick out sections of data
for example I might want to PRINT data1 but I might want to do something different Data3
Hope that made sense


If data1 always reprints the same data item, then this will be fine, but what if data1 is a different data item? This is why I should think the word (header, call it whatever) is relevant so that you know what the subsequent data represent.

Anyway, if you just want to extract the 'characters' between commas then here is a little demo program for you. I am simply looking for the first comma in a string (with INSTR), then looking if there is another comma, then if so, print the characters between the commas with the MID$ function. Keep going until no more commas, in which case just finally print out the characters after the last comma.

DIM a$ = "Start,123,456,hello,test,1a2s3,,test2, end" 'populate our test string
PRINT a$ 'display our test string
p1 = INSTR(1,a$,",") 'look for position of first comma
ww: 'a label which we will jump back to continually until we see no more commas
IF p1<> 0 AND p1 <> LEN(a$) THEN 'check there is a comma and its position isn't at the end of the string
p2 = INSTR(p1+1,a$,",") 'look for next comma AFTER current comma (i.e. from p1+1)
IF p2 THEN 'if we found another comma then now extract data between commas....
PRINT MID$(a$,p1+1,p2-p1-1) 'for now just print data
'Want data between commas hence start at p1+1, and for number of characters up to second comma i.e. p2-p1-1
p1=p2 'so we can loop through string, set new p1 as p2 and look for next comma (into p2 if comma exists)
GOTO ww 'go loop through until no more commas
ELSE
PRINT MID$(a$,p1+1,LEN(a$)-p1) 'no more commas so print remaining characters
ENDIF
ENDIF
Edited by WhiteWizzard 2016-08-30
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 12:09am 29 Aug 2016
Copy link to clipboard 
Print this post

WW that is what I needed thanks, I can work from that to get mine to do what I want.
Thanks everyone else for the help, yes the ESP gets JSON and iv'e already got it parsing only the actual information I need sent to the Micromite.
 
     Page 4 of 25    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025