fc2ブログ

Raspberry Pi Zeroをアクセスポイントとして使う(3)

 今回は、ESP8266のSPIFFS(SPI Flash File System)についてお話しします。ESP8266には1MBのArduinoスケッチ領域と3MBのファイルシステム(SPIFFS)領域があります。詳細はこのサイトに詳しく説明されています。また、ESP8266のメモリの情報は、このサイトの以下のプログラムで確認できます。
#include <ESP8266WiFi.h>

void setup(void) {
delay(1000);
Serial.begin(115200);

Serial.println();

Serial.println("-----ESP-WROOM-02 ( ESP8266 ) Chip Infomation -----");
Serial.println();

Serial.print("Core Version = ");
Serial.println(ESP.getCoreVersion());

Serial.print("CPU Frequency = ");
Serial.print(ESP.getCpuFreqMHz());
Serial.println(" MHz");

Serial.print("ChipID = ");
Serial.println(ESP.getChipId(), HEX); //MACアドレスの下位3バイト

Serial.print("Flash ID = ");
Serial.println(ESP.getFlashChipId(), HEX);

Serial.print("SDK version = ");
Serial.println(ESP.getSdkVersion());

Serial.print("Boot version = ");
Serial.println(ESP.getBootVersion());

Serial.print("Boot Mode = ");
Serial.println(ESP.getBootMode());

Serial.print("Flash Chip IDE Size = ");
Serial.print(ESP.getFlashChipSize()); //Arduino IDE 設定の Flash Size になる
Serial.println(" byte");

Serial.print("Flash Chip Real Size = ");
Serial.print(ESP.getFlashChipRealSize()); //ESP-WROOM-32 内蔵最大 Flash Size になる
Serial.println(" byte");

Serial.print("Flash Frequency = ");
Serial.print(ESP.getFlashChipSpeed());
Serial.println(" Hz");

String mode_str;
switch( ESP.getFlashChipMode() ){
case 0: mode_str = "QIO"; break;
case 1: mode_str = "QOUT"; break;
case 2: mode_str = "DIO"; break;
case 3: mode_str = "DOUT"; break;
case 4: mode_str = "Unknown"; break;
default: break;
}
Serial.println("Flash Chip Mode = " + mode_str);

Serial.print("Free Heap Size = ");
Serial.println(ESP.getFreeHeap());

Serial.print("Free Sketch Size = ");
Serial.println(ESP.getFreeSketchSpace());

Serial.print("Sketch Size = ");
Serial.println(ESP.getSketchSize());

Serial.println();

uint8_t mac0[6];
WiFi.macAddress(mac0);
Serial.printf("WiFi StationAP Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac0[0], mac0[1], mac0[2], mac0[3], mac0[4], mac0[5]);

uint8_t mac1[6];
WiFi.softAPmacAddress(mac1);
Serial.printf("WiFi SoftAP Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac1[0], mac1[1], mac1[2], mac1[3], mac1[4], mac1[5]);
}

void loop() {
}
結果は以下の通りで、実装メモリが4MBであることが確認できました。Memory_test_result_190526.png
 1回目に温湿度、気圧を計測できるセンサ(BME280)をつないだESP8266からWi-FiでデータをRaspberry Pi Zero(アクセスポイント)に自動で飛ばすシステムを構築するとお話ししましたが、このデータの一時保存としてSPIFFSを利用しようと考えました。早速、このサイトを参考にファイルシステムを利用できる環境を整えました。
 このサイトのreleases pageをクリックし、SPIFFS_install1_190526.pngESP8266FS-0.4.0.zipをダウンロードしました。SPIFFS_install2_190526.pngzipファイル解凍し、ESP8266FSフォルダを「Arduino ー toolsフォルダ」内にコピーするだけ完了です。toolsフォルダは新規に作成しました。ESP8266FS_folder_190526.png
 ファイルシステムが利用できるようになりましたので、以下のファイル(index.html)を作成し、SPIFFSに書き込んでみました。
<html>
<body>
<h1>SPIFFS test</h1>
</body>
</html>
作成スケッチのフォルダ内にdataフォルダを作成し、その中にファイルを保存し、FileUploaderSetting_190526.png「ツール-ESP8266 Sketch Data Upload」を実行すると、書き込みがスタートします。時間がかかるので、書き込みが終わるまでしばし待ちます。FileUploaderRun_190526.png
 次に、ファイルが確実に書き込まれているかを確認するために、SPIFFS内の情報を以下のプログラムで確認しました。
#include <FS.h>

String filename;

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("");

SPIFFS.begin();
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
filename = dir.fileName();
Serial.println("File Name: "+dir.fileName());

File f = dir.openFile("r");
Serial.println(String(" ") + f.size());
Serial.println(f.readStringUntil('¥n'));
Serial.println(f.readString());
}
}

