NodeMcu (2) Weather Station

この一週間Wemos miniのWiFi関連の開発中も頻繁にリブートしています。あまりにも回数が多いから、いつの間にchromeのたくさんの開いたタブも消えて復帰不能になりました。Macbook, Win10どちらも頻繁に発生。

原因がわからず、仕方なく開発中書き込み直前にUSBケーブル接続、書き込み終わったらすぐUSBケーブ抜く方法で運がよければリブート回避する状態が続て、悩んでいます。

気分転換に、IoT-Cloud-Mobile Kitに、Weather Station機能を組み入れると考えて、これも苦労の連続。

もともとWeather Station Kitは、NodeMcu V2とOLED, DHT11のセットになっている。IoT-Cloud-Mobile Kitは、Wemos MiniとOLED, BMP280のセットになっている。

IoT-Cloud-Mobile Kit Weather Station Kit
MPU Wemos Mini NodeMcu V2
OLED 128X64 OLED 128X64 OLED
Sensor BMP280  DHT11

最初は、WemosらしいのWeather Station ソースコードを改造して、IoT-Cloud-Mobile Kitで動くを考えたが、理由不明のリブートでやる気を無くされ、もうWeather Station Kitのまま部品を用意して、まず動かしてみることに。

I2CのOLED端子配列2種類があり:

  1. VCC,GND,SCL,SDA (Wemos, BMP180, BMP280バス直結可能)
  2. GND,VCC,SCL,SDA (NodeMcu直結可能)

IoT-Cloud-Mobile Kitでは、BMP280バス直結のため、1番目のOLED端子配列が欲しくて、商品写真見てこれだと、高めのOLED物を購入したが、結局送ってきたのは2番目のOLED物。

今度繋がってみたらわかった、2番目のOLED端子配列なら、嬉しいことに、NodeMcu直結可能。

つまり、1番目のOLED端子配列はWemos向き、2番目のOLED端子配列はNodeMcu向きと言える。

接線 (Wiring) NodeMCU –> OLED

  1. NodeMCU GND –> OLED GND
  2. NodeMCU 3.3V —> OLED Vcc
  3. NodeMCU D4 —-> OLED SCL
  4. NodeMCU D3 —-> OLED SDA

手元に余ってるはDHT22、それで試すことに。OLEDが邪魔で、D8に繋いで見た。

しかし上手くプログラム書き込めないので、DHT22を外したら、プログラム書き込めて、動いた。

また下記のセッティングは、自分の環境に合わせて設定。

* Begin Settings
const char* WIFI_SSID = "xxxx"; // your ssid
const char* WIFI_PWD = "xxxx"; // your password
const int I2C_DISPLAY_ADDRESS = 0x3c; // OLED I2C address
const int SDA_PIN = 13; // I2C OLED SDA
const int SDC_PIN = 14; // I2C OLED SCL
const float UTC_OFFSET = 9; // JST = +9
const String WUNDERGRROUND_API_KEY = "xxxxx"; // WUNDERGROUND API KEY
const String WUNDERGROUND_COUNTRY = "JP"; // japan
const String WUNDERGROUND_CITY = "Tokyo"; // tokyo
const String THINGSPEAK_CHANNEL_ID = "xxxxx"; // ThingSpeak CHANNEL
const String THINGSPEAK_API_READ_KEY = "xxxxx"; // ThingSpaek API KEY

OLEDの表示を上下逆にするには、void setup() の display.clear(); と ui.init(); の次にdisplay.flipScreenVertically(); を入れる。

ESP-WROOM-02 (1) Start

日本で認定されたESP8266を手元にあると、何にかいいかなと思って注文し、苦労の始まり。

電源なしで、長時間使えるもの、つまり太陽電池+バッテリーで運用を考えて、下記の品物を入手。

Wemos esp-wroom-02 Pocket 8266 D1 mini WIFI Module — ESP8266+18650 Battery

*その後の調べては、Flash Sizeは2Mしかない、Deep Sleep状態の消耗電流が大きいため、長時間運用向かないという情報が入り、時間があったら、確認して行きたい。

Wemos Pocketハードウェア

正面の左は充電回路。

背面はバッテリーホルダーになっている。

CP2102ドライバー

