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])


 

Using oddball ESP boards with TASMOTA – Part III (MQTT)

Continuing with our series of articles on utilizing Theo Arends’ TASMOTA firmware on non-Sonoff boards and devices, in this article we’ll look at using MQTT to interact with the target.

Feel free to skip over the next four paragraphs (between the horizontal delimiters) if you’re already familiar with the way in which MQTT works.


Just in case you’re not familiar with MQTT, I’d like to emphasize here that it is not an interactive mode of communicating with your device in the way that using a serial adapter, console or telnet/ssh connection is.  In concept it is more like using radios for verbal communication; you have both a transmitter and a receiver, but they are two separate pieces of equipment.  If you transmitted a message, you wouldn’t hear any reply if your receiver wasn’t turned on and tuned to the appropriate frequency.  Likewise, without a transmitter (again, tuned to the correct frequency) you would simply be a passive listener to whatever was received.  MQTT is similar; you need to know the “frequency” (the topic) which you want to communicate on and you need a transmitter (a publisher), as well as a receiver (a subscriber).

To complicate matters a little further, you are running your radio equipment in a deep valley, surrounded by mountains.  In order to use your radio you need to use a repeater station, situated on a nearby summit.  The operators of the repeater are very generous and will freely rebroadcast anything they receive on to you , just as long as you tell them which frequencies you want to receive.  All of your radio traffic, both outgoing and incoming, needs to go via this repeater.  In MQTT terms, the repeater is a “broker” which will listen for messages and rebroadcast them.  You can receive and transmit messages at will, as long as you specify a topic.

The most common MQTT broker for home use is Mosquitto, which comes with a couple of command-line utilities, “mosquitto_sub”, a subscriber (or receiver) and “mosquitto_pub”, a publisher (or transmitter).  You would run Mosquitto on one of the machines on your home LAN (say, perhaps a Raspberry-Pi or a dedicated NAS or back-up system which is running 24/7).  The Mosquitto daemon provides a fully functional MQTT “broker”, but you can also install the mosquitto-clients package on your desktop or laptop to make the mosquitto_sub/pub utilities available, without the overhead of the full daemon.

Anyway, enough of the radio analogy.  The important things to remember with MQTT are that:-

  • You won’t automatically get any response from a “pub” message sent to your ESP, unless you are also listening to the correct topic with a “sub”.
  • MQTT is a distributed protocol, in the sense that your subscribers will usually be on a different physical machine than the publishers and probably neither of them will be on the same machine as the broker.

On the ESP8266 side, there are a few libraries available which give moderately pain-free access to MQTT from your program.  Currently I’ve been favouring Nick O’Leary’s PubSubClient library and, luckily, Theo includes it by default in TASMOTA, so you don’t need to do anything extra; MQTT capability is built-in.

So, lets get started with MQTT.  As suggested in the previous article, I’d recommend opening up the wiki page describing TASMOTA commands and using it as a handy reference while you’re playing with this.

Example of "screen" with top and bottom window splitHowever, before we jump into the commands themselves, I’d recommend that you bring up two separate windows on your display to allow you input “transmissions” in one window while simultaneously being able to see received messages in the other (if you’re using a full-screen terminal window on some modern version of Un*x, you can also use the “screen” utility to split your single window into top and bottom halves, using “CONTROL-A S”, followed by “CONTROL-A TAB” to swap between the new, top and bottom windows and then “CONTROL-A c” to create a new shell in the bottom window [¹]).

In your top window, start a “receiver” process to monitor the output on TASMOTA’s “stat” (status) topic.  This is where you’ll see the messages which TASMOTA is sending back to the MQTT broker.  Your command will look something like this:-

mosquitto_sub -h mybroker.mylan.com -t “stat/sonoff/#”

…where “mybroker.mylan.com” is the machine where the main mosquitto daemon is running (your “broker”) and “sonoff” is the “friendly name” you’ve given your module in TASMOTA.  The “#” character at the end of the topic string (“stat/sonoff/#”) is the MQTT wildcard character and, in this case, tells the mosquitto_sub command that we want to see all messages that match the “stat/sonoff/” string, whether they be the result of command execution or specific subsystem (ie:- memory) informational messages.

If your broker process is running on a separate machine, the commands which you type in can get quite long, so I’d also recommend building up a couple of aliases for the mosquitto_sub and mosquitto_pub commands (I covered this in an earlier MQTT how-to article).

[ NOTE:- From this point onwards I will use the aliases “mqp” for mosquitto_pub and “mqs” for mosquitto_sub to try and limit the example commands to a single line. ]