void loop() {
}
実行結果は以下の通りで、正しくフラッシュメモリ上に書き込まれていることが分かりました。SPIFFS_FileCheck_190526.png
 次に、書き込まれたindex.htmlをWebページとして表示させるために、以下のプログラムを作成し、実行しました。ESP8266をアクセスポイントとして利用します。
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h>
#define WIFI_SSID "ESP8266-IoT"
#define WIFI_PWD "drbobt123"

ESP8266WebServer server( 80 );
IPAddress ip( 192, 168, 5, 1);
IPAddress subnet( 255, 255, 255, 0 );

void setup() {
SPIFFS.begin();

WiFi.mode(WIFI_AP);
WiFi.softAPConfig(ip, ip, subnet);
WiFi.softAP(WIFI_SSID, WIFI_PWD);

server.begin();
server.on("/",[]() {
String tmp;
File index = SPIFFS.open("/index.html", "r"); //index.html Open
if(!index)
Serial.println("file open failed");
else{
Serial.println("file open succeeded");
tmp = index.readString(); //Read index.html by string
index.close(); //close file
}
server.send(200, "text/html", tmp);} );
}

void loop() {
server.handleClient();
}
 最後にネットワークをESP8266のアクセスポイント(ESP8266ーIoT)に切り替え、NetworkSelection_190526.pngWebページ(192.168.5.1)を表示させると、フラッシュメモリ上のindex.htmlが表示できました。WebResult_190526.png
 簡便にESP8266のフラッシュメモリ内にファイルを保存できるので、様々な用途に利用できそうです。次回は、ESP8266からRaspberry Pi ZeroへのFTP通信のお話をします。
スポンサーサイト



Raspberry Pi Zeroをアクセスポイントとして使う(2)

 前回の続きです。Rebootで再起動した後、アクセスポイントとして動作させるために以下のコマンドを順番に実行しました。
sudo ifconfig wlan0 192.168.4.1 netmask 255.255.255.0 up
sudo /etc/init.d/isc-dhcp-server start
動作確認し、問題なしでした。Raspberry Pi Zeroを毎回起動するたびに同じコマンドを実行する必要があったため、自動実行するシェルスクリプトファイルを作成しました。
# dualnetwork.sh
sudo ifconfig eth0 192.168.11.30 netmask 255.255.255.0 up
sudo ifconfig wlan0 192.168.4.1 netmask 255.255.255.0 up
sudo /etc/init.d/isc-dhcp-server start
念のため、Home network用のeth0側の設定も行っています。次に、このスクリプトファイルをReboot時に自動実行させるために、crontabの設定ファイルに以下の1行を追加しました。
@reboot  bash /home/pi/dualnetwork.sh

 すべての設定、準備が終わりましたので、Raspberry Pi Zeroを再起動させて、MacBook Airからping確認をしました。
 まずは、Home network(192.168.11.0/24)です。MacのWi-Fi設定からアクセスポイントであるBuffaloのルータ(アクセスポイント)を選択します。Buffalo_setting.pngRaspberry Pi ZeroにはHome networkの192.168.11.30とIoT networkのアクセスポイント192.168.4.1を割り当てています。当然、192.168.11.30にはpingは通りますが、Buffalo_ping192_168_11_30.png192.168.4.1にはpingは通りません。Buffalo_ping192_168_4_1.png
 次に、IoT networkのアクセスポイントに接続するために、Wi-Fi設定から「Raspi_AP」を選択します。Raspi_AP_setting.pngこの時、MacBook AirのIPアドレスは192.168.4.2でした。ターミナルから192.168.11.30にpingを送りますが、今度は通りません。Raspi_AP_ping192_168_11_30.png次に、192.168.4.1については問題なくpingを通すことができました。Raspi_AP_ping192_168_4_1.pngRaspberry Pi Zeroが2つのIPアドレスを持ち、Iot networkのアクセスポイントとして機能していることが確認できました。

