A first look at the Broadcom BCM47755 dual-frequency receiver

Over the last few months, readers have sent me several data sets collected from cell phones using the Broadcom BCM47755 dual-frequency GNSS chip. In most cases, however, the quality of the data was low and the number of cycle slips made it difficult to do any meaningful analysis. More recently I was sent some BCM4755 data collected from a Xiaomi Mi8 phone mounted on a tripod with a ground plane underneath that was noticeably better quality than the previous data sets. This data came from Julian who is trying to use the phone for forestry applications and has an open project he is working on here. In this post, I will describe my experiences attempting to use RTKLIB to analyze this data.

This is the first time I have worked with L5 data with RTKLIB so I wasn’t quite sure what to expect. Fortunately, with a few minor updates to the code handling code in RTKLIB which I have included in the most recent b33 version of the demo5 code, the code was able to see and process the L5 observations. Both rover and base observation files were sent to me in rinex format.

According to the rover file header, the rover rinex file was generated by Geo++ RINEX Logger App for Android (Version 2.1.3). It contains L1/E1/B1 observations for GPS, Glonass, Galileo, and Bediou and L5/E5a observations for GPS and Galileo. Like L2C, not all of the GPS satellites support L5 yet. In this case, only two of the six GPS satellites supported L5 data. All four of the Galileo satellites supported E1 and E5a observations but the rover was unable to pick up both frequencies for the one satellite between 10 and 15 degrees elevation. Below is a plot of the rover observations using RTKPLOT. Satellites in gray are below 10 degrees elevation. The rest of the colors indicate the frequencies of the observations according to the color key at the bottom of the plot. There is an error in the Galileo plot colors in which E5a-only observations are being plotted in green rather than gray. Overall though, the data is of reasonably good quality and has only a small number of receiver-reported cycle slips (red ticks).

Rover observations for B47755

The base data was from a CORS station about 20 km away and had matching signals for all the rover observations plus many more. Here is a plot of the base observations. This data is very clean.

For my initial attempt to run an RTKLIB solution on this data, I used the same config file I use for u-blox L1-only solutions except I changed the frequency mode from “l1” to “l1+l2+l5” Even though, there is no L2 data in these observations, RTKLIB does not allow you to individually select frequencies, just the number of frequencies, so valid choices are “l1”, “l1+l2”, and “l1+l2+l5”.

This run did not go well and digging into the trace file I found that RTKLIB was detecting many false cycle slips. The code attempts to detect cycle slips using the geometry-free linear combination of the L1 and L5 phase measurements. Either the threshold ( pos2-slipthres) is too tight for this data, or there is something wrong with this check. For the time being, I increased the slip threshold from the default of 5 cm to 50 cm and this eliminated the false slip detections.

Even with this change however, the solution was still very poor. Digging back into the trace debug file, I found more problems with cycle slips. This time I was finding that real cycle slips were not being flagged by the rover receiver in the rinex data. These unreported cycle slips were introducing large errors into the bias states in the kalman filter and preventing convergence. RTKLIB has always had trouble dealing with unflagged cycle slips. The u-blox receivers are very good at consistently flagging cycle slips which is why RTKLIB tends to work better with u-blox receivers than many other receiver types.

RTKLIB has some code to detect and reject outliers, but this code has never worked very well and I have generally recommended setting the outlier threshold (pos2-rejionno) to 1000 meters to effectively disable this feature.

For the BCM47755 receiver however, it was clear that this was not going to work. So I made some changes to the RTKLIB code to more fully ignore the outliers, and to reset the phase bias estimates when an outlier was detected. I also changed the way this threshold is interpreted for phase and code observations. Previously the threshold was used without adjustment for both phase and code observations. Since the code errors are much larger than the phase errors, this meant that the limit had to be set large enough so as to catch code outliers only. For the b33 demo5 code I changed this so that the unadjusted threshold is still used for the phase observations but the threshold is multiplied by the error ratio between phase and code observations (pos2-eratio1) before being used with code observations. This means that it can be set much lower and now becomes useful for detecting cycle slips instead of just code errors.