As when using the console commands earlier, we’ll start with some simple commands to manipulate the green LED.   Here’s where a simple rule will help out — IF YOU’RE SENDING A REQUEST OF ANY SORT, YOU NEED TO USE THE “cmnd/*” TOPIC.  In this particular instance, it may seem intuitive to use the “stat/*” topic, because we want to see some status, but you need to remember that we’re not using an interactive terminal session; we’re using the transmit and receive functionality of MQTT, so we must send any request as a command.  This takes a little bit of getting used to, but will become second nature very quickly.  So in this case, the command you send to your module will look something like this:-

mqp -t cmnd/sonoff/LedPower -n

The “-n” tells mosquitto_pub that there is no message part to this particular command.

Once sent, you won’t see any  other output in your “transmit” window (unless you’ve made a typo), but over in the window where you left the mosquitto_sub command running in background, you should see the response:-

{"LedPower":"OFF"}

…or possibly “ON”, of course.

Controlling the LED is more intuitive than just getting the status:-

mqp -t cmnd/sonoff/LedPower -m "on"

We’re using the same basic command, with exactly the same topic (“cmnd/sonoff/LedPower”), but a different message (the ‘-m “on”‘ part) and, as you’d expect, this turns on the LED on your remote module and, in addition, TASMOTA automatically sends a status update message, so your mosquitto_sub (receiver) window will display:-

{"LedPower":"ON"}

Then use:-

mqp -t cmnd/sonoff/LedPower -m "off"

…to turn it back off again (hopefully your ESP8266 module is somewhere within sight, so that you can visually check that these commands are indeed working).

The next step is to simply replace “LedPower” with just “Power” and verify that the relay on your ESP8266 is also responding to on/off commands.  The output in the mosquitto_sub window will change to:-

{"POWER":"ON"}  and  {"POWER":"OFF"}

Our next command will return the status (the current pwm count between 0 and 1023) for each of our previously assigned PWM drive pins (the red and blue LED segments of the RGB LED on the Yellow Dev board).

mqp -t cmnd/sonoff/pwm -n

Note that we’re again using the “-n” to tell mosquitto_pub that there’s no message part to this topic.  The output on the mosquitto_sub screen will probably look something like this:-

{"PWM":{"PWM1":0,"PWM2":0}}

The output is just a little more complex, as there are now two separate GPIOs in the overall PWM status report.  I’m sure that by now you don’t need me to tell you that using those PWM1 and PWM2 ids, you can now control your red and blue LEDs in the same way as we did from the console, but using the message part of the MQTT command to vary the PWM drive output:-

mqp -t cmnd/sonoff/pwm1 -m "750"

…returns:-   {"PWM":{"PWM1":750,"PWM2":0}}

mqp -t cmnd/sonoff/pwm2 -m "350"

…returns:-   {"PWM":{"PWM1":750,"PWM2":350}}

Note that the response status from the command still includes all of the defined PWM pins, even though our command lines only change one GPIO pin at a time.

Following along from the examples we went through previously in the “Console” tutorial, we’ll now request TASMOTA to send us the status (including the data) from our on-board temperature sensors.  If you remember, we needed to send the command “status 10” from the console, which translates into another command string for mosquitto_pub.

mqp -t cmnd/sonoff/status -m "10"

…and the response this time (in the mosquitto_sub window) is much longer (this would all be on one line on your screen):-

{"StatusSNS":{"Time":"2018-02-14T09:46:58","DS18B20-1":{"Id":"011590E534FF","Temperature":1.50},"DS18B20-2":{"Id":"031590A618FF","Temperature":35.25},"TempUnit":"C"}}

Anyone who has played around with IOT data in the past few years will recognize this (and the previous examples) as JSON formatted data.   Here we can see that the overall encapsulation is “StatusSNS” and within that we have several different types of data returned.  The first is a timestamp which needs no explanation, but the following two blobs of data:-

"DS18B20-1":{"Id":"011590E534FF","Temperature":1.50},

and

"DS18B20-2":{"Id":"031590A618FF","Temperature":35.25},

…are more interesting.  The strings “DS18B20-1” and “DS18B20-2” are arbitrary identifiers used by TASMOTA to identify individual one-wire temperature sensors.  The “Id” numbers are the actual serial numbers of the DS18B20s themselves (each sensor has a unique serial number burned into its ROM when manufactured).  “Temperature” is again obvious, but just in case of ambiguity, the last part of the StatusSNS data (above) is a specifier for the temperature unit being used (in this case, Celsius).

We can change the temperture reporting units to Fahrenheit using the “SetOption8 1” command:-

mqp -t cmnd/sonoff/setoption8 -m "1"

…and the next time we get a temperature status report, the figures are quite different:-

{"SetOption8":"ON"}

{"StatusSNS":{"Time":"2018-02-14T09:47:38","DS18B20-1":{"Id":"011590E534FF","Temperature":35.04},"DS18B20-2":{"Id":"031590A618FF","Temperature":83.97},"TempUnit":"F"}}

Okay, we’ve covered the same commands as we did in the “Console” article and reached the point where TASMOTA and MQTT are delivering a bunch of useful data back to us from our project board.  In the next part I’ll look at creating a shell script to automatically generate and handle that (JSON) data, so that you can actually control the relay based on temperatures.


[¹] – Commands for manipulating virtual windows from within “screen” all start with a CONTROL-A character, so to create a new virtual window you would input the sequence “CONTROL-A c”, to change the current view to the next window would be “CONTROL-A n” and to change back to the previous window would be “CONTROL-A p”, and so on.  Use man screen for more details.