Visual Studio Code and PlatformIO

Regular readers will know that I’m a big proponent of PlatformIO as a programming platform for the ESP family; it’s just so much better than the Arduino IDE for us command-line interface die-hards. As I’ve noted before, I’m not a religious fanatic on the CLI vs GUI thing; it’s just that GUIs (with a couple of exceptions) don’t really click for me. Most of the time I just don’t “get it” and what’s on offer usually seems to limit the functionality without really adding much, if anything, in ease of use. Recently though, I’ve been searching for information on getting started with the ESP32’s built-in version of FreeRTOS (specifically, looking for more information on real-world use, rather than just a couple of sentences about the syntax of the xTaskCreate() call) and I found a couple of very useful videos by Xavier on his “Simply Explained” channel which, as the name suggests, do a very good job of explaining by example, how to use FreeRTOS. The thing which (as a doddering old git) really caught my attention was his use of Visual Studio Code. I was captivated by the pop-up prompt with info on the parameters (of which there are plenty) to feed to xTaskCreate. While I imagine that functionality can get pretty tedious when it pops up for each and every printf(), it does look like a definite winner when you’re learning something new (and don’t have much in the way of short-term memory any more).

Now, what was I saying again? Oh yes, here’s the link to one of Xavier’s videos. He’s got a ton of content on his channel on many diverse (but usually tech-related) topics. This one is not the first in the series, so if the abrupt lead-in is a bit too much you can go to his Intro on FreeRTOS instead. I highly recommend watching Xavier’s videos if you’re trying to get started with FreeRTOS.

Of course, I immediately went off and downloaded Visual Studio Code and fired it up …only to just as immediately get totally lost when I couldn’t get it to do anything that I wanted. I did watch a few more videos from a nice lady at Microsoft, but ended up suffering from information overload and Windows-itis. I went for a nice cup of tea instead. And then went back to PlatformIO in an xterm, just so that I could get something done.

More recently, one of my regular morning reads, Hackaday, had an article on making laminated artwork for front panels with an accompanying video (worth a look in itself) by Richard Langner. I was impressed by Richard’s succinct, no-nonsense style and dipped into his video listings to see what other goodies were there. Lo and behold, right at the top of the list were a couple of videos on how to get started with Visual Studio Code with PlatformIO. The first was only a minute and a half long and the second just over six minutes. Both are filled with essential information on doing just what I wanted to do (have the editor prompt me with useful info, but still be able to use PlatformIO as my programming environment). As they’re so short, I’m including both as embedded links below. Take a look. Even if you don’t like them, you won’t have wasted much time.

Many thanks to both Richard and Xavier (oh, and Al Williams and the team at Hackaday, as well as Ivan and everyone at PlatformIO) for making my life not just easier, but a lot more interesting, too.

First steps with the W600 (on Linux)

I ordered a couple of these W600 dev boards a few weeks ago, as they were reported to be the easiest ones to use when introducing yourself to the ThingsTurn Dev BoardW600 chip (these “ThingsTurn” boards don’t have any second processor to grapple with, but do have a UART chip and USB connector for easy power/comms).

It turned out that while the power connection was easy, the comms were anything but and I wasted far too much time messing around trying to get it to accept an upload or even just a terminal connection.  So today’s post mainly consists of a series of short tips on how to get started with the W600 “ThingsTurn” dev board without pulling out all of your hair.  Tips 1 through 4 deal with getting MicroPython onto your W600, while those from #5 onwards are examples of what you can do with the board from the MicroPython REPL (command line).

For my purposes, I just wanted to upload MicroPython as a quick, functional test, without having to download and install a toolchain and/or SDK, or really do anything at all that took more than a couple of lines of typing or 5 minutes of my time.  Two days later, I was -still- getting nowhere very fast; my blood pressure was rising and I was itching to use my magic, solves-everything tool  …the 1.5kg lump hammer.

So, tip #1 is  —  Don’t believe everything you read (including this!).  The W600 firmware and applications are still under heavy development.  Most (but not all, see tip #2) of that work is taking place in China.  The translation and maintenance of the manuals seems to be quite well down the TODO stack (something that most of us are guilty of).  Specifically, don’t bother trying to use their “download.py” (if you can find it) for anything, most especially not for uploading to ThingsTurn boards.

Tip #2  —  Volodymyr Shymanskyy has recently posted a great tool for uploading to the W600.  It knows about the two available bootloader methods and will try to do the right thing, depending upon which type of file you’re attempting to upload.  Don’t bother with anything else; go straight to his repository and start using it now.

