lynx   »   [go: up one dir, main page]

ラベル ESP32 の投稿を表示しています。 すべての投稿を表示
ラベル ESP32 の投稿を表示しています。 すべての投稿を表示

2021年6月24日木曜日

ESP32-DevkitCとDHT11とCDSで、温度・湿度・明るさのデータをPostgreSQLに保存するデータロガーを作成する

ESP32-DevkitCとDHT11とCDSで、温度・湿度・明るさのデータをPostgreSQLに保存するデータロガーを作成するには、以下の手順を実行します。
構成としてはESP32-DevkitCに接続したDHT11で温度・湿度を取得し、CDSで明るさを取得します。ESP32-DevkitCからWiFi経由でPC側のFlaskのRESTサービスにアクセスしデータを受け渡し、PostgreSQLにデータを保存します。

〇ESP32-DevkitCとDHT11とCDSを接続した写真

データロガーの開発手順 1. PC側:PostgreSQLのデータベースにテーブルを作成する
以下のSQLコマンドを実行して、温度・湿度・明るさを保持するテーブルを作成します。
create table iot_sensor_data
(
  device_name varchar(30) not null,
  data_ts timestamp not null,
  temperature integer,
  humidity integer,
  lightness integer,
  constraint pk_iot_sensor_data primary key (device_name, data_ts)
);

※PostgreSQLをインストールしていない場合は、以下の記事を参照してください。
・Ubuntu20.04にインストールしたい場合は、以下の記事のPostgreSQLのインストール部分を参照してください。
Ubuntu 20.04にNextcloud20とPostgreSQL13をインストールする

・Raspberry Piにインストールしたい場合は、以下を参照してください。
Raspberry Pi(Raspbian Buster)にPostgreSQL11をインストールしてtestデータベースとtestユーザを作成する

2. PC側:ユーザの追加
Flaskを実行するユーザpyを作成するには、以下のコマンドを実行します。
sudo addgroup py

sudo adduser --quiet --gecos "" --ingroup py py

3. PC側:pipenvのインストール
sudo apt-get -y install python3-pip python3-distutils python3-dev python3-testresources

sudo pip3 install --upgrade setuptools

sudo pip3 install pipenv

echo "export PIPENV_VENV_IN_PROJECT=true" >> ~/.bashrc

source ~/.bashrc

4. PC側:flaskとpsycopg2のインストール
以下のコマンドで、flaskとpsycopg2をインストールした仮想環境を作成します。
sudo apt-get -y install libpq-dev

sudo mkdir -p /opt/iot_logger

sudo chown py:py /opt/iot_logger
※ここから作成したpyユーザで以下のコマンドを実行します。
cd /opt/iot_logger

pipenv --python 3

pipenv install flask psycopg2-binary

pipenv shell

5. PC側:REST APIでデータを受け取り、PostgreSQLに保存するFlaskアプリケーションの構築
以下のコードを/opt/iot_loggerのapp.pyに保存します。

app.py
from flask import Flask, jsonify, request
import time
import os
import psycopg2
import psycopg2.extras

def dbconnect():
    conn = psycopg2.connect(host=os.environ['PG_HOST'], port=os.environ["PG_PORT"], database=os.environ['PG_DB'], user=os.environ['PG_USER'], password=os.environ['PG_PASS'])
    return conn

sql = """insert into iot_sensor_data values ('ESP32-DevkitC', current_timestamp, %s, %s, %s)"""

@app.route('/iot_logger', methods=["POST"])
def iot_logger():
    print(request.get_data())
    temp = int(request.json['temp'])
    humidity = int(request.json['humidity'])
    lightness = int(request.json['lightness'])

    conn = dbconnect()
    #with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
    with conn.cursor() as cur:
        cur.execute(sql , (temp, humidity, lightness))
    conn.commit()
    return {"status":"ok"}

app = Flask(__name__)
app.run(debug=True, host='0.0.0.0', port=5001, threaded=True)

4. PC側:テスト実行
Flaskを実行するには、以下のコマンドを実行します。
export PG_HOST=(PostgreSQLのホスト名またはIPアドレス)
export PG_PORT=(PostgreSQLのポート:デフォルトは5432)
export PG_DB=(PostgreSQLのデータベース名)
export PG_USER=(ユーザ名)
export PG_PASS=(パスワード)

