Name: Roger

Posts by Roger Clark:

    Re-engineered Radioddity GD-77 CPS

    February 20th, 2018

    The Radioddity GD-77 is a great DMR radio, however the CPS (PC software used to setup the transceiver), is not the most user friendly piece of software I’ve ever come across ūüėČ

    Ideally the CPS would be available as open source, possibly using a cross platform like Python, or even Java, but this is not the case.


    Fortunately however, the CPS is written using Microsoft’s Dot Net (.Net) using C#, which can be reasonably well reverse engineered using open source de-compilers like ILSpy


    This has enabled me to produce a re-engineered version of the CPS which I have made available in both source code and installer exe, which I’ve decided to call the “Community Edition”


    The installer can be downloaded from this link


    The Github repo is here


    My aim with this project is to create a version of the CPS which resolves the bugs in the existing CPS, as well as trying to address some issues in the firmware, by using work-arounds, and also makes general improvements to its operation.

    For example, the official CPS has a bugs where Scan list of more than 256 items have an error, and…

    If Dual Direct mode checked in a digital VFO and is the changed to an Analog VFO, there is a bug in the firmware version 3.0.6 which causes the GD-77 to transmit even if the PTT is not pushed.


    The CPS also didn’t prompt when you press the Read or Write, button(s), which could mean you accidentally overwrite the codeplug in the GD-77 or in the CPS.

    I also didn’t like the additional popup which appears to tell you an upload or download (Write or Read) was complete, as this seemed very clunky.


    Ideally the data storage used by the CPS needs to be completely rewritten, to unlink the position of Contacts and Rx Groups in their respective lists from the values that are selected in the Channel screen, but that’s a much bigger undertaking, which I don’t have time to investigate at the moment.

    The CPS is also missing the feature to export and import Rx Group lists and Zone lists etc, but this may be possible to do whilst using the existing data storage.


    Since publishing the files onto Github a few days ago, Colin G4ELM has sent me several PR’s to fix bugs that were present in the official CPS and some bugs which seem to be new to this version, and I’m hoping the other people will send me enhancements and bug fixes using GitHubs’ Pull Request (PR) system, as it would be good, for example to be able to include languages other than english and possibly to have example codeplugs for various countries, as part of the installed software.


    For those interested in the technicalities of how this was possible…


    Although the CPS is written in C# .net, I initially had difficulty in decompiling it. I tried using a demo version of .Net Reflector (by RedGate Software), however it was unable to read the exe, because it had been “protected” using an “obfuscator”

    After trying several de-obfuscator tools, I was able to establish that the exe is obfuscated using “.Net Reactor”, and I could not find any tools, either open source / free of commercial which would de-obfuscate the file.

    However a few weeks ago, I downloaded the latest version of de4dot ( ), and some recent updated to this excellent tool, allowed it to “Clean” the CPS DMR.exe

    De4dot is not a decompiler, its just a deobfuscator, so I took the “cleaned” exe and tried using .Net Reflector again, and this time it was able to open the file and show the internals.

    However, possibly because the version of¬† ,Net Reflector I was using was a demo copy, it didn’t seem to have a easy way to export the source code to separate .CS files.

    Searching for an alternative to .Net Relector I came across ILSpy  which is an excellent open source decompiler, and with this I was able to export all the source code to individual class and resource files, and it also creates a Visual Studio project file.


    Having the decompiled sources and a VS project file is still only half the battle in this case, because when I opened the VS project, and tied to build the application, I got hundreds of errors.

    Looking at the errors they seemed to mainly be caused by half a dozen different problems.

    Firstly many of the Class constructors had a call to a non existent function in the base class.




    My guess is that these are the default calls to the base class constructor, which normally the C# compiler hides from developers and which they take for granted,

    But the calls can be written as




    The best solution was simply to comment out these calls, because the compiler will automatically make the appropriate calls to the base class for the default constructor (constructors with no arguments)


    Also, all of the class constructors made a call to:




    But class21 looks like this:


    internal class Class21

    internal static void mKf3Qywz2M1Yy()


    These calls don’t seem to serve any purpose, and are probably just an artifact produced by the decompiler.

    I’ve looked at some tutorials about ILSpy and I have not come across these sorts of things, so they could also be caused because of the obfuscation process.

    Either way, I found I could completely remove Class21 and comment out all calls to it, and the code still ran just fine.


    The next type of error was caused because the decompiler didn’t seemed to have problem with classes with no default constructor. These classes only had constructors with arguments.

    The solution for this was to add the appropriate calls to the base constructor e.g.


    public InputReport(HIDDevice oDev) {




    Needed to be:


    public InputReport(HIDDevice oDev) : base(oDev)




    Making those changes allowed the code to compile, however it would not run because the application could not find any of its resources

    I found the solution to this was to rename the resource files which had been preface with the namespace e.g




    change to:




    And I moved these into the same folder as their respective class.


    The app then built and ran reasonably well, but I did need to resolve a few problems, in the same way you’d normally bug fix any code that didn’t seem to be working correctly. namely put a break point where the code was crashing and examine the variables etc and see why things were not doing what they were supposed to.


    The first change I made to the code was to upgrade to a newer version of WeifenLuo.WinFormsUI.Docking.dll by downloading the latest sources from Github, and rebuilding using .Net 4 to match the .Net version being used by the main application.

    The newer version of Winforms UI, had a small change to the API, and I needed to change a few places in the code where the setFont was being called as a method, but in the new version of WInforms UI this is a property.

    This seemed to work fine, except possibly it may have caused one strange bug, which I found later where I was able to open multiple copies of the same form, but in the official App this wasn’t possible

    Colin G4ELM sent me a bug fix / work around, for this, and neither of use was able to see how the original code , which checked if an existing form, of specific type was open, before instantiating a few copy.. Could have been working in the first place.

    However I tested with the original DLL and it seemed to have the same problem, so perhaps this bug was also caused by the decompilation process.


    Overall, I’ve been pleasantly surprised at how relatively easy, after just a few hours work, it has been to re-engineer this exe, and I hope that people will contribute to make it better.


    Only time will tell if Radioddity releases a firmware which requires a new CPS, in which case I’ll hopefully be able to just though the same process again.


    Starting to investigate the GD-77 USB connection

    January 22nd, 2018

    Like many other hand held radios, the Radioddity GD-77 comes with a programming adaptor cable, which has 2 jack plugs at one end, and appears to have a USB interface in the USB plug end of the cable.

    However unlike radios like the Baofeng UV-82, and many others; nothing happens when you initially plug the cable into the PC, unless the other end of the cable is plugged into the GD-77 and its turned on.

    Radios like the Baofeng UV-82, have a USB to Serial adaptor built into the USB plug/dongle, however as nothing happened when I plugged the GD-77 cable into the computer, I suspected that perhaps the USB interface was directly handled by the GD-77, and that the plug/dongle did not contain any active electronics, except possibly some buffering or protection circuit.

    The plug / appeared to be a sealed unit, so I started to use a junior hacksaw to cut along the side of the plug, and found fairly soon that I was able to lever the 2 halves of the casing apart fairly easily, to reveal a small circuit board inside.



    In hindsight, the casing can probably be opened by levering carefully along the join line, down the side of the plug, using a sharp knife
    However, I had not cut too much away and it will be easy to reassemble and glue it closed, without any noticeable damage.


    Looking at the PCB, my suspicions were confirmed, as the dongle contained even less than I thought it would; it didn’t even contain any buffering or protection circuit.

    The next thing I noticed was that the cable to the GD-77, dual jack plug, only had 3 wires, which using the conventional colour coding, would be Positive 5V , USB D- and Ground (0V), but I know that the outer 2 pins of a USB plug are power and ground and the inner 2 are the data pins. So this wiring is all wrong.

    Double checking with my volt meter and the official USB plug pinouts, confirmed that the cable to the GD-77 does not conform to the conventional colour codes at all.

    In this cable, the red wire is being used for Negative (0V), the white wire is being used for USB D+ and the black wire is being used for USB D- !!!


    Checking the other end of the cable, which has 2 jack plugs.

    • The USB D- (black) wire, is connected to the tip of the 3.5mm jack plug,
    • The GND (red) wire is connected to the outer of the 2.5mm jack plug, and
    • The USB D+ (white) wire is connected to the middle section of the 2.5mm jack plug.


    The only logical reason I can think of for this colour scheme, is that the part of the cable with the mounded dual jack plug section, and the wire/cable are a standard item, used in some other device; and that to save costs Radioddity (Tytera) are using an off the shelf cable.


    The next step was to investigate the USB data that is being sent and received by the GD-77, so while I had the dongle apart, I thought I may as well connect a logic analyser and capture a data transfer, by temporarily soldering some pins onto the PCB, after first scraping back some of the insulation layer on top of the tracks.



    Although I was able to capture a transfer where the PC software, read the 128k “codeplug” data from the GD-77, I didn’t find the data particularly useful even using the protocol analysis feature that comes with the logic analyser;
    because the analyser captures things in too much detail and produced a 22Mb file, with lots of redundant data, where the GD-77 kept sending NAK packets back.

    I tried to remove the empty NAK packets and also started to remove the packets to which the GD-77 returned NAK, but there were thousands of them and I could see this was not the best way to investigate the USB protocol.


    I then tried a trial copy of a product called USBlyzer, but it was not able to capture the any detail of the protocol; it only seemed to record the opening and closing of the USB device.
    Looking at the USBlyzer website, it has not had any updates since 2016, and also it seems to only handle mainstream protocols.
    So it was no use.


    As another approach, I used WireShark to record when the PC software (aka CPS), reads the “codeplug” file. However attempting to analyse a unknown USB protocol from scratch is very time consuming, so…


    Changing tack, I looked at the device manager on the PC to see what new USB devices appear when the GD-77 is turned on, and in normal operation it appears as this


    HID device (vID=0x15a2, pID=0x0073, v=0x0002);



    I also tried the other 2 boot modes on the GD-77, firstly the firmware update mode, where both side buttons are held when while turning on the radio, and also the “DMR ID” upload / download mode, where the blue button on the side, the green menu button and the hash key (on the keypad) need to be held in while turning on the radio; and in all 3 instances, the radio seems to enumerate with the same VID and PID values as a USB HID device, even though the operation when in these modes is completely different e.g. when in “DMR ID” update mode, the CPS (codeplug) PC application is unable to communicate with the radio.


    The fact that the radio enumerates using a FREESCALE SEMICONDUCTOR INC vendor ID is not that surprising, because the main MCU (processor) used in the GD-77 is the Freescale NXP  MK22FN512VLL12

    Doing some research, the same VID / PID combination is listed as the “NXP Kinetis bootloader”, which is a more likely match to the VID/PID number, though whether the GD-77 is using the full Kenetis bootloader seems unlikely, because looking at the PC software which communicates with the GD-77, there are some interesting files;

    specifically  STDFU.dll and STTubeDevice30.dll


    This seems to indicate, that although the code for the Kinetic booloader (or for a Mouse)¬† has been used, that the high level protocol that is used by the CPS (codeplug transfer software), and the firmware updater, both probably use a version of STM’s DFUse (Device Firmware Update) protocol.

    This is even more likely, because another Tytera radio, the MD-380, is also known to use a modified version of STM’s DFU for its USB transfers.

    I’ve done some initial tests with the md380-tools created by Travis Goodspeed, but unfortunately the GD-77 does not seem to work in the same way was the MD-380 and those tools don’t seem to work, simply by changing the USB VID/PID from the value used by the MD-380.

    I think its likely that Travis’ tools can be modified to partially work on the GD-77, but its too early to say whether they could be made to perform all the functions they do on the MD-380, and specifically whether the same bug exists in the GD-77 firmware which allowed Travis to read the bootloader firmware on the MD-380


    I now have 2 possible approaches to investigate this protocol, and hope to continue both in the forthcoming weeks and months, and I will publish any results as an update to this blog entry as I find them.



    Extending the frequency range of the GD-77

    January 18th, 2018

    Following on from my initial post about the Radioddity GD-77 DMR transceiver, I’ve now found all the places in the CPS software, where it stores the frequency limits imposed on the “Basic information” screen

    Normally the limits are

    VHF 136Mhz to 174Mhz and UHF 400Mhz to 470Mhz, however these limits don’t seem to be the practical limits of the transceiver under normal domestic conditions, and by changing the PC CPS program¬† DMR.exe the actual hardware limits can be extended (or reduced if required).



    If you change these values in your DMR.exe and update your codeplug etc with frequencies outside the normal operational range, you do so at your own risk.

    Also. The transceiver will probably not be FCC (or CE etc) compliant outside the original limits


    In version 2.0.5 of the CPS, the limit values are held at the following locations.


    UHF lower frequency is held in bytes 3e6d2 and 3e6d3 , with values  0x90 0x01 = 0x0190 = 400Mhz

    UHF lower frequency is held in bytes 3e6ef and 3e6f0 , with values  0xD6 0x01 = 0x01D6 = 470Mhz

    VHF lower frequency is held in bytes 3e6da and 3e6db, with values 0x88 0x00 = 0x0088 = 136Mhz

    VHF upper frequency is held in bytes 3e6f7 and 3e6f8, with values 0xae 0x00 = 0x00ae = 174Mhz


    Once DMR.exe has been modified with new values, in these locations, the “Basic Information” screen will check for these new value (limits), and if the frequency range is extended e.g. the upper UHF values changed to 0x08 0x02, the Basic Information panel will allow a frequency limit of 520Mhz to be entered,



    Looking at the available data on the GD-77; it uses the AT1846S, Single Chip Transceiver. The PDF datasheet AT1846S shows the frequency range as






    I have done some basic tests, and my GD-77 seems to be able to transmit on Australian UHF CB band (into a dummy load) on 476Mhz , and can receive on these frequencies

    I’ve tested the reception below the frequencies specified for the AT1846S and I’m pretty sure it will receive on 132Mhz as I appears to be able to hear some local Air Traffic Control signals on 132Mhz, but it did not detect the weather broadcast from the local airfield on 120Mhz or any FM broadcast radio stations e.g. on 107Mhz.



    Looking in more detail at the AT1846S, there seems to very little data on the internet about this device, but it seems virtually identical to the RDA1846, for which there is Programming Guide document RDA-1846_programming_guide


    Reading the Programming guide, the 200 – 260Mhz band would not be accessible, because the AT1846S has distinct bands on which it operates, and which are delectable via its MCU interface, so I’m not sure whether the GD-77 would simply be able to use this band, without a major hack to the firmware.
    I will need to look in more detail at the codeplug data in a hex viewer to see if the band value is encoded into the data or whether the firmware reads the frequency range and sets the band values in the AT1846 accordingly.


    Update. 19th Jan 2018

    Jason VK7ZJA, has let me know that the 200 – 260Mhz band does indeed work on the GD-77, by changing the UHF lower frequency to 200 or the VHF upper frequency to 260Mhz, However the GD-77 the receive sensitivity is not that good, as the receiver has band pass amplifiers for UHF and VHF and this falls half way between both filters.

    The interesting thing about this, is that the firmware must be setting the appropriate “band” value into the AT1846S chip, and this must be independent of the codeplug and the CPS.

    I’ve tested setting the VHF and UHF frequency ranges to (130 – 520) the same values and it everything seems to work fine.
    Frequency Range 1 to 130 – 520
    Frequency Range 2 to 130 – 520


    This confirms that the values in the CPS are probably there to prevent people entering values outside of defined ranges, into the channels, and I think possibly some versions of the CPS have the Basic Information screen locked so that these values can’t be changed at all, let alone outside of the range by making changes to the EXE.
    But as the software quality of the CPS is quite low, its really hard to know quite what the author was intending.


    For those that feel like doing more hacking, there is an Arduino library for this device on GitHub


    Generally I think the best option is just to extend these values to the documented range of the AT1846S, which does give a useful addition to places which have UHF CB on 470 Р520Mhz (see  Рdependent on the specific licensing in each country)


    However if you specifically wanted to receive on the 200 – 260 Mhz band, then just change the values so that both VHF and UHF contain the max range 136 – 520, and just be careful when programing the channel information or using the VFO, so you don’t end up transmitting on a frequency you are not licensed to transmit on.

    For those who do not want to edit their own files, I’ve zipped up the DMR.exe and Default.dat that I’m using, and the need to replace your existing versions (in whichever folder they are installed)


    Building a Amateur radio DMR contacts list – Attempt #1

    January 11th, 2018


    The DMR Last heard system is currently unavailable, so I will take my pages offline until It comes online again




    [Original Article starts here]

    One cool feature of Amateur radio DMR, is that the other station’s details can often be shown on the transceiver’s display.

    The trick is to have the other station’s details installed as a Contact in the transceiver’s Codeplug database.





    With firmware version 3.0.6 (and newer), a new feature was added to separately upload , up to 10920 “DMR ID”s. This feature is not integrated into the main CPS, and uses a separate program called ActiveClient and requires the transceiver to be turned on and connected to USB while several buttons are held down.

    In some respects this feature superseded the information in this post, However….
    There is one drawback with this feature. Radioddity have only allocated 8 characters for the callsign, rather than the 16 characters available for the “Digital Contact” in the CPS, and there is only enough characters for the callsign and not enough to include the name e.g. a Digital contact can hold “VK3KYY Roger….”, where as the DMR ID system can only hold “VK3KYY R”.
    So IMHO, its not as cool, as stations have to give their callsign.


    Anyway. To continue my original post, assuming you want to make the most of the 1024 Digital contacts which can store callsign and name..


    This sounds great in theory, however the problem is that the entire DMR-MARC database, has over 83,000 entries, at the time of writing this post, and most transceivers can only store a much smaller number of Contacts.

    My Radioddity GD-77 (aka Tytera MD-760) can only store 1024 Contacts using the current firmware (v3.0.6), and 15 of those “Contacts” are taken up with TalkGroups, so I only have space for just over 1000 Contacts


    Filtering the DMR-MARC database to only include Australian “VK” callsigns doesn’t help because there are around 1300 listed (at the time of writing), and I expect the number will rise as more people buy these cheap handheld transceivers.

    The question is which 1000 of the 1300 to include and one possible solution, which I’m currently using is to use the DMR-MARC “Last Heard” page with a filter for all callsigns starting with VK





    By default page only shows the last 30 entries, however the n=xx parameter allows the maximum number of entries to be changed to much bigger numbers e.g 1000 or more.

    Several Caveats.

    There is a big problem caused by the paginated form in which the data is available. On several occasions the data has changed between page 1 and page 2 etc, so that a callsign (ID) has been lost. The method described below only works correctly when there is no traffic for the callsigns in question e.g. VK* while all necessary pages are being retrieved.


    Even though the DMR-MARC database has over 1300 ID’s listed for Australian stations, the “Last heard” page only seems to be currently listing around 708 entries. Its possible that some people have registered ID’s and never used them, or used them prior to 2014, which seems to be the oldest date in the Last Heard system, but I currently think its the best option to get a list of the most active ID’s



    Currently this page is only available as HTML, and also it is paginated with the maximum number of entries per page of 100, so initially,¬† I manually cut and paste the contents of each page, into Excel, and removed unwanted columns, however as new callsigns are being added to the DMR-MARC database all the time, I would need to do this about once a week, and I have better ways to use my time ūüėČ


    As a solution to this problem, I decided to write a PHP script to “scrape” the “last heard” page and output the result as a CSV file.

    I thought this would be relatively straight forward, as PHP has a DOM object which can parse HTML pages into nicely accessible objects, but I was wrong… The “Last heard” page will not parse because the HTML authoring is invalid in multiple places, and the only way to extract the data was to treat the whole page as a string, and search for specific markers.

    This is highly likely to break if the page HTML is modified, but I think even using the DOM object would only be marginally better.


    I’ve put the code in the scripts folder, and an example usage would be

 *&limit=1000  (All VK callsigns limited to 1000 entries)*&limit=1000 (all F callsigns, limited to 1000 entries)


    The format is an index number in the first column, Callsign and name in the second column and ID in the last column. This format is not to suit any specific transceiver, so you need to append any additional columns that your transceiver software needs, and you’ll probably need to append your Talk Groups and re-number the file, to suit.

    But its a lot easier than cutting and pasting from the HTML.



    As I have a GD-77, I’ve updated the script to include a “radio” parameter e.g.



    Currently the only “radio” option which does anything is “gd-77” (or “GD-77”), and this format is only compatible with the CPS 2.0.5

    (Note. For older CPS versions, the last column has to be renamed from “Call Receive Tone” to “Rx Tone”)


    This is my current code, which works, but is not exactly elegant ūüėČ and is available for on Github a



    Update 18th Jan 2018


    I have been experimenting with using the DMR IR system in conjunction with the Digital Contacts, and unfortunately the firmware in the GD-77 does not do the logical thing.


    If I load the most active 700 VK callsigns (including names) into the Digital Contacts, and then download the full list of VK DMR ID’s , I’ve found that the name is not being displayed.

    Presumably this is because the firmware in the GD-77 is searching the DMR ID dataset first ūüôĀ

    Ideally the GD-77 firmware would search the Digital Contacts first and would therefore display the callsign and name.

    Currently my workaround is to download the entire database from DMR MARC, filter for VK* then remove ID’s from this list which are in my main Digitial Contacts.

    But this is is a laborious process, and needs to be automated.


    Update 19th Jan 2018


    I’ve found another problem with the DMR-LastHeard page

    Looking at the page, without applying any callsign filters, I noticed one line which didn’t contain the callsign or name (see line 58 below)


    57 2018-01-19 00:52:22 H 3106320 AF6BY Jeff 310668 KI6KQU San Diego 31066 TG31066 BM 2 GVF
    58 2018-01-19 00:51:59 H 1107738 310613 W6TCP Mt. Allison 91 TG91 BM 1 GVF
    59 2018-01-19 00:51:56 H 2142260 EA2SB LUKEN 214215 ED2ZAF Arnotegi – Bilbao 214 TG214 BM 1 GVF

    I initially thought that perhaps someone just entered a random ID into a DMR radio and connected via a repeater to the network

    However, when I checked the main DMR-MARC database search, it found


    DMR ID Callsign Name City State/Prov Country Remarks
    1107738 KC7VHI Dennis P Low Sunnyvale California United States DMR


    This is a valid ID, so I think the LastHeard page must not directly lookup the name etc from the main DMR database, but must take snapshots, and if the page is run where a new user is using the network, its possible that their details will not display


    As I intend making a new script, I need to take this into consideration, and not have this bug in my own code, and the script should not use the callsign and name on the LastHeard page, but should lookup the ID in a copy of the DMR-MARC database

    I could download a new database each time an unknown ID is encountered, but I think this would probably create an unnecessary load on the DMR-MARC database server, as my script would probably end up needing a new database every time it ran e.g. every 5 minutes.

    So its probably best to only download the latest DMR-MARC database on a longer schedule e.g. perhaps once every 6 hours, and simply not include any users newer than 6 hours in the Contacts list it creates


    Radioddity GD-77 is almost certainly a Tytera MD-760

    January 11th, 2018

    I’ve had a sneaking suspicion that Radioddity is just a brand name of Tytera for some time, as it seemed strange that the Radioddity GD-77 just happened to fit into the Tytera MD-380 charger.

    Then looking in the GD-77 codeplug data file, I noticed that the beginning of the binary file has this


    4D 44 2D 37 36 30 50 FF FF FF FF FF FF FF FF FF

    Which in ACSII is


    So the first characters are MD-760 or possibly MD-760P


    Looking up the MD-760, I found various rumors that the Radioddity GD-77 is a Tytera MD-760, including on


    TYT MD 760

    But most convincing was this Chinese site, which included good photos of the MD-760



    Which lists a

    Tycoon TYT MD-760 digital dual-mode walkie-talkie UV double DMR digital walkie-talkie






    Going back to the codeplug, the GD-77 codeplug, is totally different to the MD-380 codeplug, and the transceivers seem to have totally different hardware, so I don’t think that have a huge amount in common, apart from the charger.

    But I’m now convinced more than ever that Radioddity is Tytera, and possibly Baofung is also Tytera.

    Basically they are all brand names of Quanzhou Nanan Teyitong Electronic Co.,Ltd


    Radioddity GD-77 DMR transciever – initial observations

    January 9th, 2018

    I received a Radioddity GD-77 Digital Mobile Radio, handheld transceiver, as a Christmas present, for use with Ham radio,  and have spent several weeks setting it up, and working around its various quirks, so I thought it would be useful if I documented some initial observations.


    Before I describe the potential problems, I’d like to say that so far, after 3 weeks of use, I really like the radio. Its RF performance seems great, on both Tx and Rx, and people keep telling me that the audio quality is excellent.

    The radio currently have some things which could be improved, but as most of these are related to the firmware, I think that they will eventually get fixed.

    e.g. Squelch only has 2 levels, normal and tight; and even “normal” is actually too tight, because if I switch to “monitor mode’ on FM, I can hear stations just fine, which are below the “normal” squelch level.

    The PC software is very clunky, and there is only a PC version, but again, over time I’m sure this will be improved and other people may write replacement PC software, in the same way that CHIRP is used in preference to most manufacturers own software other transcievers.


    Anyway. Lets get started with some important things that you should know.


    Before the radio can be used the channels and a myriad of other settings need to be configured. I think it may be theoretically possible to set everything up using the numerical keypad on the front of the radio, but this would be totally impractical; hence the radio some with some PC software and a USB programming cable, which allow the settings (called a Codeplug) to be configured and uploaded to the radio.

    The Codeplug can also be read back from the radio if required.

    The Codeplug can also be saved to disc and opened from disk. The format of the Codeplug (.dat) file is binary… More on this later.


    The first thing to note, is that the PC software (aka CPS), is matched with the firmware inside the radio, hence if you update the firmware, you also need to use the matching CPS.

    Also, for the versions of CPS I tried, the Codeplug data file is matched to the PC software. i.e the new CPS will not read the old Codeplug ūüôĀ


    I would recommend that the best thing to do after receiving the radio is to update to the latest stable version of firmware and also to use the matching CPS software. Otherwise you will end up spending ages building a Codeplug file, only to find you can’t use it after you update.


    At the time of writing the latest firmware for the GD-77 is 3.0.6 and the CPS is 2.0.5. I don’t know why Radioddity chose to use different version numbers for this. It would make more sense for them both to be 3.x.y, even if the .x.y bit didn’t precisely match between the firmware and the CPS


    Problems with firmware update


    I’ve been told my several people that after having updated the firmware, that the transmitter would no longer work. They could receive, but the transmit power was virtually zero, as if the PA had failed.

    This sometimes gets referred to as “TX inhibit”

    The fix for this appears to to downgrade to the previous version of firmware (2.6.3) and use the previous version of CPS to upload a minimal code plug, with just one Analog (FM) channel. This seems to clear some settings inside the radio and Tx works.

    The firmware can then be updated to 3.0.6 again, and things apparently work OK.

    Note. Performing a factory reset with version 3.0.6 installed does not fix the issue, nor does loading a code plug from someone else’s GD-77 that works fine for them.

    It looks like the factory reset does not adequately reset all internal settings and whatever is causing the TX inhibit issue is not data that is inside the Codeplug.


    I did not personally experience this problem, as I updated to 3.0.6 fairly soon after receiving the radio, and its possible that a the people who reported the issue were using firmware versions 2.6.9 and 2.6.8  which may have had a bug Рas I noticed that Radioddity removed those versions from their website.

    At the time of writing the stable firmware versions seem to be 1.1.6, 2.6.3 and 3.0.6



    USB Charger is NOT a 5V USB charger !!

    Not something I discovered myself, but its important to note, that the “USB charger” power adaptor, that is supplied with the GD-77, outputs 12V on the USB connector!

    I measured the voltage as 11.7V on the one I have.

    To avoid problems in the future by accidentally attempting to use this PSU / Charger to charge a USB device e.g. a mobile phone, Its important to make it impossible to detach the cable from the power adaptor.

    The simplest way to do this is probably just to put some tape around it, but gluing the plug in place would also be a good solution. I have some glue sticks which are black rather than the normal transparent versions, so I’ve used black hot glue to hold the plug in place, as it looks a bit neater, but anything that can stop the plug being removed would work.


    Also, the power supply has 2 round mains pins, which means for most people they’ll need to use the mains connector adaptor which is supplied. This is often a very dangerous item as well, because its possible to only plug in 2 of the 2 pins, leaving the other pin exposed, and that pin will have mains voltage on it.

    I have glued the power supply into the adaptor plug.


    Charger is only a charger

    Its important to note, that the charger can be damaged if you try to transmit while the GD-77 is the cradle and on charge. I heard from VK3TY (Nick) saying that his charger was damaged, when he accidentally pressed the PTT while it was on charge. I have pushed PTT several times when my GD-77 was on charge and have not had this problem, but I suspect perhaps my GD-77 had a fairly full battery at the time, hence the total current required was less than the buck converter could supply.

    I think potentially this problem is being caused by RF injection back into the power supply, which may cause the charge current limiter to malfunction, and hence demand more current than can be delivered.

    Either way, its probably best to avoid transmitting while plugged into the cradle.


    I’ve also heard reports that the cradle creates a lot of RF noise on the supply which can make the GD-77 somewhat deaf. Again, this is not not something I have personally experienced, but I have not tested to see if it makes any difference to low signal strength reception


    The charger is known to have other problems, like charging the batteries to 8.55V rather than 8.4V, however I’ll write a separate post about the charger.



    I have double checked my charger, and I the LED turns green when the voltage to the battery gets to 8.39V (probably 8.4V assuming my meter is not super accurate).

    So it does not look I need to make the modification as described on this page

    The component values seem identical on my PCB to those in the linked article, so perhaps the problem is related to tolerances of the resistors and the buck converter.


    PC software quirks (v 2.0.5)

    The PC software appears to have a number of quirks. Including erasing the Contacts inside some of Rx Group lists. In one instance I read back from the GD-77 and some RX Groups lists appeared to be empty, yet the radio was receiving perfectly OK using those lists. So I’m not too sure whats going on.

    I suspect the software is simply not displaying the data in the Codeplug file correctly, rather than the RX Group list being empty


    Monitor function

    The monitor function, is a new feature, which I think was added in firmware version 3.0.6, On Analogue channels, it opens the squelch, and on digital channels its supposed to enable promiscuous mode,  where the RX Group list assigned to the channel is ignored and all traffic on the selected Timeslot on the current channel will open the squelch and be audible.


    I have additionally found another thing which the Monitor feature may be doing. On Analogue channels, it looks like the receiver recognises when there is digital data on that channel (frequency) and does not open the squelch. However pressing the monitor button seems to open the squelch so the digital data tones can be heard. I’m not 100% certain that this is what its doing, as its possible that the signal I was receiving was below the squelch threshold even though it seemed to be a very clear and strong signal, so I’ll need to do some more testing, but that’s my initial impression of what its doing.


    Extending the operational frequency range

    The GD-77 is listed as having a maximum operating frequency of 470Mhz, however I read in various placed that this is a semi artificial limit and the maximum frequency is set in the codeplug .dat file


    Note. Changing these settings may potentially damage or “brick” your radio, so you do so at your own risk.


    The values are stored in a strange format and the location varies depending on the PC software version.

    In version 2.0.5 the values are stored from byte location 0x000080 like this,

    00 04 20 05 36 01 74 01


    Where the 04 00 means UHF lowest frequency 0400 Mhz

    In my case I have modified the file, so the next two bytes are 20 50 =  0520 Mhz

    Then 36 01 is 0136 (136Mhz) VHF lowest frequency and 74 01 is 0174 (174Mhz)


    However, if you open the Basic Information screen in the PC software after having edited the Codeplug, the values will get set back to the defaults for the software e.g. max frequency 470Mhz


    So, rather than editing the Codeplug, I thought I’d try and find where in the PC software, the max frequency limit is stored, and to cut a long story short, the value is stored in Little Endian format, as a 16 bit number in locations 0x3e6ef and 0x3e6f0

    I’ve changed¬† my values to 0x08 0x02 as this raises the limit to 520Mhz. I have not tested whether the transceiver works at 520Mhz as the VFO may not lock on all radios.

    But I have successfully tested into a dummy load on the Australian CB frequencies of 476Mhz, so I think this is a valuable addition to the GD-77 capabilities for emergency use etc.


    For those who want a bit more detail, I used HxD to search the exe file looking for possible candidates for where 470 was stored, I looked for the same bytes as stored in the Codeplug, but could not find them, or if I could… changing them did not change the limit.

    So I then looked for 470 as a binary number in Intel format, but found around 20 occurrences in the exe of those two bytes. By doing a global search and replace to change all of them and lower the limit by 1Mhz, I was able for confirm the data was stored in one of those occurrences, however this also cause the program to crash and was just a quick test to see if I was on the right track as obviously the other 19 occurrences should not be changed as they perform some other purpose, and are potentially executable code.

    So I had to go though the file, changing each occurrence, one at a time until I found precisely the one that it uses to store the max frequency value.


    The location of these bytes is likely to change in future versions of the software, so I’ll need to do the same thing all over again when a new version is released, but it may be easier next time, as I can potentially search for a longer byte pattern, as I know the values of the bytes that surround this data.

    I don’t know where the lower limit for UFH is stored, but is likely to be close by, and I can see an 0x90 0x01 at locations 0x3e698 which is a potential candidate. but there is also the same pattern at 0x3e6d2



    I have more information about the PC software and the Codeplug data file and the changer etc, but I’ll write information about those in separate posts


    LiPo battery charging from a 1W 5V solar panel

    November 14th, 2017

    In my previous post, I reviewed some “5V 1W” solar panels, with a view to using them to power some IoT devices, and in this post I’ll show my experiments and conclusions about using the panel to charge the battery.

    LiPo cells have specific charging and usage requirements so that they don’t get damaged.¬† For charging the basic principal is that they require both constant current and then constant voltage charging. They also should not be overly discharged or float charged.


    The test setup…


    I’m using an analogue meter in series with the 2200mAH LiPo battery, set to its 250mA current range.

    I used an analogue meter because it responds quickly to changes and is accurate enough for this sort of testing.

    The variable resistor attached to via the orange and yellow wires, is to control the charge current on the TP4056 LiPo charger module. (see Charging Option 4 )

    The variable resistor connected by the 2 yellow wires, controls the output voltage from the LM2596 DC to DC converter module.

    The switch allows me to connect the battery to either the input or output of the TP4056 LiPo charger.


    Note. There is a capacitor which appears to be soldered onto the input of the DC to DC converter.

    Its actually only soldered on the positive terminal, and the negative terminal can be connected my pressing its wire onto the PCB.

    I tried most configurations with and without this 2200uF capacitor and I didn’t see any noticeable difference in the charge current¬† etc.

    Capacitor on output of solar panel


    Charging option 1.

    If you disregard the “not float” charged requirement, one option is simply to connect the LiPo battery to the solar panel, via some diodes, or a zener diode, which would limit the maximum voltage to around 4V (most batteries seem to require charging to 4.2V)


    Offload the solar panel reaches around 6.5V, so a circuit which “drops” around 2.5V would be required.

    I found some 1A diodes can drop around 0.8V, so 3 diodes in series would “drop” 2.4V, which should be sufficient to prevent the battery being overcharged.

    However in practice this solution is the worse of all those I tried, mainly because the efficiency of the panel drops a lot as its voltage increases above 5V and also the diodes dissipate around 2.4 * 0.15 = 0.36W of power

    (Power = Voltage * Current)



    Charging option 2

    Clamp the output of the solar panel so that if the voltage exceeds 4.2V.

    The simplest clamp is to use a zener diode which is capable of handling the maximum current that the panel can produce. So a 250mA zener would have plenty of current capacity to spare.


    This option charges the battery much better, because the solar panel is much more efficient at voltages below 5V than it is above 5V, and even at 3V, the battery was charged at around 150mA, and as the battery voltage increases the amount of power (voltage x current) being put into the battery increases.

    e.g. 3V @ 150mA = 0.45W

    4V @ 150mA = 0.6W


    This method worked well, but did not seem to be the optimum solution, because the solar panel was not operating at its most efficient voltage (of 5V), hence in the worst case, the battery is being charged at 0.45/0.75 of maximum efficiency (assuming the panel can produce at least 0.75W under ideal conditions, with 33 ohm load)


    Which led me to evaluate the next option.


    Charging option 3


    Connect the output of the solar panel to a DC to DC “buck” voltage regulator converter (which use the LM2596) , which can be found on eBay for $1 or less



    The reason to potentially use this module, is that it can convert the DC input voltage to a different (lower) DC voltage without as much loss as a linear regulator or resistor or diodes.


    However in practice when I connected the module between the solar panel and the battery, I found that the charge current which has been around 150mA for a direct connection, dropped to around 125mA or less.

    To add a bit more detail, what I did was connect a voltmeter to the input of the module (from the solar panel), and adjust the output voltage until the load on the solar panel reduced its voltage to around 5V

    To make this a bit easier I removed the small trim-pot variable resistor and attached a normal pot on some flying leads.




    This wasn’t what I expected to happen, so I looked in the data sheet for the LM2596 at the expected efficiency, there is a graph of the efficiency with a 3A load




    The load of the battery is about 20 times less than illustrated on the graph, but the graph implies that potentially the efficiency when the input and output voltages were low e.g. 5V in 3V out, was not very good, and potentially could be less than 70%


    To confirm the efficiency, I did some tests using a bench power supply set at 5V, a 150ma load using a resistor; and measured the input and output currents for a series of output voltages, from 3V to 4V. The results were fairly consistent with an efficiency of 75%


    The results seem to agree with what I observed when I connected the DC-DC converter to the solar panel, except the efficiency may be even lower than in the controlled environment, and may be as low as 60 to 65%


    With these low efficiencies, using this particular DC to DC converter is pointless, as its less efficient than simply loading the solar panel to a voltage where its efficiency is not optimum.

    It could be that a different type of DC to DC converter may be more suitable to low voltage operation (5V input) and where the input and output voltages are just 1 or 2 volts different.

    For example the MP1484 has a claimed efficiency of 80%, with input of 5V and output of 3.3V


    But even 80% isn’t that good, and is probably only 10% more efficient than the panel its self.


    Hence, using a switching DC to DC converter for this small panel does not seem practical.


    Charging option 4

    Use a LiPo management module which uses a TP4056 for charging


    The TP4056 is a “A Standalone Linear Li-lon Battery Charger with Thermal Regulation”



    The charging current of these modules is set to 1000mA by default, because resistor R3 is 1.2k ohms, however the charge current can be adjusted to a much lower value if the resistor is replaced by one of a higher value, and could potentially be controlled by replacing R3 with a transistor.

    I found several posts on the web, where people had been trying to use these in conjunction with a solar panel, and wanted to adjust the current so that the panel maintained its maximum efficiency voltage (of around 5V).

    However, because the TP4056 is a “linear” device, maintaining maximum efficiency at 5V does not necessarily yield the best charging methodology.


    For Example.

    At 5V the panel can produce 150mA, but as the TP4056 the most current it can deliver to the LiPo cell is the same as its input current, i.e 150mA

    The difference in input power (5 x 150ma = 0.75W) and the output power (3V x 150mA = 0.45W) is just dissipated in heat.


    Also, this module would need considerable modification, probably involving one or 2 external transistors and 2 or 3 resistors, in order that the charge current was modulated to maintain the input voltage from the solar panel at 5V

    So following a hint on another forum, I decided to simply replace the current control resistor (R3) by a 10k variable resistor, and monitor the charge actual charge current to the battery, as the resistance was varied.

    Modified LM2596 DC to DC converter moduleTo my partial surprise, I found that there seems to be an optimum resistance value which gives the most charging current under most light conditions.

    The resistance required is the value needed for a charge current of 150mA, which seems to be around 8k.

    In full sunlight, if the resistance value was adjusted to be higher than 8k, the charge current was limited by the TP4056 to a lower value e.g. 10k gives around 130mA.

    If a significantly lower value of resistance was used, the charge current also diminished below the optimum, but this effect was not as marked as higher resistances than 8k, and I am not entirely sure why this happened, but I could start to hear a high pitched whistle from the module, so I think that the increased current was causing the voltage from the solar panel to drop too low for the TP4056 to be able to charge the battery, at which time it stopped charging, and the voltage from the panel rose to where the TP4056 would operate again.

    This oscillating operation is not as efficient as just using around 8k resistance.

    Strangely at lower light levels the oscillation does not seem to occur even though the charge current is much lower.



    In conclusion


    For the configuration I investigated, the best option in my opinion, is to use a TP4056 based battery management module, preferably one which has separate battery and output terminals, so that its impossible to completely discharge the LiPo cell.

    Then simply replace resistor R4 3 with one that gives the correct maximum charge current.


    Trying to increase the efficiency of the overall system by using a DC to DC converter only gives a very marginal improvement, and the cost of the DC to DC converter e.g. $1 is over half the price of the solar panel, so it is more economic to spend $1.50 to buy another panel and put it in parallel hence doubling the charging capability.




    Update 15th Nov 2017


    I’ve been sent some interesting new information, including a link to this great video by Andreas Andreas Spiess



    And a great comment about using the CN3791. So I’ve ordered 2 of those modules for testing.



    Cheap “5V 1W” solar panel

    November 9th, 2017

    I’ve been investigating solar power options for some external monitoring devices, so I invested in three (3)¬† “5V 1W” solar panels from eBay,¬† the amazing price of¬† $1.69 AUD each (around $1.20 USD or ¬£1 UK), not really knowing what to expect.



    When the panels arrived, the first thing I noticed as that the solar collector on each of them, didn’t quite look the same.



    Also, one of them had distinct bulges of what appears to be excess resin, down the center line of the panel


    Nevertheless, I connected them to my trusty analog multi-meter, so that I could easily test both the voltage and current output from the panels (but not voltage and current at the same time)



    In the bright Australian sun, all the panels produced just over 6V when offload, and produced in excess of 250mA when the meter was switched to its current setting.

    This was a promising start, but of course the panels would not be producing 250mA at 6V, as that would be 1.5W not 1W as claimed in the eBay listing.


    To get an idea of the actual amount of power (W) that these panels are capable of producing, you need to apply an optimum value of load, so that output voltage x output current = maximum wattage.

    In commercial solar controllers, this load is provided my a “Maximum power point tracking” controller¬† which optimises the amount of current being drawn from a panel to produce the maximum power,

    But as I don’t have a MPPT controller capable of operating on a 5V 1W panel, the next best thing is to apply various load resistors to find when the output voltage drops to its specified nominal output of 5V.

    Using this method, I found the optimum resistance that still produced 5V from the panel was somewhere around 30 ohms. (33 ohms gave just above 5V and 27 ohms gave just below 5V)

    Hence, I’ll assume that in ideal conditions that a 27 ohm resistor in parallel with the panel would give 5V output, and hence a current of 185mA and total power of 0.92W


    This is a much better result than I expected for a panel in this price range, so I’m happy with this purchase and may buy a few more of the same type of panel.


    Of course this is really just half the story in terms of powering a microcontroller with transmitter etc, so the next stage in this project will be to determine the best way to charge a 3.7V LiPo cell using this panel, so I will post again when I’ve sound a solution to this problem.


    Resurrecting an old Kenwood TS-50 HF Ham radio

    November 7th, 2017

    I’ve had a full ham radio license since I was a teenager, and when HF radio was popular in the 1990’s I bought a Kenwood TS-50 HF transceiver.

    Since my last house move, its been gather dust, so this week I decided to to fire it up and see if it still worked after well over 10 years on the shelf


    The first problem, was that long ago I got rid of the large heavy 12V 20A PSU that this radio needs, but I have been accumulating a stock of ATX power supplies, salvaged from PC’s.



    Looking at the output voltages it has two separate 12V outputs, +12V1 which can deliver 14A and +12V2 which can deliver 15A.

    Both these have a minimum load 1A.

    However when I opened the case and looked inside, I realised that both +12V1 and +12V2 were connected directly together on the PCB, so there was an artificial distinction on the label which implied that these were 2 independent supplies.

    There were only 2 wires connected to +12V2 (Yellow with a blue stripe), and I unsoldered these to save confusion.

    Whether this PSU requires a load is also a matter of speculation, as it seems to output voltages on 3.3V, 5V and 12V even with no load, and they are all exactly the voltage they should be.

    Initially I connected a 12V 50W filament lamp, as it was the easiest way I had to create at least a 2A load. However this lamp was very bright and got quite hot, so I removed it, and the PSU still seems to work OK.

    In the longer term, I cost effective source of load resistors, as 50W 6 Ohm resistors seem to be sold to fix problems on cars where people have replaced their flashing indicators with LED replacement versions.

    These can be found on eBay etc, by searching for

    50W 6OHM LED Load Resistor

    So I have ordered a pack of these, and intend to put two 6 ohm resistors in series, to provide 1 Amp of load.


    Having resolved the lack of a power supply, I applied power to the rig, only to find that it turned on immediately and all the VFO band presets had been reset.

    This wasn’t much of a surprise, and I guessed that an internal memory backup battery must have gone flat.

    So after looking around on the web, I found that the normal solution is to use a button cell in a holder, and either solder it in place of the existing battery location, or use flying leads to the new battery.



    In my case, the button cell holder, was one I had salvaged from another computer and it was too tall to solder directly onto the PCB, so I used the flying lead method, and encased the battery in a small plastic bag to prevent it shorting to the case etc.

    I initially just covered the battery in insulating tape, but as the rig gets warm even just listening, the insulating tape tended to go soft and would eventually become unstuck. So the plastic bag is a better option.


    With the new battery in place, when I applied power to the rig, it does not turn on straight away, and it also remembers the VFO frequencies etc when the power is removed.


    The next job was to remove the TX frequency limiting that the rig had. This limits it to operate on the HAM bands that were valid in the UK in the 1990’s but since then, there have been changes to the bands, new bands have been introduced and band frequencies changed slighly

    On my particular version of this transceiver, it has 3 diodes which need to be removed D3,D4 and D5 (earlier models only have 1 diode that need to be removed).

    After this mod, I was able to transmit on the bands which previously I could only listen.


    I managed to unsolder these from by heating with my soldering iron from the top of the diodes, as accessing the underside of the PCB would require removal of several ribbon cables, which could be hard to refit.

    (The extra black wire seems to be some factory fitted modification, and I’ve no idea what it does, but it connects to a transistor on the other side of the PLL board via a diode)


    With the modification, I was then able to access frequencies on the 40m band between 7.1 and 7.3Mhz and also the 2200m and 630m bands.


    The final modification was the addition of computer control. Luckily the transceiver has a serial control “interface” port which is accessed by connecting to a 6 pin micro JST socket on the PLL board, via a removable plug on the base of the transceiver.

    As I didnt have any micro JST connectors and none of the local components shops stocked this part, I ordered a plug (set of 10) from eBay, but it was going to take weeks for the plug to arrive.

    So as I wanted to get this working as soon as possible, I managed to unplug the PLL board and partially remove it, while still keeping the ribbon cables attached, so that I could solder wired to the underside of the micro JST connector.

    Only 3 wires are needed for serial TX, RX and GND. I use wire-wrap wire as its small and it also it breaks before the track on the PCB would break, if I pulled on the wire too hard. To stop the wires breaking I put some hot glue on them where they were soldered to the PCB.


    At the moment these wires run out though some air holes in the case and are connected to a CP2102  USB to serial adaptor.



    Initially this didn’t work as I followed some instructions I found online which suggested that TX on the transceiver needed to be connected to TX on the USB to Serial adaptor, however in the case of my adaptor this was not the case, and I needed to connect TX¬† <–> RX

    Additionally I shorted the serial flow control pins on the socket, as my USB to serial connector did not support them.


    With these connections the correct way around, I was able to use the free (old) version of Ham Radio Deluxe to control the rig.

    I was initially hoping to be able to put the USB to serial adaptor inside the transceiver and perhaps have a USB socket on the back panel or the side. However I’m not keen on drilling holes in the bottom panel, as the rig is still in mint condition, and hand drilled holes never look as good as the original cutouts, mainly because the paint is applied after the holes were punched.

    So the next best thing appears to be to either re-purpose the external speaker 3.5mm jack socket on the rear panel, or possibly drill a hole in the rear panel and fit another 3.5mm jack socket, and fit a stereo socket, and then use an external USB to serial adaptor

    However, neither option is particularly easy, because I would need to remove the PA tuning switching board from the underside back of the rig to access the back of those sockets, so I will have to leave that until I get some more free time, and some courage to take the rig apart a bit more.



    Finally I’d like to try out some digital transmission modes, but that will need to wait for a mic plug to arrive in the post.


    Github gists for viewing images from an Arduino

    September 30th, 2017

    I find I’m often writing small snippets of code which I’d like to share but don’t warrant setting up a Github repo.

    I often end up posting them on the forum as they are often STM32 related, however sometimes things are hard to find on the forum because of the volume of posts to the site.

    So I’ve decided to cross post anything I think people may find useful as Github gists and create a blog entry about them.


    Most recently I’ve been working to interface a OV7670 camera to a Blue Pill STM32F103C8 and a ILI9341 based LCD colour display, using code by @SteveStrong and others, and I will post a separate blog entry about this.

    But as part of this project, I needed a way to view the images on a PC, so I’ve just created a couple of gists with the helper applications that I created to test various things

    The first gist is a Python based image viewer, which receives the image data from the Arduino board via serial, and displays it, with the option to save as BMP (only)

    And the second is a test image creator, which should run on most Arduino’s, even the Uno (though I’ve only tested it on the STM32)

    I hope these may come in handy to anyone else experimenting with still images from micro-controller boards


    No Comments "

    New nRF52832 based smart watch available (ID107HR Plus)

    June 19th, 2017

    It looks like the same company who make the ID107 HR have brought out a new product called and ID107 Plus, which uses the better nRF52832 MCU

    I ordered 2 of these from AliExpress and they arrived a few days ago. However at the moment I can’t work out the best way to open the device to look inside.


    I’ve also contacted the company via an Alibaba PM to confirm if this is one of their products, or whether some other company are using the same model numbering system to pass their product of as being like the ID107 HR etc




    Externally the watch has the usual rubber strap



    But the main functional part of the watch is designed to be removed for charging


    And features a USB connector at one end (sorry for the focus on this photo , but you can clearly see the USB connector ūüėČ )



    Fortunately Curt White ( ) has sent me some photos of an ID107 Plus he has managed to take apart, and also some information about the internal connections.


    Firstly the USB is only connected to power and ground, so is only usable for charging.  I suppose it could be modified so that the SWD connections, for programming where wired to the normal USB  D+ and D- but this appears to be a difficult modification to make

    The watch seems to have the nRF52832 MCU as well as :-

    KX022 accelerometer

    Si1143 optical sensor for HR

    Azoteq IQS263

    Macronix MX25L series USON package SPI flash

    Curt informs me that he thinks the MCU pins used for these are as follows


    #define  KX022_SCL                5
    #define  KX022_SDA                3
    #define  KX022_INT                6
    #define  KX022_ADDR               4
    #define  KX022_NCS                7

    #define  MX25_SO                  27
    #define  MX25_CE                  28
    #define  MX25_SCK                 30
    #define  MX25_SI                  31

    #define  SI1143_SCL               18
    #define  SI1143_SDA               10
    #define  SI1143_INT                8
    #define  SI1143_LED                9

    But I have not verified this myself


    Here are the photos Curt sent me



    I before taking my watch apart (or breaking it apart), I have looked at the Bluetooth Services which are advertised by this device, and it only advertises 1 primary service with UUID 0x0AF0 . This is a unregistered 16 bit UUID,i.e Its not a service ID which has been registered with

    Within this service there are 4 characteristics

    0x0AF6 Рread  / write

    0x0AF7 – read / notify

    0x0AF8 – read / notify

    0x0AF9 – read / write


    All of these characteristics read as 0x00 but I have not tried writing to them.

    Ideally one of these would be a DFU service in disguise, but at the moment its not possible to know if that’s the case, or possibly whether writing to one of these services would cause the device to go into DFU upload mode.


    I have asked the manufacturer via an Alibaba PM, to ask whether the device is updatable via DFU, and hopefully they will get back to me with more information (assuming they do make this device)


    If the manufacturer is not willing to give any information, one option is simply to compile a test application onto a nRF52832 dev board (I have the Nordic dev board as well as several nRF52832 based module boards), which advertises the same services, and then run the iOS or Android app, and see what comms occur e.g. what does the App send and what does it get back.

    I’ve also got a rooted Android phone, (running Lineage OS), so I can also install the VeryFit app that communicates with this device and copy the file back onto my PC and decompile it.

    I may be able to do the same thing on iOS as I have an old / rooted iPad; but it only runs iOS 6, which may not be compatible with the VeryFit app



    Its early days for customising this device but it does show a lot of promise, and if DFU could be used to upload firmware, it would make it very practical to use.




    I got a response from the manufacturer confirming that they do make the ID107HR Plus and that it uses the nRF52, however they don’t really understand my question. I asked whether it is possible to upload via DFU, but they think that I want them to write custom firmware.

    And that the minimum order quantity for this is 50,000 units !!!

    I have now asked if they have phased out the nRF52


    I’ve also asked them if there is any way they can pre-flash just a DFU service (I didnt tell them what the firmware does as I don’t think their sales person understands) e.g. if we but 100 units and pay a premium for each item.


    I suspect they don’t want to get involved in such small things, but I may as well ask



    Arduino on the ID100HR fitness tracker

    June 18th, 2017

    Some time ago…, Goran Mahovlic commented about how he was trying to run Arduino on an IDo 003, fitness tracker / smart watch which uses the nRF51822. As I’ve been interested in smart watches for some time, I thought I’d buy the same watch, and join in the fun.

    Unfortunately the first watch I bought didn’t contain an nRF51822 (see my other post about nRF51 based smart watches), so I ordered 2 more of different types, and finally after another 2 weeks, an ID100HR arrived and to my relief it did use an nRF51822, even even better it was the QFAC variant which has 256k flash and 32k RAM.





    The spec for this watch are:

    MCU: Nordic nRF51822QFAC (256k flash , 32k RAM)

    Operating clock frequency: 16Mhz

    Realtime clock crystal : 32khz

    Display: 0.49 inch OLED display (64×32 pixels) which uses the SSD1306 display controller

    Motion sensor: Kionix kx022-1020

    Heart rate sensor: Silicon labs Si1142

    Battery: LiPo 60mAH

    Charger: USB cable with 3 pins (5V, GND, 5V), (No PSU is supplied). The cable just connects 5V from the USB cable, so the battery charge controller must be inside the watch.

    One push button and a vibration alert (motor)


    Pin Assignments for the most of these watches seems to be as follows

    RX pad P0.17
    TX pad P0.18
    Vibrate P0.07
    Button P0.04 Needs input_pullup
    Accelerometer (I2C)
    P0.10-16 possible range of pins used
    P0.16 SCL
    P0.15 Possibly IRQ
    P0.14 SDA
    OLED (SPI)
    P0.29 SPI MOSI
    P0.30 SPI SCK
    P0.0  Data/Command
    P0.1 Reset
    P0.2 Chip select



    Whats great about this watch, is that they have labelled the SWDIO and SWCLK pads, and also that they have even broken out 2 pins to 2 pads labelled TX and RX.


    So its easy to connect either a JLink or Blackmagic probe to the SWD pins to reprogram it.





    I also like to thank Goran Mahovlic for his work on the ID003 smart watch, and in turn to thank the Espruino guys for giving Goran something to work from…¬†


    michael.thomas has requested the source coded I used in the Youtube video. The video was done around 18 months ago, so I don’t know whether this code still works as libraries and cores change all the time

    But here is some code I found on my hard drive related to the ID100HR



    Investigating a RCWL 9196 / RCWL-0516 “Radar” motion detector module

    June 18th, 2017

    A new type of “Radar” motion sensor has been getting a lot of attention in the last couple of months, but no one seemed to know how they worked, so I decided to buy a few of these very cheap devices (sub $1) and investigate possible methods of operation.

    The boards I bought use the RCWL 9196, but appear to have identical functionality to those with the RWCL-0516 chip on them

    This github site contains loads of useful information on these boards, and there is also an excellent video by Andreas Spiess on YouTube

    Where the properties of these devices was explored.

    I hope to have taken this at least one step forward with my tests.

    The main difference in my approach is that I have connected a wire from the analogue signal output on the only IC on the board, into an analogue input on a STM32F103C8 (aka Blue Pill) board.

    The pin I connected to is Pin 12 on U1, (RCWL 9196 and is the output of the 2nd OpAmp in that chip).

    (Schematic from Joe Desonnet’s github account)



    My RCWL 9196 board is not exactly the same as this, but the pinout of the IC is the same.

    Also the RCWL 9196 is almost identical to the BIS0001

    Where pin 12 is labelled as 2Out



    I then wrote a very simple sketch in the Arduino IDE to print both the analogue signal from 2Out and also the normal digital output from the board


    void setup() {
    void loop() {

    BTW. The reason I’m writing values of 0 at the beginning of the line of output and 4500 is because the Arduino IDE “Plotter” feature is auto ranging, and if I don’t include a lower an upper bound, the vertical scale constantly changes

    Looking at the output when nothing is moving I see this plot

    Green is the digital output (in this case its LOW / OFF), and the Red trace is the analog signal, which is close to half the 3.3V Vdd voltage supplied to the board.

    Note. The STM32F103C8 has an anlogue input range of 0 to 4096 (12 bit)


    If I start to wave my hand, starting with a small movement and then increasing, I see this plot.


    As you can see the hand movement causes an immediate effect on the output of the second OpAmp, but the value has to go above (or below) a threshold before the digital output triggers


    In this next plot. I was walking towards the sensor, and then stopped.


    As you can see the digital output holds for around 2 seconds after the end of the input fluctuations.


    The more interesting thing about this plot are the peaks and troughs at the start where I was walking towards the sensor.

    I thought this could be because its sensing the movement of my legs, so I devised a better test where I stood on a chair and dropped an object from the ceiling, and observed the results.


    I tried a variety of objects, and the best performing object that mimicked the properties of a person moving, turned out to be a damp sponge.

    I tried a dry sponge, but it had no effect on the sensor whatsoever, but as soon as I got it wet, it was immediately detected.



    In this plot the sponge is falling about 1m horizontally from the sensor, which is resting on a table about 1m from the ground.

    As you can see, there are still multiple peaks and troughs in the output signal.

    I know that there was some speculation that these devices work by using the Doppler effect,but this does not appear to be validated my the tests I have done.

    So my theory is that the peaks and troughs are caused by reflected signals from objects, interfering with the oscillator / transmitter.
    When I say interfering, I mean of wave propagation, where the reflected wave can be in phase with the oscillator or out of phase, resulting in the oscillator drawing more or less current.

    From Joe Desbonnet’s github repo,he observed that the oscillation frequency is around 3.1GHz with his module. So assuming my module is similar, then the wavelength of 3.1GHz is around 10cm.

    However in my tests, I am not sure the peaks and troughs match exactly with that frequency, and the effect I see if more consistent with perhaps twice that frequency.


    Doing some tests moving a piece of aluminium foil up and down, approximately 30cm, to 5 cm above the sensor observe these results when moving slowly



    And moving quickly



    What is fairly clear is that the interference is not from a single path, but rather that the aluminium foil (or the damp sponge), is reflecting signals directly from the device, but is also going to be reflecting, some reflections back to the device.

    So its a complex pattern of primary and secondary signals, with the strongest effect most likely to be the primary signal straight from the device (transmitter)

    Also just to complicate matters, the OpAmp IC is configured so that the output is always trying to return to a steady state.

    This can be seen when the device first turns on, and the analogue output initially is at its maximum, and takes around 10 seconds to stabilise to Vdd /2


    Looking at the schematic and also measuring the voltage from the RF oscillator / transmitter, using an oscilloscope. The oscillator output voltage, rises to around 0.4V very quickly.

    However OpAmp 1, in the RCWL9196 is configured as a high gain amplifier (and filter), whose non-inverting input will be initially 0V.

    The inverting input is fed from the output of the OpAmp via a resistor and capacitor network, and charges C7 via R6, and the RC network of R4 in parallel with C4

    I don’t know if the resistor values on my board are identical to the schematic, but a rough calculation on the RC charge time of the inverting input would be 22uF * 1M = 22 seconds.

    But thats the time to get to Vdd not to 0.4V, so I think its highly likely that the 11 seconds startup time, is the time taken to charge C7 to 0.4V.

    I observed the fluctuations of the input voltage from the oscillator using my scope, but the change was minimal; at around 4mV, and I was only able to measure this using capacitive coupling on the scope.

    So if C7 can charge from 0V to 0.4V in around 10 seconds, then it would compensate for a change in input from the osc (of 0.004V) in 1/100th of 10 seconds, i.e 1/10th Sec (100mS)

    This effect is also observable in practice, by moving an object towards the sensor and then holding it. As you normally see a peak or a tough, but very quickly the signal is pulled back to its steady state.


    I did attempt to increase the value of C7 from 22uF (226) a higher value, in the hope that I could make a much larger time constant, but I damaged the board somehow, whilst trying to do this, so I do not have any results for that test.

    BTW. I have 2 boards, but I don’t want to modify the second one in case I damage that one as well.


    So to sum up…

    My hypotheses, is that these devices are a oscillator / transmitter, and that the detection method is by wave propagation interference.

    This is consistent with many of the results I observed.

    1. Objects moving towards (or away) from the sensor, produce peaks and toughs rather than a steady state offset; which would be caused by the Doppler effect
    2. The peaks and troughs are complex, as the interference is generated by reflections of reflections.
    3. Waving a length of wire, (which would act as an inductor), near the sensor, produces little or no variation in the output
    4. As the unit has a range of around 4 or 5m, and detection does not seem to diminish strongly with increasing distance, it seems unlikely that the effect is being caused by capacitive coupling between the observed object and the oscillator (and its surroundings_


    And where does this leave us…

    Well, at the moment, I don’t see a use for these devices apart from their intended application of motion sensing.

    I think that using the analogue output from pin 12, is beneficial, as it can be used to get some indication of the scale of the detection, and would allow the trigger level, and hold time etc, to be controlled in the application (e.g. Arduino sketch).


    I think if a method was devised to be able to observe the output from the oscillator, without the current system that always returns the output to a mid point steady state, even if the oscillator is not in that state; that perhaps the device could be used more easily to perhaps determine the speed of an object. By determining the time difference between each peak.

    However even with the necessary hardware modifications to facilitate this, there would still be the problem of reflections of reflections; which would cause the data to be difficult if not impossible to analyse




    Arduino STM32 NeoPixels (WS2812B) using SPI DMA

    June 13th, 2017

    RGB LED strips (aka¬†Neopixels) have been around for a number of years now, so I’ve been somewhat behind the curve in not having tried these interesting devices until now.However I recently bought a 1M strip of 30 LEDS which feature the WS2812B device, from a local eBay vendor.

    As regular readers will know, my microcontroller of choice for most general purpose work is the cheap and trusty STM32F103C in conjunction with the Arduino API, so I checked if anyone had ported Adafruit’s NeoPixel library to the Arduino STM32, and found

    Unfortunately when I tried it, I occasionally got completely random LED colours and random flashing etc. Hooking up a logic analyser to the data pin, I found that the pulse timings produced by that library seemed considerably wrong, and were being caused by a combination of various factors including the compiler not caching the GPIO register address, and other things associated with call overhead and some inline assembler. There was also an issue with the USB Serial failing because for the entire time to send the data, all interrupts were disabled to ensure critical timing was not disturbed.

    I spent some time fixing this library (but have not published an updated version yet), and it worked OK, but I still had the issue with USB failing, So I thought that bit-banging the data to the LEDs seemed quite inefficient, as the STM32 possesses several independent subsystems which could be used for this purpose.

    The simplest and most obvious subsystem for sending a bit-stream is of course SPI, and the STM32 features DMA driven SPI, which would allow data to be sent to the LED’s while new data is prepared.

    Looking at the datasheet for the WS2812B,

    To send a “0” requires a pulse that is high for 400nS and low for 850nS (all values plus or minus 150nS)
    To send a logic 1 requires a pulse that is high for 800nS and low for 450nS (all values plus or minus 150nS)

    This is approximately a 1 to 2 ratio between the “mark” and “space” length (or vice versa)

    As the STM32F103 normal operating frequency is 72Mhz and the SPI PLL divider is available in powers of 2, I checked and found that 72Mhz / 32 = 2.25 Mhz, which equates to a pulse length of 444.44nS, and sending the binary pattern 100 results in a high pulse of 444ns followed by a low for 889nS (rounding to the nearest nS), and sending 110 results in a high pulse of 889nS and a low period of 444nS

    Both combinations are within the spec for the WS2812B.

    It should be noted at this point, that the older WS2812 has slightly different timings, e.g. a pulse of 350nS is required for a logic zero, so this device is not compatible with this method of sending data.

    Now that I knew that I could use bit triplets “100” and “110” to send a data “0” and “1” to the WS2812B, I needed a way to generate these triplets and concatenate them to produce the GRB data for each LED (The data order is Green Red Blue , not the traditional Red Green Blue), so I wrote this function which converts a single byte (colour channel) into the 24 bit (8 x 3 bit triplets)


    uint32_t convert(uint8_t data)
      uint32_t out=0;
      for(uint8_t mask = 0x80; mask; mask >>= 1)  
        if (data & mask)
          out = out | 0B110;//Bit high
          out = out | 0B100;// bit low
      return out;

    I used this function to build a buffer of “encoded” data buffer and then used the Arduino STM32 extended SPI function dmaSend() to send the buffer to the LED strip.


    Initial results of this were very promising, with the 30 LED strip being updated quickly, but I noticed that the first LED in the strip sometimes displayed the wrong colour.

    I hooked up my 100Mhz USB logic analyser, and looked at the data being and compared it with a bit-banged version I’d previously been working on.


    SPI version

    Bit-banged version


    And the length of the very first pulse (logic high), was 0.49uS long for SPI and 0.45us long for bit-banged.


    Reading the spec of the WS2812B, a pulse duration of < 550nS (0.55us) is supposed to be a logic zero, however my LED strip was treating this as a logic 1, and hence setting the Green channel to 10000000, or in a general case the MS bit was always set to 1, hence green values were never lower than 0x80 (50%)

    I don’t know why the WS2812B is treating a 490nS pulse as if it is longer than 550nS, but the only thing I can conjecture is that the pulse width being shown on the logic analyser is based on a different threshold voltage e.g. Vdd (3.3V) / 2. However according to the WS2812B spec, a High is signalled when the input voltage is 0.7 of its supply voltage which is nominally 5V, = 3.5V.
    I know that driving these devices using 3.3V logic is known to be problematic if the LED supply 5V because of this input voltage threshold, and that there are various workaround for this, usually involving diodes in series with the GND or the 5V power line to the WS2812B. But in my case I was getting the opposite effect, as if the threshold was a lower voltage than Vdd (3.3V) /2 = 1.65V


    I checked the width of the other pulses being generated by the SPI and found that only the first pulse was this length and all other pulses were 450nS (actually 444.4ns but my analyser can only resolve to the nearest 10nS), so I concluded that this effect was being caused by the MCU hardware setting up the MOSI signal in advance of the transfer starting.

    Normally this would not be a problem when using conventional SPI, as the data is clocked using a separate signal, and is only happening because I’m using the SPI hardware for a reason other than which is was designed to be used; so I don’t blame ST for building defective hardware ūüėČ


    The workaround for this is actually very simple. An additional byte of 0x00 ( 00000000″ ) was added to the start of SPI data buffer, so that the first LED pulse is actually in the second bye of the transfer.

    I also noticed that occasionally the STM32 hardware seemed to leave the MOSI signal at logic 1 after the end of the transfer, even though the last binary bit of the transfer in this protocol is always a zero. This causes a problem, because the WS2812 protocol requires that its Data In, be logic low for 50uS prior to each transfer to act as a Reset signal. The fix for this was also to append another byte of 0x00 to the end of the transfer.


    Having got this working within a test sketch, I rewrote it as a library which replicated the Adafruit NeoPixel library API as closely as possible.

    I also did some speed optimisation by replacing the function that calculates the SPI bit pattern, with a lookup table that converts a single colour channel (RGB 8 bit value) into the 24 bit encoded pulse-train needed for the SPI.


    But one thing thing was still troubling me, as although I was using DMA to send the SPI data, the existing Arduino STM32 (LibMaple) SPI function dmaSend() is “blocking” (aka synchronous). So that the code execution effectively has to wait until the DMA is complete, before the next set of LED data can be constructed.
    To overcome this, I modified dmaSend() to make a new function called dmaSendAsync(), which returns immediately after the DMA transmission of data has started, and in case the code to construct the next set of LED data completes before the current asynchronous transfer has finished, I took the blocking code from the end of dmaSend and put it into the start of dmaSendAsync and added a static flag to the function so that the blocking code (which waits for DMA completion), is only run if a DMA transfer has been has previously been started.

    Just replacing dmaSend with dmaSendAsync however, would not work correctly, because the Arduino sketch code could update the buffer of data that was currently being sent to the LED’s via DMA and cause unexpected results. To address this problem I added a double buffer system, so that the data buffer that functions like setPixelColor() interact with, is different from the buffer being sent to the LEDs; and the buffers are swapped as part of the library’s show() function – which sends the data via SPI.

    This is all very standard and easy to implement in the code, but when I ran the test / example sketch, I found that some visual effects, specifically colorWipe() function were not working as expected, and caused to flash the LED’s in a very strange way.

    Initially I presumed I must have made a mistake with how I handled the double buffering, because the problem went away if I switched back to single buffering, (with some added delays), but after exhaustive examination of the data and using the logic analyser to see what was actually being sent, I finally realised that the visual effects created by functions like colorWipe() are additive.


    void colorWipe(uint32_t c, uint8_t wait)
       for(uint16_t i=0; i<strip.numPixels(); i++)
          strip.setPixelColor(i, c);

    Where this function effectively does the following:-

    Set pixel 1 to Colour X
    Send data to all LEDs

    Set pixel 2 to Colour X
    Send data to all LEDs

    Set pixel 3 to Colour X
    Send data to all LEDs

    Set pixel 3 to Colour X
    Send data to all LEDs

    Which produces the following effect




    But if there are 2 buffers, (both initially empty) what the code would do is…

    Set Buffer 1, pixel 1 to Colour X
    Send data to all LEDs

    Set Buffer 2 pixel 2 to Colour X
    Send data to all LEDs

    Set Buffer 1 pixel 3 to Colour X
    Send data to all LEDs

    Set Buffer 2 pixel 4 to Colour X
    Send data to all LEDs


    Which produces this effect




    Unfortunately the only way around this problem is to copy the contents of the last updated frame buffer to the other frame buffer. But at least this can be done during the DMA transfer if buffer pointers are exchanged each time


    // Sends the current buffer to the leds
    void WS2812B::show(void) 
      SPI.dmaSendAsync(pixels,numBytes);// Start the DMA transfer of the current pixel buffer to the LEDs and return immediately.
      // Need to copy the last / current buffer to the other half of the double buffer as most API code does not rebuild the entire contents
      // from scratch. Often just a few pixels are changed e.g in a chaser effect
      if (pixels==doubleBuffer)
    	// pixels was using the first buffer
    	pixels	= doubleBuffer+numBytes;  // set pixels to second buffer
    	memcpy(pixels,doubleBuffer,numBytes);// copy first buffer to second buffer
    	// pixels was using the second buffer	  
    	pixels	= doubleBuffer;  // set pixels to first buffer
    	memcpy(pixels,doubleBuffer+numBytes,numBytes);	 // copy second buffer to first buffer 


    At the time of writing I’m using memcpy to copy the buffers, but this may not be the most efficient way to do this, as memcpy may be doing single byte copies, where as 32 bit copies would be faster.

    So I’m considering padding the frame buffers to 4 bytes, by adding bytes as necessary, depending on the number of LEDs. Currently each buffer is NUM_LEDs times 3 + 1 start byte + 1 end byte, e.g. 30 LEDs takes 272 bytes

    The other thing that makes the code run slower in some places than the bit-banged version is the need to use the lookup table to copy the 3 bytes per colour into the frame buffer.


    void WS2812B::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
       uint8_t *bptr = pixels + (n<<3) + n +1;
       uint8_t *tPtr = (uint8_t *)encoderLookup + g*2 + g;// need to index 3 x g into the lookup
       *bptr++ = *tPtr++;
       *bptr++ = *tPtr++;
       *bptr++ = *tPtr++;
       tPtr = (uint8_t *)encoderLookup + r*2 + r;
       *bptr++ = *tPtr++;
       *bptr++ = *tPtr++;
       *bptr++ = *tPtr++;   
       tPtr = (uint8_t *)encoderLookup + b*2 + b;
       *bptr++ = *tPtr++;
       *bptr++ = *tPtr++;
       *bptr++ = *tPtr++;

    I’ve tried to optimise the code by using sequential pointer reads and writes with increment, however it was still 60% slower than the bit-banged code, which simply needs to write the RGB values straight into the frame buffer

    Moving the LUT from flash to RAM has improved the speed by about 30%, so that setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) now takes 1224nS to execute (including the call overhead, rather than 1642nS. The bit-banged version, which just sets 3 bytes in the frame buffer takes 948nS, so is still 28% faster even with no optimisation.

    There may be further optimisations that can be performed on this code to increase the speed, possibly using the strategy described by @stevestrong on the forum

    But that will have to wait for a day when I have more free time to allocate to this.


    Overall, I think the jury is still out, about whether using SPI and DMA rather than simply bit-banging the data is the best approach.

    If the bit-banged method could be made to work without disabling the interrupts during the entire duration of the show() function, it would probably be fine for most simple effects, and may even work faster in a lot of cases.

    However, just disabling interrupts when each High / Low waveform is created, and re-enabling the interrupts between data bits, would technically break the WS2812B’s spec, as the Low period would be variable and almost always longer than is technically correct.

    Also for effects which required a lot of processing for each pixel, using DMA would potentially increase the frame rate

    If I get time I’ll also publish a bit-banged version, and in the mean time anyone interested in trying the code can download the latest version of the Arduino STM32 repo

    Or look at the library code here


    Don’t buy this smartwatch / fitness tracker !

    December 7th, 2016

    Just a quick post about another smartwatch / fitness tracker that I was miss-sold on eBay

    Its title was
    A16 Bluetooth Smart Watch Health Wrist Bracelet Heart Rate Monitor Sports New
    Do NOT buy this watch


    It is listed as using the Nordic nRF52832 Bluetooth MCU, but when I opened the watch to see how to reprogram it, I found it contained a Dialog processor


    Unfortunately as I had already accepted the item, and given feedback in eBay.
    But as the item was delivered by registered post with a tracking code and I had to sign for it, the vendor knows I received it, so I couldn’t simply pretend it had never arrived (which is sometimes the best option with dodgy vendors as they have to resend or give a refund if you don’t receive the goods)


    I have written to the vendor (¬† )¬† to complain, I doubt they care, so I think I’ve just wasted $30 as I bought 2 of them.


    But I doubt I will get a good resolution from this.


    BBC Micro bit hardware designs are now available on github

    October 21st, 2016

    I think the profile of the nRF51 is about to take a big leap forward, as the previous closed hardware design for the BBC Micro-bit, which has been rolled out around a million school children in the UK, has not been released on GitHub

    There is a press release  indicating that the micro bit foundation will be encouraging the use of the design throughout the world.

    I am not a lawyer, but the license appears to allow anyone to use these designs.

    So if this is correct, I imagine that a lot of Chinese manufacturers would be interested in producing versions of this, because at the moment, they are only available in the UK and the cost is fairly high (£13)

    Which would be good news if the price was brought down in line with boards like the Arduino Uno, or my favourite STM32 boards.


    Update. May 2017

    These reference designs appear to be for a binary compatible nRF51 board not the actual BBC Microbit board as given to students in the UK.

    The board is much bigger and uses an nRF51 module rather than the nRF51822 MCU


    No Comments "

    Blackmagic probe problems with a new nRF51822 device revision

    October 6th, 2016

    I know quiet a few readers of the blog are interested in the nRF51822, and use either the Blackmagic probe or OpenOCD to program your devices.

    So I thought it worthwhile to share my experiences today, when I was unable to program a nRF51822QFAA device


    To cut to the chase, the device identification in full is the nRF51822QFAAH1.  This appears to be a new revision of the QFAA device (16k RAM 256k flash), which neither the Blackmagic probe or OpenOCD support, as its CONFIG ID code seems to be 0x008F where as the QFAAH0 is 0x0072

    I will endeavor to update my Blackmagic probe repo as soon as I have confirmation via the Nordic developers forum that this indeed the case.

    I’ve also logged a issue on the master Blackmagic probe repo, and will bring this to the attention of the OpenOCD team if confirmed.


    In reality, the problem of not being able to program a specific board, has taken a while to quantify, as I had a batch of 40 boards to flash with custom firmware, and the first board I tried seemed to have this issue, so I ended up using a Jlink to flash the boards (which had its own issues, but thats another story).

    Anyway, of the 40 brand new boards I received from a Chinese manufacturer, only 1 seems to contain this new device, so it was sod’s law that it was the first board that I attempted to program.

    And doubly confusing, as I presumed the whole batch had the new device, so I didnt take note of which board would not initially program, So ended up having to retest all 40 again to find it, and confirm that all the other boards contained the QFAAH0 version.

    But thats the way the cookie crumbles some days.


    nRF51822 based fitness trackers

    September 20th, 2016

    As regular readers of my blog will know I’m an ardent fan of the Nordic nRF51 (and nRF52) series of Bluetooth Low Energy MCU’s.

    So when I found out that a number of fitness tracker / smart watches, used the nRF51822 and could be easily opened and reprogrammed I was very interested and ordered 2 of them to try.

    Unfortunately soon after I ordered them, it became clear that the model I had ordered would probably not be powered by an nRF51822, and hence started my quest to understand what models of smart watch do, really, use the nRF51.


    Firstly, the model number of the watch I ordered was a TW64 – which is where the confusion starts.

    A number of completely different watches are sold as a TW64 but contain completely different processors.

    The ones I ordered, from eBay, had the Quintic QN9021 (  listed as the main processor, however when I opened mine up, it actually contains a Dialog DA 14850 processor  (

    Either way my watch unfortunately didn’t contain an nRF51


    However searching for “TW64 nRF51822” does find some watches marketed as a TW64 which do contain the nRF51822, which lead me to Shenzhen DO Intelligent Technology Co., Ltd. on Alibaba.

    I contacted them to find out more details and found that all of their smart watch/ fitness trackers use the nRF51822

    Their product numbers are P101,P102,ID100HR,ID105,ID105HR,ID107,ID107HR,ID101HR,ID110HR,ID111HR and ID115HR

    So if you are looking for an nRF51 based smart watch, your best bet is to search using one of those model numbers, and double check the details in the eBay / AliExpress / Gearbest etc listing to confirm it does mention the nRF51822


    In the end I decided to buy an ID100HR and a ID107HR, via AliExpres.


    When my ID100HR arrived, and I unscrewed the back of the case on the watch, I was pleasantly surprised to find that the watch contained an nRF51822QFAC, which is the 32k RAM version (top of the range for this MCU), and also that the watch has both the 16Mhz main crystal and also the 32kHz low power mode crystal.


    With the help of Goran Mahovlic, I can now reprogram this watch using the Arduino IDE and can read from the accelerometer sensor, and write to the display, as well as get input from the button and turn on and off the vibration motor.

    I have yet to investigate how the Silicon labs Si1142, Heart Rate sensor is interfaced to the MCU, but as its I2C, its possible its wired onto the same bus as the Kionix kx022-1020 accelerometer.

    So it should be possible to use this feature of the watch as well.


    If anyone wants to give this a try for themselves, please also read my previous postings about programming the nRF51822 using the Arduino IDE and also refer to my latest Arduino for nRF51822  repo on github.




    Running RDWorks on Linux

    August 29th, 2016

    As a matter of interest, I thought I’d see if I could use the RDWorks laser cutter control program on Linux, even though its a WIndows only application.

    Linux add-in called WINE ( ) that allows Windows exe’s to be run under Linux.
    However when I tried to install RDWorks using WINE I initially got a load of error messages which implied that loads of RDWorks DLL’s were missing or could not be located.

    I initially thought this was because RDWorks had to run in a specific location, but after movingit to various places on my machine, I found the error messages were a red herring, and the problem was that WINE did not have one of the core Microsoft DLL files.

    The fix for this was to install something called “Wine Tricks” and use it to install the missing DLL.

    With this installed, The RDWorks installer will actually run and install RDWorks under Linux

    However you do not install the USB driver, as the FT232 driver is already installed on most Linux installations.

    Once installed RDWorks does run, but with one strange quirk; the vertical scaling in the design window is incorrect, and you initially get a bed shape that is very tall and narrow.

    So I changed settings for page setting, and 900 x 400 looks good on screen. This setting isnt really important to the laser cutter its self, as its completely ignored even my RDWorks, as you can edit and cut objects outside of the bounds of the laser cutter (as defined in the setup)

    One thing I have not managed to get working yet is the USB transfer to the laser cutter.
    I think the issue is the mapping of the FT232 serial device on Linux to the COM port that RDWorks requires
    The solution is probably that I need to map / link the systems’ serial port to the Wine serial port as described here … %20ipb.pdf

    But I have not had time to test this yet.

    An easier option is probably to transfer by LAN, as this works well under Windows and its likely to work on Linux.


    Mahoney CO2 laser power meter

    August 16th, 2016

    I recently bought a Mahoney laser power meter from “Bell Laser” ( , also known as, to establish whether my “50W” Chinese laser cutter was actually producing anywhere near 50W.
    Read the rest of this entry “


    Network aware laser cutter security

    August 4th, 2016

    My Chinese laser cutter has a feature which allows it to be connected to a cabled LAN, but I’m always concerned about attaching random hardware to my home network as sometimes Internet connected devices have a “phone home” feature where they connect to a central server and send back log data, or possibly do other things which you’d rather they didn’t.

    So although my workshop PC is around 5m from my laser cutter, I initially opted to use a USB extension cable to connect the PC to the laser cutter.

    Unfortunately I found that using a long USB cable was problematic as the laser cutter kept disconnecting from the PC, and I’d have to unplug and reconnect the cable, almost every time I sent a job to the cutter.


    As my workshop PC is not actually connected to the Internet, I decided it was safe to make a Ethernet crossover cable and connect the PC directly to the laser cutter via cat 5 cable. The cable worked well, and the connection does not drop out, and the cutter control software seems to work in exactly the same way as when communicating via USB.

    As I was still curious about whether the cutter had a “phone home” feature, I decided to install WireShark on the PC and monitor the LAN traffic.


    The control unit in the laser cutter is a RUIDA RDC6442G ( )

    On the control panel, you set the IP address of the laser cutter and also enter the address of a gateway, so I entered the IP of the workshop PC as the gateway IP, and then fired up Wireshark


    I was pleased to see, that the laser cutter does not appear to communicate over the LAN at all, unless sent data from the control program (RDWorks) in the PC. I left the machine for several hours and not a single packet was detected.

    This does not completely rule out that the laser cutter may attempt to communicate after an extended period e.g. every 24 hours, but at least it does not start trying to contact the Internet immediately

    The control program RDWorks doesnt seem to access the Internet either, which is also very good news.


    The main reason for monitoring the data was for network security reasons, but I had a quick look at the data protocol.

    When RDWorks communicates with the cutter it uses UDP, sending to port 50200 on the cutter, and the cutter sends back UDP data to port 40200


    The format seems to be proprietary binary, with RDWorks sending a command packet.

    e.g. This seems to be the initial packet that is always sent by RDWorks


    to which the RDC6442G  responds with


    and then sends a reply packet e.g.



    Another example is RDWorks sends


    to which the RDC6442G  responds with


    and then sends



    When I sent drew a 10mm x 10mm square in RDWorks and sent this to the laser cutter, by pressing the start button, this appears to be the data for this cut (but at lest 5 commands were sent to the cutter before this data was sent, and RDWorks sent a further 411 bytes in the next command



    I don’t think there is any point in further investigation of the actual protocol itself as RDWorks is free and although is Windows only, it appears to run OK under Wine on Linux.


    Overall, although I would not connect the laser cutter to my internal LAN because of the safety implications of any computer on the LAN sending the command to start the laser cutter running, I think that from a network security standpoint it seems relatively safe.

    If absolute network security is required a cheap wifi / wired router running OpenWRT or DDWRT could by placed between the laser cutter and the rest of the network to limit traffic to just UDP and ports and 40200 50200 and limit which IP addresses the laser cutter is allowed to communicate with.

    Or just use a dedicated PC with no other network connections, like I do.



    Changing the language setting on a Chinese laser cutter

    August 2nd, 2016

    Just a quick post in case it helps anyone who has the same problem with their newly purchased Chinese laser cutter, where the menu language is set to Chinese (probably “Simplified Chinese”)

    The original display looks like this. Note all the words are in Chinese


    If you push the button labelled “Z/U” it opens the main menu, which is also in Chinese




    If the machine has English set as the language, the menu would look like this.


    So what you need to us press the down arrow, below the “Z/U” button, until the button at the top of the second column of buttons is selected.


    This displays the language selection screen, where you need to select the third option down and press Enter.


    If English was selected, the screen would look like this



    Once English is selected, the text on the main screen will be in English and you can confirm this by pressing the “Z/U” button to enter the menu.

    BTW, Pressing “Esc” exits the current menu.


    PS. Someone else may well have already documented how to do this but I couldn’t find how to do this when I searched the web, so my method to figure out what was on the menu’s was to guess what words would be displayed e,g, “Language” and then use Google Translate to show be the Simplified Chinese equivalent, then visually compare what was on the menu with the Chinese characters, and fortunately they had called one of the menus “Language” so I was able to match the Chinese characters closely enough to work out which menu it was.

    Annoyingly, inside the language menu, it doesn’t have the language names in latin text e.g. English or French or German etc.

    So I had to google translate “English” to work out which language option


    Troubleshooting the nRF51822

    July 15th, 2016

    I’ve had quite a few comments where people are having problems uploading or running sketches on the nRF51822, so as I don’t have time to answer individual questions, I thought it best to try to cover the main reasons that things may not work


    Device is not recognised by Blackmagic probe or possibly not by JLink

    Originally I had a lot of issues with Blackmagic probe not recognising the ID code in the nRF51822. When this happens the Blackmagic probe reports the nRF51822 just as ARM cortex M0 rather than nRF51822

    If you have this issue with my latest repo, please let me know, as the only option is to manually read the ID code and send it to me, so I can add that code to the list in the firmware and then rebuild the Blackmagic probe firmware.

    The main problem is that Nordic do not keep an updated document of what ID codes they use, and most of the codes have been gathered and compilated by various users from various sources.

    However I think this situation has now stabilized and Nordic have not released any new ID codes recently

    This is not so much of an issue with JLink as you have to tell JLink which device you are programming,but this is not an option with the Blackmagic probe firmware.


    nRF51822 chip is read protected / locked

    This problem can occur if you are using a module which is pre-flashed with some firmware already.

    In my case the  modules I bought from Wireless-tag ( , specifically had this problem

    I hoped the my JLink could disable the read protection, as this is a menu option in JFlash, however the option is greyed out and JFlash gives some erroneous error message when you connect, about an issue with the RAM

    This problem can also be caused if you use JFlash to “Fill with zero”, as I found out by accident one day

    Eventually I found a solution to this, on Nordic’s website

    And the solution is to manually write commands into 3 of the nRF58122’s registers

    In JLInk the commands are

    w4 4001e504 2
    w4 4001e50c 1
    w4 4001e514 1

    And GDB has an equivalent write command

    After these registers are changed, it will cause the whole MCU to be erased and you should be able to connect via JFlash or Blackmagic probe without an errors and upload your new firmware


    S130 softdevice has not been flashed into the bottom of flash (0x00000)

    The bluetooth API functions provided by Nordic some in the form of a “Softdevice”

    The best way I can describe a Sottdevice is a cross between a bootloader and a dynamic link library.

    The code for all the BLE functions is in this closed source Softdevice, and the sketch makes calls into the Softdevice in order to access that functionalityAdditionally, the Sketch code is compiled to run at address 0x1c000 (for the V9 Soft device) – Note the latest version of the Softdevice, at the time of writing, is V2.0.1 from SDK V11, and is slightly smaller and expects the sketch (application) code to be at 0x1B000 – so make sure you download the old SDK V9 and use the S130 softdevice from that SDK.Basically the Softdevice is installed at address 0x00000 and when the MCU starts up, it runs a small amount of Softdevice initialisation code, and then the Softdevice passes control to the application sketch at 0x1B000, the Softdevice also attaches to some interrups to do its own functions, but all other iterrupts are forwarded to the application, as the softdevice inspects the applications (sketches), interrupts vector table and calculates the address to call inside the application code for each interrupt.Consequently unless you have installed the S130 softdevice into address 0x00000, the sketch will not run because it will be installed at 0x1C000 with jibberish in the flash at addresses 0x00000 to 0x1BFFF, which the MCU will run at startup.
    I suppose if the flash from 0x00000 to 0x1BFFF was filled with nops this may work, but there are better ways of running without the softdevice e.g. change the linker script to position the sketch at 0x00000 and change the upload script to make sure its flashed at 0x00000Overall, just make sure the correct version of the Softdevice is flashed at 0x00000


    Module does not have the 32Khz RealTime Clock crystal

    If you installed the Softdevice and uploaded the sketch code and nothing works, e.g. including a “Blink” sketch, the reason is probably that your “no name” board does not have a 32Khz cystal oscillator

    My current repo only works with modules that have the RTC.

    I am working on an updated version that works without the RTC, but if you have a module that omitts this, you have 4 options

    1. Solder a 32khz crystal and the 2 capacitors to the correct pins on your module (I did this with a Wireless-tag module)
    2. Use Mbed instead of Arduino
    3. Hack the latest version of the RedBearLabs Arduino repo to work with your board (this is what I’m now working on)
    4. Wait for me to release my new version


    Windows Blackmagic Probe driver problems

    The BMP drivers work fine on Windows 7 but I have not tested them on Windows 8, or 8.1 or 10.

    I have had a report that they may not work on W10 because of signing issues, which is strange as W7 requires signed drivers and they work fine.

    If you have problems with driver signing on W10, just google for running unsigned drivers and there are some work-arounds, but its generally not recommended to run Windows permanently in a special mode to allow unsigned drivers, as it could be a security issue.


    Other ways to work out whats going wrong

    If you are not sure if you code is being uploaded, I’d recommend you powercycle your board and then reconnect and read back the flash from 0x1c0000 for about 1k and compare with the first 1k of the binary compiled by the Arduino IDE

    If they are different, then you have not really uploaded, and with the Blackmagic probe this normally indicates that it has not recognised the MCU as a nRF51822 and is treating it as a normal ARM cortex M0 in which case I don’t think it can correctly erase the flash before programming it.

    If you can’t connect via SWD, one cause can be transposed SCK and SDIO lines, so try swapping them over

    JLink will not connect unless you feed 3.3V from the target board back into the “sense” input

    With BMP its often best to manually run GDB and connect to the BMP and then connect to the nRF51822. See this post about connecting via GDB


    I’m afraid I do not have much free time to answer individual questions about installation or other problems, but feel free to post in case your questions or solutions help out others


    Replacement 3D printed CO2 laser bracket

    July 2nd, 2016

    When I bought by cheap “50W” Chinese laser cutter, I was alarmed to see that the brackets holding the laser in place were just bits of bent galvanized steel, packed around with a large amount of black rubber in order to get the laser into alignment.

    And when I needed to remove the laser to clear some air bubbles that had formed in the cooling water, I found it virtually impossible to realign the laser into its original position.

    My solution was to design some custom laser brackets which I could 3D print on my old MendleMax 3D printer.

    The brackets fit a 2 inch diameter tube, with 2mm padding rubber used inside the bracket.

    Height is adjustable, but was designed to work with my machine.






    The design was done in OpenSCAD, however the code needs to be tidied up before I publish it, but I’m happy to share the STL file

    Download by right clicking and saving the contents of this link laser_tube_bracket.stl

    Note. You need to remove the .txt from the end of the file. I only added that additional (.txt) extension so that systems would download the file, as the .STL file extension is also used for security certificates and is sometimes blocked.

    No Comments "

    Reprogramming the Dash Robotics Kamigami – Part 1

    June 28th, 2016

    As regular readers will know, I’m a fan of the Nordic nRF51822 Bluetooth MCU, as it can be programmed developed using Open Source tools.

    So when I saw the Dash Robotics Kamigami at Bay Area Maker Faire in May, and spoke to their hardware engineer Dwight Springthorpe, who confirmed that this innovative educational toy used the nRF51822, I took the plunge and bought one on the spot – at the special show price ūüėČ




    Dwight told me that Dash Robotics were interested in people developing for this product using the Arduino IDE, so I hoped I could develop an Arduino library to allow the various peripherals of the Kamigami to be programmed by the Arduino IDE, or possibly develop using

    When I initially got in touch with Dash via email, they were reticent at providing me with any information about the hardware. So I set about reverse engineering the Kamigami.

    Luckily a few days later I was able to get in touch with Dwight directly via email, and he has since provided me with some technical details.


    As I first step I had to solder a 4 pin header to the empty header points on the board and hook it up to a SWD programmer and see if I could reprogram the nRF51822.




    The connections are labeled on the silk screen,

    GND = GND


    3     = Vdd (3.3V)

    D     = SWDIO

    I hooked this up to a Jlink. (remember you need to connect the 3V pin to the Jlink or it won’t detect the nr51822 as being connected.

    Before I overwrote the existing firmware, I thought it prudent to see if I could read back the existing firmware, in case I needed to re-install the existing firmware, while reverse engineering the hardware peripheral connections, and to my pleasant surprise I found that I was able to read out the all of the Flash memory, as the nRF51 had not been read protected.



    So I now had firmware backed up in case I need to a restore.

    At this point, I had intended to possibly poke around the PCB using a multi meter and a scope to try to determine how the peripherals are connected to the nRF51, but I suddenly realised that I could restore the firmware backup onto a more convenient debug platform, namely my WaveShare nRF51822 (



    This board has a slightly different MCU, as it has the better QFAC variant with 32kb of RAM instead of the QFAA on the Kamigami but apart from that the MCU is identical. The other difference between the Kamigami PCB and the Waveshare is that the Kamigami doesn’t have the 32kHz RTC oscillator crystal (and the Waveshare does). This can make a big difference to the nRF51 startup code, and also its operation, because firmware written for boards with the 32kHz osc, don’t normally work on boards that omit this oscillator.

    Fortunately the reverse is not generally true, and after flashing the firmware backup to the Waveshare board, I was able to connect to it using both Kamigami iOS app.

    I selected the “Drive” option in the app, and twiddled the joystick that controls the 2 motors, and I noticed that some of the LED’s on the Waveshare board began to light up.

    Specifically, the LED’s on pins P18,P19,and P20. All the pins seemed to be driven via PWM, as the LED intensity could be adjusted. P18 and P19 seem to get lit when the robot would be moving forward, and P20 was lit when the robot would be going backwards.

    This seemed an odd arrangement, so I checked whether and of the other adjacent pins had PWM on it when moving the virtual joystick in the app, and found that P17 seemed to modulated when the robot would be going backwards.


    P0.17 is left motor reverse control

    P0.18 is the left motor forward control.

    P0.19 is right motor forward control

    P0.20 is right motor reverse


    Hooking a scope up to these pins, revealed that they were modulated at a clock frequency of just 64Hz, and that the joystick control has slightly odd mapping, in that For Example, 100% PWM is delivered to the right motor, not when the joystick is fully forward in the middle, but is actually when the joystick is over hard to the middle left, when the robot is being commanded to turn left – not that this important information at the moment, but may come in handy later when programming some new firmware.

    Incidentally, the motor driver IC’s appear to be GPY0067A, but I can’t track down a datasheet it… Not that this is particularly important as I’m pretty sure I know how to control the motors.

    The next thing I looked for was what controlled the 3 tri-coloured LED’s (which are wired in parallel), and a quick visual inspection of the board, revealed that the LEDs were on pins P0.5, P0.6 and P0.7, and playing with the App isolated that

    P0.5 = Blue channel

    P0.6 = Green channel

    P0.7 = Red channel

    Looking at these on the scope was also interesting, as the App just seems to have each channel, either on or off, but the scope showed that the LED’s are actually being driven with 64Hz PWM (like the motors), so it would be possible to get the LED’s to be any colour from black to white, not just the 6 options in the “Games” section of the App.


    Moving on to the inputs.

    The ambient light detector seems to be attached to P0.02, as grounding this pin though a resistor changed the value displayed in the App.

    The App displays the Battery level, but I have not been able to establish if this value is taken by reading the a pin, or whether its just a calculated value, which goes down depending on the amount of motor and LED usage.


    The Kamigami also has a 6 axis IMU, with 3 accelerometers and 3 gyros. I was unable to read the markings on the IMU chip, so I emailed Dwight and he told me it is an ST LSM330.

    I’m fairly sure that its connected via SPI, but I have not confirmed this with Dwight and I have not tried to communicate with it yet.

    Its actually a real shame that Dash opted to use a IMU without a compass (magnetometer), as in my experience the outputs from the gyros and accelerometers are not especially useful, as they are subject to noise and drift which makes them useless for inertial navigation. Where as the magnetometer always lets you know which way up it is and where north is.(Assuming it has been correctly calibrated in the first place)


    Developing using mbed

    Although I have an Arduino core that works with the nRF51822, I know it doesn’t work unless the hardware has the 32kHz RTC crystal, and the Kamigami board doesn’t have this.

    However there is an mbed platform for an nRF51822 module without 32kHz crystal –¬† for the¬†HRM1017 ( , that can be used as an equivalent platform.



    More to follow…



    No Comments "

    Chinese laser dust seals

    June 3rd, 2016

    Just a quick post about keeping the dust out of laser cutters

    Australia is a very dry dusty country, and dust is a major problem for me with the laser cutter. If dust gets on the mirrors or lens, it gets heated up by the laser which then damages (spot burns) the mirror or lens

    My machine, like most, has a large extractor fan in the rear of the machine, which sucks air out.

    Air is drawn into the machine though any opening in the case, including the laser cabinet, but I saw no reason for air, and therefore dust, to be drawn though that part of the machine.

    The simple and cheap solution is to buy household draft proofing strip from the local hardware store, and stick it where the door to the laser cabinet abuts the cabinet.




    This worked best in the left of the picture, where the door presses directly into the foam strip.

    It worked slightly less well at the top of the picture as the glue on this cheap draft excluder was not strong enough to prevent it being pushed downwards.

    Nevertheless, it still provides a much better seal than there was before, and as you can see in this photo, there is no dust at all. And I promise I have not just cleaned it before taking the photo.

    I have cleaned it, but not for months, as hardly any dust gets in.



    Arduino on the nRF51822 Bluetooth Low Energy microcontroller

    November 22nd, 2015

    This is the first in a series of posts about programming the Nordic Semiconductors nRF51822 Bluetooth low energy micro-controller using the Arduino IDE. The post is a big one as it describes the entire hardware and setup process.


    The board I’m using can bought bought on eBay, AliExpress or Amazon for well under $10

    (Update 20th Oct 2016. I found who actually makes these module. See  however they are only available via companies like WaveShare and various other vendors on eBay and AliExpress etc)

    nrf51822 module

    The board does not have either USB or an onboard serial based bootloader, so at least initially, it has to be programmed using an external SWD programmer.

    I’m currently using a Maple Mini STM32¬†board as a programmer


    By programming¬†it with a custom version of the Black Magic Probe firmware (more on this later), but any SWD compatible¬†programmer should be able to program this device, as long as the programmer explicitly supports the nRF51822 –¬†One other programmer which I know works is the JLink by Segger.


    The Maple Mini is available mainly through eBay and AliExpress for around $5 ( ) and you will also need a USB to serial converter to program it, like this one  or any USB to serial that supports 3.3V devices.



    Although not essential, its a lot easier to connect the nRF51822 RF module if you use a “Motherboard” like this one, which are also available on eBay and AliExpress etc, for around¬†$12 (USD) (without the radio module)

    nrf51822 motherboard



    The main reason that you should consider buying this board, is that the RF module, uses pin size and spacing which is not commonly used on other development boards, i.e the pins are not 0.1 inch apart, and the pins are shorter and thinner than used on Arduino shields etc.

    However if you are happy to solder some wires to the module, you can save yourself at least $10, which is what I’ve done as I’m still waiting for my Motherboard to arrive.


    Anyway, enough of the hardware you’ll need…

    What software is required.

    The first thing you’ll need, if you don’t already have it, is a copy of the Arduino IDE. Currently the only versions of the IDE that I’m supporting are 1.6.4 and 1.6.5

    Once you have installed the Arduino IDE you need to add either the Arduino Due or Arduino Zero board using the  Boards Manager. The reason this is currently required, is to install the ARM compiler and not for the actual Due or Zero. At a later date I will make a JSON file so that the nRF51822 can be installed without needing to install the Due, but at the moment this is the workaound you will need to use.

    The next thing you need to do is download the third party core files from github, specifically this zip file

    Next, go to your Arduino sketches folder and if there isn’t already a hardware folder, make a folder called hardware

    Unzip it, and copy the RBL folder from inside /arduino-1.6.x/hardware into your newly created hardware folder, and restart the Arduino IDE

    Now under the boards manager you will have a new board “Generic nRF51822”


    Now to make yourself a SWD programmer from your Maple mini



    First you will need to download the firmware from github


    In order to be able to send updates to the Blackmagic probe team, I’m probably going to need to maintain a direct fork of their master version.

    In which case I will move the version with working binaries to


    And also on Windows download the Flash Loader from STM



    Connect the USB Serial to the Maple mini by RX <–>TX and using GND and Vcc to GND and 3.3V on the USB to serial connector.

    You also need to connect the Boot1 pin to gnd on the maple mini during programming

    Then press and hold the button at the end of the Maple mini and then press and release the reset button (this will put it into serial upload mode)

    Then use the STM Flash loader to upload the binary file to the Maple mini.

    Once its been flashed, connect the Maple mini via its USB connector to your PC and it should be detected as 3 new USB devices.

    On windows you will need to install the drivers for these, by downloading and unziping, then open the device manager and select each of the 3 unknown usb devices in turn and select update driver software, then browse to the folder you have just unziped and allow windows to install the drivers.

    Note in the Windows device manager, which new USB device is shown as the GDB server, as you need to select that COM port number in the Arduino IDE to upload.


    To connect the Maple mini to the nRF51822, you need to connect the following pins

    For the SWD programming of the module use

    Pin 6 -> SCLK on the nRF51822 or on the JTAG connector on the motherboard

    Pin 7 -> SDO on the nRF51822 or on the JTAG connector on the motherboard

    For USB to serial, you can use these pins on the Maple mini

    Pin 8 -> P0.09

    Pin 9 > P0.11

    GND -> Gnd on the nRF51822 or Motherboard


    You can use the USB to Serial that is on the Motherboard instead of the Maple mini, in which case don’t connect pins 8 and 9



    If you are not using the motherboard or want to power everything from the Maple mini, you will also need to connect

    Vdd to Vdd (either on the nRF51822 or the Motherboard)





    open an example sketch like Blink and upload, and if everything is working, you should see a LED blinking on the Motherboard.

    If you won’t have a motherboard, you’ll need to connect a LED to pin P0.15, as this is currently the mapping that I’ve inherited from the RebBearLab files.


    GD32F103: A STM32F103 on steroids!

    September 3rd, 2015

    The world of the STM32 continues to get more interesting, with the recent availability of micro-controller boards based on the GigaDevices GD32F103. These devices have a quoted operating frequency of 108MHz, but as I will demonstrate, these boards also seem to work fine at 120Mhz.

    I first became aware of a GD32F103C board being available on, via a posting on by @jackson009 about a month ago.

    I did some research and discovered that GigaDevices have licensed the design of the STM32F103 from STM, and produced an enhanced version of the STM32F103.

    (Update. Nov 18th 2015. When I published this article in September 2015, it appeared as if GigaDevices were a “strategic partner’ of STM. See¬† , however this has now been clarified by STM in a letter to Olimex, indicating that that STM have not licensed the STM32 core to Gigadevices

    So it appears that the GD32 has been designed by Gigadevices to be pin and generally register compatible with the STM32)


    The GD32F103 has a maximum quoted clock speed of 108MHz, rather than the 72Mhz on the STM32F103, they also have a number of other changes. However the main improvement seems to be the faster clock speeds.

    I managed to get some GD32F103C8 boards from TaoBao, (via about a week ago and set about trying to use them with the existing STM32 core.

    Initial results were good. It was possible to flash the board using a USB to Serial adaptor, and the blink sketch worked OK, albeit it blinked faster than on the STM32. However Serial didnt work correctly because the clock rate of 108Mhz is 1.5 times faster than on the STM32, so I duplicated the STM32F1 core to make a GD32F103 core and set about investigating the clock settings in order to get the Serial and other timing related things working.

    The first difference I noticed with these GD32F103 boards, is that the crystal is 12Mhz instead of the usual 8Mhz used on STM32 boards. Actually STM32 boards could use 12Mhz crystals but generally 8Mhz ones seem to be used on all STM32 boards I’ve seen on eBay and AliExpress.

    The STM32 (and GD32) have a Phase Locked Loop (PLL) that multiplies the crystal oscillator frequency to become the master clock frequency. The crystal circuit is called the High Speed External oscillator or HSE for short. On the STM32 the normal setting for the PLL is to multiply the 8Mhz by 9 times to give 72Mhz, but as the crystal on the GD32 board is 12Mhz, the 9 times multipler gives 108Mhz – which is the maximum quoted operational speed of the GD32.

    Looking at the other clock controls, the peripheral clocks APB1 and APB2 are quoted as being able to operate at 54MHz and 108Mhz respectively, so the prescalers (dividers) did not need to be changed for the board to operate at 108Mhz.

    However at 108Mhz, the USB would not function. This is because the USB prescaler on the STM32 @ 72Mhz is set to 0x00 which gives a prescale value of 1.5 and hence a USB clock of the required 48MHz, and with the GD32 main clock at 108Mhz, the USB clock would be running at 72Mhz not the required 48Mhz.

    On the STM32, there is just 1 binary bit to control the USB prescaler, with value of 1.5 x or 1 x, which means that the only clock frequencies that will allow USB operation (48Mhz clock) are 72Mhz and 48Mhz.

    However on the GD32, there is an additional bit (23) so that there are 4 USB prescaler options, 1, 1.5, 2 and 2.5, which allows for higher clock speeds to be used while still allowing USB.

    But… And its a bit but… If you do the maths,¬† to use the 108Mhz clock frequency, you need a USB prescaler value of 108/48 = 2.25,¬† But there isn’t a matching USB prescaler option ūüôĀ

    Which strikes me as being very odd.

    The new USB prescaler values of 2.0 and 2.5 allow clock frequencies of 48 x 2 = 96Mhz or 48 x 2.5 = 120MHz.

    I suspect that perhaps GigaDevices thought that they would be able to operate these devices at 120MHz and hence included a prescaler value of 2.5 to cater for this, but perhaps their production was yeild was not good for devices that could operate at 120Mhz over the spec’ed operating voltages and temperature range, so they had to fall back to saying the GD32 could operate at 108Mhz (and fail to point out that USB was not available at that frequency !)

    But like most techie’s I’m always one to push the boundaries, so I thought I may as well set the main PLL to 10 and run the GD32 at 120Mhz and set the USB prescaler to 2.5 so that USB would have the correct clock.

    The GD32’s I have, seem to run fine at 120Mhz, under normal domestic conditions, however initially the USB didn’t work.

    On closer inspection, and after finding a circuit schematic on the web, it became obvious why the USB was not working: it was because the USB DP (D+) line was not pulled high via the normal 1.5k resistor, as the board does not have a resistor on either D+ or D-.  Where as most STM32 boards have 1.5k connected to D+.

    So I fitted an external resistor, and the USB sprang into life.

    I’ve now updated both the stm32duino-bootloader to include a generic-pc13 version which runs at 120Mhz and I’ve also updated the Arduino_STM32 repo to include a generic GD32F103C option. I’ve added a clock speed menu for the GD32, which allows selection of 72,96 or 120MHz, as these are the 3 values that allow USB to work. I could have included 48MHz, but I don’t see a need for this, apart from perhaps in low power applications. I’ve not currently included a 108Mhz option as USB doesnt run at 108Mhz and generally 120Mhz seems to work fine.

    One note with the GD32 core. I understand from reading some docs translated from Chinese, that there are other changes e.g. changes to Timer Capture; but I have not made any changes to the core about this, because at the moment I’m not aware that the core uses timer capture. The only changes that probably need to be made to the EEPROM library and the bootloader, as there appear to be some changes to the flags that indicate when Flash has finished being erased, but at the moment the bootloader appears to work fine, so I will add that to my To Do list for future stability of the code.


    (Update. Nov 18th 2015.

    Since posting, this original article I have done some speed comparisons, and the improved clock frequency is not the only improvement. The Flash memory on the GD32 operates without any “wait states” (its known as “Zero wait state”). From what I recall, the STM32 requires 2 or 3 wait states at 72Mhz (don’t quote me on this, but I kown its not zero wait state).

    This change gives an instance performance increase to the GD32 even running running at 72Mhz, which result in a Dhrystone test running with a Vax MIPS speed of 64.41 (@72Mhz) where as the STM32 was showing 48.81 РSee this thread


    This is not a terribly scientific comparison, but I think gives a reasonably general indication of the performance differences between the G32 and the STM32




    In conclusion, the GD32 is an interesting new addition for anyone interested in a cortex M3 device, especially as its very similar to the familiar STM32F103, or anyone interested in more performance than the STM32F103 currently offers.


    PCB prototype milling using CNC 3020

    August 4th, 2015

    Making your own PCB prototypes without all the messing around with chemicals sounds like a dream come true. The availability of low cost and seemingly high precision engraving / milling machines could provide the ideal tool for this, but in practice things are not as simple or as good as they appear.

    Ebay has a number of vendors selling desktop CNC mills, commonly called CNC3020. I think the 3020 refers to the size 30 x 20 cm. These are also often referred to as engraving machines, which is probably nearer to the truth than them being a milling machine. Prices start at around $600 (USD).

    If you are thinking of buying one of these please read this whole posting, as there are various bits of important information, which I’ve inserted in what I think are logical places in the description of the unit and how its assembled, configured and used.


    The first thing to note with these machines, is at the time of writing there are two different variants available, the “old” and the “new” model.
    The “new” / improved model has both different mechanics and different electronics to the “old” model.
    This is an example of the “new” version.

    The key difference in the mechanics seem to be a strengthened gantry on which the “spindle” / milling motor is mounted, with¬† a thick aluminum plate all the way across. I suspect there are other mechanical changes, but its hard to tell from the photos on eBay.

    The other difference is the power supply / motor control unit. The “new” version seems to be housed in a black box, with a sloping front, where as the old version was in a blue box with vertical sides all the way around. The changes appear to be more than just the cosmetics of the box. The PCB’s in this box differ from the ones in the old model as well – however whether they are an improvement over the old version, or just an alternative set of boards, is hard to tell.

    I’ve read a lot of postings about issues of the control unit “missing steps”. This is where the PC tells the control box to move the motor a certain number of steps, but the motor doesn’t turn as much as it is supposed to because the control unit has not passed the correct number of steps onto the motor. I’ve not personally experienced this issue, as it manifests itself with cutting head not moving as far as it should do in any particular direction. However I have found other issue where the cutting head was actually moving slightly too far. More on this later.


    My CNC 3020 arrived as a partial kit, but without a mechanical assembly manual. My unit came with a CD that contained some software and a word doc explaining in pigeon English how to configure the software, again… more on this later.

    I suspect all these units arrive partially assembled, where the motors were not attached to the frame, and their control / power wires were not attached. However its a relatively simple process to attach the motors using the bolts that are supplied, and the unit even came with Hex / Allen keys to tighten up the bolts. You also need to fit the flexible couplers on between the spindle of the motors and the lead screws, but this also just involves doing up some small Hex screws.
    One thing that was slightly odd about my CNC 3020 was that the 3 couplers were not the same design, but all had the same internal diameter for the motor and lead screw shafts. As the unit didn’t come with an assembly manual, I made a guess that the odd one out, of the couplers, should go on the main, back to front / Y axis lead screw motor, however I suspect it does not make any difference.

    Once the motors are bolted on, and you guess which control / power cable goes to each motor, (you can work it out from which cable will nicely reach each motor), you can connect the 4 circular control / power cables to the back of the control unit, and connect the control unit to a PC via a Centronics printer cable.

    Yes… This unit needs your PC to have a old fashioned Centronics / parallel printer port. If your PC does not have one, you are out of luck.

    Buying a USB to Centronics adaptor cable will not work, as the software that is supplied with the unit directly generates square waves on the Centronic port’s pins, using a special Windows driver, and this will not work with a USB to Centronics adaptor.


    Anyway, assuming you have an old PC, even a laptop which has a proper Centronics / parallel printer port, you should be OK; but please note, I am also using Windows XP, and I can’t comment on whether Windows 7, or Windows 8 etc, work even if you have a machine with the correct hardware.

    The software that came on the CD with the unit, is “Mach3” except it is a “demo” / limited version, which seems to be quite old.

    Once installed, you have to enter the calibration numbers as stated on any installation documents supplied with the unit. This is basically the number of steps that each motor needs to take to move the cutting head 1mm

    The limitation of the software is that it will only process 1000 lines of GCODE data. GCODE being the standard language for CNC machines and is generated by all sorts of design packages.

    The 1000 line limitation is something which is likely to be an issue for most users fairly soon after they start to try to mill anything other than some demo files e.g. the outline of the “Roadrunner” cartoon character, and the best option for most people is to buy the full / official version of Mach3, which at the time of writing, retails for $175 (USD).

    There are other options, including using Linux to control the mill, and also to buy a dedicated USB to CNC adaptor – which replaces parts of the electronics in the control box; however I have not investigated these options as yet.

    Once you have connected it all up, and calibrated the software, you should be able to move all 3 axis motors and do a test mill of the “Roadrunner” icon to confirm that everything is working OK.

    Tip:  One thing I do to test a new set of GCODE is to set the Z  zero position of the unit to about 5cm above the actual milling bed, and without a cutter in the chuck, then run the GCODE without the spindle / cutter motor running.

    Finally after quite some time you are getting slightly closer to being able to mill your own PCBs.¬†¬† Generating the GCODE for the PCB is relatively simple. An open source package called PCB-GCODE ( ) can convert either Gerber files to GCODE, or there is a User Language Program (ULP) for Cadsoft Eagle which will generate the GCODE “tap” files from within Eagle.

    With the “etch” file loaded into Mach3, you can attempt to mill your first PCB, but first there are a few more hurdles to overcome ūüėČ

    Securing the PCB to the milling bed

    The main problem with milling a PCB is how to secure the PCB down onto the milling bed. As you will be drilling holes through the PCB as well as milling away the copper, you will need to mount something like a small sheet of wood onto the milling machine, and mount the PCB onto the wood. The best thing I’ve found so far to mount the PCB onto is MDF. The MDF needs to be thick enough so that the drill can completely penetrate the PCB and not drill into the aluminum bed of the mill. If you are careful, you can probably use 3mm or 5mm MDF, however these are likely to be too weak to attach to the bed using the bolts supplied with the machine, so I normally use 10mm or even 12mm MDF, as this feels really secure and robust. MDF has good dimensional stability as long as it doesn’t get wet or absorb a lot of moisture, but should work in most indoor environments unless you live somewhere very humid.

    Initially I used masking tape to hold the PCB onto the MDF, however this doesn’t work particularly well, as the edges of the PCB soon start to lift off slightly, as most PCB I have appears to be not entirely flat.

    If the PCB is not absolutely flat you will have major issues with the milling process. This is because the normal cutting head for milling PCB’s is a 20 deg or 30 deg V shaped engraving tool, hence the width of the section that is milled is dependent upon the depth that the point of the cutter is below the surface. So if your PCB lifts off by, for example 0.5mm, this is going to cause the cutter to penetrate into the board by an additional 0.5mm, which will mean it cuts a path which is approximately 0.25mm wider than you expect (assuming you are using 30 deg V cutter), this can be the difference between a track existing or getting milled away.

    CNC with secured PCB
    CNC with secured PCB

    The way I hold the PCB in place is to clamp down at least 3 sides of the board using steel plates. I bought some steel fixing plates from a DIY store, which are about 15cm long by 3cm wide and about 4mm thick. I’m not entirely sure what use they have in building construction, but if you overlap them onto the edge of the PCB by a 5mm (or a bit less) them screw them down onto the MDF, the PCB is prevented from lifting on any of the sides. Of course if you have a PCB which bows up in the middle you will still have a problem, so you should try to use PCBs that are as flat as possible, and even possibly flatten them before hand by storing them flat under pressure e.g. between some heavy books.

    I’ve seen some examples on the web, where people just used a small clamp in the middle of each side, and I think this would be equally effective; but either way its very important to clamp the PCB onto the MDF as flat as possible.

    Cutting tool height adjustment

    The next important thing is to set the exact height of the cutting tool. For a while I’d been using a sheet of paper as a feeler guage, and lowered the cutting head a little at a time, until it was in contact with a sheet of paper placed on top of the PCB, so that I could feel definite resistance, when trying to move the PCB, however this isn’t really accurate enough.

    A better approach is to use the a continuity meter (buzzer / beeper) setting in a normal multimeter to determine when there is an electrical connection between the cutting head and the PCB. To do this I attach crocodile chips to the PCB clamps and to the cutting bit, and slowly jog the cutting head height down 0.01mm at a time until my meter beeps, I then raise the cutter a few 1/100 of a mm until it stops beeping, and I know its very very close to zero.

    Even with the PCB clamped down, there can also be minor differences in its height, so its best to do this Z height calibration in the middle of the area you are about to mill. There is actually a program which will scan the PCB using this electrical connection and re-map the Z height of the milling to take account of minor fluctuations in the PCB thickness / height, however to use it you need to modify the control unit to accept the continuity as the Z zero limit, and so far in practice I have not found it necessary to go to this level of complexity.


    When you have finally calibrated everything, you can start to mill the board, and hopefully you will not have too many problem with board thickness or warp.

    After the “etch” path has been milled, you need to change your cutting bit to a 1mm or 0.9mm PCB drill, and load the “drill” tap GCODE file. Its important to not loose the X and Y calibration when you are changing the cutting bit for the drill bit, otherwise it will be very hard to get the machine re-positioned correctly to drill the holes in the correct locations.

    I have attempted to use the same continuity technique to calibrate the Z zero on the drill, but I think perhaps the drills come pre-coated with some varnish, as they are not good conductors when they are new.

    Its also very easy to snap the PCB drill, by applying downward pressure. So under no circumstances “jog” the drill down onto the PCB surface when its not spinning, otherwise you stand a very high chance of snapping it. Trust me, I have snapped one drill this way, and snapped a second drill trying to manually drill out some holes which the mill didn’t drill completely through a board.

    As the depth of the drill holes isn’t that critical, as long as its completely through the PCB, its safer to use the paper technique, with some thicker paper, to get the Z height about right, even if its 0.5 or 1mm above the board, and set the drilling depth to 2,3 or even 4mm to ensure the drill goes completely though the PCB. (Assuming you have a decent thickness of MDF below the PCB).

    After the board has been drilled, then and only then, should you release the clamps are remove the board.

    Results so far…

    So far I have only milled single sided boards. Milling double sided boards is technically possible, however I can see a number of possible problems around the re-registration of the zero point (X,Y), as after the board is flipped over, it would need to be repositioned to within about 0.05 of a mm in both X and Y of its original position. This can probably be achieved by adding a calibration drill hole at 0,0 in the board GCODE file. However the other problem is rotation. i.e 2 calibration holes would be needed to ensure the board is not slightly rotated. Or perhaps some sort of metal jig could be bolted to the MDF prior to milling the first side, to ensure that the board is refitted in exactly the same location.

    I’m personally very skeptical about the feasibility of doing this. I know it can be done, but I think it would take quite a lot of practice and experimentation to develop a process to make reliable double sided PCB’s a practicality.

    However overall, production of single sided prototype boards is entirely possible on the CNC 3020, it just takes some time and effort.


    Arduino STM32 – USB Serial and DFU

    June 18th, 2015

    I often get asked about why the USB Serial doesn’t seem to work on Maple mini or generic STM32F103 boards loaded with the STMduino-bootloader.

    If you buy a brand new Maple mini, and plug it into your PC or Mac or Linux box. Do not be suprised if you only see a DFU device. This is normal.

    Just compile and upload a blank sketch.¬† Even a blank sketch will contain the Serial USB code, and your board should then appear as a “Maple Serial” device.

    There is a common missconception that the STM32duino-bootloader, and the older Maple bootloader, contain both DFU (upload) USB support and also “Maple Serial” (USB Serial) functionality. However this is not the case.

    Originally when Leaflabs wrote the Maple bootloader (back in around 2012) they tried to include both  DFU and Serial functionality, however they found issues with this under Windows. This is because the DFU and Serial functionality requires the use of 2 completely different (built in) drivers in Windows; when the Maple board is only one USB device.

    Normally manufacturers create composite USB devices in this case, i.e one USB driver that performs both the DFU and Serial functions. But creation and certification of custom drivers for Windows is non-trivial and expensive. Hence LeafLabs chose to separate the DFU and Serial USB functionality, so that only the DFU driver is used when the bootloader is running and only the Serial driver is used when the Arduino sketch is running.

    This method allows the use of 2 separate Windows drivers – both of which come as standard on all Windows installations.

    Although the functionality of both DFU and USB Serial could have been included in the bootloader, it would make the bootloader and sketch core code (libmaple) more complicated, as the sketch would need to communicate with the bootloader in order to send and receive serial data.

    So Leaflabs chose to go with the simpler option of the bootloader only containing the DFU functionality, and for the USB Serial to be compiled as part of the sketch. Although this is the simpler option, its probably the best one, because if the Serial USB support was contained in the bootloader, the amount of additional code to allow the sketch to send and receive Serial via the bootloader would make the overall size of the bootloader and sketch slightly larger.

    Sketches do take slightly longer to upload than if they did not contain the USB Serial functionality, but uploads via DFU are generally faster than AVR Arduinos, so this isn’t a serious concern.

    Another consequence of splitting the functionality, is that if the sketch crashes, then the USB Serial will also crash, and often the USB Serial device will not appear at all.

    And… any board that has been freshly installed with a bootloader, will only appear as a DFU device, because the bootloader checks to see if a valid sketch is in the program (flash) memory, and if not the bootloader continues to stay in DFU mode until a valid sketch has been upload.