次回は、ESP8266のSPIFFS(SPI Flash File System)についてお話しします。

Raspberry Pi Zeroをアクセスポイントとして使う(1)

 2年ぶりに触っているESP8266を使った「簡便な自宅IoTシステム」を作ってみようと思い立ちました。思い立つ時はいつも急ですが・・。
 図にすると、こんな感じです。Multiple_Network_190519.pngすでに、自宅で「Home network」があり、Buffaloのルータ経由でInternet接続しています。ネットワークアドレスは「192.168.11.0/24」です。この「Home network」に「IoT network」を追加で構築するものです。温湿度、気圧を計測できるセンサ(BME280)をつないだESP8266からWi-FiでデータをRaspberry Pi Zeroに自動で飛ばすシステムにしようと思います。

 Raspberry Piは、有線、無線の双方を使えますが、今回はネットワークを分けますので、両方使います。有線側は「Home network」、無線側は「Iot network」で使用することにしました。「IoT network」は別のネットワークアドレス(192.168.4.0/24)に設定し、Pi Zeroはアクセスポイントとして利用する仕様です。ルータを新規に立てなくても、Pi Zero自身がルータ代わりをしてくれるのは便利ですね。アクセスポイントのIPアドレスを192.168.4.1に割り当てました。

 Raspberry Piの無線LANをアクセスポイントにする手順は、ネットにたくさん記事が出ているので、機械的にそれを真似して進めました。このサイトが非常にわかりやすかったので、参考にさせていただきました。ありがとうございます。

 以下、設定の手順等の覚書です。配線写真はこんな感じです。RaspiZero_MultiNetwork_190519.png1.固定IPアドレスの設定
 以下のコマンドでinterfacesファイルを修正し、有線、無線の双方のIPアドレスを「固定アドレス」にしました。
sudo nano /etc/network/interfaces
ファイルの中身は以下の通り。有線側のIPアドレスは192.168.11.30にしました。
auto lo
iface lo inet lookback

iface eth0 inet static
address 192.168.11.30
netmask 255.255.255.0
gateway 192.168.11.1

iface wlan0 inet static
address 192.168.4.1
netmask 255.255.255.0

pre-up iptables-restore < /etc/iptables.ipv4.nat
allow-hotplug wlan0

2.DHCPサーバー(isc- dhcp-server)のインストールと設定
 「IoT network」に接続するESP8266のIPアドレスを自動で設定するDHCP(Dynamic Host Configuration Protocol)サーバ機能の設定を行いました。まずは、アプリのインストールし、設定ファイルを修正しました。
sudo apt-get install isc-dhcp-server
sudo nano /etc/dhcp/dhcpd.conf
設定ファイルの修正箇所は、①コメントアウト2か所、②有効1か所、③追加の三点。

# option definitions common to all supported networks...
#option domain-name "example.org"; # 有効→コメントアウト
#option domain-name-servers ns1.example.org, ns2.example.org; # 有効→コメントアウト

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative; # コメントアウト→有効

ping-check true;

subnet 192.168.4.0 netmask 255.255.255.0 {
option routers 192.168.4.1;
option broadcast-address 192.168.4.255;
option subnet-mask 255.255.255.0;
option domain-name "local";
option domain-name-servers 8.8.8.8,8.8.4.4;
default-lease-time 600;
max-lease-time 7200;
range 192.168.4.2 192.168.4.254;
}
次にDHCPサーバーのデフォルトインターフェースをwlan0に設定しました。
sudo nano /etc/default/isc-dhcp-server
修正箇所は以下の通り。
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="wlan0"

3.APデーモン(hostapd)のインストールと設定
 アプリのインストールし、設定ファイルを修正しました。参考サイト通りです。