Tip #3  —  Don’t assume that your favourite terminal program(s) will work with the ThingsTurn boards, even if it has worked with everything else you’ve ever tried it with.  It turns out the the the ThingsTurn boards (note that I’m being very specific here, as I don’t believe that any of the other W600 modules suffer from this issue) have a requirement for the RTS signal to be held at “0” when connecting, otherwise the W600 will be forced into a permanent reset condition.  I was unable to get either “screen” or “minicom” (my usual goto choices for comms terminals) to play with the ThingsTurn boards.

By this time I knew that the boards worked, as they communicated with “w600tool” easily and loaded MicroPython (to displace the simple, one-second flash on/off program which comes as default on the boards).  Connecting with either screen or minicom would very occasionally produce a random, brief flash from one of the blue LEDs, but there was never any further indication of life and definitely nothing coming from the boards.  A major step forward was finding that sending a “Hang-Up” request (CTRL-A H) from Minicom produced the MicroPython header and a REPL prompt from the board, before it lapsed back into its previous, comatose state.  This confirmed that the upload had indeed worked and that, given the right conditions, MicroPython would run.  At this point I reverted back to my 1980’s RS232 self and started writing a simple C program to toggle the control lines…  before remembering that this was the glorious future and somebody else on the ‘net had undoubtedly already done it (and undoubtedly made a far better job of it than I ever did).  So I knuckled myself on the side of the head a couple of times and turned back to Volodymyr Shymanskyy, as he’d already helped me out once and seemed to have already cracked this particular problem.  That particular rabbit-hole led me, in very short order, to Python.

Tip #4  —  Use the force, Luke!  Or at least, don’t be as stupid as me and refuse to see what’s right under your nose.  You wanted to get running with something quickly:-  MicroPython.  MicroPython =~ Python.  W600tool =~ Python.  There’s a bit of a pattern emerging here.  Yup, those clever Python dev guys have already written the solution to our problem and it is called “miniterm”.  A quick check of the on-line manual pages showed that it was quite capable of toggling selected hardware control lines and holding them in the selected state, as well as all of the normal port and baud selection stuff.  So here’s the command line to get you connected, up and running using miniterm:-


python3 -m serial.tools.miniterm --rts 0 /dev/ttyUSB0 115200

[…and just a reminder here that this is from Linux, you’ll likely have to change at least the device name if you’re using a different OS].

Once you’ve typed that in you’ll see something like:-

— forcing RTS inactive
— Miniterm on /dev/ttyUSB0 115200,8,N,1 —
— Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H —

…followed by an ASCII-art representation of the Winner-Micro (stacked “W” and “M”) logo (which really confuses WordPress formatting, so is not included here), followed by:-

WinnerMicro W600
MicroPython v1.10-279-g3c60627-dirty on 2019-05-24; WinnerMicro module with W600
Type “help()” for more information.
>>>

Yay!  We’re in business!


Tip #5  —  Import the machine-specific hardware module.  Configure a W600 pin (PB14 in this case) as an output (with no pull-up or pull-down) and assign name “led14” to it.  Use the assigned name to toggle the value of the W600 pin (note that the blue LEDs on the ThingsTurn boards have their anodes connected to VCC via a 1k resistor and the cathodes are connected to the GPIO pins, so the output value of “1” turns the LED off and “0” turns it on:-


>>> import machine
>>> led14=machine.Pin(machine.Pin.PB_14,machine.Pin.OUT,machine.Pin.PULL_FLOATING)
>>> led14.value(1)
>>> led14.value(0)


Tip #6  —  Connect to an existing Access Point.  To do this, we first import the network module and then initialize as a station and scan for available networks.  We connect to an available network (SSID “BigHouse”) with whatever the password is (“Th3Pa55word” in this example), check for a valid, live connection and finally, print out the IP address.


>>> import network
>>> sta_if = network.WLAN(network.STA_IF)
>>> sta_if.active(True)
True
>>> sta_if.scan()
[(b'BigHouse', b'0Z:\xc7\x82\x10', 6, -67, 32, False)]
>>> sta_if.connect("BigHouse", "Th3Pa55word")
>>> sta_if.isconnected()
True
print("Connected, ip is: " + sta_if.ifconfig()[0])
Connected, ip is: 192.168.4.3


