WeMos D1 Mini First Impressions

Just got a $3 WeMos D1 Mini in the mail and I thought I would share a few very quick thoughts about it.

  1. This thing is tiny. It’s funny I knew it was small, but it still amazes me that you can squeeze effectively a small computer in the space of  a couple of postage stamps.
  2. The fit and finish seems pretty good for a $3 board. What an age we live in!
  3. Loading Micropython took longer than it should have but that may have been user error. This tutorial is pretty good.
  4. The LED turns on when the pin is low and off when the pin is high. Huh?
  5. Micropython is pretty awesome so far. I’m sure Arduino is more efficient but with 160 Mhz of process power and a couple of megs of space, I’m not worrying!
  6. Connecting with screen works but not picocom? Weirdness.
  7. The machine library in MicroPython is pretty handy, a good replacement for a lot of the Arduino built-ins.
  8. There is no consensus about how to capitalize Micropython. Is it micropython, Micropython, MicroPython, etc. This frustrates the copy editor in me.
  9. Wait… do I just pull the plug to turn this thing off? That feels wrong but I guess it is what I always did with my other ESP8266 boards… But it feels weird not to shut down something that has an interactive prompt.

Alright, those are some quick thoughts, more later.

Advertisements

MQTT Cookbook: Thingspeak to MQTT

One of the most common problems in IoT is the need to bridge between two different infrastructures. It is a long story, but I ran into a situation where I needed to bridge a pre-existing ESP8266 connected to Thingspeak with my broader MQTT network. Thankfully, hacking together a quick bridge between the two services proved fairly easy.

import requests
import paho.mqtt.client as mqtt

CHANNEL =
API = ""

def get_thingspeak_field(channel, api, field):
    _url = 'https://api.thingspeak.com/channels/%s/fields/%s.json?api_key=%s&results=1' % (channel, field, api)
    _r = requests.get(_url).json()
    return _r['feeds'][0]['field%s' % field]


def on_connect(client, userdata, flags, rc):
    client.publish('thingspeak/field1', field1)
    client.publish('thingspeak/field2', field2)
    client.disconnect()


def on_log(client, userdata, level, buf):
    print(level, buf)


field1 = get_thingspeak_field(CHANNEL, API, 1)
field2 = get_thingspeak_field(CHANNEL, API, 2)
client = mqtt.Client()
client.on_connect = on_connect
client.on_log = on_log
client.connect("test.mosquitto.org", 1883, 60)
client.loop_forever()

 

The code is fairly self-explanatory but lets walk through it. There is a Thingspeak library for Python but it is actually easier to just import requests and make a standard API request. To facilitate this I wrote a simple function which takes the channel, api key, and the field that you want to read. After reading the fields it connects to an MQTT broker–currently the Mosquitto test broker–and publishes the fields.

Simple as that! Now you can hook your Thingspeak and MQTT infrastructures together in any way you want.

How “Functional” Should Arduino Be?

As mentioned in my last post, using Timer.h in my DHT11/ESP8266 project required me to transform much my sketch into functions. My initial experience with programming was in BASH and since then I’ve done some Python, so I am comfortable with using functions. But in Arduino I kind of liked being able to accomplish things without them. Take a look at this snippet that does basically everything I need the board to do:

void loop() {
  for (c = 0; c < 60; c++) {
    h = dht.readHumidity();
    f = dht.readTemperature(true);
    fS = (alpha * fS) + ((1 - alpha) * f);
    hS = (alpha * hS) + ((1 - alpha) * h);
    Serial.print("c="); Serial.print(c); Serial.print(" f="); Serial.print(f); Serial.print(" fS="); Serial.print(fS); Serial.print(" h="); Serial.print(h); Serial.print(" hS="); Serial.println(hS);
    delay(1000);
  }
  Serial.println("Sending to Thingspeak");
  ThingSpeak.setField(1, fS);
  ThingSpeak.setField(2, hS);
  ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  blink(BLUE, 1);
}

That is code I can easily understand without referring to multiple functions. The new approach breaks that up into basically two functions. The first polls the sensor and records a new value:

void sensorUpdate() {
  f = dht.readTemperature(true);
  h = dht.readHumidity();
  fS = (alpha * fS) + ((1 - alpha) * f);
  hS = (alpha * hS) + ((1 - alpha) * h);
  if (isnan(fS) || isnan(hS)) {
    fS = dht.readTemperature(true);
    hS = dht.readHumidity();
    fSo = fS;
  }
}

 

The second sends to thingSpeak

void thingspeakUpdate() {
  if (fSo > fS) {
    analogWrite(RED, 0); analogWrite(GREEN, 0); analogWrite(BLUE, 50);
  }
  else if (fSo == fS) {
    analogWrite(RED, 0); analogWrite(GREEN, 50); analogWrite(BLUE, 0);
  }
  else if (fSo < fS) {
    analogWrite(RED, 50); analogWrite(GREEN, 0); analogWrite(BLUE, 0);
  }
  printVars();
  fSo = fS;
  Serial.println("Sending to Thingspeak");
  ThingSpeak.setField(1, fS);
  ThingSpeak.setField(2, hS);
  ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
}

It also does some fancy stuff with the LED on the development board I am using. (Well not that fancy, it just changes the color based on if the temperature is going up or down.)

Though it made sense to do it this way because Timer.h assumes that you have everything broken out into functions, I feel like I almost aesthetically drawn to the simplicity of the non-function version.

What do you think? Is that just a silly opinion?

Cool ESP8266 Display Project

Saw this over on Hackaday. Pretty nifty way to cheaply create an Internet-connected screen anywhere. I want dozens of them! Wish that they would put it out in kit form though, SMD and me are not always on friendly terms…

Anyone have an even cheaper, easier way of rigging up a wifi display (maybe just an LCD) with an ESP8266?

Arduino, Thingspeak & an ESP8266 (Part VI)

Fourth Revision: Has the Time come for Timer.h?

In my last post I discussed using a low-pass filter to improve readings from my DHT11. One of the major benefits of using this instead of my earlier method is that it freed me from the requirement of going through a set number of read cycles before sending to Thingspeak. Why is that important? Because I don’t really care about the exact number of read cycles, I just want to send accurate data to Thingspeak every minute or so. Another problem is that this often requires the use of long, blocking delays which are annoying and limit the future possibilities of the Sketch.

The solution to this is a small library called Timer.h. Originally developed by Simon Monk and then taken over by Jack Christensen and Damian Philip, Timer.h is a library that radically simplifies the process of timing events.

At its core is a pair of lines:

In voidSetup()

  t.every(timeperiod, function);

and in voidLoop()

  t.update();

How this works, is that it checks every cycle to see if “timeperiod” has passed and if it has it runs “function.” Simple as that!

However, it does require the script to be re-factored with functions. More on that in my next post but click below for the script

Continue reading “Arduino, Thingspeak & an ESP8266 (Part VI)”

Arduino, Thingspeak & an ESP8266 (Part V)

Fourth Revision: Now We Are Getting Somewhere!

In the fourth revision of this project things finally started to click together for me.

The problem with my last Sketch was that it used a relatively simple mechanism for averaging the readings between two successive cycles of sending data to Thingspeak. This did a decent job of leveling out strange readings but suffered from a major problem: it was impossible to tune. Is this a problem? Probably not, but it really, really annoyed me.

Another problem with this approach was that it was cycle dependent.  That means that I had no effective way of measuring the averaged reading between cycles!

The standard approach to solving this problem would be to use a moving average as is implemented here. However, I happened to be reading a copy of Simon Monk’s superb Programming Arduino: Next Steps and realized that his simple low-pass filter would do the trick.

Here is the basic equation of the filter:

(alpha * runningaverage) + ((1 - alpha) * newreading)

One way to think of this is if alpha = 0.95 then on every cycle 5% (0.05) of the new value is added to the running average.

There are a couple of advantages to this approach: 1) it is easy to understand, 2) it is easy to tweak (just change alpha), 3) it does not use arrays so is fairly memory friendly (not that that matters on the ESP8266!)

I’ll show you the actual sketch in the next post as I also changed how timing works and want to put that under a different heading.

Arduino, Thingspeak & an ESP8266 (Part IV)

Third Revision: Refactoring

The third version of this sketch is pretty similar to the last one. It just uses a for loop instead of a counter and if. Honestly the main reason for this revision is that the if seemed kind of tacky, not sure why I wrote it that way to begin with.

#include <ThingSpeak.h>
#include <ESP8266WiFi.h>
#include <DHT.h>

#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht (DHTPIN, DHTTYPE);

const char* ssid = "ssid";
const char* pass = "password";
const int RED = 15;
const int WHITE = 14;
const int GREEN = 13;
const int BLUE = 12;

int i = 0;
int c = 0;
float h = 0;
float f = 0;
float hsum = 0;
float fsum = 0;

unsigned long myChannelNumber = "channel number";
const char* myWriteAPIKey = "API Number";
WiFiClient client;

void setup() {
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  pinMode(WHITE, OUTPUT);

  Serial.begin(9600);
  delay(10);
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    analogWrite(RED, 75);
    delay(500);
    Serial.print(".");
  }

  if (WiFi.status() == WL_CONNECTED) {
    analogWrite(RED, 0);
    analogWrite(BLUE, 75);
    delay(100);
    analogWrite(BLUE, 0);
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  ThingSpeak.begin(client);

}

void loop() {
  for (c = 0; c < 10; c++) {
    analogWrite(WHITE, 50);
    Serial.print("c= ");
    Serial.println(c);
    float h = dht.readHumidity();
    float f = dht.readTemperature(true);
    Serial.print("f= ");
    Serial.print(f);
    Serial.print(" h= ");
    Serial.println(h);
    hsum = h + hsum;
    fsum = f + fsum;
    Serial.print("fsum= ");
    Serial.print(fsum);
    Serial.print(" hsum= ");
    Serial.println(hsum);
    analogWrite(WHITE, 10);
    delay(6000);
  }
  
  analogWrite(WHITE, 0);
  analogWrite(BLUE, 50);
  h = hsum / 10;
  f = fsum / 10;
  Serial.println("Sending");
  Serial.print("f= ");
  Serial.print(f);
  Serial.print(" h= ");
  Serial.println(h);
  ThingSpeak.setField(1, f);
  ThingSpeak.setField(2, h);
  ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  fsum = 0;
  hsum = 0;
  delay(100);
  analogWrite(BLUE, 0);
}


The resulting code is cleaner but it doesn’t really accomplish anything new. Oh well, this seems like the smarter, more sophisticated way to achieve the same task.

Continue reading “Arduino, Thingspeak & an ESP8266 (Part IV)”