sudo apt-get install hostapd
sudo nano /etc/hostapd/hostapd.conf
ファイルがなかったので、以下のファイルを新規作成しました。
interface=wlan0
ssid=Raspi_AP
hw_mode=g
channel=3
wpa=2
wpa_passphrase=drbobt123
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
ここで、Raspberry Pi ZeroのWi-Fiアクセスポイントは「Raspi_AP」、パスワードは「drbobt123」としました。次に、以下のコマンドを実行し、
sudo nano /etc/default/hostapd
hostapdファイルのDAEMON_CONFにconfファイルを追記しました。
# Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration
# file and hostapd will be started during system boot. An example configuration
# file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz
#
DAEMON_CONF="/etc/hostapd/hostapd.conf"

4.Wi-Fiとイーサネット (wlan0とeth0)のルーティング設定
 以下のコマンドを実行し、sysctl.confファイルを修正しました。
sudo nano /etc/sysctl.conf
修正箇所は1か所のみです。
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1 # 有効→コメントアウト
修正後、以下のコマンドを実行しました。
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
sudo reboot
話が長くなりました。ちょうど、Raspberry Pi Zeroが再起動(Reboot)した所なので、続きの操作は、次回にお話しします。

MacにArduino実行環境を作る(4)

 前々回のブログで、ESP8266モジュール(製品名はAE-ESP-WROOM-02)のファームウェアの更新の件をお話ししました。
 その時の課題として「Mac用のファームウェア書き込みツール(Flash Download Tools)がない」ために、止むを得ず超遅いWindows10 PCを利用した件もお話ししました。

 ところが、ネット上を彷徨っていると、Mac単体でもファームウェアを更新できるツール、「esptool」があることを知りました(よく知っている人からすると、いまさらかも・・)。早速、インストールしてみました。
$ sudo pip install esptool
Macのターミナルからコマンド1つであっけなくインストールできました。

 ファームウェアの更新は、Windows版の「Flash Download Tools」の時のように、アドレスとデータファイル名を順番にコマンドに仕込みます。
