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.
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 12:36am 12 Dec 2016
Copy link to clipboard
Print this post
Sorry Phil The problem this time was I was overthinking, getting confused yet again by the integers, strings and so on. I now finally have it correct Thanks for the help and sorry everyone for asking so many "stupid" questions
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2932
Posted: 12:47am 12 Dec 2016
Copy link to clipboard
Print this post
No question is 'stupid' - and this forum is a great place to be able to ask ANYTHING!
Glad that its working now for you. So have you got all of it as you need?
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 01:20am 12 Dec 2016
Copy link to clipboard
Print this post
Almost
I'm having problems "decoding" the data received on the indoor unit
[code] SUB SERIAL1 'Com1 data Local B$ B$ = Input$(254, #1) 'Suck everything in buffer out N = GetFieldArray(B$) D$ = FieldArray$(0) 'Start or Time F$ = FieldArray$(3) 'Year G$ = FieldArray$(5) 'Month H$ = FieldArray$(7) 'Day z$ = FieldArray$(9) 'Hour J$ = FieldArray$(11) 'Min K$ = FieldArray$(13) 'Sec If D$ = "Time" Then PRINT B$
RTC SETtime F$,",",G$,",",H$,",",z$,",",J$,",",K$ 'Set RTC to correct local time and date
RTC GETTIME 'read the time from MM Text 90,215, DOW$(DayOfWeek(Year, Month, Day)), CM, 1, 2, RGB(BLACK), RGB(63, 133, 195) 'Print the Day of week Under Big Ben Text 90,270, Date$, CM, 1, 2, RGB(BLACK), RGB(63, 133, 195) 'Date END SUB secs=Val(Right$(Time$,2)) 'for setting the clock on the display mins=Val(Mid$(Time$,4,2)) 'for setting the clock on the display hours=Val(Left$(Time$,2)) 'for setting the clock on the display ELSE T6 END SUB[/code]
Basically I want to check the data received, IF it starts with "TIME" then it carries on and sets the MM clock IF it has anything else it carries on to T6 which is another sub
Just off to work so I'll come back to it when I get home tonight
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2932
Posted: 01:37am 12 Dec 2016
Copy link to clipboard
Print this post
I believe you need to Put 'T6' on its own line i.e. immediately below the ELSE. Also add an ENDIF
IF D$ = "Time" Then .... ELSE T6 ENDIF
erbp Senior Member Joined: 03/05/2016 Location: AustraliaPosts: 195
Posted: 06:42pm 12 Dec 2016
Copy link to clipboard
Print this post
It also looks like there is an extra END SUB in the middle of the IF statement - see below:
Text 90,270, Date$, CM, 1, 2, RGB(BLACK), RGB(63, 133, 195) 'Date END SUB secs=Val(Right$(Time$,2)) 'for setting the clock on the display
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 12:36am 13 Dec 2016
Copy link to clipboard
Print this post
Thanks erbp, I did spot that and had changed it but thanks anyway
I have found the problem, it's with a Function to seperate comma seperated values [code]Function GetFieldArray( Record$, Delimiter$, KeepQuotes ) 'Function to get array from COM port Local Index, Char, InQuote, Count InQuote = 0 Count = 0 FieldArray$(Count) = "" If Delimiter$ = "" Then Delimiter$ = "," For Index = 1 To Len(Record$) Char = Asc(Mid$(Record$, Index, 1)) If Char = 34 Then InQuote = Not InQuote If Not InQuote And Instr(Delimiter$, Chr$(char)) >= 1 Then Count = Count + 1 FieldArray$(Count) = "" Else If Char <> 34 Or KeepQuotes Then FieldArray$(Count) = FieldArray$(Count) + Chr$(char) EndIf EndIf Next GetFieldArray = Count + 1 End Function [/code]
Here's the "relevant" sections of code that is going wrong [quote]IF LOC(#1) > 0 THEN SERIAL1 'If data in COM1 then GOSUB Serial1 END IF SUB SERIAL1 'Com1 data Local B$, Local D$ B$ = Input$(254, #1) 'Suck everything in buffer out N = GetFieldArray(B$) D$ = FieldArray$(0) 'Start or Time F$ = FieldArray$(3) 'Start or Time If D$ = "Time" Then T10 ELSE T6 [/quote]
What is happening is the function is working perfectly, and it does what I want it to do, it finds the 1st and 3rd values of the comma seperated string perfectly However, when the serial port sends different data, the Function still has the original string in it's "memory" and isn't seeing the "new data" being received by the com port
Hope that made sense as I'm hopeless at explaining what I can see in my mind
Basically I need a way to clear the com port buffer, or what the Function has in it's memory every time the serial port receives new data
The serial ports sends 2 lines One begins with "Start" and the 2nd one begins with "TIME" It's never sees the "TIME" line because it still has "Start" in it's memory.
If I end the line with a ,"*" I can search for the * character, Is there a way to clear the "memory".buffer/Function memory" when it detects the end of receive character (*)
Hope that also made sense
Edit: to put it simply The Function is seeing the first line from the Com port that starts with "START" BUT It's NOT seeing the next input from the serial port that begins with "TIME"
Edited by lew247 2016-12-14
panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1114
Posted: 12:57am 13 Dec 2016
Copy link to clipboard
Print this post
Lew, seems to me that you may have a timing/sequence issue here. You wait on a character appearing in the COM port (the LOC(#1) > 0 function) but then data is still coming in when you go to the function to analyse the data. You should probably set your LOC function to wait for the number of characters you expect in the line before you try to read it in with the INPUT$ function.
BTW, the INPUT$ character will read and remove any and all characters up to the number of characters you specify in the function. Eg. INPUT$(256,ANY$) will attempt to read and remove 256 characters but with your LOC(#1) > 0 command you will try to start taking characters out sometime after the first character - how many will depend on baud rate and the code between the LOC function and the INPUT$ function.
Hope that makes sense.
I sent you a PM with a suggested interrupt driven code snippet to handle this situation the other day. Cheers, panky.
PS. For testing, put a PRINT B$ in after your INPUT$ function to confirm what you are receiving?Edited by panky 2016-12-14... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 01:03am 13 Dec 2016
Copy link to clipboard
Print this post
Thanks Doug, I didn't actually see the message the other day, just looked at it now, am off to work so I'll "digest it" when I get home Thanks
btw I did do a Print B$ and it does receive the complete string, but it doesn't clear before the next input from the com port, maybe I need to close the com port once I've done what I need it to do and then reopen it after (you might have suggested that in your message, I'll read it properly when I'm home again)
MicroBlocks Guru Joined: 12/05/2012 Location: ThailandPosts: 2209
Posted: 03:59am 13 Dec 2016
Copy link to clipboard
Print this post
Lew the function clears the data it returns. Also the count that tells how many fields there are is working correct. Always check the count before doing further processing to make sure you have all the fields you need. [code] N = GetFieldArray(B$) IF N = 13 THEN 'change this number to the exact number of fields you expect 'All fields accounted for ELSE 'Not all fields available ENDIF [/code] Also check the string you get from the COM port to make sure you provide the function with new data.
Microblocks. Build with logic.
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9590
Posted: 08:41am 13 Dec 2016
Copy link to clipboard
Print this post
Congratulations Lew - you have a 25-page thread. No easy task. Obviously plenty of interest in the newbie questions. Smoke makes things work. When the smoke gets out, it stops!
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1667
Posted: 10:17am 13 Dec 2016
Copy link to clipboard
Print this post
I had a similar situation with timing & a variable length string being received.
Initially I used LOC(#1)>140 then had a 50ms pause to allow the buffer to completely fill. That sort of worked but still had issues occasionally when 2 transmissions randomly overlapped.
Ended up fixing it by adding a test to see if the buffer is growing (about 1.04mS per character @9600), after the point the interrupt was triggered at the 140 character mark..
Code was something like this:-
[Code] Do BuffLength=LOC(#1) Pause 5 Loop Until LOC(#1)=BuffLength [/code]
Phil
panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1114
Posted: 12:32pm 13 Dec 2016
Copy link to clipboard
Print this post
Lew,
Looking at your code I think I see the problem. My comments are in bold
IF LOC(#1) > 0 THEN SERIAL1 'If data in COM1 then GOSUB Serial1 END IF
SUB SERIAL1 'Com1 data Local B$, Local D$ 'here you declare a local variable B$ B$ = Input$(254, #1) 'Suck everything in buffer out N = GetFieldArray(B$) ' here you call an external function using ' the local variable B$ - don't think that will work D$ = FieldArray$(0) 'Start or Time F$ = FieldArray$(3) 'Start or Time If D$ = "Time" Then T10 ELSE T6 ' missing endif and end sub but that may just be where you cut off ' the sample 'code. BTW, if you indent as I have above it is very ' simple to see missing 'endifs or end subs etc.
I tested the above scenario with this simple bit of code to check on the passing of local variables
Print "testing" Test_B
Sub Test_B ' create a local variable Local B$="123" Test_A End Sub
Sub Test_A Print B$ ' try to use the local variable above End Sub
Running the above code will not print the contents of B$ as you would suspect. I think your program is setting your field array at some stage with the input data and this is then staying there and never being updated by your INPUT$ function.
Again, hope this helps
panky... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
MicroBlocks Guru Joined: 12/05/2012 Location: ThailandPosts: 2209
Posted: 03:39pm 13 Dec 2016
Copy link to clipboard
Print this post
When a function is called the data that is contained in the variable is 'copied' to the functions parameter. In the function it is available under the parameter name. It does not have to be a global variable.
Microblocks. Build with logic.
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 12:32am 14 Dec 2016
Copy link to clipboard
Print this post
Thanks everyone Panky, I didn't put the END SUB and END IF in the code snippet above, but it is in the actual full code
Jean, thanks, I now know what N does and I can do something similar to IF D$ = FieldArray$(0) = "START" and N = 20 THEN sub1 'subroutine to do something when "START" is the first word received END IF IF D$ = FieldArray$(0) = "TIME" and N = 12 THEN sub2 'Subroutine to do something when "TIME" is the first word received END IF
That "should" work I think because there are only ever 2 sentences being received by the com port and they begin with either "start" or "TIME" and I know how many fields are in each sentence (N = number of fields)
Unfortunately I can't work on this now until Friday due to work, but hopefully I can sort it now I understand what N is
EDIT: What I would like to do if it's possible is close the com port once it receives the character *
is there a way to do this by doing something like
B$ = Input$(254, #1) 'Suck everything in buffer out IF B$ (contains "*") then close com port ? Edited by lew247 2016-12-15
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2932
Posted: 11:14am 14 Dec 2016
Copy link to clipboard
Print this post
IF INSTR$(B$,"*") THEN CLOSE #1 'change to relevant file number you wish to close (note: this is NOT necessarily the COM Port Number ENDIF
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 11:41am 14 Dec 2016
Copy link to clipboard
Print this post
Thanks Phil, that's exactly what I needed, I think you did tell me before but I'd forgotten sorry
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 12:06am 17 Dec 2016
Copy link to clipboard
Print this post
I've just found the time to come back to this again [code]Open "COM1:19200" As #1 'Open port for HC-12 TX/RX
IF LOC(#1) > 0 THEN SERIAL1 'If data in COM1 then GOSUB Serial1 END IF
SUB SERIAL1 'Com1 data Local B$, Local D$ B$ = Input$(254, #1) 'Suck everything in buffer out IF INSTR$(B$,"*") THEN CLOSE #1 'change to relevant file number you wish to close (note: this is NOT necessarily the COM Port Number ENDIF N = GetFieldArray(B$) D$ = FieldArray$(0) 'Start or Time If D$ = "Time" Then T10 ELSE T6 END IF END SUB[/code]
[218] If INSTR$(B$,"*") Then Error: Expected a number
I tried changing IF INSTR$(B$,"*") to IF INSTR$(B$,CHR$(42))
but this didn't work either
What I want to do is 1: detect the * process the GetFieldArray(B$) 'Fieldarray function works perfectly 2: detect either "START" or Time" as the 1st comma seperated value 'D$ which works 3: If Time is detected then go to sub T10 4: or if START is detected go to sun T6
I have been working on this when I came home eveery night this week, but I think the problem is I've actually confused myself to the state now where this is something so simple that I can't see the solution
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10216
Posted: 12:11am 17 Dec 2016
Copy link to clipboard
Print this post
INSTR is the correct command and not INSTR$
INSTR returns a number and hence it doesn't have a $ in the function name. It happens to take a string as the parameter
if you wrote your own version then the function definition would be
FUNCTION INSTR(A$ as STRING) AS INTEGER ... END FUNCTION
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 4036
Posted: 12:11am 17 Dec 2016
Copy link to clipboard
Print this post
INSTR returns a number so has no final $
John edit: d'oh beaten to it!Edited by JohnS 2016-12-18
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702
Posted: 12:20am 17 Dec 2016
Copy link to clipboard
Print this post
Thank you both of you
A 2nd question if you dont mind
If I have something like [code] B$ = Input$(254, #1) 'Suck everything in buffer out IF INSTR(B$,"*") THEN CLOSE #1 'change to relevant file number you wish to close (note: this is NOT necessarily the COM Port Number [/code]
And I then process B$ so it goes to one of 3 subroutines
Is there a way to detect IF a com port is closed before I reopen it??
because once * is detected I am closing the com port as this will clear the com buffer But once I have done what I need to do I want to open the com port again ready for the next set of data
I could put open com 1 etc at the end of the subs, but it "may" cause a problem If I happen to use both subs sometime
Page 15 of 25
Print this page
The Back Shed's forum code is written, and hosted, in Australia.