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 : Capturing serial data with Micromite
Author | Message | ||||
SteveIzett Newbie Joined: 04/05/2023 Location: AustraliaPosts: 24 |
I'm wondering if I could please have some help with capturing rs232 ascii serial data? I am seeking to extract/parse information from a Dynon Skyview aircraft EFIS system. I began by seeking to capture and parse a 74 ascii character sentence containing flight data. The sentence begins with a ‘!’ character and ends the CR & LF characters and contains data like Airspeed and Course etc. What I have managed to achieve is intermittent. Parsing of a retrieved data string is OK. The problem is the string containing the target sentence does not reliably begin at the beginning of the sentence, being the ‘!’ character. Is my understanding correct - I'm thinking that once a serial port is opened, the uart would start buffering incoming characters into a FIFO. But how do you then Input/retrieve that data starting at the beginning of a new sentence. I thought that was the purpose of the 'int-trigger' option of the Open command. The code I found/copied used the following: Open "COM1:9600,80,Com1_Rx_Int,=10" As #1 A buffer larger than the 74 characters of a full sentence. (Maybe to small) Interrupt triggered by a ‘LF’ character (last character of a sentence) sub Com1_Rx_Int Rx-Flag = 1 'Data available Dynon_adahrs$ = input$(82,#1) 'read more chars to ensure the buffer is empty Rx_data_error_Flag = 0 'clear a flag ready for error testing If len(Dynon_adahrs$) <> 74 then ‘if not the correct sentence length set an error flag Rx_data_error_Flag = 1 endif end sub In the Main Program Loop If Rx_Flag = 1 then 'data is available after rx interrupt If Rx_data_error_flag = 0 Then Parse the data items of interest and act apporopriately Clear old sentence data ready for new data ……. My thinking: I thought it a good idea to use interrupts to maximise time available for other tasks. I've seen GPS code that just sits there waiting for a '$' character but that seemed wasteful of processor time. What I think I’ve learnt is that by the time the interrupt gets the data from the buffer there is no guarantee it begins with a new sentence (‘!’ character). I thought this was the point of an interrupt being able to be triggered by the reception of a particular character. I would appreciate being pointed in the right direction so as to enable efficient code that gets a sentence into the Dynon_adahrs string beginning with the first character - ‘!’ character! Having achieved this, I would then like to be able to read and parse a serial stream contains two different repeating sentences. Each begins with the ‘!’ character. The second character of each sentence identifies it as either Flight (74 character ADAHRS) data or Engine (225 character EMS) data sentences. Help would be greatly appreciated. Sincerely, Steve, Perth WA. |
||||
Hawk Senior Member Joined: 15/07/2021 Location: AustraliaPosts: 141 |
Hi Steve, Once your interrupt has triggered, have you considered reading the data from the buffer and discarding all the data until you get to the '!' character? Presumeably this data is the end of a previous message. You then read data into your message$ until you get a <CR><LF>. Then process your message$. You may be better increasing the size of your buffer to store up to two messages, and then raise the interrupt after the <CR><LF> has been received, indicating that there is potentally a whole message ready to process. Cheers, Mike |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6101 |
You need to 'flush' the input buffer before using the received data. The simplest way with your data is to read each line/packet and discard until the first character of the string is the desired "!" After that there shouldn't be any lost packets but I would keep the rx buffer at 256 bytes. Not all mites have the advantage of an interrupt on a specific character so don't be tempted to change chips. Jim Edited 2023-05-04 12:21 by TassyJim VK7JH MMedit MMBasic Help |
||||
SteveIzett Newbie Joined: 04/05/2023 Location: AustraliaPosts: 24 |
Thanks Mike and Jim. I'll. increase the buffer to its default which I think is 256. How do you flush the receive buffer? is it by 'Input'ing a larger sample than the buffer and then disregarding it? Cheers Steve |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3805 |
To flush, you'd use a loop reading chars until you find the "!". But it isn't a good habit to sit looping in an interrupt routine. I'd stop using the LF (the =10) part. Also, that will work on 'mites that don't support the =10 thing. Your main routine can easily test for chars being available and process them. If you keep the =10, just set a flag and have some other part of your program do what you need. John |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6101 |
Yes. read a reasonable size string and discard. repeat until nothing gets returned. This assumes that there is a reasonable time between data packets. I would set the RX buffer to 1024 bytes to allow for the engines data. Read a few bytes - 32 would do. Look for a "!" if found trim the preceding characters off, determine which packet is being received and fetch the remainder. It might take a couple of reads to gather it all. Just keep asking for whatever the remaining number of characters is. Do any checking. Make sure you have the CRLF ending. I would expect there to be a CRC or at least a checksum. repeat. Jim VK7JH MMedit MMBasic Help |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9131 |
Here is how I would do it: Open the serial port with an interrupt to trigger every say 20 characters In the interrupt copy all received data into a longstring using LONGSTRING APPEND This then runs in the background capturing the data without missing anything REPEAT Then in the main program you can use the LINSTR function to find your start character. Use LONGSTRING TRIM to remove the characters to the left of the start character if any Test for CRLF using LINSTR and when found use LGETSTR$ to copy the complete message into a normal string for processing END REPEAT |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6101 |
I am not sure if his maximite has LONGSTRING... VK7JH MMedit MMBasic Help |
||||
SteveIzett Newbie Joined: 04/05/2023 Location: AustraliaPosts: 24 |
Im wondering about the pros and cons of the interrupt routine reading one character at a time vs reading a whole buffers worth of data. Any wisdom and code fragments you recommend. Cheers Steve |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2140 |
"Capturing serial data with a MicroMite" MM2 perhaps? |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3805 |
I'd read one char at a time in the interrupt unless I had a compelling reason to do otherwise. Save the char. Let the main code deal with it from there. If you feel like it, the interrupt code could set a flag for "!" seen and another flag for LF seen. LONGSTRING doesn't look worthwhile here. You're dealing in short simple stuff. Keep it simple :) John |
||||
lizby Guru Joined: 17/05/2016 Location: United StatesPosts: 3152 |
Micromite offers interrupt upon receipt of a specific character, e.g.: OPEN "COM1: 300, 256, MyInt, =10" will interrupt upon receipt of linefeed. See Appendix A – Serial Communications. PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
SteveIzett Newbie Joined: 04/05/2023 Location: AustraliaPosts: 24 |
Thanks everyone. Very helpful. I'll have a go tomorrow. Cheers Steve |
||||
SteveIzett Newbie Joined: 04/05/2023 Location: AustraliaPosts: 24 |
Hi people. I increased the size of the buffer and the code works just fine. Thanks again for the help. Steve |
||||
Print this page |