Tip #7  — Create an access-point on the W600  …and then shut it down again.  First we need to load the easyw600 module, which contains Winner Micro’s own helper functions to make this easy.  There’s just a single call to easyw600.createap(), with your choice of SSID.  You’ll find that the  new access point pops up immediately and is visible and accessible (but not very useful) from any nearby device equipped with WiFi:-

>>> import easyw600
>>> easyw600.createap(ssid="W600_softAP")
softap working, ip is 192.168.43.1

When you’re finished, there’s just a single call to easyw600.closeap() to shut it all down again:-

>>> easyw600.closeap()


Tip #8  –  Enable an FTP server process.  This will allow us to manipulate files on the W600, so that longer MicroPython programs can be written elsewhere and then debugged on the device itself.   Before you start with the FTP server, you need to make sure that your W600 is already on-line and associated with an existing AP (see tip #6, above).

The FTP server is included in yet another module, this time named simply “w600”, so to begin with, we need to make sure that it is imported.  After that, there’s just a one line command to start the FTP server with a given username and password (note that in the given example, the username and password are both set literally to the word “None”):-

>>> import w600
>>> w600.run_ftpserver(port=21,username="None",password="None")
ftpserver is running.

[After writing this tip, I found that the “easyw600” module has a wrapper for run_ftpserver() which is even easier to use, just:-  “easyw600.ftpserver()” ]

You can now access your W600 from any local machine and you’ll see something like this:-

Connected to 192.168.4.3.
220-= welcome on W600 FTP server =-
220
Name (192.168.4.3:guest): None
331 Password required for None
Password:
230 User logged in
Remote system type is UNIX.
ftp> ls
200 Port Command Successful.
150 Opening Binary mode connection for file list.
drwxrwxrwx 0 root root 0 Jan 1 2018 sys
drwxrwxrwx 0 root root 0 Jan 1 2018 lib
drwxrwxrwx 0 root root 0 Jan 1 2018 cert
-rwxrwxrwx 0 root root 139 Jan 1 2018 boot.py
-rwxrwxrwx 0 root root 34 Jan 1 2018 main.py
-rwxrwxrwx 0 root root 40 Jan 1 2018 easyw600.py
226 Transfert Complete.
ftp>

So, we can now create a file, “fc.py” containing Python code on our local Linux machine:-

def wibble(FC="dog"):
    print("Furry creature: " + FC)

wibble("cat")
wibble()
wibble("ferret")

Now upload it to the W600 using FTP’s “put” command and then go back to the W600 console and type:-

>>> import fc

…(note:- there’s no “.py” on the end) and you’ll see the output from your new code.

If you repeat the “import fc” command, there’s no further output, but you can now call the “wibble” function from the REPL command line.  Try:-

>>> fc.wibble()

and

>>> fc.wibble("rabbit")

Note that it isn’t really possible to un-import a file (or module) once it has been cached, so -don’t- edit your file remotely and then expect to see the changes reflected when it is re-uploaded. MicroPython generally ignores an import request for something which it already has marked as existing in cache. The only bullet-proof way around this is to reboot the W600.


Tip #9  –  How do I reboot the W600 (without pulling the power cord)?

>>> import machine
>>> machine.reset()

Tip #10 – And finally, here’s a replacement main.py file which you can now upload to your W600 to have it automatically connect to your WiFi network and start the FTP server (both as described above) on reboot. You -will- need to set the SSID and password for your access point before installing it.

##
## main.py file content. Used to automatically start
## the network, join an access-point and then start
## an FTP server on the W600 at initial boot.
##
## *** You must set an SSID and password ***
##
import network
import w600
import time

print(“Starting network and FTP server…”)

##
## Join Existing Access-Point (Local Wireless Network).
##
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.scan()
sta_if.connect(“MY_SSID”, “MY_PASSWORD”)

##
## Start built-in FTP Server.
##
w600.run_ftpserver(port=21,username=”None”,password=”None”)

##
## …and let the user know what our address is.
##
print(“Waiting for DHCP…”)
time.sleep(5)
sta_if.isconnected()
print(“Connected, ip is: ” + sta_if.ifconfig()[0])


 

ESP01S USB Adapter Mod

Up until a couple of months ago, I’d never been interested in ESP01 modules (it seemed fairly pointless to buy an ESP8266 crippled by both lack of memory and lack of IO pins when the price wasn’t substantially different). That changed recently for a couple of reasons. Obviously, the appearance of the 1MB ESP01S modules made a huge difference to the functionality of the ESP01 (TASMOTA would fit comfortably into flash and they became OTA upgradeable), but I also had the need for some physically small modules, as I’m adding functionality to some external light fittings (more on that below†).