export FLASK_APP=app.py

flask run -h 0.0.0.0 -p 5001
※Ctrl+Cで停止します

5. PC側:サービス化
以下のコマンドでFlaskアプリケーションをサービス化して実行します。
cat << EOF | sudo tee /etc/systemd/system/iot_logger.service
[Unit]
Description=IoT logger
[Service]
Type=simple
Environment=export PG_HOST=(PostgreSQLのホスト名またはIPアドレス)
Environment=export PG_PORT=(PostgreSQLのポート:デフォルトは5432)
Environment=export PG_DB=(PostgreSQLのデータベース名)
Environment=export PG_USER=(ユーザ名)
Environment=export PG_PASS=(パスワード)
Environment=export FLASK_APP=app.py
ExecStart=/opt/iot_logger/.venv/bin/python3 app.py
User=py
Group=py
WorkingDirectory=/opt/iot_logger
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable iot_logger

sudo systemctl start iot_logger

6. ESP32-DevkitC側:ESP32-DevkitCとDHT11/CDSの配線
ESP32-DevkitCとDHT11センサーモジュール/CDSを配線します
DHT11のDigitalピンへ(付属ケーブルの緑) -> ESP32-DevKitCのIO27ピン
DHT11のGNDへ(付属ケーブルの黒) -> ESP32-DevKitCのGNDピン
DHT11のVへ(付属ケーブルの赤) -> ESP32-DevKitCの3V3ピン

※ESP32とDHT11の接続は以下の記事を参照してください。
ESP32-DevkitCとDHT11で計測した温度・湿度をWiFi経由のREST APIで通知する

CDS,10KΩ抵抗を以下の様に接続します。
※CDSの接続は以下の記事を参照してください。
ESP32-DevkitCとCDSで明るさを計測する

4つのエネループをセットした電池ボックスのプラスは5V端子、マイナスはGNDに接続します。
※電池と基板の接続は以下の部品を使用しました。
XHコネクタ ベース付ポスト トップ型 2P B2B-XH-A(LF)(SN)
https://akizukidenshi.com/catalog/g/gC-12247/

電池ボックス 単3×4本 スイッチ付 XHコネクタ付
https://akizukidenshi.com/catalog/g/gP-12242/

7. ESP32-DevkitC側:プログラミング
以下のプログラムをmain.pyとして、ESP32-DevkitCに保存します。dhtのライブラリ導入は、上記のDHT11の記事を参照してください。
import machine 
import time
import dht
import urequests
import ujson
import network

# WiFiのssid
ssid = "WiFiのssid"
# WiFiのパスワード
password = "Wifiのパスワード"
# REST APIの接続先
url = "http://(ホスト名またはIP):(ポート番号)/iot_logger"
header = {'Content-Type':'application/json'}

def connect_wifi():
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print("connecting to network...")
        sta_if.active(True)
        sta_if.connect(ssid, password)
        while not sta_if.isconnected():
            pass
    print("network config:", sta_if.ifconfig())

# ADC初期化
pin35 = machine.Pin(35, machine.Pin.IN)
cds = machine.ADC(pin35)
cds.atten(machine.ADC.ATTN_11DB) # 11dBの減衰率、約3.6v が最大入力電圧

# DHT11初期化
dht11 = dht.DHT11(machine.Pin(27))
time.sleep(1)
while True:
    # WiFi接続
    connect_wifi()

    # 測定
    dht11.measure()
    temp = dht11.temperature()
    humidity = dht11.humidity()
    lightness = cds.read()

    # REST APIに通知
    data = ujson.dumps({"temp":str(temp), "humidity":str(humidity), "lightness":str(lightness)})
    try:
        resp = urequests.post(url, data=data.encode("utf-8"), headers = header)
        print(resp.json())
        resp.close()
    except OSError as err:
        print(err)
        print("----")
    
    # deepsleep
    #time.sleep(2)
    machine.deepsleep(60*60*1000) # 3600sec=1時間

8. ESP32-DevkitC側:データ確認
以下のSQLを実行して、センサーデータが保存されていることを確認します。
select * from iot_sensor_data