まずシリアル変換:CP2102のため、ドライバーのインストールが必要。

Silicon Labsの以下のURLから「Windows 7/8/8.1/10用」ドライバをダウンロード
USB – UART ブリッジ VCP ドライバ|Silicon Labs
ダウンロードしたZIP(CP210x_Windows_Drivers.zip)を展開し、CP210xVCPInstaller_x64.exeを実行し、ドライバインストールを開始する。

Arduino IDE 設定

それから、Wemosみたいな、メニューに専用設定選択肢がないため、Generic ESP8266 Moduleを選び、下記の様に細かく設定を変える。

設定項目 パラメーター
マイコンボード Generic ESP8266 Module
Flash Mode QIO
Flash Frequency 80MHz
Upload Using Serial
CPU Frequency 80MHz
Flash Size 4M (1M SPIFFS)
Debug port Disabled
Debug Level None
Reset Method nodemcu
Upload Speed 115200

Generic ESP8266 Moduleを選ぶ時のメニュー内容。

細かく設定を変えったあとの様子。

動作確認

簡単なスケッチで動作確認。WeMos の字の上にある 青色のLED ( GPIO 16 ) を点滅させる。

void setup() {
  pinMode(16, OUTPUT);
}
void loop() {
  digitalWrite( 16, HIGH );
  delay(25);
  digitalWrite( 16, LOW  );
  delay(250);
}

 

Webduino (5) Smart+DHT+OLED

Webduino Cloud Platformは、スケッチ保存できるクラウド環境。

(それまで、作ったスケッチは、保存できない!)

開始使用:https://cloud.webduino.io

Gmailのアカウントで簡単にログイン可能。

早速公開しているのスケッチ(Public Files から検索)を試す。意外に簡単。

Smart+OLED(圖片)

まずOLEDを増設、スケッチの通り結線しただけで表示ができた。

OLEDの接続と表示。

Smart+DHT+OLED

さらにDHT11を追加し、スケッチの通り結線しただけ、すごく気楽にできた。

DHT11を接続して、温度と湿度も簡単に表示できた。

Webduino (3) RGB LED

Webduino Smartに接続

Webduino Smartに接続方法は2つある

WiFi接続

WiFi接続はデバイスIDを利用して接続する。

この場合はWebduino Blockly ( https://blockly.webduino.io )を開いてプログラミングする。

WebSocket接続

WebSocket接続は、デバイスのローカルIPで接続する。

この場合、http://blockly.webduino.io/ を開いてプログラミングする。

ボタンでRGB LED点灯

Webduino Smartには、RGB LED内蔵なので、まず点灯してみる。

http://blockly.webduino.io/ を開いて、下記の通り、プログラミングする。

右上の “Run Blocks”をクリックして、Web Demo エリアのボタン1..5をクリックすると、対応色が点灯する。

Webduino (2) Update Firmware

ブラウザからデバイスにアクセスする場合、画面の左下に、Firmwareのバージョンが表示され(Ver 3.0.07)

セットアップが終わり、ファームウェアのアップデートを行うと勧められて、しかしどうしてもうまくいかないて、二日悩み中。

英語と中国語のtutorialsは、ここでマイクロスイッチを押し続け、ファームウェアのアップデートが自動的に行う。

  • https://webduino.io/en/tutorials/smart-02-setup.html
  • https://tutorials.webduino.io/zh-tw/docs/basic/board/smart-setup.html

しかし、いくら押し続けでも、LEDの反応がない、だがなぜかファームウェアのアップデートできない。ファームウェアのアップデートため、デバイスIDが取得できない。そして、Webduinoクラウドにも繋げられない。

悩んだ末、たまたまtutorialsのyoutubuを見てわかった。電源を再投入して、赤いLED点滅してる間に、マイクロスイッチを押し続ける

これてうまく行った!緑LED点灯など、しばらくして更新終了(無論更新中電源OFF駄目)、今度ブラウザからデバイスにアクセスする場合、デバイスIDが表示され、画面の左下に、更新後のFirmwareのバージョンが表示された。

Ver 3.1.4_0802

次にWebブラウザを使ったプログラミングを行う。

 

Webduino (1) Setup

About Webduino Smart

Webduino Smartとは、Web + Arduinoの意味合いをもち、ブラウザプログラミングができるESP8266モジュール。

https://webduino.io/

外形はESP8266でできたWemosと似ている、ただ基板の裏面は3色LED」と「明度センサー」が付いている。

Webduino Smart Wi-Fi Setup

このリンク先Webduino Smart Wi-Fi Setupを参考しながら進み。

まずはmicroUSBケーブルをさして電源を入れる。青LEDが点灯し、また裏面の3色LEDは赤点灯する。

この状態で、Webduino SmartはAPモードになる。

スマホなどからWiFi APを検索すると「Smart」というAPがいるので、そこに接続する。接続パスワードは「12345678」。

接続したらブラウザから「http://192.168.4.1」にアクセス。WiFi SSID/WiFI PWDは、自宅などのWiFI APを指定。また、Device IDは識別できるようなものを指定。「SUBMIT」ボタンをクリックし、変更を反映したら、電源を抜く。

電源を入れ直すと、裏面の3色LEDは、赤点灯したあと、一瞬緑点灯し、消灯する。

この状態で、自宅WiFI APに接続された状態となる。

Webdiunoに割り当てられたIPアドレスを確認するには、スマホなどでWiFi AP検索する。

上記の様に「Smart_<IPアドレス>」という形でIPアドレスが表示されるので確認する。

まずは動作確認として、パソコンから「http://<IPアドレス>」にアクセスできることを確認。

表示画面は、APモードでブラウザから「http://192.168.4.1」にアクセスする際と同じです。

 

C.H.I.P. (8) BMP280 i2c

OLED繋いだから、早速同じi2cのBMP280を試す。

chen@chip:~$ git clone https://github.com/prisme60/BMP280.git

コメントに書いてる方法でコンパイル

chen@chip:~/BMP280$ gcc -Wall -o BMP280 ./BMP280.c
./BMP280.c: In function ‘main’:
./BMP280.c:339:2: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode
for(int i = 0; i < argc; i++) {
^
./BMP280.c:339:2: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code
./BMP280.c:371:4: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode
for(int i=0;i<20;i++) {
^

エラーがたくさんある。オプションがつければいいらしい。

chen@chip:~/BMP280$ vi BMP280.c

でもソースを斜めてみると、二箇所だけfor文に定義するから、簡単に直せる。ただ定義文を関数先頭に書くだけ。

chen@chip:~/BMP280$ gcc -Wall -o BMP280 ./BMP280.c
chen@chip:~/BMP280$ ./BMP280

i2c_Open : Failed to open the i2c bus, error : 13
Check to see if you have a bus: /dev/i2c-1
This is not a slave device problem, I can not find the bus/port with which to talk to the device

sudoじゃないとダメだね。

chen@chip:~/BMP280$ sudo ./BMP280

Device accessed via File descriptor:3 at Address:0x76 has returned:0
[0]=3 [1]=6E [2]=B5 [3]=66 [4]=32 [5]=0
T1=28163 T2=26293 T3=50
P1=38053 P2=-10790 P3=3024 P4=7462 P5=-175 P6=-7 P7=15500 P8=-14600 P9=6000
adc_Temperature=536630 adc_Pressure=311387
{“temperature”:26.96,”Pressure64″:1017.5,”Pressure32″:1017.5,”PressureDouble”:1017.5}
adc_Temperature=536636 adc_Pressure=311390
{“temperature”:26.97,”Pressure64″:1017.5,”Pressure32″:1017.5,”PressureDouble”:1017.5}
adc_Temperature=536636 adc_Pressure=311390
{“temperature”:26.97,”Pressure64″:1017.5,”Pressure32″:1017.5,”PressureDouble”:1017.5}

延々と続く…

C.H.I.P. (7) OLED i2c

NokiaのLCDを付けるつもりで進んていたが、接続例が見つからないので、例があるOLEDにした。

Battery Connector, OLED, BMP280, Buttons shield

バッテリー、OLED、温度気圧センサー、いくつボタンを入れたシェルターを作った。(バッテリーちょっと大きかった)

OLEDは、i2c-1に繋いだ。

いざmakeすると、足りないものが多いので、足しながら、makeが成功。

root@chip:/home/chip# apt-get update #しないと、パッケージインストールがうまくいかない

root@chip:/home/chen# git clone https://github.com/vkomenda/ssd1306.git

root@chip:/home/chen# cd ssd1306/

root@chip:/home/chen/ssd1306# apt-get install gcc make #make がまたないので、追加

root@chip:/home/chen/ssd1306# make

 

これてやっと完了。

root@chip:/home/chen/ssd1306# ./ssd1306_demo /dev/i2c-
i2c-0 i2c-1 i2c-2
root@chip:/home/chen/ssd1306# ./ssd1306_demo /dev/i2c-1

devには、i2cは3つもあるので、繋がっているのは、i2c-1でしょうだから、試したら、成功。

 

WeMos (c8) Web Motor Shield Control

学園祭のため、IoTぼいのスマート車を作る。

しかし、注文したMotor Shield とは、違うもの(base only)が来たので、急遽自作する。

そのためのコントロールするAppも作りたいが、時間がなくって、ネットからWebページでコントロールするものを探して、沢山手直して、動くようになった。

車数台用意して、各車のIPは固定にしたいので、WiFiManager使わない方法をとった。

Webページでコントロールするから、遅延は目たつ。

時間があったら、ちゃんとアクセルペダルなど追加して、アプリの形にしたい。

// include libraries
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

#define motor_lf D3
#define motor_lb D4
#define motor_rf D6
#define motor_rb D5

// configure server
ESP8266WebServer server(80);
const char *form = "<!DOCTYPE HTML>"
"<meta name='viewport' content='width=device-width'>"
"<html>"
"<center><form action='/'>"
"<button name='dir' type='submit' value='4'>Forward</button><p>"
"<button name='dir' type='submit' value='1'>Left</button> "
"<button name='dir' type='submit' value='2'>Right</button><p>"
"<button name='dir' type='submit' value='3'>Reverse</button><p><p>"
"<button name='dir' type='submit' value='5'>Stop</button>"
"</form></center>"
"</html>";
void stop(void)
{
    analogWrite(motor_lf, 0);
    analogWrite(motor_lb, 0);
    analogWrite(motor_rf, 0);
    analogWrite(motor_rb, 0);
}
void forward(void)
{
    analogWrite(motor_lf, 1023);
    analogWrite(motor_lb, 0);
    analogWrite(motor_rf, 1023);
    analogWrite(motor_rb, 0);
}
void backward(void)
{
    analogWrite(motor_lf, 0);
    analogWrite(motor_lb, 1023);
    analogWrite(motor_rf, 0);
    analogWrite(motor_rb, 1023);
}
void left(void)
{
    analogWrite(motor_lf, 0);
    analogWrite(motor_lb, 0);
    analogWrite(motor_rf, 1023);
    analogWrite(motor_rb, 0);
}
void right(void)
{
    analogWrite(motor_lf, 1023);
    analogWrite(motor_lb, 0);
    analogWrite(motor_rf, 0);
    analogWrite(motor_rb, 0);
}
void handle_form()
{
    // only move if we submitted the form
    if (server.arg("dir"))
    {
        // get the value of request argument "dir"
        int direction = server.arg("dir").toInt();
        // chose direction
        switch (direction)
        {
            case 1:
                left();
                break;
            case 2:
                right();
                break;
            case 3:
                backward();
                break;
            case 4:
                forward();
                break;
            case 5:
                stop();
                break;
        }
        // move for 300ms, gives chip time to update wifi also
        delay(300);
    }
    
    // in all cases send the response
    server.send(200, "text/html", form);
}
void setup()
{
    // connect to wifi network
    WiFi.begin("uislab003", "**password**");
    // static ip, gateway, netmask
    WiFi.config(IPAddress(192,168,11,10), IPAddress(192,168,11,1), IPAddress(255,255,255,0));
    // connect
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(200);
    }
  
    // set up the callback for http server
    server.on("/", handle_form);
    // start the webserver
    server.begin();
    pinMode(motor_lf, OUTPUT); // 
    pinMode(motor_lb, OUTPUT); // 
    pinMode(motor_rf, OUTPUT); // 
    pinMode(motor_rb, OUTPUT); // 

}
void loop()
{
    // check for client connections
    server.handleClient();
}