CH340 Issues on Surface Pro 3?

I picked up a few LoLin NodeMCU v3 boards the other day (you can read a comparison of the various NodeMCU dev boards here).  However, I had a hiccup with it.

I couldn’t get it to work reliably on my Surface Pro 3 (running Windows 10).  Yet, when I plugged it into a colleague’s Lenovo running Ubuntu, it worked fine.

The serial UART (a CH340) was disappearing when the NodeMCU attempted to start up WiFi.  If I held down the reset button so that the ESP never initialized, the UART worked just fine.  Strange.

Then I tried plugging the NodeMCU into a dumb powered USB hub instead of directly into my Surface.  It worked just fine!

My suspicion is that the problem is caused by the power demand reported by the CH340.  It says it needs < 100mA, but I know that the power draw on these things can be upwards of 300mA.  So, I suspect that the Surface is limiting the power draw to what the USB device says is its maximum on startup.  The dumb hub doesn’t care about such things, so it powers the device regardless.

TLDR;  If you have problems with NodeMCU devices vanishing off your USB bus when you do things with them, plug them into a dumb USB hub.

ESP8266 Environment Widget – Software

Last post I mentioned how I got an ESP8266 board.  Well, I’ve put together that with a DHT11 and MQTT to create a widget that senses temperature and humidity, then posts that on a regular basis to your MQTT message broker.  The data comes out in JSON format for ease of use.  I’ll cover the hardware later, once I get the rest of my prototype boards.

Preparing your ESP8266

Following guides mentioned in my previous post, wire up your ESP8266.  Then, connect your DHT such that the output pin is going to GPIO2 on the ESP8266.

Go and install NodeMCU.  Remember to ground GPIO0 if you are going to upload firmware!  You can use either the float or integer version (I used the float version).  The DHT11 only produces integer temperature and humidity stats anyway, so it doesn’t make any difference.

Next, go to my Github repository and grab the two LUA files.  Don’t upload them to the ESP yet!  Just put them somewhere.

If you have installed NodeMCU, you can now stop grounding GPIO0.  Technically you should pull that high with a pullup, but I haven’t bothered yet.  I’ll do that in the final hardware.

Lastly, fire up LuaLoader and configure your wifi.  This is persistent, as long as you don’t reflash the NodeMCU firmware.

The init script

If you put immediately-executing code into init.lua, you run into a problem – you can’t break out into the interactive shell anymore, and therefore you have to reflash in order to get back.  Not optimal.

The way around that is to have init.lua wait a short time and then execute a different script.  You then have time to either manually abort the alarm timer, or get rid of init.lua and reboot.

Here’s a code fragment that does that;

function startup()
	print('executing script')

print("in startup, 'tmr.unregister(0)' to abort")

Pretty simple.  You get 10 seconds to abort before the main script executes.

The reader script

I’m not going to go through the reader script line-by-line, but I will mention some bits about how it works.  First up, NodeMCU is heavily callback driven.  You’re intended to use an event-based paradigm with it, leading to some strange-looking code.  Also, my Lua is pretty limited, I mostly just bumbled my way through it.

Anyway, configuration is with the variables at the top.  dht_gpio = 4 corresponds to GPIO2.  Set your mqtt details appropriately, including the client ID you want this widget to use.  Leave mqtt_ip and mqtt_client nil, they’re used internally.

The actual code execution is event driven by callbacks.  Everything is triggered off by attempting to do DNS resolution for your MQTT server.  NodeMCU includes a nice watchdog timer, and the watchdog is used extensively.  It’s armed at the beginning, and gets reset only when an MQTT message is successfully published.  If anything happens so that an MQTT message won’t be published, something bad happened and the device will eventually reset.

That should cover all possibilities of wifi going away, mqtt broker dying, no IP address etc etc.

It’s notable that NodeMCU on my ESP8266 does not have the sntp module.  This means it has no idea what the real time is, not even close.  As such, I don’t address that.  The ‘raw’ JSON that’s published is intended to be cooked by another script which will add an expiry time.  More on that later.

After unwrapping all the callbacks, our control flow looks like this;

  1. Arm the watchdog timer.  If it goes off, we reboot.
  2. DNS resolve MQTT broker.  If we got an IP…
    1. Connect to the MQTT broker.  If we connected…
      1. Start a repeating alarm every minute.  When that alarm goes off…
        1. Get the DHT sensor details.  If that worked…
          1. Publish that to MQTT and reset the watchdog
  3. Twiddle thumbs

It’s a little more complicated than that (ie, it tries to reconnect to the broker if it disconnects), but not much.

It should be fairly straightforward to wrangle that to support more complex devices such as stuff on an I2C bus.


ESP8266 First Steps

The ESP8266 is a ridiculously cheap ($2 or so from China), WiFi equipped breakout board which has a 32-bit microcontroller and Flash (1MB) onboard.  It comes in a bunch of different versions (mine is an ESP-01), and all with different Flash capacities.  The pinout of the one I have appears below;

ESP-01 Pinout (courtesy MyElectronicsLab)

The most notable limitation of the ESP8266 is the extremely limited I/O capability.  There’s only two GPIOs in addition to the UART, and even those GPIOs configure the boot mode if they’re held high/low during startup!  There is some info about how to get around this limitation at this article though.

DANGER:  The ESP8266 is a 3.3v level device.  Driving the inputs with 5v signalling without a level converter will kill it!

Anyway.  Using a simple 3.3v USB-to-UART converter and a little wiring will allow you to get something useful out of this in a few ways;

I did the last.  I threw on the floating point firmware for NodeMCU onto my ESP-01, which gives you a nice interactive serial interface, standalone capability, and a built-in WiFi connection library.  You can then upload code you’ve written in a LUA-style language to do stuff on the thing.

Now for the real magic.  You can use the GPIO2 pin to read temperature/humidity data into the ESP8266.  A very simple guide about how to do that appears in the NodeMCU documentation for the dht module.

It also turns out that NodeMCU contains a module for communicating to MQTT message brokers (it’s actually got a whole lot of really handy IOT modules already in place).

Next plan is to assemble some code for the ESP8266 so that it reads temperature/humidity data and then publishes that to a MQTT channel for aggregation by something else.

Should make for some pretty cheap WiFi-enabled temperature/humidity sensors!