2021年6月23日水曜日

ESP32-DevkitCとCDSで明るさを計測する

ESP32-DevkitCとCDSで明るさを計測するには、以下の手順を実行します。

〇ESP32-DevkitCとCDSを接続した写真

開発手順 1. ESP32-DevkitCの他、以下の部品を用意します。
・CdSセル 5mmタイプ
https://akizukidenshi.com/catalog/g/gI-00110/

・カーボン抵抗(炭素皮膜抵抗) 1/4W10kΩ (100本入)
https://akizukidenshi.com/catalog/g/gR-25103/

・プリント基板 両面 HK-PKW01H
https://elpadirect.com/shopdetail/000000001788/
※その他、適当な大きさのユニバーサル基板でも大丈夫です。

・分割ロングピンソケット 1×42 (42P)
https://akizukidenshi.com/catalog/g/gC-05779/
※ESP32-DevkitCを上記基板に挿すのに使用しています

※以下の2つはCDSを上記基板に直付けしない場合は、以下の様なサブ基板を使用します。
・16ホールユニバーサル基板(2.54mm)
https://akizukidenshi.com/catalog/g/gP-02515/

・ピンソケット(メス) 1×3(3P)
https://akizukidenshi.com/catalog/g/gC-10098/

・ピンヘッダ 1×40 (40P)
target=_blank">https://akizukidenshi.com/catalog/g/gC-00167/

〇使用部品(一部)の写真

2. 配線
CDS,10KΩ抵抗を以下の様に接続します。

3.ESP32-DevkitCでのプログラミングと実行
デフォルトだとADCで1Vまでしか測れないので、atttenメソッドで減衰率を設定して3.6Vまで計測できるように設定します。
attenメソッドの詳細は以下を参照してください。
ADC (アナログ/デジタル変換)
https://micropython-docs-ja.readthedocs.io/ja/latest/esp32/quickref.html#adc-analog-to-digital-conversion

以下のプログラムをmain.pyとしてESP32-DevkitCに保存し、実行します。
import machine 
import time

pin35 = machine.Pin(35, machine.Pin.IN)
cds = machine.ADC(pin35)
cds.atten(machine.ADC.ATTN_11DB) # 11dBの減衰率、約3.6V が最大入力電圧

while True:
    lightness = cds.read()
    print("cds: {}".format(lightness))
    time.sleep(2)

2021年6月22日火曜日

ESP32-DevkitCとBME680で計測した温度・湿度・気圧・ガスセンサー値をWiFi経由のREST APIで通知する

ESP32-DevkitCとBME680で計測した温度・湿度・気圧・ガスセンサー値をWiFi経由のREST APIで通知するには、以下の手順を実行します。今回は、ESP32-DevkitCで計測した温度・湿度・気圧・ガスセンサー値の情報をRESTで送信しPC側のFlaskで受信します。

〇ESP32-DevkitCとBME680を接続した写真

開発手順 1. PC側:pipenvの導入
pipenvをインストールしていない場合は、以下のコマンドを実行します。
sudo apt-get update

sudo apt-get -y install python3-pip python3-distutils python3-dev

sudo pip3 install --upgrade pip

sudo pip3 install --upgrade setuptools

sudo pip3 install pipenv

echo "export PIPENV_VENV_IN_PROJECT=true" >> ~/.bashrc

source ~/.bashrc

2. PC側:flaskがインストールされた仮想環境の作成
pipenvを使用する場合は以下のコマンドで、flask用の仮想環境を作成します。
mkdir -p ~/flask_bme680

cd ~/flask_bme680

pipenv --python 3

pipenv install flask

pipenv shell

3. PC側:Flask REST APIアプリケーションの作成
/bme680にPOSTされた温度・湿度・気圧・ガスセンサー値データを取得して表示し、再びJSONで返すコードを実装します。

app.py
from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/bme680', methods=["POST"])
def receive_bme680_values():
    print(request.get_data())
    temp = request.json['temp']
    humidity = request.json['humidity']
    pressure = request.json['pressure']
    gas = request.json['gas']
    print("temp: {}C".format(temp))
    print("humidity: {}".format(humidity))
    print("pressure: {}".format(pressure))
    print("gas: {}".format(gas))
    return {"temp":str(temp), "humidity":str(humidity), "pressure":str(pressure), "gas":str(gas)}