ESP01S module and Adapter

When the modules I’d ordered finally arrived, I was pleasantly surprised by their compact size and by the 8-pin connector (I hadn’t, before now, tumbled to the fact that people might be buying these simply because they were easier to solder than the minuscule, castellated edge connections common to the other modules in the family). After assembling a prototype, I ordered more ESP01S modules and, on impulse, added a $1 USB adapter (left), which looked like an easy method of programming and testing the individual units before installing them into the main boards.

It was only when the adapter arrived that I realized why they were priced so cheaply …no reset switch, no programming switch and none of the RTS/DTR auto-program mode selection of the NodeMCU (and knock-off) boards. Duh! It turns out that there’s a very slightly larger version of the ESP01 USB adapter (with a red PCB, so it’s easy to identify) which does have a programming switch, but it sells for about $3.20.

Anyway, all was not lost; rather than wait another month for another order to perhaps arrive (and we’re getting a little too close to the Chinese new year to have warm and fuzzy feelings about estimated delivery times), I thought I’d just hack the existing $1 version to be programmable. This turned out to be even easier than expected (and even I didn’t expect the addition of one switch to be hard).

I had a bag of about 100 “tact” switches sitting in the parts bin, but if you don’t happen to have any to hand, I recommend dead, ancient, mechanical mice as a source of (usually) good quality tact switches.

Switch supported by yellow connector body

After fiddling with a switch and the USB adapter for a couple of minutes, it seemed obvious that attaching the switch to the side of the board (with the button facing horizontally outwards) at the yellow connector end of the board was a pretty good position; the switch connections were next to the ESP01S pins and the body of the yellow connector provided mechanical support. My board had the characters “HW-305” on the top surface of the PCB, just where I situated the switch.  I’m not a huge fan of hot glue, but in the spirit of a $1 hack, it looked like a good choice for this assembly. Cutting a bit of fairly dense, firm foam (shipping protection for the pins of some ICs) to shape provided a nice shim between the side of the connector and the bottom of the switch and with hot glue on both sides (as well as just a smear down the edge of the PCB), the switch was firmly held in place, even when pressed.

 

Bottom, showing switch connections

On the reverse side of the board, both of the pins we need (GND and GPIO00) are on the inside row of the connector. The ground pin is right next to the edge where the switch is situated and GPIO00 is the third pin in. I decided to use a resistor between the switch and GPIO00 for a couple of reasons …first, I have an aversion to connecting pins directly to VCC or GND and secondly, the resistor body provides extra support for the switch. I happened to use a 1k5 resistor, but the value isn’t critical and anything between 3k3 and 100Ω should work fine.  As the unit comes with unprotected soldered connections on the bottom anyway (and I’m using it on a wooden tabletop), I’m not going to worry too much about insulating it. 

Completed adapter mod with ESP01S mounted

Does it work?  Heck yes!  The switch is firmly supported against the connector body, so it’s very easy to press it at the same time as inserting the adapter into a USB port.  Obviously, inserting the adapter without pressing the switch drops the ESP straight into normal “run” mode.

 


 

† – We have about a dozen outside lights scattered around the property.  They all use E17 base bulbs (the little brother to the normal E26/E27 screw type base).  Unfortunately, there’s a severe dearth of “smart” bulbs with E17 bases and zero (that I can find, anyway) that are “smart” and (importantly) have any sort of useful light output.  I’ve started using these LED (“dumb”) bulbs, which give way better output than the older, equivalent compact fluorescents and are much smaller, too.  Using these, I can cram a mini PSU, ESP01S and a Triac (plus driver) into a cut-down compact-fluorescent base and still fit it into the oblate glass cover that these lamps all have (saving myself the hassle of running an extra neutral wire into a dozen switch boxes and/or the cost of replacing a dozen outside light fittings with E26 versions).

The ESP01S runs TASMOTA which makes control fairly trivial.  The default mode is “on”, so the light switch still works.  The lamps have a couple of  TASMOTA rules enabled; one to switch on at dusk, plus or minus a few minutes and another to switch off at about 4.5 hours after dusk (nice for coming home after dark and being able to see the keyhole).  As a bonus (though not, I have to admit, particularly useful), they all become voice controllable, too.