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 : Continuation from cog31s GPS issue.
Page 1 of 3 | |||||
Author | Message | ||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5911 |
VK7JH MMedit  MMBasic Help |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5911 |
Don't know what happend to my first post and not able to edit it. Most of the time your tfrgps sub runs without being interrupted by the serial routine. When it DOES coincide, you notice the longer times. I added a global counter to record the number of calls to the spcomrec4 sub during the tfrgps sub and added the count to the printout. This was run on an explore64 and a real GPS. It is likely that my GPS is configured differently to yours so I would expect some variation but it does suggest that the timing differences you see are caused by the program flow, not an underlining problem with MMBasic. Modified program: OPTION EXPLICIT OPTION AUTORUN ON CONST top1s=31 '16 CONST cnbcde = 3 CONST cnbch = 18 CONST cnbbuf = 10 CONST ccptvdg = 5 'comptage nb sec sans reception com CONST maxto = 500 'ex ime out 5 sec DIM i AS INTEGER DIM i1 AS INTEGER DIM i2 AS INTEGER DIM intCall AS INTEGER DIM tmcde(cnbcde) AS STRING LENGTH 3 DIM nbcde AS INTEGER DIM tmgps(cnbcde,cnbch) AS STRING LENGTH 20 DIM nbgps(cnbcde) AS INTEGER DIM ptcde AS INTEGER DIM ptgps AS INTEGER DIM flggps(cnbbuf) AS INTEGER DIM txcrc AS STRING DIM nbcar AS INTEGER DIM cptm3 AS INTEGER DIM cptvdg AS INTEGER DIM ptime1 AS FLOAT DIM ptime2 AS FLOAT DIM validgps AS INTEGER DIM tmbuf(cnbbuf) AS STRING DIM flgtmbuf(cnbbuf) AS INTEGER DIM ptWrite AS INTEGER DIM ptRead AS INTEGER DIM txbufgps AS STRING DIM txchamp AS STRING DIM flgf AS INTEGER i=0 i=i+1:tmcde(i)="GGA" i=i+1:tmcde(i)="GSA" i=i+1:tmcde(i)="RMC" nbcde=i txbufgps="" flgf=0 OPEN "COM1:9600,255,spcomrec4" AS #2 ptWrite=0 ptRead=0 FOR i=1 TO cnbbuf tmbuf(i)="" flgtmbuf(i)=0 NEXT i '***************************** DO ptime1=TIMER intCall = 0 tfrgps ptime2=TIMER IF ptime2-ptime1>50 THEN PRINT TIME$;" ->";STR$((ptime2-ptime1)/1000,4,3);" ";STR$(intCall) END IF PAUSE(10) LOOP '***************************** SUB tfrgps() 'store in database LOCAL txt AS STRING LOCAL flgg AS INTEGER FOR i=1 TO cnbbuf ptRead=ptRead+1 IF ptRead>cnbbuf THEN ptRead=1 IF flgtmbuf(ptRead)=0 THEN EXIT FOR IF flgtmbuf(ptRead)=2 THEN txt=tmbuf(ptRead) spgps(txt,flgg) IF flgg>0 THEN flgtmbuf(ptRead)=0 calccrc2(txt) IF (validgps AND 16)=16 THEN rangegps(txt,flgg) END IF END IF END IF NEXT i END SUB SUB calccrc2(txc AS STRING) LOCAL jc AS INTEGER LOCAL ic AS INTEGER LOCAL i3 AS INTEGER jc=INSTR(txc,"*") IF jc>2 THEN ic=0 FOR i3=2 TO jc-1 ic=ic XOR ASC(MID$(txc,i3,1)) NEXT i3 END IF txcrc=HEX$(ic) IF LEN(txcrc)=1 THEN txcrc="0"+txcrc IF txcrc=RIGHT$(txc,2) THEN validgps=(validgps OR 16) ELSE validgps=(validgps AND &hEF ) PRINT txc PRINT txcrc;"<>";RIGHT$(txc,2) END IF END SUB SUB spgps(txg AS STRING, ergp AS INTEGER) LOCAL i AS INTEGER ergp=0 FOR i=1 TO nbcde IF MID$(txg,4,3)=tmcde(i) THEN 'for gps($gp) or glosnass($gn) frames ergp=i EXIT FOR END IF NEXT i END SUB SUB rangegps(txcrc AS STRING, flge AS INTEGER) LOCAL b$ AS STRING LENGTH 1 IF LEFT$(txcrc,1)="$" THEN ptgps=0 ptcde=flge txchamp="" FOR i2=1 TO LEN(txcrc) b$=MID$(txcrc,i2,1) IF b$="," THEN ptgps=ptgps+1 tmgps(ptcde,ptgps)=txchamp txchamp="" ELSE IF ASC(b$)>31 THEN txchamp=txchamp+b$ END IF NEXT i2 ptgps=ptgps+1 IF ptgps<=cnbch THEN tmgps(ptcde,ptgps)=txchamp END IF flggps(ptcde)=2 nbgps(ptcde)=ptgps END IF END SUB SUB spcomrec4 LOCAL tx$ AS STRING 'length 3 LOCAL i1 AS INTEGER LOCAL i2 AS INTEGER LOCAL a$ AS STRING LENGTH 1 LOCAL vai AS INTEGER intCall = intCall + 1 i1=LOC(#2) IF i1=0 THEN EXIT SUB ELSE tx$=INPUT$(i1,#2) FOR i2=1 TO i1 a$=MID$(tx$,i2,1) vai=ASC(a$) IF a$="$" THEN ptWrite=ptWrite+1 IF ptWrite>cnbbuf THEN ptWrite=1 tmbuf(ptWrite)="" flgtmbuf(ptWrite)=1 END IF IF vai=10 THEN flgtmbuf(ptWrite)=2 ELSE IF vai>31 THEN tmbuf(ptWrite)=tmbuf(ptWrite)+a$ END IF NEXT i2 ENDIF END SUB VK7JH MMedit  MMBasic Help |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5911 |
I made one small change to your com port specs. The interrupt routing is only called when a LF character is received. I don't know what your program is doing so that might not be suitable but I generally find it more efficient to let the operation system do its receiving in the background. Jim VK7JH MMedit  MMBasic Help |
||||
panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1094 |
@goc30 Your biggest problem with your program is that you are calling the interrupt program for every character received and then only retrieving 1 character at a time with your input$ statement, therefore your main loop will be interrupted continuously throughout the loop. As there is effectively no gap in the character stream from the GPS for each frame of 8 records (about 470 characters and at 9600 baud, about 470mS per frame, repeated at 1 second intervals), the input buffer may build up to several characters waiting while the interrupt routine is processing the last interrupt. It will only clear out at the end of of the 8 records before the next set starts (about 500mS after the end of the last record - the GPGLL record) Because you may get an indeterminate number of interrupts between your two timer catches while you are processing the tfrgps routine (which also calls three other sub routines - spgps, calccrc2 and rangegps), the timing is unpredictable. As a suggestion, if you want predicability, there are several steps you might consider:- 1. As Jim has pointed out, it would be easier to wait on a specific character in the GPS stream before triggereing the interrupt - maybe the $ at the start of each frame then you can check for the particular frame you want eg. GPRMC has the time and speed data. 2. Rather than just grabbing 1 character at a time with your input statement, grab at least 80 ( longer than the longest frame) then just keep everything up to the CR. 3. Lastly, if you were to wait on a GPRMC header than grab at least 480 characters, you could be sure of getting a full set of GPS records then you would have at least half a second before the next data stream starts to do all the post processing you want of the GPS data. If none of that works for you, you could write your own CFunction or better still, move to another language. With the greatest respect, your somewhat pointed response to Geoff in your recent post on your problems, indicates that despite your lengthy resume of all your prowess and experience, you might benefit from suggestions on programming from others. panky ... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it! |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
hi Jim and panky thank for your helps contrary to what you imply, I am quite open to any solution, otherwise I would not be on this forum. Moreover, computer requires that we learn to learn and listen and that we can question ourselves Ithink that you do not fully grasp the problem of GPS, especially underperforming Chinese modules (there is no activate writing functions and no speed change). 1 - When you start your program, you can receive any end of any frame without begin char, so you do not start with a "$". Because of this, you have to test each received character to know where your frame begins. 2 - the content of a frame is variable, depending on the state of reception of gps signals. Let's say that there are 4 states to a gps (no exchange, exchange without information, exchanges with invalid information - for example the internal clock only and no position, and exchanges with valid infos) 3 - my applications do not manage all the frames. For example for the reference clock, I only need the frame "RMC". on the other hand to do race recognition, I need almost all the frames. 4 - the current modules receive both gps and galileo or glonass, so the number of frames received in the second is more variable. 5 - if you looked at the last example that I put in the other thread, you would have seen that the more one puts of instruction in the part "reception of characters", the more one slowed strongly the duration of execution of the sub -program. And this is THE real problem: why is this duration so important, when it is only a few simple instructions (marked loop) that should be executed in less than 100 microseconds, and not more than 1 millisecond. And i don't say about memory limitations on mx170. For exemple, it is not possible to have an array 8 by 18 (8 frames with 18 fields max) in string format, without have an memory capacity error more generally, I think you have not understood the architecture of my program. the goal is to lose as little time as possible to read the received frame and only to store it in a rotating stack, then when there is time available, ie between two receptions of characters, we continue the work of depilation and in the right boxes. The main loop can be interrupted as many times as necessary, it does not matter. But provided that the receiving routine leaves free time and does not take up too much CPU time. but in my case, it is this problem that annoys me. And so if, as you put it, I wait for the end of a frame to treat it, I have all the more characters to arrange, and so in this case, I would lose even frames. I tested your solution, and that's what happened to me. the more time you spend in the re-capture routine, the more chances you have to have overlapping frames. remember that the interrupt generated by the chip does not go directly into my routine, but goes through a MMBasic layer, and what does this layer ??, you know? What guarantee do I have that with the stop code(10), there will only be one interrupt or that, as I think, there will always be an interrupt with each character processed by MMBasic, and it's only MMbasic who after these treatments, will call my routine at the reception of the stop code. And how many time is used by MMBasic to process internales interrupts? Also, I know that in "UART by interrupt" pogram writing in "C" and given by Microchip, it is necessary to mask interrupt bit when you receive a char. Is it same case in MMbasic?? I have also other GPS programs in other langages (Asm, "C" ,Pascal, Python) on other platforms. My choice depending of necessity to have more or less graphicals capacity and others reel-times process (like trip-master, car speed, alarms,etc). If I choice MMbasic, it is for simplicity (1 mx170/470 +1 GPS + 1 rtc + 1 tft 2.8"). My error is to think that a cpu (mmx470) who work at 120mghz can do more than an arduino in 16 mghz Edited 2019-10-08 17:35 by goc30 |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8592 |
Use the ArmmiteF4 with the matching ILI9341 screen. Supports the OPEN "COMn:baudrate" as GPS command and then all the GPS processing is done in the firmware. Just use the GPS function to interrogate the variables you need. See the ArmmiteH7 manual for details |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
Hi peter I use your function on my H7, and it work correctly (very good job thank). My only problem is your "valid" function who work only in binary state (yes or no), but some times I need to know if I receive internal time or gps real time, but it is no important. in the case of this thread, I wanted to build a small box that gives exactly the time and closes a relay contact every minute at exactly "00 seconds" (with an accuracy of 1 millisecond). And it is not possible because no stability or precision. |
||||
panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1094 |
@goc30, You're absolutely correct - it is a complex issue to fully analyse and interract with a GPS stream - even more so given that the internals of the PIC chip itself are somewhat obscured by MMBasic (a good thing for most of us, particularly with less time critical applications). Would a precision oscillator with hardware division to precisely generate a 1 second control signal be an option. A periodic GPS check could apply an analogue correction to the oscillator via the Micromite perhaps? panky ... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it! |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
my proto box |
||||
panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1094 |
As a more general observation, it seems to me that GPS is better for precise time averaging (in a Micromite environment) as the processing and interpretation of the GPS stream adds a level of uncertainty for absolute time action - even though the GPS timing itself is particularly correct? Thus, if you could use the GPS time info averaged over a period of time and compare that with averaged Micromite time (which would/should minimise interrupt processing variables), you could apply the differences as a feedback control. Just some thoughts - I would be interested to see any comments Geoff or Peter may have regarding very precise timing related issues and how to best integrate GPS timing for enhanced accuracy. panky Thinking further, for 1mS accuracy with +/- 1% repeatability, you would need to have better than +/- 10uS processing - way beyond a 170! Edited 2019-10-08 20:14 by panky ... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it! |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
in my case, precision of 1 millisecond is good, no need more. And gps module give a "PPS" signal who come exactly at "000" millisec. I use this data to close my relay. For open relay, I use an other interrupt task (settick 10ms). and in this case problem begin to be strong, because relay close at "0", but re-open at a random time (normaly after 20ms) between 25ms and ... 800ms. to finish, I have an other interrupt task who print time on screen each seconde. When you look at screen, some time it lost seconds or pass immediatly for exemple from second "23" to second"24". for info, on h7 with peter's GSP function, I have no pb. That say that it is an MMbasic timing problem on mx170/470. |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3661 |
Why not get the code and study it? Geoff does allow that, and readily. John |
||||
panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1094 |
Could you use a 555 monostable triggered by the 1PPS signal and then the reasonably precise 10mS timing to turn the relay off? Use the Micromite as a control manager to either enable of disable the triggering of the 555? ... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it! |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
when you use an gps as reference time, you must use "PPS" signal, who is the most precision data. After, you need to synchro all of your process with this signal. with olds gps modules, you can say to gps that you want receive only RMC and at speed you choice, but with chineses modules it is not possible, they are closed transmit function (or may be change crc compute). for that you must process all frames and spend time for that. In race cars, I need precision time (races in milliseconds times). for that we have precision boxes, but this boxes need to be synchronized, and my box is made for that (when it work good) |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 3552 |
In other words: build a software PLL. That is also how calibration of Rubidium frequency references works. The average GPS signal over 24 hours and adjust the Rubidium tuning according. Then you get within 1ppm accuracy. Volhout P.S. 1 mSec accurate relay operation may need compensation, since mechanical relays take 3-20mSec to switch the contact, only reed relays are faster. You can do this by measuring the exact opening time and closing time of the contact (in the actual circuit) and compensating for it. PicomiteVGA PETSCII ROBOTS |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
with mmbasic, problem is not to have an exact interrupt signal (it work good), but only why and where mmbasic spend time between hard or timer interrupt and user begin's program interrupt subroutine. |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8592 |
The search funmction is difficult on the new BB but ages ago I wrote a Cfunction that worked as a monostable. i.e. an external interrupt on one pin (the PPS output from the GPS) could trigger a timed pulse on another pin to a very high level of accuracy. If you search for it you should find it and I seem to remember it worked on MM2 and possibly MM+ |
||||
goc30 Guru Joined: 12/04/2017 Location: FrancePosts: 425 |
in race cars, it is not a real problem. If all of yours chronos (who use also relays) are synchro with the same box, it is correct (time is calculate with difference between start time and arrival time. This is for that I need stable execution programs for references chrono (who are used for records) whe used transistors or statics realys and not mechanicles relays but they are more delicates to use Edited 2019-10-08 20:36 by goc30 |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8592 |
Here you go |
||||
Chopperp Guru Joined: 03/01/2018 Location: AustraliaPosts: 1032 |
The last C_fuction in the post works better. @matherP Sent you a PM in case you missed it. Edited 2019-10-08 21:46 by Chopperp ChopperP |
||||
Page 1 of 3 |
Print this page |