4. PC側:Flast REST APIアプリケーションの実行
Flaskを実行するには、以下のコマンドを実行します。
export FLASK_APP=app.py

flask run -h 0.0.0.0

実行時に表示されるURLを控えておきます。

5. ESP32-DevkitC側:BME680の準備
BME680は秋月電子さんの「BME680使用 温湿度・気圧・ガスセンサモジュールキット」を使用しました。
https://akizukidenshi.com/catalog/g/gK-14469/

6. ESP32-DevkitC側:ESP32-DevkitCとBME680の配線
ESP32-DevkitCとBME680センサーモジュールを配線します
ESP32-DevkitCの3V3ピン(USBを手前・ピン足を下にした時、左上のピン) -> BME680のVIN
ESP32-DevkitCのIO21ピン(USBを手前・ピン足を下にした時、右上から6番目のピン) -> BME680のSDA
ESP32-DevkitCのIO22ピン(USBを手前・ピン足を下にした時、右上から3番目のピン) -> BME680のSCL
ESP32-DevkitCのGNDピン(USBを手前・ピン足を下にした時、右上のピン) -> BME680のGND

7. ESP32-DevkitC側:ESP32-DevkitCにMicroPythonの導入
PCにインストールしたThonnyなのでMicroPythonファームウェアを書き込みます。
MicroPythonファームウェアは以下のページから「esp32-20210418-v1.15.bin」をダウンロードしておきます。
https://micropython.org/download/esp32/

8. ESP32-DevkitC側:urequests/bme680モジュールのアップロード
以下のページからダウンロードした(RAWボタンでリンク先を保存)urequests.py/bme680.pyをESP32-DevkitCの/libフォルダに配置します(/libフォルダが無い場合はThonnyなどで作成します)
https://github.com/micropython/micropython-lib/blob/master/urequests/urequests.py

https://github.com/robert-hh/BME680-Micropython/blob/master/bme680.py

9. ESP32-DevkitC側:プログラミングと実行
以下のコードのssid/パスワード/URLを設定してmain.pyとしてESP32-DevkitCに保存します。実行後、温度と湿度がPC側に2秒おきに表示されることを確認します。
from bme680 import *
import machine 
import time
import urequests
import ujson
import network

# WiFiのssid
ssid = "xxx"
# WiFiのパスワード
password = "xxx"
# REST APIの接続先
url = "http://xxx.xxx.xxx.xxx:5000/bme680"
header = {'Content-Type':'application/json'}


def connect_wifi():
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print("connecting to network...")
        sta_if.active(True)
        sta_if.connect(ssid, password)
        while not sta_if.isconnected():
            pass
    print("network config:", sta_if.ifconfig())


# BME680初期化
i2c=machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21))
#print(i2c.scan())
bme = BME680_I2C(i2c)
time.sleep(1)
while True:
    # WiFi接続
    connect_wifi()

    # 測定&REST APIに通知
    data = ujson.dumps({"temp":str(bme.temperature), "humidity":str(bme.humidity), "pressure":str(bme.pressure), "gas":str(bme.gas)})
    resp = urequests.post(url, data=data.encode("utf-8"), headers = header)
    print(resp.json())
    resp.close()
    
    # deepsleep
    machine.deepsleep(2000)

2021年6月21日月曜日

ESP32-DevkitCと照度センサーモジュールで照度を測る

ESP32-DevkitCと照度センサーモジュールで照度を測るには、以下の手順を実行します。
照度モジュールは、秋月電子さんの以下の照度センサーモジュールを使用しました。i2cでESP32-DevkitCと通信します。

TSL25721使用 照度センサーモジュール
https://akizukidenshi.com/catalog/g/gK-15536/

開発手順 1. ピンのハンダ付けと、ESP32-DevkitCへの接続
・ESP32-DevkitCとジャンパー線で接続した照度センサーモジュール