0x00000 boot_v1.2.bin 
0x01000 user1.1024.new.2.bin
0x3FB000 blank.bin
0x3FC000 esp_init_data_default.bin
0x3FE000 blank.bin
0x7E000 blank.bin
コマンドは以下の通りです。以下のコマンドは「binファイル」がesptool.pyと同じフォルダ内にある時の例です。
$ esptool.py write_flash 0x00000 boot_v1.2.bin 0x01000 user1.1024.new.2.bin 0x3FB000 blank.bin 0x3FC000 esp_init_data_default.bin 0x3FE000 blank.bin 0x7E000 blank.bin
実行画面はこんな感じです・・。デバイス情報に続いて16行目から書き込みが行われています。
(py37) bin $ esptool.py write_flash 0x00000 boot_v1.2.bin 0x01000 user1.1024.new.2.bin 0x3FB000 blank.bin 0x3FC000 esp_init_data_default.bin 0x3FE000 blank.bin 0x7E000 blank.bin
esptool.py v2.6
Found 2 serial ports
Serial port /dev/cu.usbserial-FTB4XJSL
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: 5c:cf:7f:08:b0:4c
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0040
Compressed 1936 bytes to 1462...
Wrote 1936 bytes (1462 compressed) at 0x00000000 in 0.1 seconds (effective 107.7 kbit/s)...
Hash of data verified.
Compressed 419204 bytes to 300520...
Wrote 419204 bytes (300520 compressed) at 0x00001000 in 26.7 seconds (effective 125.6 kbit/s)...
Hash of data verified.
Compressed 4096 bytes to 26...
Wrote 4096 bytes (26 compressed) at 0x003fb000 in 0.0 seconds (effective 2053.4 kbit/s)...
Hash of data verified.
Compressed 128 bytes to 75...
Wrote 128 bytes (75 compressed) at 0x003fc000 in 0.0 seconds (effective 63.9 kbit/s)...
Hash of data verified.
Compressed 4096 bytes to 26...
Wrote 4096 bytes (26 compressed) at 0x003fe000 in 0.0 seconds (effective 2045.8 kbit/s)...
Hash of data verified.
Compressed 4096 bytes to 26...
Wrote 4096 bytes (26 compressed) at 0x0007e000 in 0.0 seconds (effective 2071.5 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
(py37) bin $
問題なく、ファームウェアが更新され、ATコマンドを受け付けることができました。Windows10のツールを使わなくてもよくなりました。やれやれ・・。

 その後、ESP8266のWiFiのモードを変えて遊んでいるのですが、モードを切り替えるごとにファームウェアの更新は必要ないようですね。Arduinoのプログラム上でモードを記載するだけで変更可能でした(これもいまさら・・)。結局、ファームウェアを更新するのはATコマンドを実行したい時や、ESP8266の調子が悪くなってリセットする時のみで良さそうです。
 また、ESP8266にデータを書き込む時、接続(connect)段階でエラーが出ることがよくありました。I00端子をGNDにするのは当然ですが、そのあとに、おまじない(Reset)として、原始的ですが+/-の電源線を数回抜き差ししています。その後、書き込みエラーは発生していません。変な感じですが・・。

 次回は、ESP8266のデータをRaspberryPi zeroにFTPで飛ばす件についてお話しします。

令和ゆかりの坂本八幡宮に行く

 GWも残り2日足らずになりました。5/2から実家の博多に一人で帰省しています。明日(5/5)の昼の新幹線で関西に戻る予定です。
 昨日(5/3)は年寄り2人と「博多どんたく」に出かけました。人の数が半端でないですね。毎年こんな感じですが・・。先日(4/29)の鎌倉以来の人人人の波です・・。GWの10連休の中にあって、どこに行っても人ばかりです。

 その中でも懲りずに、今日(5/4)はTVで騒がれている令和ゆかりの「坂本八幡宮」に行きました。先日のブログで「時代が変わろうが変わるまいが、自分自身がまず変わらないとね・・」のような偉そうなことを書いておきながら(その気持ちは変わらないですが)、話題の場所がどのような所か知りたくて、思わず行ってしまいました。実家から目的地までは1時間程度で行ける場所なので。

 坂本八幡宮の最寄りの駅は、西鉄の都府楼前という駅で、その昔、大宰府政庁があった場所のすぐそばです。大宰府政庁跡(都府楼跡)は小学生の頃、遠足で毎年のように行っていました。大宰府政庁跡1_190504現在は、かつて政庁の建物があったと思われる場所に土台の石が残るのみです。平坦な大変広い場所で、遠足にはもってこいの場所だったのではないかと思いました。周りに何もなく退屈だったかもしれませんが、記憶にありません・・。大宰府政庁跡2_190504 大宰府政庁跡を横目に、少し歩くと坂本八幡宮に着きました。すでに大勢の観光客が列をなしていました。参拝用の列と御朱印(手書)用の列が別々にありました。御朱印をネット販売・購入している呆れる人たちがニュース等で報道されていますが、バチ当たりですね。暑い中、長時間並んでいる人もいるんですよ・・。坂本八幡宮2_190504坂本八幡宮3_190504 今日は9時半ぐらいに目的地に着きましたが、御朱印(手書)の列が約3時間ぐらいの長蛇でした(警備の人談)。御朱印は参拝した証として入手するものという認識をもっているので、先に参拝せずに、御朱印の列の方に先に並ぶ方々もおられたのは、如何なものかなとも思いました。
 私は参拝用の列に並び、45分ぐらい待って参拝することができました。坂本八幡宮1_190501参拝後、直の手書ではありませんが、書き置きの御朱印を入手して、坂本八幡宮をあとにしました。坂本八幡宮御朱印_190504書き置きとは言え、大変立派なものをいただきました。

 日差しは大変強く、熱中症になりそうでしたが、お昼まで時間がありましたので、太宰府天満宮へ向かいました。御朱印と一緒に「梅ヶ枝餅1個の無料引換券」が付いていたこともあったので・・。梅ヶ枝餅引き換え_190504太宰府天満宮も人が非常に多いですね。参拝後、いつも太宰府に行った時に梅ヶ枝餅を必ず購入する店「きくち」で、無料の1個(食べ歩き用)とお土産を購入して帰宅しました。いつもながら美味しかったです。
 今日も昨日と同様、非常に暑いので、午後からうろうろするのは避けました。明日の移動にも差し支えますからね・・。

 それにしてもどこに行っても人ばかりの10連休ですね。ちなみにこのGW期間中に私が放浪した場所の人口密度は以下の通りでした。
 鎌倉(参道) > 博多どんたく > 太宰府 > 横浜 = お台場 
 明日は半日移動で終わってしまうので、明後日ゆっくり自宅で過ごし、再び始まる現実に備えようと思います。残り2日ありますが、英気は十分養うことができたと思います。

MacにArduino実行環境を作る(3)

 前回の続きです。ESP8266のアクセスポイントの設定が済みましたので、配線後にコーディングを行いました。配線図は以下の通りです。ESP8266_circuit_190501.pngメインの構成は、ESP8266(ESP-WROOM-02)と温湿度センサAE-BME280です。双方の通信は「I2C」を利用しました。MAX3232ECPEはMacとESP8266間の通信をするために利用しています。TA48033SはDC 5V電源を3.3Vに変換するためのものです。

 ソースコードはSwitch ScienceさんのGitHubサイトを参考にさせていただきました。ありがとうございました。作成したコードは以下の通りです。
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Wire.h>
#define WIFI_SSID "ESP8266-IoT"
#define WIFI_PWD "drbobt123"
#define BME280_ADDRESS 0x76

ESP8266WebServer server( 80 );
IPAddress ip( 192, 168, 4, 2 );
IPAddress subnet( 255, 255, 255, 0 );

unsigned long int hum_raw,temp_raw,pres_raw;
signed long int t_fine;
double temp_act = 0.0, press_act = 0.0,hum_act=0.0;
char temperature[16];
char atmospheric_pressure[16];
char humidity[16];

uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int8_t dig_H1;
int16_t dig_H2;
int8_t dig_H3;
int16_t dig_H4;
int16_t dig_H5;
int8_t dig_H6;

void setup()
{
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(ip, ip, subnet);
WiFi.softAP(WIFI_SSID, WIFI_PWD);

server.on ("/",handleRoot);
server.begin();
Serial.println ( "HTTP server started" );

uint8_t osrs_t = 1; //Temperature oversampling x 1
uint8_t osrs_p = 1; //Pressure oversampling x 1
uint8_t osrs_h = 1; //Humidity oversampling x 1
uint8_t mode = 3; //Normal mode
uint8_t t_sb = 5; //Tstandby 1000ms
uint8_t filter = 0; //Filter off
uint8_t spi3w_en = 0; //3-wire SPI Disable

uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
uint8_t config_reg = (t_sb << 5) | (filter << 2) | spi3w_en;
uint8_t ctrl_hum_reg = osrs_h;

Serial.begin(9600);
Wire.begin(4,5);

writeReg(0xF2,ctrl_hum_reg);
writeReg(0xF4,ctrl_meas_reg);
writeReg(0xF5,config_reg);
readTrim();
}

void loop()
{
signed long int temp_cal;
unsigned long int press_cal,hum_cal;

delay(5000);
readData();

temp_cal = calibration_T(temp_raw);
press_cal = calibration_P(pres_raw);
hum_cal = calibration_H(hum_raw);
temp_act = (double)temp_cal / 100.0;
press_act = (double)press_cal / 100.0;
hum_act = (double)hum_cal / 1024.0;
Serial.print("TEMP : ");
Serial.print(temp_act);
Serial.print(" DegC PRESS : ");
Serial.print(press_act);
Serial.print(" hPa HUM : ");
Serial.print(hum_act);
Serial.println(" %");

server.handleClient();
}

void readTrim()
{
uint8_t data[32],i=0;
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0x88);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,24);
while(Wire.available()){
data[i] = Wire.read();
i++;
}

Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xA1);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,1);
data[i] = Wire.read();
i++;

Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xE1);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,7);
while(Wire.available()){
data[i] = Wire.read();
i++;
}
dig_T1 = (data[1] << 8) | data[0];
dig_T2 = (data[3] << 8) | data[2];
dig_T3 = (data[5] << 8) | data[4];
dig_P1 = (data[7] << 8) | data[6];
dig_P2 = (data[9] << 8) | data[8];
dig_P3 = (data[11]<< 8) | data[10];
dig_P4 = (data[13]<< 8) | data[12];
dig_P5 = (data[15]<< 8) | data[14];
dig_P6 = (data[17]<< 8) | data[16];
dig_P7 = (data[19]<< 8) | data[18];
dig_P8 = (data[21]<< 8) | data[20];
dig_P9 = (data[23]<< 8) | data[22];
dig_H1 = data[24];
dig_H2 = (data[26]<< 8) | data[25];
dig_H3 = data[27];
dig_H4 = (data[28]<< 4) | (0x0F & data[29]);
dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
dig_H6 = data[31];
}

