I recently bought a Proform 12.0TT treadmill from Costco. One of the major reasons I picked this particular treadmill was because it supports iFit Live, which is supposed to allow you to make custom workouts with google maps. Unfortunately, iFit Live has turned out to be complete garbage. My first frustrations started when I tried to connect my treadmill to my iFit account. I spent a couple of hours and got nowhere, because it kept complaining that it wasn’t able to contact the iFit server. I thought maybe it was that my WiFi wasn’t configured correctly, even though the treadmill was able to obtain a valid IP address. I tried submitting a support ticket, and was completely appalled by the horrible total lack of support. They didn’t even bother to respond to my ticket for more than a week, and by that time, I’d figured out that there server had gone down for a few days… one day, it finally just started talking to their server.
iFit Live, which is the only way to make custom workouts is quite expensive, and the treadmill doesn’t even come with so much as a free trial. It costs $9.99/mo or $99/yr. I was thinking of trying it out, but with their crappy support, I don’t want to give them my money. The worst part is that there’s this really cool iFit app that runs on iOS and Android that lets you visualize your workouts in realtime, but it only works on a handful of treadmills, and mine is not included on the list. Of course, they don’t tell you this, so I didn’t figure it out until I’d already bought the treadmill. Doing the workouts on the treadmill’s rather ugly and primitive display isn’t nearly as cool as via google Street View, or at least tracking it on a live google map.
The treadmill’s controller is garbage, too. It doesn’t let you customize the built-in workouts, and doesn’t even let you input things such as age/gender/weight, so the calorie calculations are completely worthless. I started thinking about hacking my own controller for the treadmill, but then decided to first see what could be done via software.
It turns out the treadmill has a built in telnetd, and if you telnet to its IP number, you can log in as root without using any password. ssh is also supported, but it requires the root password. Once you telnet in, it’s readily apparent that it’s running embedded Linux of some sort on an ARM processor. The treadmill control stuff is all in directory /icon/bin. Here is a list of the running processes:
PID Uid VSZ Stat Command
1 root 652 S init
2 root SWN [ksoftirqd/0]
3 root SW< [events/0]
4 root SW< [khelper]
5 root SW< [kthread]
16 root SW< [kblockd/0]
19 root SW< [khubd]
50 root SW [pdflush]
51 root SW [pdflush]
52 root SW [kswapd0]
53 root SW< [aio/0]
666 root SW [sdioeventd]
667 root SW [sdiod0]
669 root SW [mtdblockd]
709 root SW [nandeventd]
710 root SW [nandthread]
713 root SW< [scsi_eh_0]
739 root 3148 S /usr/bin/syslogd -S -b 10 -D -s 32 -O /tmp/logfile.tx
753 root 2292 S /usr/bin/dropbear
783 root SW [RtmpTimerTask]
784 root SW [RtmpMlmeTask]
785 root SW [RtmpCmdQTask]
786 root SW [RtmpWscTask]
792 root 3124 S /usr/bin/httpd -f -p 8080 -h /icon/bin/html
793 root 3020 S sslwrap -cert /usr/bin/sslwrap.cert -accept 443 -port
794 root 2880 S ./utwatch
795 root 652 S init
796 root 652 S init
798 root 652 S init
800 root 652 S init
810 root 2740 S utaudio
811 root 6476 S utcompete
812 root 2864 S utcontrol
813 root 2744 S utdevcom
814 root 2764 S utinput
815 root 2740 S utlog
816 root 6940 S utnetstatus
817 root 2200 S utuserlog
819 root 2740 S utvalues
820 root 2888 S utwifi
826 root 2872 S utwpl
827 root 2272 S utdisplay
828 root 2740 S utworkout
831 root 4640 R N web_serv
928 root 652 S udhcpc -i apcli0 -a -n -t 4
974 root 664 S telnetd
7348 root 764 S /bin/sh
26665 root 764 S /bin/sh
14635 root 656 R ps
14636 root 648 R sh -c iwconfig
From dmesg, I found that it’s running on a NuMicro NUC950 MCU running at 200MHz with 32MB RAM and 130MB of NAND flash. Here is the entire output of dmesg after bootup:
Linux version 18.104.22.168 (sbarton@sbarton-VirtualBox) (gcc version 4.2.1) #95 PREEMPT Thu Nov 21 10:08:23 MST 2013
CPU: ARM926EJ-Sid(wb)  revision 5 (ARMv5TEJ)
Memory policy: ECC disabled, Data cache writeback
On node 0 totalpages: 8192
DMA zone: 8192 pages, LIFO batch:1
CPU NUC950 (id 0x02900910 system clock:200MHZ)
CPU0: D VIVT write-back cache
CPU0: I cache: 8192 bytes, associativity 4, 32 byte lines, 64 sets
CPU0: D cache: 8192 bytes, associativity 4, 32 byte lines, 64 sets
Built 1 zonelists
Kernel command line: root=/dev/ram0 console=ttyS0,115200n8 initrd=0xa00000,4000000 mem=32M
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80×30
selected clock e4e1c0 quot 7
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 26440KB available (1676K code, 309K data, 80K init)
Calibrating delay loop… 99.73 BogoMIPS (lpj=498688)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
checking if image is initramfs…it isn’t (no cpio magic); looks like an initrd
Freeing initrd memory: 3906K
NET: Registered protocol family 16
* You selcet NUC950,Start Init NUC950EVB *
SCSI subsystem initialized
usbcore: registered new driver usbfs
usbcore: registered new driver hub
NET: Registered protocol family 2
IP route cache hash table entries: 256 (order: -2, 1024 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 1024 bind 512)
TCP reno registered
NetWinder Floating Point Emulator V0.97 (double precision)
io scheduler noop registered (default)
NUC900 uart driver has been initialized successfully!
nuc900-uart.0: nuc900_serial0 at MMIO 0xb8000000 (irq = 7) is a NUC900
nuc900-uart.1: nuc900_serial1 at MMIO 0xb8000100 (irq = 8) is a NUC900
nuc900-uart.2: nuc900_serial2 at MMIO 0xb8000200 (irq = 9) is a NUC900
RAMDISK driver initialized: 16 RAM disks of 8192K size 1024 blocksize
loop: loaded (max 8 devices)
Card0 Detect !!!
NUC900 SD driver has been initialized successfully!
CFI: Found no nuc900nor device at location zero
NUC900 USB host driver has been initialized successfully!
nuc900-ehci nuc900-ehci: Nuvoton nuc900 EHCI Host Controller
nuc900-ehci nuc900-ehci: new USB bus registered, assigned bus number 1
nuc900-ehci nuc900-ehci: irq 15, io mem 0xb0005000
nuc900-ehci nuc900-ehci: USB 2.0 started, EHCI 0.95, driver 10 Dec 2004
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
nuc900-ohci nuc900-ohci: Nuvoton nuc900 ohci Host Controller
nuc900-ohci nuc900-ohci: new USB bus registered, assigned bus number 2
nuc900-ohci nuc900-ohci: io mem 0xb0007000
usb usb2: configuration #1 chosen from 1 choice
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 2 ports detected
Initializing USB Mass Storage driver…
usb 1-2: new high speed USB device using nuc900-ehci and address 2
usb 1-2: configuration #1 chosen from 1 choice
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
ts: Compaq touchscreen protocol output
i2c /dev entries driver
nuc900-i2c-p0 nuc900-i2c-p0: bus frequency set to 100 KHz
nuc900-i2c-p0 nuc900-i2c-p0: i2c-0: nuc900 I2C port0 adapter
client [NAU882] registered with bus id 0-001a
NUC900 Audio driver has been initialized successfully!
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
RAMDISK: Compressed image found at block 0
VFS: Mounted root (romfs filesystem) readonly.
Freeing init memory: 80K
selected clock e4e1c0 quot 7
selected clock e4e1c0 quot 7
selected clock e4e1c0 quot 7
gnand: module license ‘Nuvoton’ taints kernel.
1. ===> write SMCSR
scsi0 : Nuvoton NUC900 GNAND DRIVER!
nand card init
1. ===> write SMCSR
card reset4. ===> write SMCSR
6. ===> write SMCSR
Valid P2LN 577, block 1022
There are a bunch of shell scripts in there to do various things. When the machine boots up, it runs go.sh, which in turn runs loadapp.sh, and then runapp.sh. This loads a bunch of utXXX processes, which are all ELF binaries, unfortunately, and run the core functions of the treadmill. download.sh downloads the latest scheduled workout in your iFit account into /icon/bin/iFit/download/wpl2. It uses http downloads from iFit’s server, machines.iconfitness.com. The server host name is stored in the IFIT_SERVER environment variable, so it’s quite easy to redirect it to download from a different server. I envision writing a local http server to emulate some of the iFit server’s functionality. It’s easy to follow what the script does by just typing bash -x download.sh in the shell. The server uses SOAP for its API, and downloads are handled via a binary called soap_get.
It turns out that the workouts are consist of 2 files: layout.fit, and a file with .wpl extension, which is the actual workout data. the name of the .wpl file is the first field in layout.fit. Unfortunately, wpl is a proprietary binary format, so it will take some effort to figure it out, but once that is done, it will be possible to create your own custom workouts without using ifit.com! The built-in workouts are all stored in /icon/bin/iFit/builtin/builtin.xx where xx is a number.
To get the files off of the machine for easy examination, all you have to do is launch the built-in ftpd command to get an anonymous ftp server. Even though it’s already configured in inetd.conf, the server won’t start unless you launch it manually on the command line:
Substitute your treadmill’s IP number where I have 192.168.1.111. I dumped out the whole /icon/bin directory for perusal. I used the Filezilla ftp client on MS Windows.
One final thing… download_firmware.sh checks for and downloads the latest firmware. The firmware updates are in the form of a .tgz file. You can take a look at the contents by looking at /icon/restore/app.tgz, which is a copy of the firmware that’s probably for recovering from a botched update..
That’s all for now. I’m surprised that iFit left the system so wide open. It’s possible that when they find out that people are hacking their systems that they will close the telnet backdoor, so if you want to play, it’s probably a good idea not to update your firmware.
If you play around with your iFit, please share your discoveries in the comments below.
Update 2016-04-04: Thanks to Stefano Livi’s uber hacking skillz, I’ve created a github repo: iFitWPL. Using information provided by Stefano, I wrote a C++ program to (mostly) decode WPL files. I have not yet had time to write code to create new WPL files, but there is a file where Stefano shows code in an obscure programming language to create a new WPL: Notes_on_wpl.txt. Please contribute to the github repo, and feel free to discuss any progress in the comments below.
The Scosche Rhythm+ is an optical BLE/ANT+ armband heart rate monitor that’s highly recommended by DC Rainmaker. There are many posts around the Internet which claim that it doesn’t have updateable firmware, but that’s not always the case. Prior to firmware V2.5, the Rhythm+ had to be sent back to Scosche for firmware updates, but if you’re lucky to have firmware 2.5+ installed, you can update the firmware yourself with your phone and Scosche’s Fitness Utility. The procedure is quick and easy. Pair the Rhythm+ to your phone and launch the Fitness Utility. You will be presented with the Attributes screen, which lists the current firmware version:
If you have Firmware Revision 2.5 or higher, tap the Commands button, and you’ll be presented with this screen:
Tap the Firmware Update Start button, and the utility will update you to the latest firmware. I got a nice new feature when I upgraded mine to firmware 2.26. Now, after setting my HR Zone Min and HR Zone Max via the Fitness Utility, the LED on the Rhythm+ blinks blue when my HR is below HR Zone Min, purple when I’m between HR Zone Min & Max, and red when I’m above HR Zone Max. I guess if you only use ANT+, and want to save some battery life, you can turn off the BLE Radio as well, but I haven’t tried playing with any of the other functions yet.
It infuriates me how so many WiFi routers are designed with inadequate cooling. I have a whole pile of routers that got flaky or crapped out after a few years due to overheating. The only ones that are still rock solid after years of continuous service are my WRT54Gs. My Linksys E4200 has been getting long in the tooth lately. On hot days, I need to blow a fan on it, and lately, even colder weather, it slows down to a crawl at random times and needs a reboot. I could try installing a big heatsink in it, but I thought maybe it was time for an upgrade to one of the fancier new technology routers. What most people don’t realize about the latest crop of router technology, such as AC3200, is that unless you upgrade your clients, you’re not going to get performance anywhere close to what these things can do. Most of the devices in my house are 2.4GHz 802.11n and can’t even handle MIMO, but smallnetbuilder had an article which showed that you can get a speed boost with 802.11n on a 802.11ac router. I figured I might as well future proof myself and look for a midrange AC router.
After lots of research on smallnetbuilder’s site, I settled on the Linksys WRT1900AC. This router, built by Belkin, is a nod to the venerable WRT54G, and is designed to be hacked with open source firmware. The specs are pretty good, even in the 2.4GHz band, which is often neglected these days, and I was particularly impressed with the speed of its NAS function, which vastly outperforms anything out there. It has a USB 3.0 port + a combo USB3.0/eSATA port on the back, and lightning fast storage performance. When I received it, I was impressed with the build quality. This thing is a beast! It looks like a WRT54G on steroids, and makes its predecessory look like a toy. Big & beefy and heavy. I specifically got the V1 because it has a built in cooling fan which kicks in only when necessary (which isn’t very frequent, due to its gigantic heatsinks). The later V2, also known as the WRT1200ACS, no longer has a fan. This is not going to be a full review of the WRT1900AC, but only a synopsis of my experiences trying to get decent 2.4GHz throughput out of it.
I really wanted to like the WRT1900AC. It is a thing of beauty, and I spent quite a few hours trying to tweak it, but to no avail. Despite the 90Mbps 2.4GHz LAN to WAN downlink throughput measured by smallnetbuilder, I was not able to get more than about 30Mbps downlink out of any of the devices in my house, even when sitting only a few feet from the WRT1900AC. This is only about half what I get out of my old E4200, which works as fast wirelessly as it does through Ethernet, maxing out at almost 60Mbps, which is the speed of my Time Warner cable service. No amount of tweaking over two days (about 6 hours of mucking with it) could speed up the 2.4GHz downlink performance. I scoured google for tweaks and even tried OpenWRT. I figured that I could figure out to get more speed out of it with OpenWRT’s tweakability, but it actually got slightly slower.
Although the speed with a very strong signal was only half as fast as my E4200, at the edges of my house, where the signal was weak, the WRT1900AC performed admirably, giving not only better throughput, but also being able to actually function at distances where the E4200 signal was completely dead. This left me in a dilemma, because the extended range is actually pretty useful to me. Also, for some reason, the storage performance came up quite short of what was tested by smallnetbuilder. I have a Seagate 2TB USB 3.0 drive, which is normally connected to a hacked Pogoplug E02 running Debian linux. The Pogoplug only supports USB 2.0, and doing a file copy across the network on Windows 8.1, I the maximum throughput I get is about 11MBps. Disappointingly, when attached directly to the USB 3.0 port on the WRT1900AC, the throughput topped out at a measly 4MBps. This was the last straw for me.
The 5GHz wireless performance on the other hand, was terrific. It easily saturated my 60Mbps downlink. But I can’t just switch to 5Ghz, because its range is too short in my house, and the signal drops out in some of my bedrooms. Also, not all of my devices support the 5GHz band. So, with a heavy heart, I decided to return the WRT1900AC. Just as I suspected, upgrading to the fancy 802.11ac router doesn’t necessarily help performance with 802.11n clients. In fact, looking at smallnetbuilder’s testing, lots of the latest and greatest routers put less emphasis on 2.4GHz performance, so if like me, you don’t have any 802.11ac clients, you should save your money and buy something cheaper. As for me, I’m going to try hacking a temperature-controlled fan into my old E4200, and see if that makes it more stable.
I recently discovered the PCD Mobility Rev Bluetooth HRM on Amazon.com, for the ridiculously low price of $7.95 including shipping (currently also available on eBay for $9.95). This is a Bluetooth 4.0 (Bluetooth Smart/Bluetooth Low Energy) HRM with strap, for half the price of a replacement strap for a Garmin or Polar HRM! Despite the 1 star reviews on Amazon, I figured that if the HRM was total trash, I would still have a decent spare HRM strap. It arrived a few days ago, and I put it through its paces on a couple of workouts. I wasn’t expecting much, given the bad reviews, and was pleasantly surprised to find that it’s actually a decent piece of hardware.
The receiver is a bit chunkier and clunky looking compared to my Garmin HRM:
Note how it uses industry standard metal snaps, spaced that the standard distance, so the receiver and strap are compatible with Garmin/Polar/Wahoo/etc.
The Mobility Rev uses a CR2032 battery (included). The battery door has a rubber o-ring to seal out moisture from your sweaty chest. I don’t know how water resistant it is, however, and am not going to try immersing it. Unlike the Garmin, which requires a small Philips screwdriver to replace the battery, the Mobility Rev’s battery cover easily comes off with a twist of a coin.
The Mobility Rev strap (bottom) is the same quality and of similar design to my Polar strap (top):
I use the Polar strap with my Garmin HRM, because the fancy strap that it came with has rather sharp and hard edges that chafe during a long workout.
So far, I have taken the Mobility Rev HRM out for a 1.5 hour bike ride and a 3.5 mi trail run, using the Wahoo Fitness app on an iPhone 6, and it has worked quite well. Here are the metrics I use for evaluating wireless heart rate monitors:
accuracy: Since this is a cheapo HRM, I’m not going to do detailed testing with graphs. At steady state, the heart rate reading is identical to that from my fingertip SpO2 meter. On my 1.5 hour bike ride, I didn’t bother to bring another HRM to compare against, but the heart rate readings looked consistent with my experience, and there were no dropouts or spikes, even when I was riding over very bumpy pavement. On my 3.5 mi trail run, I brought along my Garmin HRM, and did concurrent recordings. I was disappointed to find that during the first minute of recording, the Mobility Rev spiked up abnormally to 144 bpm before stabilizing at my true HR of 109 bpm. This phenomenon, however, is a regular occurrence with my optical HRM’s (Wahoo Rhythm+ and Garmin Forerunner 225 built-in). Since I was wearing two heart rate straps, making the sensor placement less than ideal, it’s possible that this glitch was due to poor contact with my chest. After this initial spike, it settled down, and had identical readings to the Garmin during the rest of the workout, deviating by 1 bpm on occasion, even when my heart rate was fluctuating, due to my switching back and forth between hiking and running. My Pyle strap often spikes up to unrealistically high HR’s when there is intense vibration from my running. The Mobility Rev displayed no such aberrant behavior. For the most part, I was impressed by the accuracy and consistency of its readings.
signal stability: During use, the signal was rock solid and never dropped out.
range: my iPhone 6 was able to reliably receive the signal 40 feet away from the HRM even while indoors.
overall fit and finish: The plastic casing seems of decent quality, and the strap is of comparable quality to the Polar HRM strap.
reliability: Since I have only had it for a day, I don’t yet know if it will crap out after just a few uses. I will update this article after more testing.
Using the free LightBlue Explorer iOS app, I found that it identifies itself as BLUETOOTH SMART HRM, and reports the following device information:
The manufacturer string is Maxwell Guider. It’s a nice touch that it seems to support reporting of battery status, but I don’t have any partially dead batteries to test with, so I don’t know if it actually outputs anything besides 100% [Update: see below, it always outputs 100% even with bad batteries].
One caveat of the Mobility Rev HRM is that it only outputs heart rate, so you can’t use it for HRV analysis, which requires R-R interval data. I tried to use it with the Elite HRV app on my iPhone, and it wasn’t able to read any HRV data. As a cross check, I took a look at the raw heart rate data output, and found that it indeed only reports 8-bit heart rate and nothing else. Most people, however, are only interested in heart rate, and won’t find this to be a problem.
I have only had the Mobility Rev BT HRM for a day, so I don’t yet know if it will stop working after only a short period of use. If there are any changes to its performance, I will update this article. Even if it does fail, I’ll still be happy to have an extra $8 Garmin/Polar/Wahoo/etc compatible strap.
Update 2015-11-24: After only 3 days of use, it died. I tried putting several new CR2032’s into it, and it was still dead. I was ready to write it off as a piece of junk until I finally found one that works. Now, it’s working perfectly again. I think the people who are reporting on Amazon that it connects inconsistently or fails after a couple of days are just suffering from weak cells. This device seems to need a higher voltage than others in order to function properly. The functional cell has an open circuit voltage of 3.25V, while another that reads 3.21V doesn’t work. This makes me question the manufacturer’s claim of 1800hrs battery life. Also, during this testing, I found that the Battery Level service is fake, and always outputs 100%. Some of the weak cells would actually operate it for a few seconds at at time before cutting out, and it still outputted a Battery Level of 100%.
Update 2015-12-03: I’ve used the Mobility Rev HRM for at least 8 hours of cycling and running workouts now, and the readings have been absolutely rock solid. No spiking up of HR during the start of a workout, no spiking up of HR during running, and no dropouts. The HR readings are totally glitch free. One problem I’ve had, however, is that sometimes, it’s a bit difficult to get the unit to wake up. I wetting the strap contacts usually helps. One time, I had it mounted upside down on the strap, and it woke up when I inverted it. I’m surprised that it seems to be sensitive to L/R, but unit is actually labeled for left & right sides on the back. In the meantime, the price dropped to $6 on Amazon, so I ordered a 2nd one to keep as a spare.
Banggood.com recently had a special on the Gopher TechnologyCPS-3205 bench power supply. After searching for reviews, which were generally favorable, I decided to get one for $42.99 including shipping. At this low price, I figured it was worthwhile if it worked at all. The unit is small, fanless, and appears well-constructed. What convinced me to try it was Voltlog’s exhaustive video review of the CPS-3205C, which is a more expensive version with active PFC:
I am not able to use the CPS-3205C, because it only works on 240V, unlike the CPS-3205, which is dual-voltage 120/240V.
Upon unboxing, my initial impression of the CPS-3205 was very good. The unit is quite compact, nicely built, and easy to use. One trivial but annoying defect, however, is that the front panel meters are mislabeled. The voltmeter (on the left) is labeled A and the ammeter (on the right) is labeled V:
I can’t imagine how such a glaring error could have happened. The photos on Gopher’s website, and most photos from various vendors have the meters labeled correctly:
I started to wonder whether Banggood was selling counterfeits, also because mine is labeled GOPHERT rather than GOPHER. However, my fears were laid to rest when I found this photo on Gopher’s own website:
There are definitely genuine devices out there labeled GOPHERT and with the V and A reversed.
One important attribute of the CPS-3205 is that it doesn’t suffer from voltage transients at power up and power down, which can fry an attached circuit, unlike another cheap power supply I was considering, the PS-305D. Here is a test of the PS-305D’s nasty startup transient: Quick test of the PS-305D PSU. Although Voltlog’s testing shows that the CPS-3205 doesn’t suffer from startup voltage transients, there’s even a second layer of protection. By default, the outputs are disabled when it’s powered up. The ammeter displays OFF, and you must press the ON/OFF button on the front panel to enable the output. This further assures that the power is already stable by the time it reaches your attached circuit. Note that the ON/OFF button only controls the output. The main power switch is on the back of the unit. If, for some reason, you prefer to have the output enabled a power on, you can toggle this feature by holding the ON/OFF button depressed for 5 sec. If the ammeter displays dOn, then the output is enabled at power on, and if it displays dOF, then it’s disabled at power on.
The CPS-3205 has over current, over voltage, and over temperature protection, so it’s pretty robust.
I am not going to go into detail on operation of the CPS-3205, because it’s easy to read in the manual, and Voltlog demos it in his video. Suffice to say that the adjustment knob is very handy, because every time you press it, it shifts to a different digit to adjust, making it very fast to do fine or coarse adjustments. The LOCK button locks the adjustment knob and ON/OFF button from changes, and a nice feature is that it’s persistent even if you power the unit off/on.
WARNING: One attribute that’s not clearly stated in the manual is that in constant voltage (CV) mode, the current set in the constant current (CC) mode is an upper limit for the current that can be output. So, for instance, when the voltage is set to 25.00V and the current is set to 100mA, no more than 100mA can be output, so the output voltage will drop if you attempt to draw >100mA. I found this out the hard way, because mine had the current set to 000mA when I received it, so the output was zero in CV mode. I thought the unit was defective, as shown in my video:
After I played around with it some more, I realized that I had to switch it to CC mode and turn up the current before it would output any voltage.
I tested the accuracy of the CPS-3205 against a TES 2208 DMM. This TES meter has been my workhorse for the past 35 years or so, and has never been recalibrated. It’s no Fluke, but in my testing against other meters it’s been pretty good. That being said, I haven’t tested its accuracy in well over 15 years.
Out of the box, I tested a few random voltages in CV mode, and they were spot on. However, the ammeter displayed 5mA even when no current was flowing. Before running the tests below, I calibrated the CPS-3205 against the TES 2208 DMM, following the procedure at the bottom of this article. In the tables below, the readings are all shown to their maximum resolution.
The performance in CV mode was quite impressive, tracking to within .1V, and well within its rated spec of <=0.3% + 10mV.
TES 2208 DMM
Generally, the voltage reacted to setting changes within a second, but when I dialed it down from 28.00V to 00.01V, it seemed like it took about a minute to ramp down and finally stabilize. Interestingly, at low voltages <=.10V, even though the panel meter displays on the high side, the actual output is actually quite a bit more accurate.
In CC mode, the performance was not as impressive, but within the rated spec of <=0.3%+20mA.
TES 2208 DMM
While CC mode’s accuracy isn’t very good it’s still within its rated spec. The .3%+20mA accuracy makes it basically useless at low currents, so don’t use it for tiny loads, such as 20mA LED’s. The lower currents is where the PS-305D is a better performer.
I didn’t bother testing output ripple, because the accuracy of my CPS-3205 was very similar to that of Voltlog’s CPS-3205C, so I’m going to assume that the output ripple is similar. Also, I am not going to post teardown photos, because Voltlog’s video already goes over the innards of the CPS-3205C in quite some detail.
I am impressed that such an inexpensive piece of Chinese equipment is of such high quality. The CPS-3205 is well mode, easy to use, and surprisingly, comes from the factory fairly well calibrated. The user interface is well thought out.
Being a switch mode supply, it is light, compact, and quiet. Even though it’s fanless, it runs cool at the currents I tested.
One quibble I have is that the binding posts are in the rear of the unit. I wish that they were on the front panel, so I wouldn’t have to reach behind it. Also, the binding posts are lacking a hole drilled into the bolt for easy insertion of wires, and I wish the standoffs were a bit higher, so that they stood a bit farther away from the case.
The CPS-3205 not accurate enough for lab use, but for general hobby use, the performance is pretty impressive, as long as you can live with .3%+20mA accuracy on current control. It’s a great buy for the price. Currently, it can be had for <$50USD if you search around. It’s too bad that the current control isn’t better <100mA. It would have been nice to have the functionality to be able to run it between 5-25mA.
For those who want to re-calibrate the unit, it is easy to do, and the procedure is listed below.
WARNING: ONCE YOU ENTER CALIBRATION MODE, YOU MUST COMPLETE THE ENTIRE PROCEDURE. IF CALIBRATION MODE IS ABORTED BEFORE COMPLETION, THE UNIT WILL ALWAYS DISPLAY ECP/ECP(OCP) AND BE NON-FUNCTIONAL UNTIL YOU COMPLETE A CALIBRATION CYCLE:
1. Set V/A switch to A
2. Power on while adjustment knob is pressed in. PUSH OFF will be displayed
3. Press ON/OFF once, then LOCK twice. Display will be 03.00/001.
4. Hook up voltmeter to outputs and adjust output voltage to 3.00V with adjustment knob. Pressing the adjustment knob will toggle the sensitivity – ammeter will alternate 001/010 (001 is fine adjust, 010 is coarse adjust).
5. Press ON/OFF and display will be 30.00/001. Adjust output voltage to 30.00V
6. Hook up ammeter across outputs (dummy load is optional… the resistance in the leads is sufficient). Press ON/OFF and display will be 0001/1.00. Adjust current to 1.00A.
7. Press ON/OFF and display will be 0001/5.00. Adjust current to 5.00A.
8. Press On/OFF and unit will return to normal operation, with OFF displayed and outputs disabled.
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:
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 stm32load.py 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:
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
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 stm32load.py 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 stm32loader.py:
C:\git\Arduino_STM32\tools\win>stm32loader.py -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
Traceback (most recent call last):
File “C:\git\Arduino_STM32\tools\win\stm32loader.py”, line 531, in
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 stm32loader.py, 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
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.
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.
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.
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. Many people use a precision 25.2V power supply and 100 ohm .1% resistors to do the calibration (see Joe Rouvier’s post for this method), 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. The temperature port is located on the left side of the unit, and consists of a 3-pin header:
[above image copyright the owner of: http://sysmagazine.com/posts/150213/. Note, the TX function does not apply to fake 80W iMax B6’s. AFAIK, it is only for temperature input on this clone]
I hooked up a 5K potentiometer, outer terminals across the +5V and GND on the temperature port, center terminal (wiper) to Vin, and adjusted it to 1.00V between Vin and GND. I think if you don’t plan to hook up a temperature sensor, you can skip this step. The voltage calibration seemed to work OK without hooking anything up to the temperature port.
Once you have everything hooked up, power up the charger while holding down the Stop and Start buttons:
(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.
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, v22.214.171.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.
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.