Interfacing a TFT_320QVT LCD/Touchscreen/SD to a Teensy 3.0

I’m working on a project which needs a touchscreen LCD. After searching eBay for a while, I noticed that many vendors were selling basically the same 3.2″ 320×240 TFT with resistive touchscreen and SD card reader. Though there were slight variations in the silkscreens, they all had the same model number – TFT_320QVT. I bought mine from digitalzone88 for $12.29. TK0466-1-digitalzone88 TK0466-4-digitalzone88 The board uses a SSD1289 LCD driver IC, and runs on 3.3V. The 3.3V voltage is incompatible with the typical Arduino, which runs at 5V (some vendors have created shields to interface it to an Arduino Mega). However, I purchased the TFT_320QVT with the intention of interfacing it to a Teensy 3.0, which runs at 3.3V. I noticed that there were not enough through-hole I/O pins on Teensy 3.0 to simultaneously interface to the LCD, touchscreen, and SD card. This necessitated the usage of the Teensy 3.0’s additional I/O pins, accessible only via solder pads on its underside: teensy3b To facilitate access to the 14 solder pads, I attached some header pins to piece of stripboard, and soldered 40AWG wire-wrap wire to between the pads and headers: extenderThe Teensy 3.0 runs on PJRC’s specially modified version of Arduino – Teensyduino. The task was to find compatible Arduino libraries. First order of business was the LCD. I searched the web, and found that dawnmist had spent a considerable effort in modifying Henning Karlson’s UTFT to work with the Teensy 3.0. Unbeknownst to me at the time, dawnmist’s modified UTFT is actually bundled with Teensyduino!

Next, was to get the touch screen working. It turns out that the current version of Henning Karlson’s UTouch is compatible with the Teensy 3.0.

For the SD slot, I tried the version of the Arduino SD library that’s bundled with Teensyduino. Unfortunately, though the SD library works with the TFT_320QVT’s SD reader, it stops working if you instantiate a UTFT object in the sketch. I tried sdfatlib, and found that not only does it work w/ the Teensy 3.0, but it coexists fine with UTFT. The only catch I found is that it works only with SPI_HALF_SPEED. When I set it to SPI_FULL_SPEED, it stops working.

Here is the Teensy 3.0 running UTFT‘s demo sketch on the TFT_320QVT: utft

Below is the step-by-step procedure to getting the TFT_320QVT up and running with Teensy 3.0:

Step 1: Install the libraries

1. UTFT: Run the Teensyduino installer, and when the Libraries to Install dialog is displayed, check the box next to UTFT in the Choose Additional Libraries to Install combobox. (Note: Henning Karlson’s latest UTFT also works with Teensy 3.0, but my discussion below will show how to interface to the UTFT that’s bundled with Teensyduino 1.18).

2. UTouch: Download UTouch.rar. Use WinRar or 7-zip to extract the enclosed UTouch folder. From the Arduino IDE pull-down menu, use Sketch->Import Library->Add Library… to install the extracted UTouch folder. Alternatively, you can just copy Utouch/ to your arduinosketchbook/libraries directory.

3. sdfatlib: Download the latest version of sdfatlib. From the Arduino IDE pull-down menu, use Sketch->Import Library->Add Library… to install the downloaded file. You can alternatively just extract the SdFat/ folder into your arduinosketchbook/libraries directory.

Step 2: Wire it up

1. LCD: dawnmist‘s modified UTFT library that’s bundled with Teensyduino has a configuration file: arduinofolder\libraries\UTFT\hardware\arm\HW_Teensy3.h. Inside HW_Teensy3.h, there are 3 options for the LCD pin assignments: USE_B_D_PORTS, USE_C_D_PORTS, and USE_USER_PORTS. By default, the file has