void writeReg(uint8_t reg_address, uint8_t data)
{
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(reg_address);
Wire.write(data);
Wire.endTransmission();
}

void readData()
{
int i = 0;
uint32_t data[8];
Wire.beginTransmission(BME280_ADDRESS);
Wire.write(0xF7);
Wire.endTransmission();
Wire.requestFrom(BME280_ADDRESS,8);
while(Wire.available()){
data[i] = Wire.read();
i++;
}
pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
hum_raw = (data[6] << 8) | data[7];
}

signed long int calibration_T(signed long int adc_T)
{

signed long int var1, var2, T;
var1 = ((((adc_T >> 3) - ((signed long int)dig_T1<<1))) * ((signed long int)dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T>>4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;

t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}

unsigned long int calibration_P(signed long int adc_P)
{
signed long int var1, var2;
unsigned long int P;
var1 = (((signed long int)t_fine)>>1) - (signed long int)64000;
var2 = (((var1>>2) * (var1>>2)) >> 11) * ((signed long int)dig_P6);
var2 = var2 + ((var1*((signed long int)dig_P5))<<1);
var2 = (var2>>2)+(((signed long int)dig_P4)<<16);
var1 = (((dig_P3 * (((var1>>2)*(var1>>2)) >> 13)) >>3) + ((((signed long int)dig_P2) * var1)>>1))>>18;
var1 = ((((32768+var1))*((signed long int)dig_P1))>>15);
if (var1 == 0)
{
return 0;
}
P = (((unsigned long int)(((signed long int)1048576)-adc_P)-(var2>>12)))*3125;
if(P<0x80000000)
{
P = (P << 1) / ((unsigned long int) var1);
}
else
{
P = (P / (unsigned long int)var1) * 2;
}
var1 = (((signed long int)dig_P9) * ((signed long int)(((P>>3) * (P>>3))>>13)))>>12;
var2 = (((signed long int)(P>>2)) * ((signed long int)dig_P8))>>13;
P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
return P;
}

unsigned long int calibration_H(signed long int adc_H)
{
signed long int v_x1;

v_x1 = (t_fine - ((signed long int)76800));
v_x1 = (((((adc_H << 14) -(((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) +
((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) *
(((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) *
((signed long int) dig_H2) + 8192) >> 14));
v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
v_x1 = (v_x1 < 0 ? 0 : v_x1);
v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
return (unsigned long int)(v_x1 >> 12);
}

void handleRoot() {

char temp[1000];
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;

dtostrf(temp_act,5,2,temperature);
dtostrf(press_act,5,1,atmospheric_pressure);
dtostrf(hum_act,5,2,humidity);

snprintf(temp,1000,"<html>\
<head>\
<meta http-equiv='refresh' content='5'/>\
<title>BME280 Measure</title>\
<style>body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }</style>\
</head>\
<body>\
<h2>BME280 Measurement</h2>\
<h2><p>Uptime: %02d:%02d:%02d</p></h2>\
<h2><p>Temperature: %s [ºC]</p></h2>\
<h2><p>Atmospheric pressure: %s [hPa]</p></h2>\
<h2><p>Humidity: %s [%]</p></h2>\
</body>\
</html>",
hr, min % 60, sec % 60, temperature, atmospheric_pressure, humidity);
server.send ( 200, "text/html", temp );
}
4、5行目にアクセスポイントにしたESP8266のSSIDとパスワードを設定しています。loopルーチンの83〜89行目は、Arduinoのターミナル上に表示されるデータです。実行時はこんな感じです。ESP8266_Terminal_output_190501.pngESP8266のWebサーバで表示される情報は、handleRootルーチンの233〜247行目に記載されています。出力はこんな感じです。ESP8266_Web_output_190501.png計測に5secのウェイト、ページ自動更新までの5secが加算されて10sec毎に自動でデータが表示されました。
 今後は採取したデータを別のPC(サーバ)に保存する計画です。

MacにArduino実行環境を作る(2)

 前回、MacにArduinoの実行環境を構築し、ESP8266モジュール(製品名はAE-ESP-WROOM-02)を操作し、Lチカする所まで終えました。
 今回は、以前のブログでお話しした、温湿度センサBME280、ESP8266、PICマイコン、7セグを組み合わせて作製したシステムを簡素化することからスタートしたいと思います。7セグとそれを制御しているPICマイコンはカットして、センサとESP8266のシンプルな構成にします。その際に追加で、ESP8266は無線のアクセスポイント(Webサーバ)として使用し、自宅でInternetに接続しているネットワークアドレス(192.168.11.0)と違うものに設定することにしました。

 早速、ATコマンドを打ち込んで、アクセスポイント設定を行おうとしましたが、いきなりつまづきました。ターミナルから「ATコマンド」を受け付けないのです・・。半日程度、ネットで情報を調べつつ、悩みながら、彷徨っていました。その中で、過去に自分が書いたブログに行き着きました。2年半前(2016/10/29)の記事です。以下抜粋。

「Arduino IDEでWi-Fiの通信のコードを書いてテストを行っている中で、ATコマンドを受け付けないことに気付きました。そう言えば、個人のシステムを書き込んでしまったら、元のファームウェアが消えてしまう記事を読んだことがありました・・。」

 結局、ファームウェアを入れ直さなくてはならないということです。2年半ほど前のことですが、記憶が吹っ飛んでいました・・(悲しいですね・・)。

 自分のブログ記事を頼りにESP8266のファームウェア更新を試みましたが、ここでまたつまづきました。結論から言うと、以下の問題がありました。
 ① Mac用のファームウェア書き込みツール(Flash Download Tools)がなかった。
 ② 最新のSDK(19/04/27現在:V3.0.0, 18/08/24 Release)は書き込みできなかった(エラーが出る)。
結局、①については、自宅で使うのを封印していたWindow10 PC(UbuntuとDual-bootのHPノート)を立ち上げて、②については2年半前のブログの記事の通りに古いファームウェアを入れ直しました。
・・それにしても、久々にWindows10を起動させましたが、涙が出るほどの遅さでした・・。HDDはクラッシュしそうなくらいカリカリ言っているし・・。

 ファームウェアも更新できたので、Windows10 PCの電源も早々にOFFにして再封印。Macに切り替えてATコマンドの確認を行いました。AT_command_check1_190501.png問題なく動作しました。次に、アクセスポイントの設定です。「AT+CWSAP」コマンドで設定しますが、説明は以下の通り。AP_setting_command_190501.pngSSIDを「ESP8266-IoT」、パスワードを「drbobt123」、ch No.は「5」、暗号化は「WPA2_PSK」に設定しました。ちなみに、パスワードは英字のみではエラーが出ました。数字が必要なようです。AT_command_check2_190501.png
 ESP8266側の設定が終わりましたので、Mac側からアクセスを確認します。Wi-Fiマークをクリックすると、登録したアクセスポイントが表示できました。Wi-Fi_setting1_190501.png接続するために、先ほど登録したパスワードを入力します。Wi-Fi_setting2_190501.pngTCP/IPを確認すると、アクセスポイントが「192.168.4.2」のIPアドレスで登録されたことが分かりました。Wi-Fi_setting3_190501.png早速、pingを通してみます。ping_check_190501.png問題なさそうです。

長くなりましたので、次回は、Arduinoでコーディングして、温湿度センサBME280のデータをWeb形式で確認する内容について、お話したいと思います。

ご訪問者数

(Since 24 July, 2016)

タグクラウド


プロフィール

Dr.BobT

Author: Dr.BobT
興味のおもむくままに生涯考え続けるエンジニアでありたい。

月別アーカイブ

メールフォーム

名前:
メール:
件名:
本文: