NMEA2000
NMEA2000 copied to clipboard
SetN2kGNSSSatellitesInView
Hi! Please tell me how to properly parse satellites from NMEA 0183 and transfer them to NMEA2000. NMEA0183ParseGSV -> SetN2kGNSSSatellitesInView. Maybe there is a ready-made example? I can't do it right myself yet!
Have not seen example.
In NMEA0183 there are totalMSG, thisMSG and SatelliteCount. So if there is 6 satellites on view, there will be 2 NMEA0183 messages you need to catch:
- totalMSG=2, thisMSG=1, SatelliteCount=6, read sat info 1-4.
- totalMSG=2, thisMSG=2, SatelliteCount=6, read sat info 5-6 (skip if of two satellites on message - they should be empty)
One way is to collect satellites info from NMEA0183 first to vector and then send that to NMEA2000. One way is to add it N2kMsg something like below. I wrote code from head and have not tested does it compile or work.
void HandleGSV(const tNMEA0183Msg &NMEA0183Msg) {
static tN2kMsg N2kMsg;
static int WaitSatelliteCount=0;
static int ReceivedSatelliteCount=0;
static int WaitMsg=0;
static int WaitMsgCount=0;
if ( NMEA0183Msg.IsMessageCode("GSV") ) { // Do not know why this is not tested on NMEA0183ParseGSV as should
int totalMSG, thisMSG, SatelliteCount
tGSV NMEA0183GSV[4];
if ( NMEA0183ParseGSV(NMEA0183Msg,totalMSG, thisMSG, SatelliteCount, NMEA0183GSV[0],NMEA0183GSV[1],NMEA0183GSV[2],NMEA0183GSV[3]) ) {
if ( ThisMsg==1 ) {
SetN2kGNSSSatellitesInView(N2kMsg);
WaitSatelliteCount=SatelliteCount;
WaitMsg=1;
WaitMsgCount=totalMSG;
ReceivedSatelliteCount=0;
}
if ( WaitMsg!=thisMSG || WaitMsgCount!=totalMSG || WaitSatelliteCount!=SatelliteCount ) {
// Not proper message group. Cancel receiving.
WaitMsg=0; WaitMsgCount=0;
return;
}
int MsgSatelliteCount=min(4,WaitSatelliteCount-ReceivedSatelliteCount);
ReceivedSatelliteCount+=MsgSatelliteCount;
tSatelliteInfo SatelliteInfo;
SatelliteInfo.RangeResiduals=N2kDoubleNA;
SatelliteInfo.UsageStatus=N2kDD124_Unavailable;
for ( size_t i=0; i<MsgSatelliteCount; i++ ) {
SatelliteInfo.PRN=NMEA0183GSV[i].SVID;
SatelliteInfo.SNR=NMEA0183GSV[i].SNR;
SatelliteInfo.Elevation=NMEA0183GSV[i].Elevation;
SatelliteInfo.Azimuth=NMEA0183GSV[i].Azimuth;
AppendSatelliteInfo(N2kMsg,SatelliteInfo);
}
if ( WaitMsg==totalMSG ) {
// All received, send N2k message
NMEA2000.SendMsg(N2kMsg);
WaitMsg=0; WaitMsgCount=0;
} else WaitMsg++;
}
}
}
thank you very much!
good time of day. Doesn't work directly. But I'm worried about something else. Fields with a zero value are not read from 0.
SatelliteInfo.Elevation -1000000000.00 SatelliteInfo.Azimuth -1000000000.00
$GPGSV,3,2,12,09,79,119,28,11,25,274 ,, 16,34,062,37,20,34,304,*7B SatelliteInfo.PRN -1000000000.00
They are not 0 values. They are empty values, which will be read as NA. At very beginning I had trouble of using nan in all small MCU:s so I defined NMEA0183DoubleNA=-1e9; When you get any value from functions, you can test it if ( NMEA0183IsNA(val) ) ...
. To check is value NA . Use defined function not comparison val==NMEA0183DoubleNA
. There are own function for each types and will be always properly checked. Also if you do not have value for some parameter, you have to provide NMEA0183DoubleNA. E.g., NMEA0183SetHDG(NMEA0183Msg, Heading, NMEA0183DoubleNA, Variation);
thanks a lot
On NMEA2000 library there NMEA2000DoubleNA which has been set same as NMEA0183DoubleNA. There is als N2kIsNA(val)
thanks again. I went to read the description. There is still a lot to understand.
- I did not understood your question? There is something wrong with your data: $GPGSV,4,3,14, 20,00,219,, 21,05,068,17, 22,57,197,14, 23,11,339,7D SNR can not be 7D or is SNR missing and 7D is checksum. * is missing in all your messages.
- Do not understand that either. What display?
About PGN 129540 I am not sure how MFDs will handle separate messages. PGN 129540 can hold up to 18 satellites so normally GPS systems sends all visible satellites with one message. You are no sending 4 separate messages.
totalMSG = 4. thisMSG = 4. SatelliteCount = 14. You can only get data totalMSG = 3. only about 12 satellites. not all 14. I can't read all 14.
A bit complex to follow... But... You set ReceivedSatelliteCount+=MsgSatelliteCount; So when you get third message, your received satellite count is 12. Then later: Satviv = (WaitSatelliteCount -ReceivedSatelliteCount); So on third message you get Satviv=14-12=2 Then: if ( Satviv <4 ) { Now Satviv=2 on third message, which means that 4th message will not be handled properly and actually will cause message sent twice s far as I could read your code.
Also as far as I understood your code does not handle case you miss one message for any reason. You should also test that message sequence is right (1,2,3,4) and start over to wait sequence 1, if for any reason there is one missing e.g. 1,3,4. You may also get sequence 2,3,4, so you should not do anything, if sequence has not been started.
Thanks a lot. I also suspect a mistake. I will look for
Also remember to limit for single NME2000 message satellites to 18. NMEA0183 can send up to 9 messages and so have 36 satellites.
Good afternoon. I would like to return to the question. When the data in the row is everywhere tGSV &Msg1, tGSV &Msg2, tGSV &Msg3, tGSV &Msg4. the data can be received and processed. If the data is only in tGSV &Msg1, tGSV &Msg2 .tGSV &Msg3 Data no tGSV &Msg4-NA. data cannot be obtained. It's just impossible to read the line $GPGSV,3,3,11,29,34,244,13,31,13,324,14,32,05,267,1447 or this option. $GLGSV,3,3,09,88,36,080,3153 It won't be read anyway.
Now I see the problem. I do not have standard, so I can not say what is requirement. On examples I have seen there is always all fields listed. Fields without information will be empty (,,) like in $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D For that reason parser has test bool result = ( NMEA0183Msg.FieldCount() >= 19);
You can change in your code test to bool result = ( NMEA0183Msg.FieldCount() >= 7);
Then it should read your messages and fill rest data with NA.
Please use proper message format where checksum is separated with * . You messages confused me and they looked like they would have been cut of and not had all data.
I'm sorry. it's hard to write questions when the result is in front of your eyes :))
GPGSV fields 1 = Total number of messages of this type in this cycle 2 = Message number 3 = Total number of SVs in view 4 = SV PRN number 5 = Elevation in degrees, 90 maximum 6 = Azimuth, degrees from true north, 000 to 359 7 = SNR, 00-99 dB (null when not tracking) 8-11 = Information about second SV, same as field 4-7 12-15= Information about third SV, same as field 4-7 16-19= Information about fourth SV, same as field 4-7
In can be with length 7, 11, 15 and 19
"In can be with length 7, 11, 15 and 19" is that from NMEA0183 standard document?
The standard says:
2) A variable number of "Satellite ID-Elevation-Azimuth-SNR" sets are allowed up to a maximum of four sets per sentence. Null fields are not required for unused sets when less than four sets are transmitted.
Since null fields are not required, the valid lens are 7,12,15 and 19
OK. Then test bool result = ( NMEA0183Msg.FieldCount() >= 7);
is enough, since function will just set rest NA.
I updated fix to library. Please test.
Also noticed that github changes * before checksum one message. It must be escaped. $GPGSV,3,3,11,29,34,244,13,31,13,324,14,32,05,267,14*47
This is a completely different matter. I used to suffer like a fly on a window. Everything is fine. Thank you.
I have not tested, but if you provide NMEA0183DoubleNA for missing satellites, they should be left empty meaning NA.
Fix: NMEA0183UInt32NA . For some reason setter data has been done with uint32_t.
Two groups of satellites 10, and 11.
Processed the same way.
The result is bad for 11.
New MSG WaitMsg 1 thisMSG 1 WaitMsgCount 3 totalMSG 3 WaitSatelliteCount 11 SatelliteCount 11 SVID 6 Elevation 34.00 Azimuth 51.00 SNR 30.00 SVID 11 Elevation 55.00 Azimuth 95.00 SNR 30.00 SVID 12 Elevation 66.00 Azimuth 131.00 SNR 27.00
SVID 19 Elevation 1.00 Azimuth 67.00 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 1 totalMSG 3 WaitMsg++ 2
WaitMsg 2 thisMSG 2 WaitMsgCount 3 totalMSG 3 WaitSatelliteCount 11 SatelliteCount 11 SVID 20 Elevation 17.00 Azimuth 118.00 SNR 27.00 SVID 24 Elevation 4.00 Azimuth 179.00 SNR 0.00
SVID 25 Elevation 74.00 Azimuth 267.00 SNR 0.00
SVID 28 Elevation 33.00 Azimuth 305.00 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 2 totalMSG 3 WaitMsg++ 3
WaitMsg 3 thisMSG 3 WaitMsgCount 3 totalMSG 3 WaitSatelliteCount 11 SatelliteCount 11 SVID 29 Elevation 35.00 Azimuth 244.00 SNR 0.00 SVID 31 Elevation 14.00 Azimuth 324.00 SNR 0.00
SVID 32 Elevation 4.00 Azimuth 266.00 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 3 totalMSG 3
---->SendMsg(N2kMsg)
WaitMsg++ 0
New MSG WaitMsg 1 thisMSG 1 WaitMsgCount 3 totalMSG 3 WaitSatelliteCount 10 SatelliteCount 10 SVID 65 Elevation 17.00 Azimuth 355.00 SNR 0.00 SVID 70 Elevation 1.00 Azimuth 300.00 SNR 0.00
SVID 71 Elevation 16.00 Azimuth 345.00 SNR 0.00
SVID 72 Elevation 12.00 Azimuth 31.00 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 1 totalMSG 3 WaitMsg++ 2
WaitMsg 2 thisMSG 2 WaitMsgCount 3 totalMSG 3 WaitSatelliteCount 10 SatelliteCount 10 SVID 78 Elevation 29.00 Azimuth 147.00 SNR 19.00 SVID 79 Elevation 81.00 Azimuth 196.00 SNR 0.00 SVID 80 Elevation 37.00 Azimuth 315.00 SNR 0.00
SVID 81 Elevation 70.00 Azimuth 196.00 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 2 totalMSG 3 WaitMsg++ 3
WaitMsg 3 thisMSG 3
WaitMsgCount 3 totalMSG 3
WaitSatelliteCount 10 SatelliteCount 10
SVID 82 Elevation 20.00 Azimuth 212.00 SNR 0.00
SVID 88 Elevation 49.00 Azimuth 47.00 SNR 29.00
----> AppendSatelliteInfo
WaitMsg 3 totalMSG 3
---->SendMsg(N2kMsg)
WaitMsg++ 0
Damn, should read carefully everything others add to libraries and did even thought, when it was front of me. All values should be in SI units. Now NMEA2000 is in SI, but NMEA0183 satellite data is in degress. So you have to make conversion
...
SatelliteInfo.Elevation=DegToRad(NMEA0183GSV[i].Elevation);
SatelliteInfo.Azimuth=DegToRad(NMEA0183GSV[i].Azimuth);
AppendSatelliteInfo(N2kMsg,SatelliteInfo);
...
I'll fix some day NMEA0183 library to handle data properly. I'll force
became more beautiful. But there is still a problem with satellites from 1 to 31 I sent it but they are not there
New MSG
WaitMsg 1 thisMSG 1
WaitMsgCount 4 totalMSG 4
WaitSatelliteCount 14 SatelliteCount 14
SVID 1 Elevation -1000000000.00 Azimuth -1000000000.00 SNR 16.00
SVID 4 Elevation 0.05 Azimuth 5.79 SNR 0.00
SVID 5 Elevation 0.66 Azimuth 2.01 SNR 23.00
SVID 9 Elevation 0.12 Azimuth 0.16 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 1 totalMSG 4 WaitMsg++ 2
WaitMsg 2 thisMSG 2
WaitMsgCount 4 totalMSG 4
WaitSatelliteCount 14 SatelliteCount 14
SVID 11 Elevation 0.33 Azimuth 0.93 SNR 37.00
SVID 12 Elevation 0.21 Azimuth 2.55 SNR 22.00
SVID 16 Elevation 0.07 Azimuth 5.46 SNR 0.00
SVID 18 Elevation 0.54 Azimuth 3.75 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 2 totalMSG 4 WaitMsg++ 3
WaitMsg 3 thisMSG 3
WaitMsgCount 4 totalMSG 4
WaitSatelliteCount 14 SatelliteCount 14
SVID 20 Elevation 0.65 Azimuth 1.13 SNR 8.00
SVID 25 Elevation 0.70 Azimuth 2.86 SNR 0.00
SVID 26 Elevation 0.54 Azimuth 5.31 SNR 0.00
SVID 28 Elevation 0.42 Azimuth 4.31 SNR 0.00
----> AppendSatelliteInfo
WaitMsg 3 totalMSG 4 WaitMsg++ 4
WaitMsg 4 thisMSG 4
WaitMsgCount 4 totalMSG 4
WaitSatelliteCount 14 SatelliteCount 14
SVID 29 Elevation 1.54 Azimuth 4.76 SNR 0.00
SVID 31 Elevation 0.52 Azimuth 4.82 SNR 9.00
----> AppendSatelliteInfo
WaitMsg 4 totalMSG 4
---->SendMsg(N2kMsg)
Try first to send only message having satellites from 1 to 31. If they show up, then your receiver doe not handle 2 different PGN 129540. Then you should collect all visible (e.g., elevation>5 deg) ones to one. Single fastpacket PGN 129540 can contain max 18 satellites. Unfortunately I do not currently support TP message with longer data.
Do not close yet.
Which device your read on NMEA0183 side and which device you use for showing satellites on NMEA2000 side?
Also you could test to send PGN as TP. N2kMsg.SetIsTPMessage(true); NMEA2000.SendMsg(N2kMsg);
And check does it handle it properly. If it does, something else could be tested.
NMEA0183 --- GPS NEO-8M , NMEA2000 -- lowrance eite ti9 SNR 0.00 ----removed from recoil
N2kMsg.SetIsTPMessage(true); pNMEA2000-> SendMsg(N2kMsg);
So now you can either filter satellites to 18 to fit single fastpacket message or increase message size to fit all of them and send them as TP message. Message size is defined on N2kMsg.h
class tN2kMsg
{
public:
/************************************************************************//**
* \brief Maximum number of bytes that can be stored in the data buffer
* With fast packet the first frame can have 6 byte and rest 31 frames
* 7 bytes.
*/
static const int MaxDataLen=223;
/** \brief Priority of the NMEA2000 message*/
unsigned char Priority;
So if you increase MaxDataLen to e.g., 448, it can hold 37 satellites (3+12*nSats + added one extra). Unfortunate is that library has internal message buffer with default 5 messages (see tNMEA2000::SetN2kCANMsgBufSize) so definition eats 225 * 6 bytes = 1350 more RAM. I have not tried, but library should not use other limit except MaxDataLen.
I am curious to know will long TP message work.