enabled. USE_B_D_PORTS gives the best performance when your sketch needs to use SPI (which is needed for the SD card slot). USE_C_D_PORTS gives the fastest performance, but is incompatible with SPI. USE_USER_PORTS allows you to configure arbitrary pins (by changing the DB_0-DB_16 #defines), but results in the slowest performance. I elected to use the default USE_B_D_PORTS setting.

2. SD card reader: The SD card reader works via SPI, so it needs to use SD_DIN->DIN (MOSI – 11), SD_DO->DOUT (MISO – 12), SD_CLK->SCK (13), and one of the chip select pins, CS0-CS4 (10,9,20,21, or 15). I chose to use SD_CS->CS4 (15).

3. Touchscreen: The touchscreen uses 5 pins, T_DIN/T_DO,T_CS/T_CLK/T_IRQ, which can be assigned to any arbitrary free GPIO pins.

Below is a chart of my pin assignments:

Teensy_pin = TFT_320QVT_pin
0 = LCD_DB4
1 = LCD_DB5
2 = LCD_DB8
3 = LCD_LED_A (backlight)
5 = LCD_DB15
6 = LCD_DB12
7 = LCD_DB10
8 = LCD_DB11
11 = SD_DIN (MOSI)
12 = SD_DO (MISO)
13 = SD_CLK (SCK)
14 = LCD_DB9
15 = SD_CS
16 = LCD_DB0
17 = LCD_DB1
18 = LCD_DB3
19 = LCD_DB2
20 = LCD_DB13
21 = LCD_DB14
22 = LCD_WR
23 = LCD_RS
24 = T_CLK
25 = LCD_DB7
26 = T_CS
27 = T_DIN
28 = T_DO
29 = T_IRQ
32 = LCD_DB6

LCD_RD needs to be pulled up to 3.3v

I have created a sketch, UTFT_UTouch_SdFat_teensy3, that simultaneously demonstrates the LCD, touchscreen, and SD card by modifying the UTouch demo sketch. Below are the lines which are critical to configuring it to work with the above pin connections:
[code language=”c”]
#include <UTFT.h>
#include <UTouch.h>
#include <SdFat.h>

// bitmap file to load as background.
// must be 320×240 and in format output by ImageConverter565
char bkgRaw[] = "ade.raw";

uint8_t sdCS = 15; // SD_CS – chip select
SdFat sd;
SdFile inFile;

uint8_t lcdRS = 23;
uint8_t lcdWR = 22;
uint8_t lcdCS = 4;
uint8_t lcdReset = 9;
uint8_t lcdBacklight = 3; // must be a PWM pin for variable brightness
uint8_t lcdBacklightBrightness = 255; // 0-255
UTFT myGLCD(SSD1289, lcdRS, lcdWR, lcdCS, lcdReset);

// Initialize touchscreen
uint8_t t_Clk = 24;
uint8_t t_CS = 26;
uint8_t t_DIn = 27;
uint8_t t_DOut = 28;
uint8_t t_IRQ = 29;
UTouch myTouch(t_Clk, t_CS, t_DIn, t_DOut, t_IRQ);

The file displays a bitmap, ade.raw, as the background. Before running the sketch, copy ade.raw to a FAT-formatted SD card, and insert it into the TFT_320QVT’s SD card slot.

You can also substitute your own bitmap file. To create a .raw file, first create a 240×320 pixel jpg, png, or GIF file. Run it through either imageconverter565.exe (bundled with UTFT) or the online ImageConverter 565 make sure to select Convert to .raw file and Target Platform Arduino (AVR).

Here’s what UTFT_UTouch_SdFat_teensy3 looks like when it’s running:

Many thanks to dawnmist, and the others who figured out how to get UTFT working with the Teensy 3.0.


I obtained much of the information I needed from these pages:
dawnmist – screen working … finally
Teensy 3.0 – driving an SSD1289 with utft

ITEAD Studio IBOX Part 2: Booting up Debian Linux 7.0

My IBOX came shipped with Android TV A20 pre-loaded in the NAND flash. I plugged a Microsoft keyboard and mouse into the USB ports, and used my Panasonic plasma TV as a HDMI display.  The boot screen is a bit confusing, because it implies that the device has WLAN support:


You can ignore the big WLAN banner on the screen, because the IBOX only has a RJ-11 100BT Ethernet port. The main screen has typical media center functions. Applications takes you into an Android launcher screen, Settings takes you to a typical Android settings screen. Going to the Applications screen shows that it has some typical apps pre-installed:


Most notable is the Google Play store support. I tried logging into Google Play and installing a few apps. They worked fine. However, I’ve heard that YMMV … some apps don’t work properly. Adobe Flash is also pre-installed, which is a plus. I did not play with it much, beyond some cursory tests, because I am more interested in running Debian Linux on the IBOX. ITEAD has a Debian 7.0 image, which runs off an SD card. Instead of downloading the version from ITEAD’s OS page, I used an alpha version built on 2014-03-27 which ITEAD sent me. To install it, first extract the  iteados-A20-debian-xfce-2.0-alpha-2014-03-27.img file from the downloaded.bz2 archive. I used WinRAR on my Windows machine to extract it. The image file needs to be copied to a 4GB or bigger micro SD card. Note that the .img file cannot be copied to a FAT-formatted SD card, because it contains an entire Linux filesystem. Instead, it must be raw-copied using a utility. In Windows, Win32 Disk Imager is a free utility that fits the bill:


Simply select the image file and the SD card’s drive letter, and then click the Write button. After the image is successfully written, insert the microSD card into the IBOX, and power it up. If all goes well, you will first see two Linux Penguins in the upper left corner of the screen. After a while, the login screen should appear:


Log in with user: root, password: root. While Android TV A20 was incompatible with my Dell LCD monitor (all I got was a blank screen), Debian 7.0 is working great. Unfortunately, I’m having the same problem with both my Dell LCD and my Panasonic plasma: when the screen blanks out after inactivity, I am not able to wake it up again. Therefore, I have to reboot it after every time the screen blanks. Hopefully, ITEAD will be able to tell me how to fix this.

Previous Article: ITEAD Studio IBOX – Part 1: First Look
Next Article: ITEAD Studio IBOX – Part 3: Installing Java and Processing

ITEAD Studio IBOX – Part 1: First Look

ITEAD Studio recently contacted me to let me know that they’re going to display my Lampduino project at the Shenzhen Makerfaire. I thought that was a pretty cool idea, and am honored to hear that. They also asked if I wanted to test out their IBOX mini multifunction single board computer, which is currently in its final days of its campaign on Indiegogo, having already raised over 4.5x its funding goal. The IBOX is designed with hackers in mind, and is driven by an Allwinner A20 ARM Cortex-A7 processor. Here are the salient hardware specs:

  • CPU Dual-core ARM Cortex-A7
  • GPU Mali 400 MP
  • DDR3 RAM 1GByte
  • 4x USB
  • 1x HDMI
  • 1x optical S/PDIF
  • 1x 100BT Ethernet
  • 1x 7-24V DC power jack

ITEAD touts the IBOX as a very open hackers platform, capable of running a plethora of OS’s.  Currently, the following distros are available for booting from its onboard NAND flash:

  • Android TV A20 (from ITEAD)
  • Android 4.2 (from Cubietech)
  • Lubuntu (from Cubietech)

The following distros must be booted from the microSD:

  • Android SD bootable image (from LinkSprite)
  • Debian 7.0 (from ITEAD)
  • Cubian (from Liu)
  • Arch Linux (from

The IBOX comes in an anodized aluminum case that has a glossy plexiglas top:


Being a pre-production sample, I’ll excuse the fact that the top had a lot of superficial scratches on it, but I wonder if a matte surface would be better, since it scratches so easily. The left side of the unit contains a plethora of connectivity:


The small rectangle on the left labeled Uboot is a switch for entering the U-Boot bootloader. The right side contains a micro SD slot:


Behind the rectangular window is a 2-color status LED and an IR receiver for talking to remote controls. The back panel contains a 32-pin expansion interface connector:


The expansion connector is what really separates the IBOX from the typical ARM mini PC. It opens up the platform for hardware hackers, containing pins for UART, TWI, SPI, SATA, etc.  You can find the full pinouts on the Indiegogo page. The bottom of the IBOX is held on with 4 Philips screws:


A set of rubber feet would be a nice addition.  Removing the metal bottom cover reveals the bottom of the baseboard:


The baseboard is a very tight fit into the case.  In order to remove it, you must first pry the it away far enough to clear the various ports from their cutouts in left side of the case, and then pry upwards from the front.  The baseboard is a modular backplane which contains all of the I/O connectors, as well as the socketed core board:


The core board is essentially the “brain” of the IBOX, containing the A20 processor, RAM, etc. Since the core board is socketed, it can be swapped out as newer, more powerful ones become available (e.g. A31, etc).  Here is a close-up of the A20 core board:


Note that there are two pushbuttons, SW1 and SW2. I’m not sure of their purpose, but they are not accessible when the IBOX is assembled. The plexiglas top was attached to my IBOX with some rather messy clear silicone caulk:


Again, I’ll excuse the mess because it’s a pre-production sample. I hope that the production units will have cleaner assembly.

So far, the IBOX looks like an interesting platform for building an energy efficient media center, file server, http server, etc. I’m looking forward to powering it up and putting it through its paces. Perhaps I will use it to replace my Raspberry PI that’s currently running XBMC. In my next article, I will boot up the IBOX, and test it out.


Indiegogo campaign – the most information can currently be found on this page.
ITEAD blog – contains various informative posts on the IBOX
A20 core board schematic
IBOX baseboard schematic
IBOX baseboard design files
Case dimensions
distro downloads

Noritake 24×6 Character VFD Module

I’ve always thought VFDs were pretty cool. They used to be the rage in high end consumer electronics. Back in the mid 70’s, I built a VFD alarm clock. Recently, I got my hands on a modern VFD module to play with. The Noritake-itron SCK-Y100-24063-N14 is a very flexible 24×6 character VFD module in the same form factor of a 20×4 character LCD module. It is a member of Noritake’s CU-Y series VFDs.



  • 5V supply voltage
  • serial (asynchronous and synchronous) and 8-bit parallel communication
  • CMOS signal and RS-232 (+-15V) voltage compatible
  • jumper-selectable baud rate: 9600, 19200, 38400(default), 115200.
  • extensive built-in character sets: USA, European, Japanese (Katakana only), Multilingual – various fonts and symbols, Canadian and French, Nordic, WPC1252 – european fonts and symbols, Cyrillic, Latin, Portuguese, PC858 – european fonts and symbols
  • adjustable brightness
  • locally selectable brightness for highlighting (useful for implementing menus)
  • double width, and double width & height characters

The video below compares the Noritake 26×6 VFD to a 20×4 LCD. The characters are noticeably smaller on the VFD due to the higher density, but still quite readable.

This page shows some of the versatility of the Noritake VFD: Versatile Character Display CU-Y Series

The VFD comes pre-configured to operate in async serial mode at 38400 baud. It isn’t necessary to use a UART to talk to the VFD; any GPIO pins will suffice. A minimum of 2 pins are needed, for SIN (input) and SBUSY (output). A third GPIO pin can be connected to RESET (input). I hooked mine up to an Arduino UNO as follows:

D2 -> SIN

Here’s what it looks like from the front, running Noritake’s Arduino menu demo:


The lower contrast on the left side of the photo is due to my camera’s reflection – the glass is very reflective. Note the highlighting via localized variations in brightness. Here’s what it looks like with a blue filter on top (again, apologies for the reflections – it actually looks a lot better than this photo):


Though my photos are crap, the display is quite easy to read indoors. I wouldn’t recommend it for outdoor use, however, or anywhere that you expect direct sunlight.

Back view:


The 10-pin  jumper block on the top center is used for configuration, and the 14-pin jumper block on the bottom right is used only for parallel mode.

The writing speed of this VFD is very fast. Running in async serial mode on an Arduino UNO at 38400 baud, I was able to output 120 characters in a mere 38ms, which is about 3x faster than LiquidTWI2 can muster, even after the I2C bus is tweaked (and over 100x faster than LiquidTWI2 w/o I2C bus frequency tweaking). Unfortunately, Noritake’s Arduino library doesn’t compile on a Teensy 3.x, because it contains AVR assembly code in a timing function, and calls _delay_us(), which isn’t implemented on the Teensy 3.x. On the other hand, it should not be hard to replace these two functions. To use the Noritake VFD with Arduino, first download the Arduino code library. From the Arduino IDE’s pull-down menu, use Sketch->Import Library…->Add Library... to import Include the following headers into your sketch:

[code language=”c”]
#include <CUY_Interface.h>
#include <CUY_Serial_Async.h>
#include <Noritake_VFD_CUY.h>

Two classes need to be instantiated:

[code language=”c”]
CUY_Serial_Async interface(38400,2, 3, 4); // SIN,BUSY,RESET
Noritake_VFD_CUY vfd;

Here is what initialization looks like:

[code language=”c”]
void setup() {
delay(500); // wait for device to power up
vfd.begin(24, 4); // 24×4 character module
vfd.interface(interface); // select which interface to use
vfd.CUY_init(); // initialize the module

Note that Noritake chose to implement only partial compatibility with the LiquidCrystal library.  So while vfd.print(s) is supported, vfd.setCursor(x,y) is not; one has to instead call vfd.CUY_setCursor(x,y). The Noritake_VFD_CUY class methods are declared in Noritake_VFD_CUY.h. Noritake includes a few sample sketches, which you can access from Arduino’s menu via File->Examples->CUY.

Noritake also provides a handy host program, which lets you configure and test the display without a microcontroller.


To use the program, connect the VFD to a PC running Microsoft Windows via a Serial->USB adapter, such as an FTDI cable. Using the Serial->USB adapter opens up the possibility of using the VFD  as a USB auxilliary display for a PC.

The Noritake SCK-Y100-24063-N14 is a very cool device, and I’m looking forward to building a project with it.

Resource Links

SCK-Y100-24063-N14 Overview 
CU-Y: Y-Series Evaluation Software
Code Library
Arduino Library with examples
Sample C++ code and configuration/hookup
How to use custom fonts
How to use the built-in font tables
How to use the font magnification command
How to create a menu using the highlight effect

TL-WR703N: Adding Storage Space – EXTROOT

Once you have your TL-WR703N running OpenWrt, you’ll find that it doesn’t have a lot of free space for adding your own files. Here is the output from df from after installing attitude-adjustment:

root@OpenWrt:/# df -h
Filesystem Size Used Available Use% Mounted on
rootfs 1.1M 352.0K 736.0K 32% /
/dev/root 2.0M 2.0M 0 100% /rom
tmpfs 14.3M 56.0K 14.2M 0% /tmp
tmpfs 512.0K 0 512.0K 0% /dev
/dev/mtdblock3 1.1M 352.0K 736.0K 32% /overlay
overlayfs:/overlay 1.1M 352.0K 736.0K 32% /

Note how rootfs has only 736KB free.  Luckily, there’s an easy way to put your rootfs onto external storage (extroot), which lets you easily expand your root file system onto a USB flash drive. In the instructions below, I will illustrate how to implement the pivot overlay flavor of extroot.

First, format your USB flash drive with an ext4 filesystem. I used an old 512MB Crucial USB drive. If you are using Windows, MiniTool Partition Wizard Home Edition can easily create an ext4 filesystem on your USB flash drive.

Before you can mount the USB flash drive on your TL-WR703N, certain packages need to be installed.  ssh into your TL-WR703N, and issue the following commands:

opkg update
opkg install block-mount kmod-fs-ext4 kmod-usb-storage

After OpenWrt reboots, access it via LuCI in your web browser, and navigate to the System->Mount Points tab. You should see a disabled mount point for /dev/sda1 as below:


Click the Edit button and then check Enable this mount and Use as root filesystem:


Click Save & Apply, and then reboot OpenWrt.

If you don’t have LuCI installed, you can alternatively directly edit /etc/config/fstab. Add the following lines to the file:

config mount
  option device /dev/sda1
  option fstype ext4
  option is_rootfs 1
  option enabled_fsck 0
  option enabled 1

After your system reboots, if all is well, your USB drive will become your root file system:

root@OpenWrt:/# df -h
Filesystem Size Used Available Use% Mounted on
rootfs 462.3M 2.3M 435.4M 1% /
/dev/root 2.0M 2.0M 0 100% /rom
tmpfs 14.3M 48.0K 14.2M 0% /tmp
tmpfs 512.0K 0 512.0K 0% /dev
/dev/sda1 462.3M 2.3M 435.4M 1% /overlay
overlayfs:/overlay 462.3M 2.3M 435.4M 1% /

Note how rootfs/overlayfs now have 435.4MB free. From LuCI, it looks like this:



Related Articles: TL-WR703N

Hacking the TP-Link TL-WR703N – Part 2: Bring it back from the dead (How to unbrick it)

This morning, I realized that I actually had a 3.3V UART in my house that I could use to connect to my bricked TL-WR703N‘s serial port .. the Raspberry Pi runs on 3.3v! I dug up the instructions on how to hook it up on the OpenWrt forum. After hooking it up, configuring it, and firing up PuTTY, I found via the serial terminal output that OpenWrt was booting up just fine, but that the ethernet port was disabled. The problem is that mine has the newer bootloader which disables the LAN port:

U-Boot 1.1.4 (Mar 21 2013 – 10:09:10)

In my haste to flash it with OpenWrt, I missed the Gotchas in the OpenWrt wiki.  It turns out that my version of the TL-WR703N boots up with the ethernet port disabled, and the version of OpenWrt that I installed did not enable it. Fortunately, nebbia88 posted a special firmware which enables both the LAN port and WiFi by default, which I downloaded from dropbox (20170927: link is dead. download it here). The next step was to figure out how to get it loaded into my TL-WR703N. Unfortunately, the Raspberry Pi serial port was too flaky. It was printing out gibberish.

Method #1: Failsafe Mode

This is the easiest way to unbrick a TL-WR703N, because it doesn’t require any soldering, or even opening up the case. YOU DON’T NEED TO ACCESS THE TL-WR703N’s SERIAL PORT.  However, it will only work if your TL-WR703N will actually go into failsafe mode.

To get it into failsafe mode, power up the unit. The blue LED will flash once, and then go off for a few seconds. As soon as the LED turns on again, press the reset button. The LED should begin flashing very quickly, indicating that you are in failsafe mode. OpenWrt will always enable the ethernet port, and set its IP number to when in failsafe mode. Next, set your host computer’s ethernet IP number to, and connect a CAT-5 cable between the TL-WR703N and the computer.  Instructions for this how to do this in Windows are below.

Step 1: open the Ethernet adapter’s property sheet:


Step 2: double click on Internet Protocol Version 4:


Step 3: Set your IP address to and click OK:


Step 4: Telnet to your TL-WR703N, in Windows, you can use PuTTY:

Step 5: After PuTTY connects, and you hit the enter key, you should be presented with the OpenWrt console:

If you cannot telnet into the TL-WR703N and get a console as shown above, then you will have to proceed to Method #2.

Before we can flash our new firmware file, openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-sysupgrade.bin, we need to transfer it to the TL-WR703N.  One way to do it is to use nc, which is documented here, but I found it easier to use wget, which is also available in failsafe mode. First, we need to set up an http server on the host computer to send the file to OpenWrt.  onehttpd is a handy minimalist web server which can handle the task.  In Windows, simply drag and drop the folder containing your firmware file on top of onehttp-0.8.exe to launch the web server.

Step 6: Get the file into the TL-WR703N from the OpenWrt failsafe console, and the flash it in:

root@(none):/# cd /tmp
root@(none):/tmp# wget
root@(none):/tmp# sysupgrade openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-sysupgrade.bin
root@(none):/tmp# reboot

After the unit reboots, you should be able to ping it at via the ethernet port.

Method #2: Bootloader Mode:

If you are not able to successfully enter OpenWrt failsafe mode, the bootloader is the only way to load the firmware. After hacking your TL-WR703N serial port, Connect your 3.3V UART->USB adapter to your host computer and connect to its virtual serial port using communication parameters: 115200,N,8,1. Open up your terminal program to connect to the virtual serial port. I used PuTTY:


Power up the TL-WR703N, and type “tpl” (without the quotes) and then the enter key immediately after Autobooting in 1 seconds appears. If you do it correctly, you will get the hornet> prompt:


The timing is a bit tricky. If you fail, just power cycle the TL-WR703N and try again. You don’t need to reset your serial terminal between tries. The bootloader only supports tftp to receive the new firmware file. In Windows, tftp32 is a free server which works well. Download either the 32-bit or 64-bit version according to your version of Windows. Launch tftp32.exe (or tftp64.exe), set the Current Directory to the folder where your firmware file resides, and the Server interfaces to your ethernet adapter:


From the hornet prompt in the serial console, issue the following commands:

hornet> setenv serverip
hornet> tftpboot 0x81000000 openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-sysupgrade.bin
hornet> erase 0x9f020000 +0x3c0000
hornet> cp.b 0x81000000 0x9f020000 0x3c0000
hornet> bootm 9f020000

After it’s done running the commands, wait a few seconds, and power cycle the unit. After it reboots, you should be able to access the unit via its ethernet port.

Previous: Hacking the TP-Link TL-WR703N – Part 1: Brick it and then hack its serial port

Hacking the TP-Link TL-WR703N – Part 1: Brick it and then hack its serial port

I’m working on an embedded project that needs to be able to run node.js over WiFi. There aren’t too many cheap boards that can run linux. The $25 Raspberry Pi and the discontinued Pogoplug V2, which can be had for about $15 immediately came to mind. However, each of these boards had their shortcomings.  The Pogoplug is discontinued, so it may not be available in the future, and also, the PCB is rather big.  Neither of them has  built-in storage, and while both of them can take cheap <$10 USB WiFi adapters, the usable range is rather short.  Adding a power supply and a better USB WiFi adapter can easily drive the cost up by another $25. I recently discovered that the Arduino Yun, which has built-in WiFi, embeds an AR9331 processor.  The Arduino Yun is much too expensive, so I wondered if AR9331‘s could be bought separately. It turns out the answer is no, but then I discovered the vary hackable TP-Link TL-WR703N. A lot of hardware hackers are loading OpenWrt into this cute little WiFi router, and taking advantage of the many precompiled packages that are available. While node.js isn’t currently officially supported, I found that Giorgio Cefaro had gotten node.js running on an Arduino Yun. The Yun runs linio, which is based on OpenWrt, and since it uses the AR9331, I’m hoping that I can use his precompiled packages on my TL-WR703N.

I put “TL-WR703N” in to, and found it for $19.99 – what a steal, I thought. When it arrived, I found out that I’d ordered a TL-WR702N by mistake (grr.. Amazon for returning the wrong model in my search), which uses the same processor, but has much too little flash memory to load OpenWrt, and doesn’t have a USB port. Oh well, it works very well as a low-power WiFi client. I took it out to my garage, which is very far away from my AP, and was amazed that it worked as well as my Linksys WRT54G, which has dual external antennas! Furthermore, the TL-WR702N is has very flexible firmware, which allows it to act as a portable AP, repeater, etc. A great little device to carry around on trips. But I digress …

I ended up buying a TL-WR703N on eBay for $23. It came with Chinese firmware, but I was able to load OpenWrt following the instructions on the wiki page.  Much to my chagrin, after rebooting into OpenWrt, I was not able to ping or connect to it. The unit is now bricked. The only way to bring it back from the dead is to load new firmware via a serial connection.  [UPDATE: I found a way to unbrick it without any hardware hacking, if it is able to go into OpenWrt failsafe mode. See Method #1] Luckily, the TL-WR703N has a built-in UART for this purpose, but the PCB only has tiny pads for connecting to it. There are lots of instructions on other sites describing how to do this, but I’ll document my experiences here. Here’s what the case looks like with the top lid removed:


It’s held on by 3 clips. I first tried to use a guitar pick, and several plastic tools to open it up without marring the surface, but the case was just too tight. Finally, I wedged a small screwdriver in the location pictured below:


Once the first clip popped loose, I was able to just carefully pry the lid up and off from that edge, popping the other two clips open in the process. To hook up the UART, 3 pins are needed: Tx, Rx, and GND. Most writeups say to solder onto the round gold pads labeled TP IN  (Rx) and TP OUT (Tx). However, from Squonk’s reverse engineering of the PCB, I noticed that C57 connects between TP_IN and GND, and C55 connects between TP_OUT and GND:


It turns out that C57 and C55 are unpopulated on the board. I decided that it would be easier to solder to the pre-tinned pads instead of trying to scrape the solder mask off of the round pads:


It turns out that I was wrong. I managed to solder my 40AWG wire-wrap wire onto one of C55‘s pads, but the rest of them were too tricky due to their small size. So I scraped off the solder mask on TP IN, and soldered there, and I found a relatively large capacitor, C37 to use for my GND connection:


TIP: Modern machine-assembled PCB’s are typically coated with a solder mask, which is an insulator. Before attempting to solder to one of the copper pads, scrape off the solder mask where you want the solder to stick with an x-acto knife, exposing the bright copper below.  Try not to scrape off the solder mask in adjacent areas, to reduce the chance of creating solder bridges (shorts).

Next, I applied a liberal amount of hot melt glue to secure the connections:


To connect the UART to a PC, the easiest way is to use a USB to 3.3V UART adapter. Unfortunately, the only one I have is 5V, which would fry the AR9331. I ordered this CP2102-based one which I found on eBay:

CP2102_0Connecting the USB UART adapter to the TL-WR703N is easy:


To access the serial console from your PC, you must first install the appropriate drivers for your USB UART adapter. Then, use a serial terminal client program (I like to use PuTTY), and connect to the virtual serial port with parameters: 115200,N,8,1.

To be continued after I receive my USB -> TTL adapter …

Next: Hacking the TP-Link TL-WR703N – Part 2: Bring it back from the dead

LeafCAN v2 Firmware in Alpha Test

I have been working on v2 of the LeafCAN firmware, which adds a whole slew of new screens, selectable via a rotary encoder.  The rotary encoder is connected to the AD0/1/2 pins on the expansion header of the LeafCAN V2 hardware.  The code is currently in alpha testing, and is available in the development branch of the LeafCAN github repository.  Be aware that the development branch is for my bleeding edge code, and at any time, the code there may be broken, as I continually checkpoint my code.  I will move it to the master branch when it’s ready to be released.

While I was developing the LeafCAN v2 firmware, I received a pleasant surprise in the mail from Barbouri (GregC) of the MyNissanLeaf forum.  He designed a PCB with 16×2 OLED display + RGB Led Rotary Encoder support,


and sent me a completely assembled and tested rig.  I immediately added support for this new hardware variant into my working LeafCAN v2 firmware code.  The RGB knob is cool:


but I am still pondering how best to use it. Currently, I have it blue when the car is idle, red when it’s consuming power, and green during regen.
Below is an overview of LeafCAN v2Alpha3. The various screens are selected by rotating the encoder knob. Some of the screens have different modes, selected via a press of the encoder knob. The first screen is the familiar info screen from LeafCAN v1.3:


The top line from left to right is: kWh remaining/gids/fixed fuel bars, and the bottom line is: pack voltage/SOC%/instantaneous kW. The next screen is an idea lifted from Turbo3’s WattsLeft, the DTE (distance to event) screen:


The top line shows various miles/kWh values, 2.0/3.0/4.0/5.0/6.0, and bottom line shows the distance in miles to the event, in this case, Low Battery.  Pressing the encoder button switches it to miles until Very Low Battery:


and pressing the button a third time shows miles until Turtle:


Thanks to a breakthrough in active can sampling, spearheaded by GregH and TickTock, I was able to implement the following new screens. The first one has on the top line, High Precision State of Charge (SOC)%.  The bottom line shows State of Charge (Ah), and possibly a Battery Health %.


The next screen shows the 4 battery pack temperature sensors:


The units are selectable between Celcius and Fahrenheit with a press of the button. Finally, the last screen shows the minimum and maximum cell-pair voltages in mV, as well as their difference:


When an OLED is installed, the display now blanks after 5 sec of inactivity on the CAN bus. Pressing and holding the knob for a second wakes the display up for 5 sec.  When an LCD is installed, the press/hold turns on the backlight for 5 sec, instead.

I will be working towards finishing LeafCAN v2.0 in the coming weeks, and will announce its release here.

Barbouri and I are also collaborating on a dual-CAN bus version of the LeafCAN hardware, which will be able to monitor the Car-CAN as well as the EV-CAN on the Nissan Leaf. This will open up access to various information which is accessible only via the Car-CAN, such as friction brake actuation, steering angle, etc.

I would also like to point out that GregH has yet another cool Leaf CAN bus dash display in the works (only $80) that is worth checking out. Also, TickTock and garygid are working on the very fancy dual-touchscreen open-source CANary Project. Turbo3 has also figured out how to extract data from the Leaf Car-CAN using a cheap ELM-327 clone dongle and an Android phone. There is currently a flurry of CAN bus hacking on the Leaf.

UCTronics 3.2″ TFT LCD Arduino Shield with Touchscreen

Updated 2014-03-14

I’ve been looking for a way to add a touchscreen UI to my projects.  To this end, I purchased a UCTronics 3.2″ TFT LCD Arduino Shield.  Most of the cheap TFT touchscreens that I found need about 38 pins, and therefore, need to interface with an Arduino Mega.  What makes this UCTronics shield unique is that it uses an onboard latch to convert the onboard SSD1289 TFT driver data bus from 16-bits to 8-bits.  This allows it to connect to an Arduino Duemilanove or UNO.  The board I received is a RevB board, and it looks somewhat different from the board pictured in the UCTronics product description.  The resistive touch panel on top of the TFT very similar to the touch panel used in the Nintendo DS.  Below is the board running UTFT’s demo (UTFT_Demo_320x240):


When I purchased this display, I had to use a specially modified version of UTFT downloaded from UCTronics: This is because at the time, UTFT only supported the SSD1289 in 16-bit mode. However, as of 2014/14/03, the shield now works with the official UTFT distribution. The key is to supply the correct parameters to the UTFT constructor:

[code lang=”c”]

UTFT myGLCD(SSD1289_8,A1,A2,A0,A3);


SSD1289_8 specifies that we’re using an SSD1289 controller in 8-bit mode. The rest of the parameters are the pin assignments.

When compiling for an Arduino Duemilanove or UNO, the IDE will complain that the sketch is too big, unless you comment out all of the #define DISABLE_xxx except for #define DISABLE_SSD1289 in UTFT’s memorysaver.h.

While UCTronics’ version of UTFT comes preconfigured, it is based on an older version of UTFT, which is slower. On my Duemilanove, the UTFT_Demo_320x240 sketch takes 57.7 sec to execute with UCTronics’ UTFT, and 48.6 sec with the official UTFT library.  This is mainly because the latest UTFT has a new function called _fast_fill_8(), which speeds up certain fills. However, the sketches built with the newer UTFT library are bigger. With UCTronics’ UTFT, UTFT_Demo_320x240 compiles to 27248 bytes, and 30092 bytes with official UTFT.

Here is a bottom view of the shield:


At right is the integrated micro SD card reader, which is handy for storing bitmap data to load into the screen.

UCTronics supplies ArduCAM_Touch to support the touchscreen. However, I decided to just use UTouch, instead. Below is the UTouch_ButtonTest example sketch:


To use UTouch, you must configure the following lines in the sketch:

[code lang=”c”]
UTFT myGLCD(SSD1289_8,A1,A2,A0,A3);
UTouch myTouch(13,10,11,12,9);

I was able to operate the buttons by pressing firmly with my fingers. Note that the touchscreen is resistive, not capacitive, so it works by pressure. A stylus gives you considerably more control. The touchscreen is very similar to the one found in a Nintendo DS.

At first, I was disappointed by the bitmap display.  This is the output of the UTFT_Read_BMP demo sketch supplied by UCTronics:


There is severe quantization of the colors. This is the way due to the way that UCTronics implemented the UTFT::dispBitmap() function in their modified UTFT library. I wrote my own function, dispRaw(), to instead display .raw files generated by UTFT’s ImageConverter 565:

[code language=”c”]
// display a raw bitmap that was processed with ImageConverter565

#include <UTFT.h>
#include <SD.h>
#include <Wire.h>

#define SD_CS 8

//UTFT(byte model, int RS, int WR,int CS,int RD)
UTFT myGLCD(SSD1289_8,A1,A2,A0,A3);

void dispRaw(UTFT *utft,File inFile)
char VH,VL;
int i,j = 0;
cbi(utft->P_CS, utft->B_CS);
for(i = 0; i < 320; i++)
for(j = 0; j < 240; j++) {
VL =;
VH =;
sbi(utft->P_CS, utft->B_CS);

void setup()
if (SD.begin(SD_CS))
char VH,VL;
File inFile;
inFile ="ade.raw",FILE_READ);
if (! inFile)
while (1); //if file does not exsit, stop here.

void loop(){}

The output looks a lot better:


The display is actually much higher quality than the photo above.  The photo contains screening and moire patterns that you don’t see with the naked eye.  To create a RAW file, first create a 240×320 pixel jpg,png, or GIF file.  Run it through either imageconverter565.exe or the online ImageConverter 565 make sure to select Convert to .raw file and Target Platform Arduino (AVR). Copy it to a FAT-formatted uSD card, and insert it into the uSD slot.

It takes about 6 seconds to load a fullscreen RAW file. I’m think the bottleneck is the reading of the data from the SD card. Clearing the screen takes almost 1 second. The speed is acceptable when running UTFT_Demo_240x320.  This is board is no speed demon, but the speed seems adequate for implementing a graphic touchscreen control panel. If you need a fast display, look elsewhere.


User Guide
UCTronics Customized UTFT library


EKitsZone UNO Rev.3 First Look

I recently decided to buy an Arduino UNO R3, to test compatibility with my sketches, which I have been testing w/ a Deumilanove.  The UNO R3 contains an ATmega16U2  instead of an FTDI chip to do the serial to USB conversion, as well as 3 extra pins on the digital side of the board: SCL/SDA/AREF.  One thing I don’t like about the Arduino UNO is that while it uses a 16MHz crystal for the 16U2, the main 328P MCU runs on a resonator, which is not as accurate.  I found the EKitsZone UNO Rev.3 on eBay for $14.99, and decided to give it a try.

unor3The notable differences in the EKitsZone Rev.3 versus the Arduino UNO R3 are:

  1. the ATmega328P uses a 16MHz crystal oscillator instead of a resonator, so its timing is just as accurate as a Deumilanove
  2. the reset button is mounted at a right angle, so it’s easily accessible even when a shield is attached on top
  3. it uses a mini-USB connector instead of a full-sized one
  4. the JP2 pins aren’t filled with solder, so it’s easier to solder in headers, should you want to connect something the PB4..PB7 pins on the 16U2
  5. the programming header for the 16U2 isn’t installed, but it’s easy to solder one in

I see 1-4 as advantages.  Plus, the board is a cool looking red color.