ESP32-DevkitCと照度センサーモジュールは以下の様に接続します(モジュールの裏面にピン略称が印刷されています)
ESP32-DevkitCの3V3ピン(USBを手前・ピン足を下にした時、左上のピン) -> TSL25721のVIN
ESP32-DevkitCのIO21ピン(USBを手前・ピン足を下にした時、右上から6番目のピン) -> TSL25721のSDA
ESP32-DevkitCのIO22ピン(USBを手前・ピン足を下にした時、右上から3番目のピン) -> TSL25721のSCL
ESP32-DevkitCのGNDピン(USBを手前・ピン足を下にした時、右上のピン) -> TSL25721のGND

2. プログラムの作成と実行
以下のプログラムをmain.pyファイルとしてESP32-DevkitCに保存して、実行します。

import time
from machine import Pin, I2C
i2c=I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)

addr_tsl25721=0x39
#print(i2c.scan())
FIELD_COMMAND = 0x80 # Write
FIELD_TYPE = 0x20 #  Auto-increment protocol transaction

REG_CONTROL = 0x0F # Control Register
VAL_CONTROL_RESET = 0x00 # Reset Value for Control Register
REG_CONFIG = 0x0D # Config Register
VAL_CONFIG_RESET = 0x00 # Reset Value for Config Register
REG_ATIME = 0x01 # ATIME(ALS time) Register
VAL_ATIME_C64 = 0xC0 # INTEG_CYCLE=64, Time=175ms
REG_ENABLE = 0x00 # Enable Register
VAL_ENABLE_PON = 0x01 # Power ON
VAL_ENABLE_AEN = 0x02 # ALS Enable
VAL_ENABLE = VAL_ENABLE_PON | VAL_ENABLE_AEN

REG_C0DATA = 0x14 # CH0 ADC low data register

# Initialize
# Reset Control Register
buf = bytearray(1)

buf[0] = VAL_CONTROL_RESET
i2c.writeto_mem(addr_tsl25721, FIELD_COMMAND | FIELD_TYPE | REG_CONTROL, buf)

# Reset Config Register
buf[0] = VAL_CONFIG_RESET
i2c.writeto_mem(addr_tsl25721, FIELD_COMMAND | FIELD_TYPE | REG_CONFIG, buf)

# Set ALS time
buf[0] = VAL_ATIME_C64
i2c.writeto_mem(addr_tsl25721, FIELD_COMMAND | FIELD_TYPE | REG_ATIME, buf)

# Power on and enable ALS
buf[0] = VAL_ENABLE
i2c.writeto_mem(addr_tsl25721, FIELD_COMMAND | FIELD_TYPE | REG_ENABLE, buf)
time.sleep(1)

def read_lux():
  atime = 0xC0 # 192
  gain = 1.0

  dat = i2c.readfrom_mem(addr_tsl25721, FIELD_COMMAND | FIELD_TYPE | REG_C0DATA, 4)
  adc0 = (dat[1] << 8) | dat[0]
  adc1 = (dat[3] << 8) | dat[2]

  cpl = (2.73 * (256 - atime) * gain)/(60.0)
  lux1 = ((adc0 * 1.00) - (adc1 * 1.87)) / cpl
  lux2 = ((adc0 * 0.63) - (adc1 * 1.00)) / cpl
  lux = 0
  if ((lux1 <= 0) and (lux2 <= 0)) :
    lux = 0
  if (lux1 > lux2) :
    lux = lux1
  elif (lux1 < lux2) :
    lux = lux2

  return lux

while True:
  lux= read_lux()
  print("lux:{:.1f}".format(lux))
  time.sleep(1)

2021年6月20日日曜日

ESP32-DevkitCとDHT11で計測した温度・湿度をWiFi経由のREST APIで通知する

ESP32-DevkitCとDHT11で計測した温度・湿度をWiFi経由のREST APIで通知するには、以下の手順を実行します。今回は、ESP32-DevkitCで計測した温度・湿度の情報をRESTで送信しPC側のFlaskで受信します。

〇ESP32-DevkitCとDHT11を接続した写真

開発手順 1. PC側:pipenvの導入
pipenvをインストールしていない場合は、以下のコマンドを実行します。
sudo apt-get update

sudo apt-get -y install python3-pip python3-distutils python3-dev

sudo pip3 install --upgrade pip

sudo pip3 install --upgrade setuptools

sudo pip3 install pipenv

echo "export PIPENV_VENV_IN_PROJECT=true" >> ~/.bashrc

source ~/.bashrc

2. PC側:flaskがインストールされた仮想環境の作成
pipenvを使用する場合は以下のコマンドで、flask用の仮想環境を作成します。
mkdir -p ~/flask_dht11

cd ~/flask_dht11

pipenv --python 3

pipenv install flask

pipenv shell

3. PC側:Flask REST APIアプリケーションの作成
/dht11にPOSTされた温度・湿度データを取得して表示し、再びJSONで返すコードを実装します。

app.py
from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/dht11', methods=["POST"])
def receive_temp_adn_humidity():
    print(request.get_data())
    temp = request.json['temp']
    humidity = request.json['humidity']
    print("temp: {}C".format(temp))
    print("humidity: {}C".format(humidity))
    return {"temp":str(temp), "humidity":str(humidity)}

4. PC側:Flast REST APIアプリケーションの実行
Flaskを実行するには、以下のコマンドを実行します。
export FLASK_APP=app.py

flask run -h 0.0.0.0

実行時に表示されるURLを控えておきます。

5. ESP32-DevkitC側:DHT11の準備
以下のようなDHT11温湿度モジュールを準備します。

・DHT11温湿度モジュール(Temperature and Humidity Sensor)
https://akizukidenshi.com/catalog/g/gM-07040/

6. ESP32-DevkitC側:ESP32-DevkitCとDHT11の配線
ESP32-DevkitCとDHT11センサーモジュールを配線します
DHT11のDigitalピン(付属ケーブルの緑) -> ESP32-DevKitCのIO32ピン(USBを手前・ピン足を下にした時、左上から7番目のピン)
DHT11のGND(付属ケーブルの黒) -> ESP32-DevKitCのGNDピン(USBを手前・ピン足を下にした時、右上のピン)
DHT11のV(付属ケーブルの赤) -> ESP32-DevKitCの3V3ピン(USBを手前・ピン足を下にした時、左上のピン)

7. ESP32-DevkitC側:ESP32-DevkitCにMicroPythonの導入
PCにインストールしたThonnyなのでMicroPythonファームウェアを書き込みます。
MicroPythonファームウェアは以下のページから「esp32-20210418-v1.15.bin」をダウンロードしておきます。
https://micropython.org/download/esp32/

8. ESP32-DevkitC側:urequestsモジュールのアップロード
以下のページからダウンロードした(RAWボタンでリンク先を保存)urequests.pyをESP32-DevkitCの/libフォルダに配置します(/libフォルダが無い場合はThonnyなどで作成します)
https://github.com/micropython/micropython-lib/blob/master/urequests/urequests.py

9. ESP32-DevkitC側:プログラミングと実行
以下のコードのssid/パスワード/URLを設定してmain.pyとしてESP32-DevkitCに保存します。実行後、温度と湿度がPC側に2秒おきに表示されることを確認します。
import dht
import machine
import time
import urequests
import ujson
import network

# WiFiのssid
ssid = "xxx"
# WiFiのパスワード
password = "xxx"
# REST APIの接続先
url = "http://xxx.xxx.xxx.xxx:5000/dht11"
header = {'Content-Type':'application/json'}


def connect_wifi():
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print("connecting to network...")
        sta_if.active(True)
        sta_if.connect(ssid, password)
        while not sta_if.isconnected():
            pass
    print("network config:", sta_if.ifconfig())


# DHT11初期化
dht11 = dht.DHT11(machine.Pin(32))
time.sleep(1)
while True:
    # WiFi接続
    connect_wifi()

    # 測定
    dht11.measure()
    temp = dht11.temperature()
    humidity = dht11.humidity()

    # REST APIに通知
    data = ujson.dumps({"temp":str(temp), "humidity":str(humidity)})
    resp = urequests.post(url, data=data.encode("utf-8"), headers = header)
    print(resp.json())
    resp.close()
    
    # deepsleep
    machine.deepsleep(2000)

Лучший частный хостинг