Maple Mini – Serial Programming and Upgrading to Bootloader 2.0

My BAITE BTE14-07 Maple Mini clone came with LeafLabs’ original bootloader. I decided to upgrade to Bootloader 2.0 in order to free up some RAM, and take advantage of some of the new features. The procedure looks pretty straightforward, but I ran into some snags. Perhaps the easiest way to change the bootloader in a Maple Mini is to use the STM32’s built-in serial bootloader to flash it in. The serial bootloader is in ROM, so it’s a fail-safe method to program the chip. The technique involves hooking up UART1 to a USB->UART adapter. I had a spare CP2101-based adapter that works with 3.3V hardware:


The hookup is straightforward:

TX -> rx1
RX -> tx1
3V3 -> Vcc

Here is what it looks looks like all hooked up:

Actually the RX1 & TX1 pins are 5V tolerant, so you can even use a 5V USB->UART adapter. Just make sure to hook up 5V -> vin instead of to Vcc, or you’ll be in for a very unpleasant surprise.

There are several programs available that can program the STM32 in serial bootloader mode. I tried both and stm32flash. Also, you will need the binary bootloader file, maple_mini_boot20.bin.

To put the board into serial bootloader mode, press and hold reset and but, release reset, and then release but. The board will look dead. This is normal. Then execute the command to flash in the bootloader. stm32flash is more straightforward, because it doesn’t require you to install Python. There are pre-compiled versions of stm32flash for various platforms in Arduino_STM32’s tools directory. My computer runs Windows 8.1, so I used the stm32flash.exe:

C:\git\Arduino_STM32\tools\win>stm32flash -w maple_mini_boot20.bin COM19 -b 230400 -g 0
stm32flash 0.4

Using Parser : Raw BINARY
Interface serial_w32: 230400 8E1
Version : 0x22
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0410 (Medium-density)
– RAM : 20KiB (512b reserved by bootloader)
– Flash : 128KiB (sector size: 4×1024)
– Option RAM : 16b
– System RAM : 2KiB
Write to memory
Erasing memory
Wrote address 0x08001b7c (100.00%) Done.

Note that you need to substitute your USB->UART converter’s serial port for COM19.

If you prefer Python, you can use instead. Make sure to use the version from the Arduino_STM32/tools directory. I tried to use the version from STM32duino-bootloader and the version from libmaple, and both of them wrote only the first 512 bytes of the bootloader, so the Maple Mini was no longer detected at all when plugged into my computer.

Here is how to execute

C:\git\Arduino_STM32\tools\win> -p COM19 -evw \hacking\STM32\maple_mini_boot20.bin
Reading data from \hacking\STM32\maple_mini_boot20.bin
Bootloader version 0x22
Chip id 0x410, STM32F1, performance, medium-density
Writing 7036 bytes to start address 0x8000000
Write 256 bytes at 0x8000000
Write 256 bytes at 0x8000100
Write 256 bytes at 0x8000200
Write 256 bytes at 0x8000300
Write 256 bytes at 0x8000400
Write 256 bytes at 0x8000500
Write 256 bytes at 0x8000600
Write 256 bytes at 0x8000700
Write 256 bytes at 0x8000800
Write 256 bytes at 0x8000900
Write 256 bytes at 0x8000A00
Write 256 bytes at 0x8000B00
Write 256 bytes at 0x8000C00
Write 256 bytes at 0x8000D00
Write 256 bytes at 0x8000E00
Write 256 bytes at 0x8000F00
Write 256 bytes at 0x8001000
Write 256 bytes at 0x8001100
Write 256 bytes at 0x8001200
Write 256 bytes at 0x8001300
Write 256 bytes at 0x8001400
Write 256 bytes at 0x8001500
Write 256 bytes at 0x8001600
Write 256 bytes at 0x8001700
Write 256 bytes at 0x8001800
Write 256 bytes at 0x8001900
Write 256 bytes at 0x8001A00
Write 256 bytes at 0x8001B00
Read 256 bytes at 0x8000000
Read 256 bytes at 0x8000100
Read 256 bytes at 0x8000200
Read 256 bytes at 0x8000300
Read 256 bytes at 0x8000400
Read 256 bytes at 0x8000500
Read 256 bytes at 0x8000600
Read 256 bytes at 0x8000700
Read 256 bytes at 0x8000800
Read 256 bytes at 0x8000900
Read 256 bytes at 0x8000A00
Read 256 bytes at 0x8000B00
Read 256 bytes at 0x8000C00
Read 256 bytes at 0x8000D00
Read 256 bytes at 0x8000E00
Read 256 bytes at 0x8000F00
Read 256 bytes at 0x8001000
Read 256 bytes at 0x8001100
Read 256 bytes at 0x8001200
Read 256 bytes at 0x8001300
Read 256 bytes at 0x8001400
Read 256 bytes at 0x8001500
Read 256 bytes at 0x8001600
Read 256 bytes at 0x8001700
Read 256 bytes at 0x8001800
Read 256 bytes at 0x8001900
Read 256 bytes at 0x8001A00
Read 256 bytes at 0x8001B00
Verification OK
Traceback (most recent call last):
File “C:\git\Arduino_STM32\tools\win\”, line 531, in
if conf[‘go’]:
KeyError: ‘go’

I don’t know what’s the cause of the error at the end, but as long as it writes 7036 bytes, you see Verification OK, the bootloader is installed correctly. Whe I ran the bad versions of, here is what the output looked like:

Bootloader version 22
Chip id `[‘0x4’, ‘0x10′]’
Write 256 bytes at 0x8000000
Write 256 bytes at 0x8000100
Read 256 bytes at 0x8000000
Read 256 bytes at 0x8000100
Verification OK

Even though it showed Verification OK, note how only 512 bytes were written to the Maple Mini.

If you have successfully flashed in the bootloader, the LED will flash continuously after you reset the board, indicating that the bootloader is running. In Arduino, you also must switch the setting to from Original to Bootloader 2.0:


If, for some reason, you want to revert to LeafLabs’ original bootloader, you can download it here: maple_mini_boot.bin.

The built-in STM32 serial bootloader is not only for installing bootloaders. You can also use it to flash in any other BIN file, including Arduino_STM32 sketeches.

BAITE Maple Mini Clone – First Look

Recently, I’ve been searching around for inexpensive higher powered alternatives to AVR-based Arduinos. There are several ARM MCU’s available that give a lot more bang for the buck in terms of RAM, speed, flash, and I/O. While I like PJRC’s Freescale-based Teensy 3.x boards a lot, they’re only available from a single source, and use a proprietary bootloader hosted on a separate MCU. FadeCandy is an OSHW board based on the same MCU as the Teensy 3.0, which is optimized for controlling LED’s. Unlike the Teensy 3.x, it uses an open source bootloader which is hosted on the Freescale MCU itself.

There are a lot of STM32 boards of various types available on eBay and AliExpress. LeafLabs’ Maple series of STM32 boards were pioneers in adapting Arduino for use with the STM32 platform. Unfortunately, the boards were quite expensive, and with the proliferation of cheap Chinese clones, they business was not sustainable, and they discontinued the line. Luckily, the OSS community has picked up the pieces, notably Roger Clark’s Arduino_STM32 project. The current state of the project is very impressive. Not only has Arduino compatibility been greatly improved, but they have created a new bootloader, and many other STM32 families are not supported beyond the Maple’s STM32F1.

I decided to dive in when I had a project that needed 10 PWM channels. The Maple Mini fit the bill. I bought a couple of BAITE BTE14-07 Maple Mini clones. They are quite cheap, under $4.50 including shipping from China. The board is packaged in an anti-static bag, and includes header pins:



While the pinouts, LED, and buttons of the BAITE BTE14-07 are identical to the original LeafLabs Maple Mini, the BAITE version is only 2-layer, instead of 4-layer. Also, instead of using two MCP1703 voltage regulators, one for the digital and one for the analog plane, the BAITE uses a single AMS1117. This means that LeafLabs version is probably more suitable for applications where ADC accuracy is required, but the BAITE version is better when more current is needed to drive attached peripherals.

I tried some sample sketches using Arduino 1.6.5 and Arduino_STM32, and the BAITE board worked perfectly. Some people on the STM32duino board consider it to be somewhat of a benchmark as far as Maple Mini clones go, so it’s probably a good bet for n00bs to the platform like me.

2002 Honda Reflex R&R Starting Enrichment Valve DIY

I’ve had my 2002 Honda Reflex scooter for many years. It tends to sit a lot in the garage, and I go through only about 2 tanks of gas a year, so lots of gunk probably builds up in the fuel system. One problem that I’ve always had, but never bothered to fix is that if it sat a long time, it would start cold OK and idle, but then when I tried to open the throttle, it would stall. The worst thing I could do is open up the throttle wide while this was happening… it seems like it would flood the engine, because it would stall, and then become hard to start for a while. Usually, running it for a few minutes and letting it warm up a bit would get it going enough that I could finally rev it up. If I managed to get it to rev w/o stalling just once, then it would run perfectly after that. The above problem would happen only if I let the bike sit for several weeks w/o riding it. Otherwise, it would cold start OK, and no problem with it stalling on initial rev up.

For the last 3 times I’ve ridden it, the problem has gotten a lot worse. I always have to use starter fluid to get it running. Then it idles fine, but stalls instantly when I try to rev it, just like before. But the difference is that now, I have to run it forever before I can rev it without stalling. And even if I manage to get it to rev to say 4000RPM and hold it there a while, when I let it go back to idle, then it goes back to stalling when I try to rev it. This is different from before, in the past, because holding it at 4000RPM for a few seconds just once would fix the stalling when attempting it to rev. Furthermore, now, I have to ride it without stopping for a few miles, or it will again stall when I try to rev it up. Also, there is a bit of hesitation when I start of from a traffic light.

After doing some research on the Internet, I guessed that the problem had something to do with the starting enrichment circuit. Rather than a choke, the Reflex has a starting enrichment valve which blocks a jet that lets in a bit of air when the engine is cold. This causes it to run rich, so functions a bit like a choke. Working on the Reflex’s engine is generally a pain, because it takes so long to take off all the panels to get access to it. To my delight, I discovered that the starting enrichment valve is accessible if you remove the plastic battery cover under the seat. Next to the battery is an access hole to the engine, which gives you peek at the top of the carburetor.

The starting enrichment valve is the black booted assembly pointed to by the red arrow below:


It’s held on by two screws, one of which is circled in red in the photo above. The other one is impossible to photograph, but it’s in the vicinity of where the red arrow points. Make sure to use a strongly magnetized philips screwdriver to remove the screws, to help avoid dropping them into the dark netherworld of the engine compartment. The clip in the photo below is clamped down by the two screws, and it in turn holds the starting enrichment valve in place.


Once the clip is removed, the valve simply lifts out. Mine was moving freely, and looked fairly clean. I didn’t bother testing it it, since my problem is with cold running. The valve is fully extended by default, which blocks an orifice that lets air in, so the engine runs rich. As the engine warms up, the valve is supposed to retract, letting more air into the engine, leaning out the mixture.


I sprayed some carb cleaner on the valve and wiped it off just for the hell of it, and then sprayed more carb cleaner into the jet:


Reinstallation of the starting enrichment valve is just the reverse of the removal.  The procedure takes about 3x as long as removing it, especially when your screwdriver slips into the bowels of the engine, and you have to locate it and fish it out. I magnetized the screws to make them stick better to my screwdriver before very carefully putting them back in.

After I put everything back together, the bike started up without start fluid, so cleaning the valve & jet definitely helped a bit, but I still had to warm it up for several minutes before I could open the throttle without stalling. So I only fixed part of the problem. I guess the other jets in the carburetor are still clogged up. I headed out and bought some fuel injector cleaner. After pouring a couple of tablespoonsful into my tank, I added a gallon of gas, and took it on a 10 mile ride. It’s already running smoother, and no longer hesitates when I start off from a traffic light. I’m eager to see how it behaves next time I do a cold start. If the problem still doesn’t clear up after running the gallon of gas through the engine, I guess I’ll have to remove the carb and do a proper cleaning on it… something I’m not looking forward to. Access to the carb will require removing a lot of panels.


SkyRC iMAX B6 80W (Fake?) Battery Charger

After reading about the SkyRC iMax B6 Charger on rcgroups, I decided to buy one. I chose a US-based seller, globalexcellent_ltd on eBay, and paid $17.99. The listing claimed that had a max charge power of 50W, and due to the low price, I figured I was getting a clone. I didn’t mind if it was a clone, because my plan was to install cheali-charger on it if it didn’t behave properly. I was surprised when a couple of days later, I received an 80W model:


I was also surprised (but skeptical) that there was a label on the back of the box claiming that it was a genuine SkyRC product:


However, the box lacks the hologram which can be used to confirm a genuine product on SkyRC’s website, so I’m pretty sure it’s a fake. This is the start up message:


I did some initial testing, and found that it was almost half a volt off in its readings. My first thought was to try calibrating it via the Calibration Menu, which is supposed to be accessible by powering it up while simultaneously holding down the Dec and Start buttons. Much to my chagrin, I could not activate the calibration menu. Also, the Balancing Calibration Menu, which is supposed to be accessible by powering it up while holding down Stop and Inc didn’t work. After doing some searching, I found a discussion on the cheali-charger google discussion group about a Clone iMax B6 SKYRC (80W). It turns out the model in question has a mystery MCU which is not labeled, and is not compatible with cheali-charger. I took mine apart to see what PCB was inside:


I forgot that the buttons were protruding from the case, so after I took off the end caps, I tried to slide out the PCB. Big mistake! I broke all 4 buttons! The proper way to remove the PCB is to carefully bend the case until the PCB can be pulled out the bottom of the case, rather than sliding it. Another diversion … I had to fix the broken buttons with super glue. After carefully examining the PCB, I figured out that I am unlucky, and mine is definitely the model with the unknown CPU that’s not compatible with cheali-charger. So, I had to find another way to make it functional.

From the google discussion thread, I found out that this particular version of the B6 has only one calibration menu, and it’s accessed by holding down the Stop and Start buttons while powering it up. It looks like the balance calibration menu on a normal B6 charger, showing 6 voltages. WARNING: DO NOT PRESS START AND STOP WHILE POWERING UP UNLESS YOU HAVE A CALIBRATION CIRCUIT HOOKED UP. OTHERWISE, IT WILL COMPLETELY MESS UP YOUR B6’s VOLTAGE CALIBRATION. Most people use a precision 25.2V power supply and 100 ohm .1% resistors to do the calibration, but having neither of those available, I decided to instead build up a 6S pack of fully charged LiPos. Here is the battery hookup:


I charged each individual cell on another charger to exactly 4.19V. Also, according to Joe Rouvier’s post in the cheali-charger discussion, the temperature input also needs ~1V during calibration, so I hooked up a 5K potentiometer across terminals 1 & 3 on the temperature port, wiper to terminal 2, and adjusted it to 1.00V.  Next, I powered it up with the Stop and Start buttons pressed down:

(Note, in the video, the temperature calibration circuit is not hooked up… I redid the calibration after I shot the video). After the voltages stabilize, calibration is complete, and the power may be disconnected. Interestingly, after the display stabilized, the iMAX B6 displayed all of the voltages exactly at 4.19V… spot on. This is different from I was expecting, because Joe Rouvier had mentioned that the charger just assumes every cell is 4.2V during calibration.

After calibration was complete, I tried test charging the battery that I used for calibration. I tried both Charge and Balance modes. In both modes, the main screen displayed the voltage as 25.1V, and after less than 1 minute, displayed FULL. But strangely, the cell voltage screen (press Inc during a charging session) was showing mismatched voltages (e.g. 4.20/3.94/4.18/3.98/4.19/4.12). In Balance mode, the voltages would start at the mismatched values, but then finally stabilize to be equal. However, after the charge session ended, if I started Balance mode again, the voltages would again be mismatched when the session started.

Next, I tried charging a single 3.7V/2000mAh LiPo cell. During charging, the 4.20V was always displayed, regardless of the actual voltage across the charge terminals. During the constant current phase, the voltage fluctuated, and often went above 5V. After ramping down the current charger stopped and displayed FULL and 4.20V. However, when I measured the cell with my DVM, it was 4.00V. I guess it’s good that it doesn’t overcharge and destroy your cells, but .2V low is a pretty big discrepancy. I tried restarting the session and playing with various charge currents from 2A-.2A, but it just kept stopping with the cell voltage exactly 4.00V.

Next, I hooked up my hand built 6S balancing pack again. Before charging, I verified that the cell voltages were still at 4.19V and triple checked the wiring. A normal Charge session ended with the both the battery and display at 25.1V, but the cell voltage screen was again displaying mismatched voltages. Next, I tried a Balance charge session again. This time, the charger started to smoke around the balance inputs! I quickly unplugged everything, but it was too late. The charger is now toast, as well as one of my one my LiPo cells, which now reads 0.00V.

Sheesh, what a short-lived charger. I don’t know if I just got a defective unit, or if this thing is junk, but I’m wondering whether I should try another iMax B6 or buy a different charger.

UPDATE 2015-07-28: Amazingly, the charger still works when not in Balance mode. At least, I’ve been charging single LiPo cells. It still charges them up to exactly 4.00V (though the display still always shows 4.20V during and after charging). This is what the board currently looks like:


The rightmost row of balancer resistors is fried, as the power resistor at the top right. I’m not sure if I’m going to bother trying to fix it, since I can’t change the firmware to fix the 4.00V charge voltage bug.

Update 2015-08-04: OK, I’m a moron. I bought a genuine SkyRC 50W iMax B6 on Amazon, and it too seemed to be charging to exactly 4.00V as measured from the battery terminals. Then I found that during charging, the voltage at the charging terminals was 4.25V, while the voltage at the battery terminals was 4.00V. So, I tested the resistance of my charging jumpers, and found about 3 ohms resistance! The 4.00V terminal charging voltage was caused by excessive resistance in my charging jumpers! After swapping to some new jumpers, the genuine SkyRC iMax B6 charges 1S LiPo cells to 4.19V. Pretty good calibration from the factory. Next, I tried the fake 80W iMax B6 that I calibrated, and it too, charges to 4.19V. But there’s a big difference during charging. While adjusting current, the genuine iMax B6 never exceeds 4.25V while it’s adjusting the charging current. On the other hand, the fake 80W iMax B6 often overshoots in excess of 5V while adjusting down the charging current. I’m not sure if these temporary voltage spikes will damage your batteries or not, but to be on the safe side, I would avoid the 80W clone, until someone figures out how to get an open source firmware into it.

Pyle PSWGP405BK GPS Watch Software and Firmware Updates

Today, I discovered that the New Balance NX990 GPS Cardio Trainer Watch, like the Pyle PSWGP405BK, is just another Latitude Limited Nav Master II clone.  Following my hunch, I searched for the NX990’s accompanying software, and lo and behold, it’s just rebranded version of GPS Master! Best of all, it’s an updated version, v2.0.16.124, vs the older v1.2 version that I got from Pyle. Besides the red background, it has a much improved interface, showing a google map of your track, and a zoomable graph with user selectable data that tracks your stats live on the map.


So for instance, you can select the point on the graph where your heart rate is highest, and see where you were located on the map.

Best of all is the new Data Transfer->AGPS menu item. A-GPS (Assisted GPS) lets you use the Internet to download GPS satellite almanac data. Your GPS watch can download the almanac data directly via the satellites, but it is a very slow procedure. By connecting your watch to GPS Master once a week and downloading new AGPS data, you can get a hot GPS fix a lot faster. I wasn’t sure if my Pyle firmware had A-GPS support built in, so I took a risk, and used Setting->Watch firmware update to update my Pyle watch to the latest New Balance firmware. I’m happy so say that my watch did not get bricked! [DISCLAIMER: YMMV. I AM NOT RESPONSIBLE IF YOU DECIDE TO INSTALL THE NEW BALANCE FIRMWARE ON YOUR WATCH, AND IT TURNS INTO A PAPERWEIGHT] The New Balance v1.20 firmware appears to have all of the functions of my Pyle firmware. The most obvious difference is just that the screen fonts are more squared off looking. Some of the menus look slightly different, too. I took my watch outside after updating the AGPS data, and it got a GPS fix basically instantly!!

Another great discovery is that unlike my GPS Master 1.2, NB 990 GPS’s exported GPX track files now contain heart rate data! This means when upload your GPX track files to web sites such as RunKeeper, your heart rate data will be saved and displayed, as well. Meaning that you don’t have to use the csv2gpx/csv2tcx utilities that I wrote yesterday in order get your HRM data into other platforms.

All and all, I am very happy with both the software and firmware updates. I took my watch and HRM out for a workout today, and they worked flawlessly with the new firmware.


NX990 GPS Master PC Software
NX990 GPS Master User Manual
NX990 User Manual

Update 2015-03-15:

Here are some open source goodies for the watch:

Crane GPS Watch Client : command line utility. Most notably, it exports TCX files, which is important if you like to use the watch with the GPS turned off, since GPX files that contain HRM data w/o GPS data aren’t valid.

kalenji-gps-watch-reader : exports a multitude of formats, including Garmin FIT. Also performs elevation corrections via Google Elevation API.

GPX and TCX output from GPS Master Software

A couple of years ago, I bought a Pyle PSWGP405BK GPS watch with Heart Rate Monitor.


It’s been a great device, though it’s big, and a bit ugly. The battery far outlasts my wife’s Garmin watches, and I love the customizable screens. My main problem has been the lack of a useful way to extract heart rate data. The problem is that the GPS Master software offers only two ways to export heart rate data: 1) TKL format, which is an undocumented file format used only by GPS Master, and 2) CSV format, which isn’t compatible with any web sites or software that I use.  Although GPS Master can directly export GPX files, they do not include the heart rate data.

I finally got sick of it today, and after wasting some time looking for an easy way to adapter existing converter software to work w/ GPS Master’s CSV files, I gave up, and decided to write my own programs. So, I give you csv2gpx, and csv2tcx. csv2gpx takes a GPS Master CSV file as input, and outputs a GPX file with heart rate data embedded. csv2tcx takes a GPS Master CSV file as input, and outputs a TCX file with heart rate data. Both programs have a simple command line interface. I have supplied full source code on github, so anyone can compile them to run on their own platforms. For Windows users, I have supplied EXE files. The command line syntax is quite simple:

csv2gpx workout.csv


csv2tcx workout.csv

The output will automatically be generated as workout.gpx and workout.tcx, respectively.

Here is a sample session:

C:\git\csv2gpx\test>csv2gpx 20150125074851.csv
Lincomatic GPS Master CSV to GPX Converter v0.2

Converting 20150125074851.csv -> 20150125074851.gpx
Avg HR: 131
Max HR: 159
Trackpoints 2398

Note that the output file is the same as the input file, but with GPX extension. csv2tcx works in a similar fashion.

I think csv2gpx and csv2tcx should work with any other watches that work with GPS Master, as well. Runtastic’s watch looks identical to my Pyle, as well as several other models that I’ve seen. For instance, the New Balance NX990 also uses GPS Master, and looks identical. As I’ve stated in a previous article, the watch is built by Latitude Limited, and the OEM calls it the Nav Master II.

Update 2015-01-27: Argh! I just confirmed that the fancy new updated version of GPS Master bundled with the New Balance NX990, aka NB 900 GPS, now exports HRM data inside its GPX files! So I wasted my time writing the utilities above yesterday! It has some nice UI enhancements, as well. Highly recommended! You can read my detailed description: Pyle PSWGP405GK Software and Firmware Updates.

Downloads: csv2tcx and csv2gpx executables for Windows

Installing English Firmware on a FAST FWR171

I recently learned that the FAST FWR171-3G is a lower cost clone of the TP-Link TL-WR703N, the only difference being the case. While browsing AliExpress, I found what I thought was a great deal… the FAST FWR171 for only $16. After waiting over a month to receive it, I noticed that it doesn’t have a USB port. Sheesh! I’m such an idiot. Just like when I mistakenly ordered a TL-WR702N from Amazon, it turns out that the FAST FWR171 is a clone of the TL-WR702N, not the TL-WR703N. AAARRGGGH!!! The trailing -3G in the FWR171-3G model number denotes the TL-WR703N clone!! So, not only did I end up with a router that’s useless for hacking, because it doesn’t have a enough RAM to load OpenWrt, has no USB port, and the firmware is in Chinese! FWR171_2 Notice the lack of a USB port in the photo of the FWR171 above. That alone should have warned me that I was ordering the wrong model. The FWR171-3G is slightly larger, and has a USB port on the side. Not wanting to be left with a completely useless device, I started browsing around for an English version of the firmware. None exists, but I found one for the TL-WR702N. Unfortunately, the web admin interface of the FWR171 checks the firmware for the correct device, and it won’t allow you to load a firmware for th TL-WR702N. Luckily, an OpenWrt forum member named jvvh5897 figured out how fool the firmware loader into thinking that it’s loading the appropriate firmware for a different model. In this thread, he describes how to modify an English TL-WR702N firmware to run on the Chinese model. I took that information, and used it to modify the English TL-WR702N firmware to run on the FW171. To adapt the TL-WR702N firmware to be accepted by the FWR171, we need to change two fields: 1) the system identifier and 2) the MD5 checksum of the firmware. In the TL-WR702N English firmware that I downloaded, the bytes in the blue box are the system identifier, and the bytes in the red boxes are the 16-byte MD5 checksum. 702fw Note that the system ID contains 0702 for the TL-WR702N. I downloaded a firmware for the FWR171 and found that the system ID was 01 71 02 01. To update the MD5 sum, you must calculate the MD5 sum of the entire file, with the dummy MD5 sum CC 96 28 EE 8D FB 21 BB 3D EF 6C B5 9F 77 4C 7C inserted. Here is what the file looked like after I prepared it for calculating the MD5 sum: 151fwdummy Next, I calculated the MD5 sum of the English TL-WR702N firmware file modified as above, and it was 06 7e a9 aa 7d 1e 75 10 b0 09 84 19 f1 d9 93 2d, so I replaced the dummy MD5 sum with those bytes and saved the file. Amazingly, the FW171’s firmware upgrader accepted it! To skip the hassle of modifying the firmware yourself, you can download my pre-hacked English TL-WR702N for FW171 firmware file. Using google, I found several descriptions of how to load the new firmware file into the FW171, but they were all wrong, because mine had the newer firmware, which checks for the proper system ID. To get to the web interface, set the IP number of your host computer’s Ethernet adapter to Plug the FW171 into your host computer’s Ethernet port, and point a web browser to Below is the firmware page for mine, which happened to be the latest firmware posted on fwver-sm To load your English firmware, you must set up a TFTP server on your host machine. In Windows, you can use TFTPD32. If you don’t know how to use TFTPD32, I have a description in this article. Point your TFTP server to the directory containing your firmware file, and type the name of the file into the box containing fwr171v1-cn-up.bin below: fwupg-sm   Click the bottom left button in the dialog, and a progress bar will appear, indicating that the firmware is being loaded. Once it is done, the device will automatically reboot, and your host computer should see a new WiFi AP with SSID TP-LINK_xxxxxx, where xxxxxx are the last 6 digits of your FW171’s MAC address. This indicates that you have successfully loaded your English TP-WR702N firmware! Next, set your host computer’s Ethernet port to DHCP, and plug the FW171 into it. Your host computer will receive an IP number in the range of 192.168.0.X. Point your web browser to the TL-WR702N’s IP number, and log in with user admin, password admin. Downloads: English TL-WR702N firmware for FW171

How to Repair a Panasonic Massage Chair, Part 3

Unfortunately, my rubber hose hack from Part 2 worked only for a few weeks. The belt again stretched, and became loose:


One thing you can also see in the photo above is that I’ve slid the motor as far to the left as the adjusters allow (the slotted holes for the two brass screws). I couldn’t bend the motor mounts any more to tighten up the belt, so in addition to the rubber hose shim from Part 2, I wrapped 4 layers of electrical tape around each of the two pulleys:


Amazingly, this increased the diameter of the pulleys enough that the belt became taut. I have tested the chair for a few hours, and this fix seems to be working well. Let’s see how long this hack holds up…

Previous related article: How to Repair a Panasonic Massage Chair, Part 2

Quickie Hack: Turn Your Bicycle Into A Party Machine

I was looking for a way to play tunes while biking the other day, and was too lazy to get out the CAD program and design something to print on my RepRap. Here’s a dirt cheap & quick hack to get some decent quality sound while riding your bike. All you need is 4 zip ties:






The only tricky part is that I criss-crossed the ties that attach it to the bike.. that is, I took the end of one tie and inserted it into the other tie, instead of its own end. This added some stability, and prevents the speaker from getting damaged due to rubbing against the handlebars. Be sure to rotate the speaker to the proper orientation for you to access its controls before tightening it up.

The speaker I used is a cheap Chinese fake Beats by Dr Dre speaker. I bought it on AliExpres for $13.88 including shipping from China. It’s also known as the “S11 bluetooth speaker,” and is available on eBay, as well. It has a built-in lithium-ion battery, Bluetooth connectivity, including speakerphone (the microphone is crap, though), and even has pause and track skipping buttons. It also has a cable for connecting it via a headphone jack, and even sports a microSD slot, so you can use it completely standalone. Not only is it loud, but the sound is actually better than lots of speakers I’ve tried that cost a lot more. The black model has a rubberized casing, which helps avoid damage from rough handling. It also comes in a rainbow of colors, some with metal casing, instead.

Now, I just keep my iPhone in my pocket, and pause/skip tracks using the buttons on the speaker. The speaker doesn’t have a volume control, but I can easily reach in my pocket and hit the volume buttons w/o looking at it. I took it on a 50 mile bike ride the other day, and the speaker didn’t vibrate off.


OpenWrt: Cross-compiling libmicrohttpd for TL-WR703N

Recently, I’ve been developing embedded webapps using node.js. Unfortunately, node.js is a bit bloated for resource-constrained platforms, such as the TL-WR703N running OpenWrt. Not only is it too large to fit into flash memory, requiring an external USB drive to run EXTROOT, but I’ve even encountered circumstances where I’ve been running out of RAM. Thus, I’ve been looking for a lean & mean HTTP library written in C. Right now, my top two candidates are axTLS and libmicrohttpd. Since it’s impractical to host a toolchain on the TL-WR703N, we have to cross-compile everything, which can be a bit of a chore to set up. The first step is to download and unpack the source code:

% wget
% tar xzvf libmicrohttpd-0.9.38.tar.gz

If you don’t already have an OpenWrt toolchain set up, you can download and install it as follows:

% wget
% bzip2 -dc OpenWrt-Toolchain-ar71xx-for-mips_r2-gcc-4.6-linaro_uClibc- | tar xvf –

Next, we need a build script. Save the bash script below as

# compile libmicrohttpd for ar71xx (mipsbe)

export BASEDIR=$(pwd)

### begin configuration

# node src directory
export SRCDIR=libmicrohttpd-0.9.38

#adjust STAGING_DIR and TOOLDIR below based on location of your toolchain
export STAGING_DIR=${BASEDIR}/OpenWrt-Toolchain-ar71xx-for-mips_r2-gcc-4.6-linaro_uClibc-
#export STAGING_DIR=${BASEDIR}/openwrt/attitude_adjustment/staging_dir

export TOOLDIR=${STAGING_DIR}/toolchain-mips_r2_gcc-4.6-linaro_uClibc-

### end configuration

export TARGET_PATH=${BASEDIR}/${SRCDIR}-mipsbe
export PREFIX=${TOOLDIR}/bin/mips-openwrt-linux-
export LIBPATH=${TOOLDIR}/lib/
# MIPS cross-compile exports
export CC=${PREFIX}gcc
export CXX=${PREFIX}g++
export AR=${PREFIX}ar
export RANLIB=${PREFIX}ranlib
export LINK=${PREFIX}g++
export CPP="${PREFIX}gcc -E"
export STRIP=${PREFIX}strip
export OBJCOPY=${PREFIX}objcopy
export LD=${PREFIX}g++
export OBJDUMP=${PREFIX}objdump
export NM=${PREFIX}nm
export AS=${PREFIX}as
export PS1="[${PREFIX}] \w$ "
export LDFLAGS='-Wl,-rpath-link '${LIBPATH}
rm -rf ${TARGET_PATH}
mkdir ${TARGET_PATH}
cd ${SRCDIR}
make clean
make distclean
./configure --prefix=${TARGET_PATH} --host=mips-openwrt-linux-uclibc --without-snapshot --with-mips-float-abi=soft
make install

If your toolchain is in a different place from the STAGING_DIR specified in the script, adjust it to point to the proper location. Finally, execute the build script:

% sh

After the build is complete, you can test it out by transferring one of the example files to your TL-WR703N running OpenWrt. A good candidate would be src/examples/fileserver_example. In addition to the executable, you also need to get the shared library onto your OpenWrt machine. It is built into a strange location: src/examples/microhttpd/.libs/ Put the file in /usr/lib/ on your target machine. Finally, you should be able to execute fileserver_example on the target machine.