I have actually been using this fix for custom versions of RTKLIB for a while and usually get good results setting this to roughly one GPS L1 cycle or 20 centimeters. In this case though the rover data appears to be too noisy for this and I had to set the threshold to 50 centimeters (pos2-rejionno=0.50) to avoid triggering an excessive number of outliers.

With this change, the solution was much better and provided a solid fix after about four minutes with a “forward” solution as shown in the plot below. Even though the rover was static, I ran the solution as kinematic to get a better indication of the unfiltered errors. I also verified that this solution is using all the available measurements in the rinex file.

With a “combined” solution, the result was 100% fix.

This appears to be a fairly promising start for the BCM47755. It is still not nearly as solid as a u-blox receiver but some of this can be attributed to the fact that this data was collected with the internal phone antenna which is likely to be fairly low quality.

Unfortunately, other data sets from the same experimental setup did not generate solutions as solid as this. In particular the Galileo observations sometimes were not consistent with observations from the other constellations and prevented the kalman filter from converging.

Overall, my impression is that using BCM47755 and RTKLIB together for PPK solutions is still fairly immature and not ready for any real applications but hopefully this will change with time.

I am very interested in anyone else’s experiences with the BCM47755 for RTK or PPK solutions, particularly in combination with RTKLIB and hoping anyone with experience with this chip will add a comment below.


