Toshiba FlashAir

The Canon cameras we are using are programmable thanks to CHDK... which is not supported by Canon. Unfortunately, that's the norm, not the exception: most companies try to prevent users from reprogramming their products. Fortunately, Toshiba has taken a different path with their wireless SD cards. In fact, they support three different flavors of somewhat programmable wireless SD cards: FlashAir, NFC, and TransferJet.

FlashAir Overview

Toshiba's FlashAir at first seems a lot like what a company called eyefi was doing first. Both offer wireless image upload to smartphones, tablets, computers, or even cloud or photosharing sites. However, the difference is that FlashAir is user programmable and bidirectional. In other words, unlike eyefi, FlashAir has an open API that lets you do pretty much anything the hardware is capable of. To be precise, it allows scripting in Lua. This isn't really an SD card, but an Internet of Things (IoT) engine including compute, some I/O, and 8, 16, or 32GB of NAND flash memory.

So, aside from being nice little class 10 SD cards (minimum 10MB/s read or write speed), what can our $20 FlashAir W-03 cards do?

I bet you weren't expecting that last one! I sure wasn't. However, it is true. This little SD card can act as an IoT controller all by itself. Here's Toshiba's diagram showing this:

FlashAir For CACS

Ok, so these are remarkably capable SD cards. What are we going to do with them? Several things, actually:

We've never used these before -- literally just got them in late August 2016. Once we get a little more familiar with these cards, there will be more details posted here. For now, take a look at the rather extensive FlashAir Developers website.

Well, as often happens with "new" things, it turns out that file upload to the card doesn't work as advertised. In theory, you should be able to simply mount the card via WEBDAV. If you have davfs support installed, that mostly works using something like:

sudo mount -t davfs 192.168.0.1 mountpoint -o uid=yourname

The problem is that any writes made to the card don't stick. They look like they happen, but don't actually update the card. Fortunately, there is a workaround:

http://192.168.0.1/upload.cgi

A detailled description of how this works is at the extrud3d WWW site. There is also an interesting "improved" web interface posted there. That's all well and good, but that still doesn't tell you how to do this with scripts....

Sending A File To The SD Card

The easiest way I've found is using the utility cURL. File upload via the standard FlashAir upload.cgi interface is rather dumb, so you'll need to have the file with the same name in the current directory where curl is run from. For example, to send a file named CMD, simply:

curl -s --form "file=@CMD" http://192.168.0.1/upload.cgi >/dev/null

In the curl command, the -s option means "silent" and >/dev/null sends the form contents (which curl fetches) harmlessly into oblivion. This takes about 1.25s of real time to transmit a short file to the SD card -- provided the file isn't locked on the SD card side. How does it get locked? Very easily. If the SD card thinks anything else might be touching that file, it blocks uploads to it until the file is not contended. For example, if the SD card file is A/X/CMD, merely opening the SD card file as http://192.168.0.1/X/CMD in a WWW browser causes the file to be locked until you request a different file through that interface. (I can't prove it, but I suspect this is why writes don't work when files are mounted via davfs; it even seems to block writes when CHDK has the file open!) You should also be warned that the SD card doesn't know what time the host thinks it is, so it doesn't set the file timestamp correctly.

Where does the file go in the SD card? To the pre-specified directory. Before you can upload anything to the SD card, you need to make sure your SD card's file SD_WLAN/CONFIG includes something like:

UPDIR=/X
UPLOAD=1

The second line enables upload to the SD card. The first line sets the default directory for file upload, in this case to what CHDK would call "A/X", which is the subdirectory named X in the card's root directory. You can change the default via a CGI command, but I'd strongly recommend not doing that because it is too easy to bump into the file locking problem mentioned above or even to create file allocation inconsistencies that could scramble the card such that a complete reformat is needed (which awkwardly involves reinstalling the FlashAir firmware; doing a conventional reformat of the SD card will eliminate all the FlashAir features, making the card behave like an ordinary SD card).

Having CHDK See The Uploaded File

There's really nothing tricky about making CHDK see an uploaded file, but there is that funny interlock issue. Fortunately, CHDK does very little buffering of file I/O, so it seems to be sufficient that we avoid keeping the file open during any period where we want wifi to be able to update the file. In other words, open the file, read what you want, and then close the file -- don't have CHDK/Lua keep the file open while waiting for stuff to appear so you can read it. For the same reason, you might want to sleep(500) between polling a file for changes -- you don't want your polling to delay update via WiFi.

Lua file I/O is a lot like what C implements, and it is well documented with various tutorials, etc., online. For example, this is a nice reference for Lua. CHDK doesn't implement everything Lua can do (e.g., there's no floating point), but most stuff works as expected. For example, to read the first line of a file into first, you'd do something like:

wifile = io.open("A/X/CMD", "r")
first = wifile:read()
wifile:flush()
wifile:close()

The open, read, and close should come as no surprise. The flush is just being paranoid, trying to discourage the operating system under CHDK from keeping the file buffered after closing.

Just as I used A/X/CMD here, I'd suggest using one, short, pre-created, file to send commands to CHDK. That way, there isn't any actual file system allocation going on when you write via WiFi -- you're simply overwritting file data in the already-allocated block. By the way, this is flash memory, so you don't get a huge number of write cycles (perhaps 10K) before it will wear out and start to have errors, but the SD card will automatically perform wear-leveling internally remapping to different physical blocks so the card shouldn't wear-out very quickly as long as the card isn't too close to full.

WiFi File Download From The SD Card

You can use curl to copy files via WiFi from the SD card to your computer:

curl -s http://192.168.0.1/DCIM/101___09/CRW_0003.DNG -o CRW3.DNG

Will quietly download a copy of A/DCIM/101___09/CRW_0003.DNG and name it CRW3.DNG on your computer. File downloads went at a very respectable rate of more than 100KB/s -- but that means nearly 40s to transfer one 4MB JPEG file, and correspondingly longer for the larger raw files.

My suggestion would be to try to minimize the amount of data you try to transfer in real time. For example, your script could delay fetching files from the camera until the end of capture, or you could save files at a lower resolution on the camera so the file transfers will have fewer bytes to send. For simple "handshake" messages, I'd suggest having CHDK just updating a single, small, preallocated file that you grab via WiFi. It's essentially the same trick I suggested for uploading commands to CHDK, but don't use the same file for commands to and responses from the camera.


http://aggregate.org/CACS/ Computers as Computing Systems