夏休みの工作特別企画 wifi 温度計を作る。
ソースの場所
携帯に自分の部屋の温湿度を表示
1000円以下で
資料
Arduino
のIDEを準備する。
環境設定のメニューから
追加のボードマネージャのURLに
https://arduino.esp8266.com/stable/package_esp8266com_index.json
設定すると
Generic ESP8266が選択できるようになる。
先ほどダウンロードしたESP-01S-DHT11-v1.0-master\ESP-01S-DHT11-v1.0-master\ESP01 01S DHT11 Arduino demo code\ESP01 01S DHT11 Arduino demo code\demo\Arduno_DHT11の中のArduno_DHT11.inoをIDEに読み込む。
```Arduno_DHT11.ino
/* DHTServer - ESP8266 Webserver with a DHT sensor as an input
Based on ESP8266Webserver, DHTexample, and BlinkWithoutDelay (thank you)
Version 1.0 5/3/2014 Version 1.0 Mike Barela for Adafruit Industries
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#define DHTTYPE DHT11
#define DHTPIN 2
// Replace with your network details
const char* ssid = "自分のSSID";
const char* password = "自分のパスワード";
ESP8266WebServer server(80);
// Initialize DHT sensor
// NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
// you need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold. It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value. The default for a 16mhz AVR is a value of 6. For an
// Arduino Due that runs at 84mhz a value of 30 works.
// This is for the ESP8266 processor on ESP-01
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
float humidity, temp_f; // Values read from sensor
String webString=""; // String to display
// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0; // will store last temp was read
const long interval = 2000; // interval at which to read sensor
void handle_root() {
server.send(200, "text/plain", "Hello from the weather esp8266, read from /temp or /humidity");
delay(100);
}
void setup(void)
{
// You can open the Arduino IDE Serial Monitor window to see what the code is doing
Serial.begin(115200); // Serial connection from ESP-01 via 3.3v console cable
dht.begin(); // initialize temperature sensor
// Connect to WiFi network
WiFi.begin(ssid, password);
Serial.print("\n\r \n\rWorking to connect");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("DHT Weather Reading Server");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", handle_root);
server.on("/temp", [](){ // if you add this subdirectory to your webserver call, you get text below :)
gettemperature(); // read sensor
webString=String((int)temp_f); // Arduino has a hard time with float to string
server.send(200, "text/plain", webString); // send to someones browser when asked
});
server.on("/humidity", [](){ // if you add this subdirectory to your webserver call, you get text below :)
gettemperature(); // read sensor
webString=String((int)humidity);
server.send(200, "text/plain", webString); // send to someones browser when asked
});
server.begin();
Serial.println("HTTP server started");
}
void loop(void)
{
server.handleClient();
}
void gettemperature() {
// Wait at least 2 seconds seconds between measurements.
// if the difference between the current time and last time you read
// the sensor is bigger than the interval you set, read the sensor
// Works better than delay for things happening elsewhere also
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
// save the last time you read the sensor
previousMillis = currentMillis;
// Reading temperature for humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
humidity = dht.readHumidity(); // Read humidity (percent)
temp_f = dht.readTemperature(false); // false は、摂氏 ~~Read temperature as Fahrenheit~~
// Check if any reads failed and exit early (to try again).
if (isnan(humidity) || isnan(temp_f)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
}
}
もとのプログラムは、温度データが華氏なので摂氏にするには、
temp_f = dht.readTemperature(false); // Read temperature as Fahrenheit
dht.readTemperature(true)を上記のように変更する。
プログラムの書き込みには、
が必要になる。
→マークで書き込む
esptool.py v2.6
2.6
esptool.py v2.6
Serial port COM4
Connecting....
Chip is ESP8266EX
Features: WiFi
MAC: 84:0d:8e:a7:ea:70
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 1MB
Compressed 295984 bytes to 212035...
Writing at 0x00000000... (7 %)
Writing at 0x00004000... (15 %)
Writing at 0x00008000... (23 %)
Writing at 0x0000c000... (30 %)
Writing at 0x00010000... (38 %)
Writing at 0x00014000... (46 %)
Writing at 0x00018000... (53 %)
Writing at 0x0001c000... (61 %)
Writing at 0x00020000... (69 %)
Writing at 0x00024000... (76 %)
Writing at 0x00028000... (84 %)
Writing at 0x0002c000... (92 %)
Writing at 0x00030000... (100 %)
Wrote 295984 bytes (212035 compressed) at 0x00000000 in 21.5 seconds (effective 110.0 kbit/s)...
Hash of data verified.
シリアルモニターを立ち上げる
'HTTP server started'となればOK
もし書き込みを失敗したなら次を試そう。
flash_download_tools_v3.6.6.exeを実行する
ファイル名 | アドレス |
---|---|
ESP8266_NONOS_SDK\bin\boot_v1.2.bin | 0x00000 |
ESP8266_NONOS_SDK\bin\at\512+512\user1.1024.new.2.bin | 0x010000 |
ESP8266_NONOS_SDK\bin\esp_init_data_default.bin | 0xfc000 |
ESP8266_NONOS_SDK\bin\blank.bin | 0x7e000 |
ESP8266_NONOS_SDK\bin\blank.bin | 0xfe0000 |
STRTボタンで書き込み出来るはずだ。
ブラウザーにアドレスを入れてみよう。温度
http://192.168.1.13/temp
ブラウザーにアドレスを入れてみよう。湿度
http://192.168.1.13/humidity
動作確認終了!!!
import requests
t = requests.post('http://192.168.1.13/temp').text
h = requests.post('http://192.168.1.13/humidity').text
print(t,h)
29 49
それらしい値が出ていますね。
pythonとbottleの組み合わせで温度や湿度を表示するためのガジェットを表示するためには、ちょっと工夫が必要です。
今回は、出来合いのゲージを使用します。
このキャンバスゲージを用いると簡単に下記のような表示することができる。
キャンバスゲージのhtml定義
gauges.py
canvas=[
'''<canvas
id="tmp1"
data-type="radial-gauge"
data-width="300"
data-height="300"
data-units="°C"
data-title="Temperature"
data-min-value="-50"
data-max-value="50"
data-major-ticks="[-50,-40,-30,-20,-10,0,10,20,30,40,50]"
data-minor-ticks="2"
data-stroke-ticks="true"
data-highlights='[
{"from": -50, "to": 0, "color": "rgba(0,0, 255, .3)"},
{"from": 0, "to": 50, "color": "rgba(255, 0, 0, .3)"}
]'
data-ticks-angle="225"
data-start-angle="67.5"
data-color-major-ticks="#ddd"
data-color-minor-ticks="#ddd"
data-color-title="#eee"
data-color-units="#ccc"
data-color-numbers="#eee"
data-color-plate="#222"
data-border-shadow-width="0"
data-borders="true"
data-needle-type="arrow"
data-needle-width="2"
data-needle-circle-size="7"
data-needle-circle-outer="true"
data-needle-circle-inner="false"
data-animation-duration="1500"
data-animation-rule="linear"
data-color-border-outer="#333"
data-color-border-outer-end="#111"
data-color-border-middle="#222"
data-color-border-middle-end="#111"
data-color-border-inner="#111"
data-color-border-inner-end="#333"
data-color-needle-shadow-down="#333"
data-color-needle-circle-outer="#333"
data-color-needle-circle-outer-end="#111"
data-color-needle-circle-inner="#111"
data-color-needle-circle-inner-end="#222"
data-value-box-border-radius="0"
data-color-value-box-rect="#222"
data-color-value-box-rect-end="#333"
data-font-value="Led"
data-font-numbers="Led"
data-font-title="Led"
data-font-units="Led"
></canvas>''',
'''<canvas
id="humid1"
data-type="radial-gauge"
data-width="300"
data-height="300"
data-units="%"
data-title="Humidity"
data-min-value="0"
data-max-value="100"
data-major-ticks="[0,10,20,30,40,50,60,70,80,90,100]"
data-minor-ticks="2"
data-stroke-ticks="true"
data-highlights='[
{"from": 0, "to": 50, "color": "rgba(0,0, 255, .3)"},
{"from": 50, "to": 100, "color": "rgba(255, 0, 0, .3)"}
]'
data-ticks-angle="225"
data-start-angle="67.5"
data-color-major-ticks="#ddd"
data-color-minor-ticks="#ddd"
data-color-title="#eee"
data-color-units="#ccc"
data-color-numbers="#eee"
data-color-plate="#222"
data-border-shadow-width="0"
data-borders="true"
data-needle-type="arrow"
data-needle-width="2"
data-needle-circle-size="7"
data-needle-circle-outer="true"
data-needle-circle-inner="false"
data-animation-duration="1500"
data-animation-rule="linear"
data-color-border-outer="#333"
data-color-border-outer-end="#111"
data-color-border-middle="#222"
data-color-border-middle-end="#111"
data-color-border-inner="#111"
data-color-border-inner-end="#333"
data-color-needle-shadow-down="#333"
data-color-needle-circle-outer="#333"
data-color-needle-circle-outer-end="#111"
data-color-needle-circle-inner="#111"
data-color-needle-circle-inner-end="#222"
data-value-box-border-radius="0"
data-color-value-box-rect="#222"
data-color-value-box-rect-end="#333"
data-font-value="Led"
data-font-numbers="Led"
data-font-title="Led"
data-font-units="Led"
></canvas>''',
'''<canvas
id="pressure2"
data-type="radial-gauge"
data-width="300"
data-height="300"
data-units="hPa"
data-title="Pressure"
data-min-value="300"
data-max-value="1200"
data-major-ticks="[300,400,500,600,700,800,900,1000,1100,1200]"
data-minor-ticks="2"
data-stroke-ticks="true"
data-highlights='[
{"from": 300, "to": 900, "color": "rgba(0,0, 255, .3)"},
{"from": 900, "to": 1200, "color": "rgba(255, 0, 0, .3)"}
]'
data-ticks-angle="225"
data-start-angle="67.5"
data-color-major-ticks="#ddd"
data-color-minor-ticks="#ddd"
data-color-title="#eee"
data-color-units="#ccc"
data-color-numbers="#eee"
data-color-plate="#222"
data-border-shadow-width="0"
data-borders="true"
data-needle-type="arrow"
data-needle-width="2"
data-needle-circle-size="7"
data-needle-circle-outer="true"
data-needle-circle-inner="false"
data-animation-duration="1500"
data-animation-rule="linear"
data-color-border-outer="#333"
data-color-border-outer-end="#111"
data-color-border-middle="#222"
data-color-border-middle-end="#111"
data-color-border-inner="#111"
data-color-border-inner-end="#333"
data-color-needle-shadow-down="#333"
data-color-needle-circle-outer="#333"
data-color-needle-circle-outer-end="#111"
data-color-needle-circle-inner="#111"
data-color-needle-circle-inner-end="#222"
data-value-box-border-radius="0"
data-color-value-box-rect="#222"
data-color-value-box-rect-end="#333"
data-font-value="Led"
data-font-numbers="Led"
data-font-title="Led"
data-font-units="Led"
></canvas>'''
]
テンプレートへの受け渡しと温度、湿度の読み出し
routes.py
from bottle import route, view
from datetime import datetime
import time,requests,json
import gauges
@route('/')
@route('/home')
@view('index')
def home():
return dict(
year=datetime.now().year,gauge=gauges.canvas
)
global temp, humid,temp1,humid1,press1
temp, humid,temp1,humid1,press1=0,0,0,0,0
@route('/temp',method = "GET")
def temp():
global temp, humid,temp1,humid1,press1
try:
r = requests.post('http://192.168.1.13/temp')
rx = requests.post('http://192.168.1.13/humidity')
t=int(r.text)
h=int(rx.text)
if t==2147483647 or h==2147483647: return dict(text="",text1="",t=temp,h=humid,t1=temp1,h1=humid1,p1=press1)
temp, humid=t,h
rxx= requests.get('http://192.168.1.111:8080/BME280')
j=json.loads(rxx.text)
print(j)
temp1,humid1,press1=j['temp'],j['humid'],j['pressure']
except:
dict(text="",text1="",t=temp,h=humid,t1=temp1,h1=humid1,p1=press1)
tmp=str(datetime.now().strftime('%Y/%m/%d %H:%M:%S'))+"<br>温度:%7.2f℃"%temp+"<br>湿度:%7.2f%"%humid
print(tmp)
tmp1=str(datetime.now().strftime('%Y/%m/%d %H:%M:%S'))+"<br>温度:%7.2f℃"%temp1+"<br>湿度:%7.2f%"%humid1+"<br>気圧:%7.2fhp"%press1
print(tmp1)
return dict(text=tmp,text1=tmp1,t=temp,h=humid,t1=temp1,h1=humid1,p1=press1)
bootle web site 起動ルーチン
app.py
"""
This script runs the application using a development server.
"""
from gevent import monkey
monkey.patch_all()
import bottle
import os
import sys
# routes contains the HTTP handlers for our server and must be imported.
import routes
#if '--debug' in sys.argv[1:] or 'SERVER_DEBUG' in os.environ:
# # Debug mode will enable more verbose output in the console window.
# # It must be set at the beginning of the script.
# bottle.debug(True)
def wsgi_app():
"""Returns the application to make available through wfastcgi. This is used
when the site is published to Microsoft Azure."""
return bottle.default_app()
if __name__ == '__main__':
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static').replace('\\', '/')
HOST = os.environ.get('SERVER_HOST', 'localhost')
try:
PORT = int(os.environ.get('SERVER_PORT', '5555'))
except ValueError:
PORT = 5555
@bottle.route('/static/<filepath:path>')
def server_static(filepath):
"""Handler for static files, used with the development server.
When running under a production server such as IIS or Apache,
the server should be configured to serve the static files."""
return bottle.static_file(filepath, root=STATIC_ROOT)
HOST,PORT="0.0.0.0",8080
bottle.run(server='gevent', host=HOST, port=PORT)
実行
console.txt
# python app.py
Bottle v0.12.17 server starting up (using GeventServer())...
Listening on http://0.0.0.0:8080/
Hit Ctrl-C to quit.
{'temp': 25.661778078996576, 'humid': 35.98232774210494, 'pressure': 1090.1052745508491}
2019/08/17 15:34:34<br>温度: 27.00℃<br>湿度: 43.00%
2019/08/17 15:34:34<br>温度: 25.66℃<br>湿度: 35.98%<br>気圧:1090.11hp
192.168.1.10 - - [2019-08-17 15:34:34] "GET /temp HTTP/1.1" 200 413 0.495693