27 thoughts on “A first look at the Broadcom BCM47755 dual-frequency receiver”

  1. @rtklibexplorer, nice to have found this post/blog, unfortunately just recently.
    First of all, heavy congratulations for your work, very interesting and useful! It serves as inspiration for trying to overcome troubles that I encounter with my data.
    I’m working on raw GNSS smartphone measurements and I modified the Matlab code coming from Google to process measurements from all the constellations (GPS, Glonass, Galileo and Beidou), smoothing raw measurements with the Doppler, to compute the phase derived from the pseudorange, to compute the position using WLS algorithm and to generate Rinex data in the end.
    Using these Rinex data with standard RTKlib and data from a close base station, and comparing the results with Rinex data recorded through GEO++ Rinex logger app, performing a static analysis on dual frequency measurements coming from all the constellations I obtain most of the time a float solution (using the RTKlib default parameters), while with GEO++ data I’m able to obtain a fixed solution on a 90% basis.
    I analyzed and compared raw data in detail and I’ve found a slight cyclic bias in all the pseudorange measurements (hence, in the derived-phase measurements too) between my measurements and GEO++ measurements, which probably altered the results.
    Since I’m not able to overcome antivirus issues and downloading your executables in any way, do you mind if I should ask you to analyze data with your code?
    Any kind of help would be really appreciated.


  2. Also worth a first look, the STM EVB-T5. I understand it is a tri-band receiver. I’d really like to see how much performance this adds. Finding a good, low cost antenna might be a challenge.

    I expect that we are soon going to see much less expensive RTK capable dual-band receiver modules.


    1. Hi Jon. I haven’t looked at any of the most recent STM receivers but do think they may be promising. As you say though, antennas, especially in cell phones, are going to be the biggest challenge.


    1. Hi Nan. Sorry, it’s not clear from the post, exactly which version of code I was using. Reviewing my solutions, I believe it was the b33a code. At this point, though I would suggest using the latest code instead ( b33c)


      1. Hi, I found your post really interesting. but, I couldn’t understand one thing from the post.
        – taking b33c (or b33a) as a reference code. did you only make changes in config parameters (like pos2-rejionno) as you mentioned in the post or you also changed the source code? In case you made changes in the source code, could you please share more details.


      2. And now the recommended code would be b33f probably ?
        I’m having trouble replicating the adjustments you made using the “Options” tab,
        Is “increased the slip threshold from the default of 5 cm to 50 cm” done in “Outage to Reset Amb/Slip Thres (m)” ?
        Not sure where “pos2-rejionno=0.50” would be done ?
        Thanks !


        1. Hi Web Van. Yes, I would use the b33f code now. In the post, I listed the option names used in the config file. If you are using RTKPOST, then you would use the “Slip Thres” and “Innov” options on the Setting2 page of the options menu.


          1. Hi Web Van. Even “high quality” cellphone GNSS observations are relatively low quality compared to typical u-blox or other low cost receiver observations due to limitations of the cellphone antenna. The other issue is that I don’t believe RTKLIB has been optimized for L5 observations to the extent that it has been for L1 and L2. I do hope to spend more time looking at this for the demo5 code and appreciate the link to some reasonably decent cellphone data. I did take a quick look at this data and was not immediately able to get a fixed solution either. However, running an L1 only solution with an SNR mask of 32 along with the modifications I mentioned in the post did give me a mostly fixed solution.

            Liked by 1 person

          2. Hello, I have been working with smartphone positioning for quite a while now. I agree with your remarks on not optimized L5 data handling inside RTKLIb. I did a series of experiments with smartphone logged data including https://www.unibw.de/lrt9/lrt-9.2/aktuelles/unibwm-researchers-achieved-unprecedented-1-2-cm-accurate-gnss-positioning-with-commercial-smartphone shared by someone in our community. Just to summarize, a good quality smartphone data (less multipath and good SNR) when processed with a commercially available processing tool, was able to give ambiguity fix with cm level positioning accuracy. However, I did not do an extensive test with RTKLib but, I believe that the L5 handling as mentioned by you could be one of the culprits. Please, let me know if I could provide you the observation data I used and you can try at your side. or maybe you can suggest a specific configuration where I might expect better results with RTKLib.

            Liked by 1 person

          3. Hi Himanshu. I have the observation files that you link to in the above article but if you have other data sets that you feel are also decent quality examples of cellphone data I’d love to take a look at them.


          4. @rtklibexplorer – thanks for the tip on forcing L1 and the 32dB, I must be doing something wrong though because I’m still at Q=2 99% of the time. Any chance you could share your .conf file ? I’m pretty new to this, sorry ! My email is webvan [AT] gmail [dot] com, thanks !
            Looking forward to future versions that may be able to cater to the logs of the Android dual-band phones that can capture raw data…in spite of their weak antennas !


          5. Hi Web Van. Sorry I went back and looked at my config file and I had adjusted the AR ratio from 3.0 to 2.0 for testing purposes when I did this experiment. I don’t recommend that for general use but it can be useful for debugging. If you start with the f9p_ppk.conf that is included with the demo5 executables, change frequency to l1+l2+l5, snrmask_r and snrmask_b to on, all snrmask values to 32, arthres=2.0, slipthres=50, and rejionno=0.5 you should be able to duplicate my results

            Liked by 1 person

          6. I might be doing something wrong but while trying to troubleshoot one of my Mi 8 observations I noticed that there no L5 data was shown after loading the rinex and using the Plot feature. I then went back to the HQ data I linked above from unibw and found there was no L5 data either.
            OK it must just be a display bug in b34 (L5 are shown in b33) it’s not there…but the results are better with the HQ data in b34.


          7. Hi Web Van. The L5 data is actually plotted OK with the b34 RTKPLOT code but it’s a little confusing. The demo5 b34 code uses the new name conventions from the latest 2.4.3 code which is L1=L1/G1/E1/B1I, L2=L2/G2/E5b/B2I, L3=L5/G3/E5a/B2a so you’ll find it under L3.

            One thing to be aware of when comparing the HQ data from unibw with your own data is that it was taken with a special choke ring ground plane to reduce multipath so it will likely be better than your own data unless you do something similar. There are more details on the experiment configuration in the second link from Himanshu.


          1. @rtklibexplorer – thank you very much, that did the trick indeed with 97% fix ! Better than the 84% of Inertial Explorer 😉 I’m going to try reprocessing my own Mi 8 logs to see if it helps.
            PS – In case someone is also looking for f9p_ppk.conf it’s with the b34 executables.


  3. This seems like a golden opportunity for “frugal DIY”ing, provided one can use another antenna. Main problem is that phones tend to be super proprietary or at least hard to customize so I don’t know if they can reach professional levels of ease of use and serviceability like a full blown custom solution.
    I imagine one could use one of them as a client that all the software required and another as a base (or two). Then again, that might mean, one would need a good android rtklib port..


    1. PS. Well, if one did customize it that much, I guess they wouldn’t really need to port rtklib, they’d run it straight on the basic linux shell of android, at most after rooting.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: