Archiv der Kategorie: ESP8266

Arduino compile on command line for ESP8266 for CI (Continuous Integration)

I wanted to test the functionality of GitLab for CI. As I have a lot of code which was written with the Arduino IDE for ESP8266-Boards, especially for the WeMos D1 Mini, I figured that I should try to automate the compile process for verification of the code.

There were some minor problems that I had to work out first, though:

# Unpack newest Arduino IDE somewhere, e.g. /opt/arduino/arduino-1.8.5 and cd to that dir
mkdir /opt/arduino
cd /opt/arduino
wget https://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz
tar xvfJ arduino-1.8.5-linux64.tar.xz
cd arduino-1.8.5

The further configuration MUST be made under the new user „gitlab-runner“, as this context will be used during the CI. So we have to create the user first and switch into his context:

sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
sudo su - gitlab-runner

Make sure that the current user is now the gitlab-runner, than continue:

# Add Additional Boards (ESP8266)
cd /opt/arduino/arduino-1.8.5
./arduino --pref "boardsmanager.additional.urls=https://adafruit.github.io/arduino-board-index/package_adafruit_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs
./arduino --install-boards esp8266:esp8266

The resulting board specifications can be found here:
~/.arduino15/packages/esp8266/hardware/esp8266/2.4.0/boards.txt

Some libraries can be installed easily as they are available directly from the official library list, these can be installed like this:

# Install SimpleDHT
./arduino --install-library SimpleDHT

Than there are some libraries, preferably on github, which are available as a tar.gz-File, these should be installed to the ~/Arduino/libraries-Directory, like this (for AsyncMQTTClient):

# Install AsyncMQTTClient
wget -q https://github.com/marvinroger/async-mqtt-client/archive/v0.8.1.tar.gz -O - | tar xvfz - -C ~/Arduino/libraries/

The above mentioned Library depends on ESPAsyncTCP, which is NOT available as a ZIP-File, so we have to clone the github directory and copy the relevant part to the Library-Directory:

# Install ESPAsyncTCP
GITCLONEDIR=$(mktemp -d) && git clone https://github.com/me-no-dev/ESPAsyncTCP ${GITCLONEDIR} && cp -r ${GITCLONEDIR}/src ~/Arduino/libraries/ESPAsyncTCP

To test compilation, we’ll be using the following short code, put it in a directory „ESP-TEST“ and name it „ESP-TEST.ino“:

#include <ESP8266WiFi.h>
 
void setup() {
  Serial.begin(115200);
  Serial.println("5s Deep Sleep initiating");
  ESP.deepSleep(5000000);
  delay(100);
}
 
void loop() {}

To run the compilation, we have to set the CPU Frequency (here: 80 MHz) and the Memory Ratio on how much we want to give to SPIFFS (here: 1M for SPIFFS):

./arduino -v --board esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M1M --verify ESP-TEST/ESP-TEST.ino

To activate the CI in GitLab, we first have to install the gitlab-runner as a service. Trouble is, the gitlab-runner which is available from within Ubuntu (17.10 as of the time of this writing) is incompatible with gitlab >10.0, so we MUST install it manually as mentioned on the GitLab Runner Install Site.

sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
sudo chmod +x /usr/local/bin/gitlab-runner
sudo /usr/local/bin/gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start

For updates of the runner in the future, you have to follow these instructions:

sudo gitlab-runner stop
sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
sudo chmod +x /usr/local/bin/gitlab-runner
sudo gitlab-runner start

In your GitLab Project-Settings, go to „CI/CD“ and use the values under „Specific Runners“ to register the runner. When asked for a executor, answer „Shell“. Please activate „git clone“ instead of „git fetch“, at least in my configuration I got errors like error: could not lock config file, the switch to „git clone“ resolved these.

sudo gitlab-runner register

By now the runner should be registered, but we still have to „run“ it. I prefer using a screen session for this. Exit the session by pressing CTRL+a and then „d“ (this „detaches the screen“, to return to the screen, enter screen -r gitlabrunner).

screen -S gitlabrunner
cd ~gitlab-runner
sudo gitlab-runner run --user=gitlab-runner
# Exit by pressing "CTRL+a" and then "d".

Finally we can start with the .gitlab-ci.yml. Add a file with this name to your project and add the following context (assuming you were using the example project from above):

build:
  stage: build
  script: 
  - /opt/arduino/arduino-1.8.5/arduino -v --board esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M1M --verify ESP8266-DHT22.ino

Batteriegestütztes Internet-of-Things-Device: ESP8266 Wemos D1-mini Temperatursensor mit WLAN und MQTT

Ich habe für das ChaosBBQ einen kleinen Workshop vorbereitet, bei dem man sich ein kleines IoT-Device selbst zusammenlöten kann. Die Idee war, dass es möglichst lange mit einfachen Batterien läuft. Daher habe ich ein paar Aspekte darin verarbeitet, die im Umgang mit Internet-of-Things („Internet der Dinge“) häufig verwendet werden:

  • Wemos D1.mini, ein Breakout-Board mit dem ESP8266-Chip
  • Programmierung mit der Arduino IDE
  • Kommunikation mit WLAN
  • Protokoll MQTT zur Kommunikation mit einem MQTT-Broker, um die gemessenen Temperatur-Werte zu übermitteln

Hier der kurze Überblick über die benötigten Utensilien:

  • Wemos D1.mini
  • Stiftleisten (sind meistens mitgliefert
  • 4.7 kOhm Widerstand
  • Temperatursensor DS18B20
  • Batteriebox (alternativ auch eine 3er-Box aus Conrad/Völkner/Reichelt/….
  • Nicht abgebildet: Lötkolben, Lötzinn, etwas kleine Kabel

Hier der Wemos D1.mini im Detail:

Als Trick zum einfach festlöten der Stiftleisten steckt man am besten die reinen Leisten mit den reinen Stiften umgedreht in ein Breadboard:

Hier noch Kabel, Temperatursensor und der Widerstand:

Okay ein wenig Standard-Lötzinn braucht man zum Löten doch noch:

Die Stiftleisten auf den Wemos D1.mini anlöten:

Die zweite Seite ist eigentlich optional, da nur eine Seite für den Sensor verwendet wird. Aber da wir schon mal dabei sind…

Von der Batteriebox aus muss noch die Stromversorgung angelötet werden. Dazu den nun mit den Stiftbuchsen bestückten Wemos D1.mini im Breadboard belassen und bei „3V3“ den Pluspol und bei „G“ den Minuspol anlöten.

Sofern nicht-aufladbare Batterien verwendet werden (wie in diesem Beispiel), so sollte man die Gesamtspannung bei 3 Volt belassen. Daher den dritten Batteriehalter mit einem Stück Draht überbrücken (hier in weiß). Verwendet man stattdessen Akkus, so liefern diese jeweils nur 1.2 Volt je Zelle und daher werden insgesamt 3.6 Volt benötigt. Mit 2.4 Volt wollte der ESP8266 partout nicht starten…

Damit der ESP8266 aus dem DeepSleep, in den wir ihn später schicken wollen, sich auch selbst wieder aufwecken kann, benötigt dieser noch eine Drahtbrücke zwischen D0 und RST (hier in blau). WICHTIG: Zur Programmierung muss diese Drahtbrücke wieder entfernt werden, daher diese dafür entfernen und – ganz wichtig – die Verbindung NICHT LÖTEN.

Fehlt noch der Temperatursensor selbst und ein Widerstand. Der Temperatursensor sollte mit der flachen Seite zum Chip liegen. Dann gehört das linke Bein in D5, die Mitte in D6 und das rechte Bein in D7. Nachdem man den Sensor eingesteckt hat, wird noch ein Widerstand zwischen 3V3 und dem mittleren Bein, also D6 benötigt. Dieser fungiert als „Pull-Up“ und stellt damit die Protokollfähigkeit sicher. Sollte der Sensor öfter sehr merkwürdige Werte (z.B. -127 °C) liefern, ist wahrscheinlich der Widerstand etwas herausgerutscht.

Damit der Sensor seine Daten auch verschickt, brauchen wir noch ein Programm, welches wir mit der Arduino IDE auf den ESP8266 aufspielen. Hierzu beachten, dass unter „Boards“ auch der Wemos D1.mini ausgewählt ist.

Voraussetzungen für die Arduino Umgebung:

Neueste Arduino Umgebung herunterladen und installieren (Stand Dezember 2017 ist das 1.8.5)

In den Voreinstellungen diese Boardverwalter-URL einfügen. Falls schon eine dort steht, kann man mit dem Knopf rechts daneben noch mehr hinzufügen.

Unter Werkzeuge -> Board -> Boardverwalter (erster Eintrag) sollte man dann nach „esp“ suchen und den Eintrag ESP8266 installieren.

Die OneWire-Bibliothek, die wir im Programm verwenden, muss unter Sketch -> Bibliothek einbinden -> Bibliotheken verwalten hinzugefügt werden.

Dasselbe muss auch für die DallasTemperature-Library geschehen.

Die verwendete AsyncMQTTClient-Bibliothek gibt es leider nicht fertig in Arduino hinterlegt, hier muss die Bibliothek als ZIP-Datei hinzugefügt werden. Sketch -> Bibliothek einbinden -> .ZIP-Bibliothek einbinden.

Diese URL hinzufügen (oder alternativ jede neueres Release vom async-mqtt-client, welches auf github von marvinroger liegt).

https://github.com/marvinroger/async-mqtt-client/archive/v0.8.1.zip

Dasselbe mit der Library ESPAsyncTCP, auf welche die async-mqtt-client basiert:

https://github.com/me-no-dev/ESPAsyncTCP/archive/master.zip

Im nachfolgenden Programm müssen noch die WLAN-SSID, das WLAN-Passwort, die IP des MQTT-Servers und der Topic-„Pfad“ und ggf. der Topic-„Name“ geändert werden.

// Wemos D1 board, connected to a battery box and a DS18B20 temperature sensor
//
 
// For temperature reading
// Libraries needed:
// * OneWire
// * DallasTemperature
//
// Pinout: https://wiki.wemos.cc/products:d1:d1_mini
// D0 = GPIO16 --> Connect D0 to RST for Deep Sleep-Wakeup
 
#include <OneWire.h> 
#include <DallasTemperature.h>
 
const char* ssid = "ENTER_YOUR_SSID_HERE";
const char* password = "ENTER_YOUR_WLAN_PASS_HERE";
 
#define DEVICENAME "maintopic/devicename"
#define TOPIC DEVICENAME"/temperature"
#define ONLINETOPIC DEVICENAME"/online"
#define MQTTSERVER IPAddress(37, 187, 106, 16) // test.mosquitto.org = 37.187.106.16
const int sleepTimeS = 300; // Reduce this value for debugging. Increase if you want more battery life
 
#define VCCPIN D7
#define ONE_WIRE_BUS D6
#define GNDPIN D5
 
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature sensors(&oneWire);
 
float tempC;
 
// For WLAN & MQTT
#include <ESP8266WiFi.h>
#include <AsyncMqttClient.h>
AsyncMqttClient mqttClient;
uint16_t packetId1Pub;
bool packet1Ack = false;
 
bool ready = false;
 
char *ftoa( double f, char *a, int precision)
{
 long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
 
 char *ret = a;
 long heiltal = (long)f;
 itoa(heiltal, a, 10);
 while (*a != '\0') a++;
 *a++ = '.';
 long desimal = abs((long)((f - heiltal) * p[precision]));
 itoa(desimal, a, 10);
 return ret;
}
 
void onMqttPublish(uint16_t packetId) {
  Serial.println("** Publish acknowledged **");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  if (packetId == packetId1Pub) {
    packet1Ack = true;
  }
  if (packet1Ack) {
    ready = true;
  }
}
 
void onMqttConnect(bool sessionPresent) {
  char buf[7];
  packetId1Pub = mqttClient.publish(TOPIC, 1, true, ftoa(tempC, buf, 2));
}
 
void setup() {
  pinMode(GNDPIN, OUTPUT);
  pinMode(VCCPIN, OUTPUT);
  digitalWrite(GNDPIN, LOW);
  digitalWrite(VCCPIN, HIGH);
  Serial.begin(115200); 
  Serial.println("ESP-Temperature-Reader-and-MQTT-Poster-via-WiFi"); 
  // Start up the sensors library 
  sensors.begin(); 
}
 
void loop() {
  // Send the command to get temperature readings 
  Serial.println("Requesting Temperature"); 
  sensors.requestTemperatures();
 
  // You can have more than one DS18B20 on the same bus.  
  // 0 refers to the first IC on the wire 
  Serial.println("Requesting Temperature from Device 0"); 
  tempC = sensors.getTempCByIndex(0);
 
  Serial.println("Connecting to WIFI"); 
  // Connect to WiFi
  WiFi.begin(ssid, password);
  int timeout = 0;
  while (WiFi.status() != WL_CONNECTED) {
    timeout++;
    if (timeout>20) {
        // WIFI isn't available after 10 seconds -> abort mission, mission's a failure
        initiateDeepSleep();
      }
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Print the IP address
  Serial.println(WiFi.localIP());
 
  // Publish result to MQTT
  mqttClient.onConnect(onMqttConnect);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTTSERVER, 1883);
  mqttClient.setKeepAlive(5).setCleanSession(false).setWill(ONLINETOPIC, 2, true, "no"); // .setCredentials("user", "pass").setClientId(DEVICENAME);
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
 
  timeout = 0;
  while (!ready) {
    delay(250);
    timeout++;
    if (timeout > 40)
    {
        // MQTT isn't available after 10 seconds -> abort mission, mission's a failure
        initiateDeepSleep();
    }
    Serial.print(".");
  }
  Serial.println("");
  initiateDeepSleep();
}
 
void initiateDeepSleep()
{
  ESP.deepSleep(sleepTimeS * 1000000);
  delay(100); 
}

Die Gesamtpräsentation mit allen Informationen von dieser Webseite könnt ihr hier auch noch herunterladen:

IoT Temperatursensor Präsentation ODP

IoT Temperatursensor Präsentation PDF

ESP8266-01 – Erste Schritte

Günstig kann man z.B. bei ebay ein paar ESP8266-Module kaufen, die ESP8266-01 sind besonders für den einfachen Start geeignet. Leider sind diese nicht 5V-freundlich (sondern hätten gerne 3.3V) und sind durch den 2×4-Pin-Anschluss nicht Breadboard-freundlich. Für die ersten fliegenden Tests mit ein paar Kabeln reicht es allemal.

Damit man zu Beginn nicht über ein paar Hürden stolpert, hier die von mir durchgeführten Schritte zur Inbetriebnahme eines ESP8266-01-Boards.

ESP8266-01

Über die Espressif-Seite erhält man am bequemsten die Information über das neuste SDK. Herunterladen kann man das SDK selbst dann in einem verlinkten Forum. Letztere Link ist mit Vorsicht zu genießen, lieber immer über die Hauptseite einsteigen. Im Forum kann man dann die letzte Version des SDKs herunterladen, zum Zeitpunkt der Verfassung dieses Artikels war das esp_iot_sdk_v1.2.0_mesh_v0.0.6_15_07_03.zip.

*** Hier Verkabelung ***

Jetzt wollen wir aber endlich mit unserem ESP8266 sprechen. Wenn alles richtig verkabelt ist, mit Putty im „Serial“-Modus und bei 76800 Bauds auf den COM-Port des USB-RS323 verbinden und AT gefolgt von STRG+M und STRG+J eingeben. Letzteres ist leider etwas umständlich, habe hier noch nichts bequemeres gefunden. Antworten sollte das ESP8266-01 mit „OK“. Hier der Auszug:

AT

OK
AT+GMR
0018000902-AI03

OK

Das zweite Kommando, AT+GMR liefert die aktuelle Firmwareversion des Chips aus.

Meine Version ist die 000902 firmware version 0.9.2, 0018 das AT-Level. Wir sind also hoffnungslos veraltet und sollten den Chip erstmal upgraden.

In den ausgepackten Ordner des SDKs wechseln, dort in den Unterordner „examples/at“ und das gen_misc.sh starten, folgende Auswahlen treffen:

gen_misc.bat version 20150511
.
Please follow below steps(1-5) to generate specific bin(s):
STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none)
enter(0/1/2, default 2):1
boot mode: new

STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin,
2=user2.bin)
enter (0/1/2, default 0):1
generate bin: user1.bin

STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)
enter (0/1/2/3, default 2):2
spi speed: 40 MHz

STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)
enter (0/1/2/3, default 0):
spi mode: QIO

STEP 5: choose flash size and map
    0= 512KB( 256KB+ 256KB)
    2=1024KB( 512KB+ 512KB)
    3=2048KB( 512KB+ 512KB)
    4=4096KB( 512KB+ 512KB)
    5=2048KB(1024KB+1024KB)
    6=4096KB(1024KB+1024KB)
enter (0/1/2/3/4/5/6, default 0):2