Compare commits

...

13 Commits

Author SHA1 Message Date
Klug 8b88aa1a69 Merge branch 'feat/esp32-flash' of cklug/iotnight into master 2019-01-29 09:01:21 +00:00
Michael Traeger dfe9abc3cc esp32 improvements 2019-01-28 20:16:31 +01:00
Clemens Klug b4c405ccbb c-c-c-changes 2019-01-28 19:30:26 +01:00
Clemens Klug c701cd00bd iotnight v1.1 2019-01-28 13:34:27 +01:00
Clemens Klug e3aa121024 re-add route-converter (http://flask.pocoo.org/docs/0.12/api/#url-route-registrations) 2017-12-04 15:06:06 +00:00
clemens 4cb65f7d7b better image for dht 2017-11-27 23:07:31 +01:00
Clemens Klug 2b56e23b9a Merge branch 'master' into 'master'
fix slides

See merge request cklug/iotnight!5
2017-11-27 22:02:21 +00:00
clemens 78bb708119 final version 2017-11-27 23:00:51 +01:00
Michael Traeger 85e2fffb7f fix id 2017-11-27 20:19:04 +01:00
Michael Traeger 4c11796157 fix install esptool ubuntu and flask 2017-11-27 20:17:15 +01:00
clemens c2249db282 add pinmap-printout 2017-11-27 17:06:13 +01:00
clemens 28b15337e0 fix options 2017-11-27 16:51:13 +01:00
clemens 07d5c67afb rmeove iot.wiai links, unify language, bump version 2017-11-24 20:09:23 +01:00
20 changed files with 1002 additions and 84 deletions

259
bme280.py Normal file
View File

@ -0,0 +1,259 @@
# Authors: Paul Cunnane 2016, Peter Dahlebrg 2016
#
# This module borrows from the Adafruit BME280 Python library. Original
# Copyright notices are reproduced below.
#
# Those libraries were written for the Raspberry Pi. This modification is
# intended for the MicroPython and esp8266 boards.
#
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# Based on the BMP280 driver with BME280 changes provided by
# David J Taylor, Edinburgh (www.satsignal.eu)
#
# Based on Adafruit_I2C.py created by Kevin Townsend.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import time
from ustruct import unpack, unpack_from
from array import array
# BME280 default address.
BME280_I2CADDR = 0x76
# Operating Modes
BME280_OSAMPLE_1 = 1
BME280_OSAMPLE_2 = 2
BME280_OSAMPLE_4 = 3
BME280_OSAMPLE_8 = 4
BME280_OSAMPLE_16 = 5
BME280_REGISTER_CONTROL_HUM = 0xF2
BME280_REGISTER_CONTROL = 0xF4
class BME280:
def __init__(self,
mode=BME280_OSAMPLE_1,
address=BME280_I2CADDR,
i2c=None,
**kwargs):
# Check that mode is valid.
if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4,
BME280_OSAMPLE_8, BME280_OSAMPLE_16]:
raise ValueError(
'Unexpected mode value {0}. Set mode to one of '
'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or '
'BME280_ULTRAHIGHRES'.format(mode))
self._mode = mode
self.address = address
if i2c is None:
raise ValueError('An I2C object is required.')
self.i2c = i2c
# load calibration data
dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26)
dig_e1_e7 = self.i2c.readfrom_mem(self.address, 0xE1, 7)
self.dig_T1, self.dig_T2, self.dig_T3, self.dig_P1, \
self.dig_P2, self.dig_P3, self.dig_P4, self.dig_P5, \
self.dig_P6, self.dig_P7, self.dig_P8, self.dig_P9, \
_, self.dig_H1 = unpack("<HhhHhhhhhhhhBB", dig_88_a1)
self.dig_H2, self.dig_H3 = unpack("<hB", dig_e1_e7)
e4_sign = unpack_from("<b", dig_e1_e7, 3)[0]
self.dig_H4 = (e4_sign << 4) | (dig_e1_e7[4] & 0xF)
e6_sign = unpack_from("<b", dig_e1_e7, 5)[0]
self.dig_H5 = (e6_sign << 4) | (dig_e1_e7[4] >> 4)
self.dig_H6 = unpack_from("<b", dig_e1_e7, 6)[0]
self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL,
bytearray([0x3F]))
self.t_fine = 0
# temporary data holders which stay allocated
self._l1_barray = bytearray(1)
self._l8_barray = bytearray(8)
self._l3_resultarray = array("i", [0, 0, 0])
def read_raw_data(self, result):
""" Reads the raw (uncompensated) data from the sensor.
Args:
result: array of length 3 or alike where the result will be
stored, in temperature, pressure, humidity order
Returns:
None
"""
self._l1_barray[0] = self._mode
self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL_HUM,
self._l1_barray)
self._l1_barray[0] = self._mode << 5 | self._mode << 2 | 1
self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL,
self._l1_barray)
sleep_time = 1250 + 2300 * (1 << self._mode)
sleep_time = sleep_time + 2300 * (1 << self._mode) + 575
sleep_time = sleep_time + 2300 * (1 << self._mode) + 575
time.sleep_us(sleep_time) # Wait the required time
# burst readout from 0xF7 to 0xFE, recommended by datasheet
self.i2c.readfrom_mem_into(self.address, 0xF7, self._l8_barray)
readout = self._l8_barray
# pressure(0xF7): ((msb << 16) | (lsb << 8) | xlsb) >> 4
raw_press = ((readout[0] << 16) | (readout[1] << 8) | readout[2]) >> 4
# temperature(0xFA): ((msb << 16) | (lsb << 8) | xlsb) >> 4
raw_temp = ((readout[3] << 16) | (readout[4] << 8) | readout[5]) >> 4
# humidity(0xFD): (msb << 8) | lsb
raw_hum = (readout[6] << 8) | readout[7]
result[0] = raw_temp
result[1] = raw_press
result[2] = raw_hum
def read_compensated_data(self, result=None):
""" Reads the data from the sensor and returns the compensated data.
Args:
result: array of length 3 or alike where the result will be
stored, in temperature, pressure, humidity order. You may use
this to read out the sensor without allocating heap memory
Returns:
array with temperature, pressure, humidity. Will be the one from
the result parameter if not None
"""
self.read_raw_data(self._l3_resultarray)
raw_temp, raw_press, raw_hum = self._l3_resultarray
# temperature
var1 = ((raw_temp >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11)
var2 = (((((raw_temp >> 4) - self.dig_T1) *
((raw_temp >> 4) - self.dig_T1)) >> 12) * self.dig_T3) >> 14
self.t_fine = var1 + var2
temp = (self.t_fine * 5 + 128) >> 8
# pressure
var1 = self.t_fine - 128000
var2 = var1 * var1 * self.dig_P6
var2 = var2 + ((var1 * self.dig_P5) << 17)
var2 = var2 + (self.dig_P4 << 35)
var1 = (((var1 * var1 * self.dig_P3) >> 8) +
((var1 * self.dig_P2) << 12))
var1 = (((1 << 47) + var1) * self.dig_P1) >> 33
if var1 == 0:
pressure = 0
else:
p = 1048576 - raw_press
p = (((p << 31) - var2) * 3125) // var1
var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25
var2 = (self.dig_P8 * p) >> 19
pressure = ((p + var1 + var2) >> 8) + (self.dig_P7 << 4)
# humidity
h = self.t_fine - 76800
h = (((((raw_hum << 14) - (self.dig_H4 << 20) -
(self.dig_H5 * h)) + 16384)
>> 15) * (((((((h * self.dig_H6) >> 10) *
(((h * self.dig_H3) >> 11) + 32768)) >> 10) +
2097152) * self.dig_H2 + 8192) >> 14))
h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4)
h = 0 if h < 0 else h
h = 419430400 if h > 419430400 else h
humidity = h >> 12
if result:
result[0] = temp
result[1] = pressure
result[2] = humidity
return result
return array("i", (temp, pressure, humidity))
@property
def values(self):
""" human readable values """
t, p, h = self.read_compensated_data()
p = p // 256
pi = p // 100
pd = p - pi * 100
hi = h // 1024
hd = h * 100 // 1024 - hi * 100
return ("{}C".format(t / 100), "{}.{:02d}hPa".format(pi, pd),
"{}.{:02d}%".format(hi, hd))
# ==================================================================
# BME280 readings can be executed in thread:
'''
import machine, _thread, time
import micropython, gc
import bme280
i2c=machine.I2C(scl=machine.Pin(26),sda=machine.Pin(25),speed=400000)
bme=bme280.BME280(i2c=i2c)
def bmevalues():
t, p, h = bme.read_compensated_data()
p = p // 256
pi = p // 100
pd = p - pi * 100
hi = h // 1024
hd = h * 100 // 1024 - hi * 100
#return "[{}] T={0:1g}C ".format(time.strftime("%H:%M:%S",time.localtime()), round(t / 100,1)) + "P={}.{:02d}hPa ".format(pi, pd) + "H={}.{:01d}%".format(hi, hd)
return "[{}] T={}C ".format(time.strftime("%H:%M:%S",time.localtime()), t / 100) + "P={}.{:02d}hPa ".format(pi, pd) + "H={}.{:02d}%".format(hi, hd)
def bmerun(interval=60):
_thread.allowsuspend(True)
sendmsg = True
send_time = time.time() + interval
while True:
while time.time() < send_time:
notif = _thread.getnotification()
if notif == 10002:
_thread.sendmsg(_thread.getReplID(), bmevalues())
elif notif == 10004:
sendmsg = False
elif notif == 10006:
sendmsg = True
elif (notif <= 3600) and (notif >= 10):
interval = notif
send_time = time.time() + interval
_thread.sendmsg(_thread.getReplID(), "Interval set to {} seconds".format(interval))
time.sleep_ms(100)
send_time = send_time + interval
if sendmsg:
_thread.sendmsg(_thread.getReplID(), bmevalues())
_thread.stack_size(3*1024)
bmeth=_thread.start_new_thread("BME280", bmerun, (60,))
'''

BIN
dist/ESP32-Development-Board-Pinout.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

259
dist/bme280.py vendored Normal file
View File

@ -0,0 +1,259 @@
# Authors: Paul Cunnane 2016, Peter Dahlebrg 2016
#
# This module borrows from the Adafruit BME280 Python library. Original
# Copyright notices are reproduced below.
#
# Those libraries were written for the Raspberry Pi. This modification is
# intended for the MicroPython and esp8266 boards.
#
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# Based on the BMP280 driver with BME280 changes provided by
# David J Taylor, Edinburgh (www.satsignal.eu)
#
# Based on Adafruit_I2C.py created by Kevin Townsend.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import time
from ustruct import unpack, unpack_from
from array import array
# BME280 default address.
BME280_I2CADDR = 0x76
# Operating Modes
BME280_OSAMPLE_1 = 1
BME280_OSAMPLE_2 = 2
BME280_OSAMPLE_4 = 3
BME280_OSAMPLE_8 = 4
BME280_OSAMPLE_16 = 5
BME280_REGISTER_CONTROL_HUM = 0xF2
BME280_REGISTER_CONTROL = 0xF4
class BME280:
def __init__(self,
mode=BME280_OSAMPLE_1,
address=BME280_I2CADDR,
i2c=None,
**kwargs):
# Check that mode is valid.
if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4,
BME280_OSAMPLE_8, BME280_OSAMPLE_16]:
raise ValueError(
'Unexpected mode value {0}. Set mode to one of '
'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or '
'BME280_ULTRAHIGHRES'.format(mode))
self._mode = mode
self.address = address
if i2c is None:
raise ValueError('An I2C object is required.')
self.i2c = i2c
# load calibration data
dig_88_a1 = self.i2c.readfrom_mem(self.address, 0x88, 26)
dig_e1_e7 = self.i2c.readfrom_mem(self.address, 0xE1, 7)
self.dig_T1, self.dig_T2, self.dig_T3, self.dig_P1, \
self.dig_P2, self.dig_P3, self.dig_P4, self.dig_P5, \
self.dig_P6, self.dig_P7, self.dig_P8, self.dig_P9, \
_, self.dig_H1 = unpack("<HhhHhhhhhhhhBB", dig_88_a1)
self.dig_H2, self.dig_H3 = unpack("<hB", dig_e1_e7)
e4_sign = unpack_from("<b", dig_e1_e7, 3)[0]
self.dig_H4 = (e4_sign << 4) | (dig_e1_e7[4] & 0xF)
e6_sign = unpack_from("<b", dig_e1_e7, 5)[0]
self.dig_H5 = (e6_sign << 4) | (dig_e1_e7[4] >> 4)
self.dig_H6 = unpack_from("<b", dig_e1_e7, 6)[0]
self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL,
bytearray([0x3F]))
self.t_fine = 0
# temporary data holders which stay allocated
self._l1_barray = bytearray(1)
self._l8_barray = bytearray(8)
self._l3_resultarray = array("i", [0, 0, 0])
def read_raw_data(self, result):
""" Reads the raw (uncompensated) data from the sensor.
Args:
result: array of length 3 or alike where the result will be
stored, in temperature, pressure, humidity order
Returns:
None
"""
self._l1_barray[0] = self._mode
self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL_HUM,
self._l1_barray)
self._l1_barray[0] = self._mode << 5 | self._mode << 2 | 1
self.i2c.writeto_mem(self.address, BME280_REGISTER_CONTROL,
self._l1_barray)
sleep_time = 1250 + 2300 * (1 << self._mode)
sleep_time = sleep_time + 2300 * (1 << self._mode) + 575
sleep_time = sleep_time + 2300 * (1 << self._mode) + 575
time.sleep_us(sleep_time) # Wait the required time
# burst readout from 0xF7 to 0xFE, recommended by datasheet
self.i2c.readfrom_mem_into(self.address, 0xF7, self._l8_barray)
readout = self._l8_barray
# pressure(0xF7): ((msb << 16) | (lsb << 8) | xlsb) >> 4
raw_press = ((readout[0] << 16) | (readout[1] << 8) | readout[2]) >> 4
# temperature(0xFA): ((msb << 16) | (lsb << 8) | xlsb) >> 4
raw_temp = ((readout[3] << 16) | (readout[4] << 8) | readout[5]) >> 4
# humidity(0xFD): (msb << 8) | lsb
raw_hum = (readout[6] << 8) | readout[7]
result[0] = raw_temp
result[1] = raw_press
result[2] = raw_hum
def read_compensated_data(self, result=None):
""" Reads the data from the sensor and returns the compensated data.
Args:
result: array of length 3 or alike where the result will be
stored, in temperature, pressure, humidity order. You may use
this to read out the sensor without allocating heap memory
Returns:
array with temperature, pressure, humidity. Will be the one from
the result parameter if not None
"""
self.read_raw_data(self._l3_resultarray)
raw_temp, raw_press, raw_hum = self._l3_resultarray
# temperature
var1 = ((raw_temp >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11)
var2 = (((((raw_temp >> 4) - self.dig_T1) *
((raw_temp >> 4) - self.dig_T1)) >> 12) * self.dig_T3) >> 14
self.t_fine = var1 + var2
temp = (self.t_fine * 5 + 128) >> 8
# pressure
var1 = self.t_fine - 128000
var2 = var1 * var1 * self.dig_P6
var2 = var2 + ((var1 * self.dig_P5) << 17)
var2 = var2 + (self.dig_P4 << 35)
var1 = (((var1 * var1 * self.dig_P3) >> 8) +
((var1 * self.dig_P2) << 12))
var1 = (((1 << 47) + var1) * self.dig_P1) >> 33
if var1 == 0:
pressure = 0
else:
p = 1048576 - raw_press
p = (((p << 31) - var2) * 3125) // var1
var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25
var2 = (self.dig_P8 * p) >> 19
pressure = ((p + var1 + var2) >> 8) + (self.dig_P7 << 4)
# humidity
h = self.t_fine - 76800
h = (((((raw_hum << 14) - (self.dig_H4 << 20) -
(self.dig_H5 * h)) + 16384)
>> 15) * (((((((h * self.dig_H6) >> 10) *
(((h * self.dig_H3) >> 11) + 32768)) >> 10) +
2097152) * self.dig_H2 + 8192) >> 14))
h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4)
h = 0 if h < 0 else h
h = 419430400 if h > 419430400 else h
humidity = h >> 12
if result:
result[0] = temp
result[1] = pressure
result[2] = humidity
return result
return array("i", (temp, pressure, humidity))
@property
def values(self):
""" human readable values """
t, p, h = self.read_compensated_data()
p = p // 256
pi = p // 100
pd = p - pi * 100
hi = h // 1024
hd = h * 100 // 1024 - hi * 100
return ("{}C".format(t / 100), "{}.{:02d}hPa".format(pi, pd),
"{}.{:02d}%".format(hi, hd))
# ==================================================================
# BME280 readings can be executed in thread:
'''
import machine, _thread, time
import micropython, gc
import bme280
i2c=machine.I2C(scl=machine.Pin(26),sda=machine.Pin(25),speed=400000)
bme=bme280.BME280(i2c=i2c)
def bmevalues():
t, p, h = bme.read_compensated_data()
p = p // 256
pi = p // 100
pd = p - pi * 100
hi = h // 1024
hd = h * 100 // 1024 - hi * 100
#return "[{}] T={0:1g}C ".format(time.strftime("%H:%M:%S",time.localtime()), round(t / 100,1)) + "P={}.{:02d}hPa ".format(pi, pd) + "H={}.{:01d}%".format(hi, hd)
return "[{}] T={}C ".format(time.strftime("%H:%M:%S",time.localtime()), t / 100) + "P={}.{:02d}hPa ".format(pi, pd) + "H={}.{:02d}%".format(hi, hd)
def bmerun(interval=60):
_thread.allowsuspend(True)
sendmsg = True
send_time = time.time() + interval
while True:
while time.time() < send_time:
notif = _thread.getnotification()
if notif == 10002:
_thread.sendmsg(_thread.getReplID(), bmevalues())
elif notif == 10004:
sendmsg = False
elif notif == 10006:
sendmsg = True
elif (notif <= 3600) and (notif >= 10):
interval = notif
send_time = time.time() + interval
_thread.sendmsg(_thread.getReplID(), "Interval set to {} seconds".format(interval))
time.sleep_ms(100)
send_time = send_time + interval
if sendmsg:
_thread.sendmsg(_thread.getReplID(), bmevalues())
_thread.stack_size(3*1024)
bmeth=_thread.start_new_thread("BME280", bmerun, (60,))
'''

BIN
dist/button-nodemcu.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
dist/esp-bme.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

37
dist/grafana_docker-compose.yml vendored Normal file
View File

@ -0,0 +1,37 @@
version: "3"
services:
influxdb:
image: influxdb:1.7-alpine
restart: on-failure:5
networks:
- traefik_net
volumes:
- ./data/influx:/var/lib/influxdb/
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_net"
- "traefik.http.frontend.rule=Host:iot-db.uni.clkl.de"
grafana:
image: grafana/grafana:5.4.3
volumes:
- "./data/grafana/:/var/lib/grafana/"
environment:
- "GF_SECURITY_ADMIN_USER=admin"
- "GF_SECURITY_ADMIN_PASSWORD=secret"
restart: on-failure:5
networks:
- traefik_net
- default
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_net"
- "traefik.http.frontend.rule=Host:iot.uni.clkl.de"
networks:
traefik_net:
external:
name: traefik_net
# initialize DB: requests.post("http://iot-db.uni.clkl.de/query?q=CREATE DATABASE ids"

BIN
dist/node-led.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
dist/nodemcu-dht22.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
dist/pinmap.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 KiB

View File

@ -0,0 +1,315 @@
%Berkeley / Goettingen / Hannover / Marburg / PaloAlto / Rochester
\usetheme[hideothersubsections]{Goettingen}
\RequirePackage{pgf}
\RequirePackage{tikz}
\RequirePackage{pdfrender}
\tikzset{
rectangle with rounded corners north west/.initial=4pt,
rectangle with rounded corners south west/.initial=4pt,
rectangle with rounded corners north east/.initial=4pt,
rectangle with rounded corners south east/.initial=4pt,
}
%\makeatletter
\pgfdeclareshape{rectangle with rounded corners}{
\inheritanchorborder[from=rectangle]
\savedmacro{\neoffset}{
\pgfkeysgetvalue{/tikz/rectangle with rounded corners north east}{\pgf@rectc}
\let\neoffset\pgf@rectc
}
\savedmacro{\nwoffset}{
\pgfkeysgetvalue{/tikz/rectangle with rounded corners north west}{\pgf@rectc}
\let\nwoffset\pgf@rectc
}
\savedmacro{\seoffset}{
\pgfkeysgetvalue{/tikz/rectangle with rounded corners south east}{\pgf@rectc}
\let\seoffset\pgf@rectc
}
\savedmacro{\swoffset}{
\pgfkeysgetvalue{/tikz/rectangle with rounded corners south west}{\pgf@rectc}
\let\swoffset\pgf@rectc
}
\savedanchor{\north}{
\pgf@y=.5\ht\pgfnodeparttextbox
\pgf@x=0pt
\setlength{\pgf@ya}{\pgfshapeminheight}
\ifdim\pgf@y<.5\pgf@ya
\pgf@y=.5\pgf@ya
\fi
}
\savedanchor{\south}{
\pgf@y=-.5\ht\pgfnodeparttextbox
\pgf@x=0pt
\setlength{\pgf@ya}{\pgfshapeminheight}
\ifdim\pgf@y>-.5\pgf@ya
\pgf@y=-.5\pgf@ya
\fi
}
\savedanchor{\east}{
\pgf@y=0pt
\pgf@x=.5\wd\pgfnodeparttextbox
\addtolength{\pgf@x}{2ex}
\setlength{\pgf@xa}{\pgfshapeminwidth}
\ifdim\pgf@x<.5\pgf@xa
\pgf@x=.5\pgf@xa
\fi
}
\savedanchor{\west}{
\pgf@y=0pt
\pgf@x=-.5\wd\pgfnodeparttextbox
\addtolength{\pgf@x}{-2ex}
\setlength{\pgf@xa}{\pgfshapeminwidth}
\ifdim\pgf@x>-.5\pgf@xa
\pgf@x=-.5\pgf@xa
\fi
}
\savedanchor{\northeast}{
\pgf@y=.5\ht\pgfnodeparttextbox % height of the box
\pgf@x=.5\wd\pgfnodeparttextbox % width of the box
\addtolength{\pgf@x}{2ex}
\setlength{\pgf@xa}{\pgfshapeminwidth}
\ifdim\pgf@x<.5\pgf@xa
\pgf@x=.5\pgf@xa
\fi
\setlength{\pgf@ya}{\pgfshapeminheight}
\ifdim\pgf@y<.5\pgf@ya
\pgf@y=.5\pgf@ya
\fi
}
\savedanchor{\southwest}{
\pgf@y=-.5\ht\pgfnodeparttextbox
\pgf@x=-.5\wd\pgfnodeparttextbox
\addtolength{\pgf@x}{-2ex}
% \pgf@x=0pt
\setlength{\pgf@xa}{\pgfshapeminwidth}
\ifdim\pgf@x>-.5\pgf@xa
\pgf@x=-.5\pgf@xa
\fi
\setlength{\pgf@ya}{\pgfshapeminheight}
\ifdim\pgf@y>-.5\pgf@ya
\pgf@y=-.5\pgf@ya
\fi
}
\anchor{text}{%
\northeast%
\pgf@x=-.5\wd\pgfnodeparttextbox%
\pgfmathsetlength{\pgf@y}{-.5ex}
}
\anchor{north east}{
\northeast
\pgfmathsetmacro{\nw}{(1-sin(45))*\neoffset}
\addtolength{\pgf@x}{-\nw pt}
\addtolength{\pgf@y}{-\nw pt}
}
\anchor{center}{
\pgf@x=0pt
\pgf@y=0pt
}
\anchor{south west}{
\southwest
\pgfmathsetmacro{\nw}{(1-sin(45))*\swoffset}
\addtolength{\pgf@x}{\nw pt}
\addtolength{\pgf@y}{\nw pt}
}
\anchor{north west}{
\northeast
\pgfmathsetmacro{\temp@x}{\pgf@x}
\southwest
\pgfmathsetmacro{\temp@xtwo}{\pgf@x}
\northeast
\pgfmathsetmacro{\xdiff}{\temp@x-\temp@xtwo}
\def\pgf@xa{\pgf@x-\xdiff}
\
\pgfmathsetmacro{\nw}{(1-sin(45))*\nwoffset}
\def\pgf@xaa{\pgf@xa+\nw}
\def\pgf@yaa{\pgf@y-\nw}
\pgfpoint{\pgf@xaa}{\pgf@yaa}
}
\anchor{south east}{
\southwest
\pgfmathsetmacro{\temp@x}{\pgf@x}
\northeast
\pgfmathsetmacro{\temp@xtwo}{\pgf@x}
\southwest
\pgfmathsetmacro{\xdiff}{\temp@x-\temp@xtwo}
\def\pgf@xa{\pgf@x-\xdiff}
\pgfmathsetmacro{\nw}{(1-sin(45))*\seoffset}
\def\pgf@xaa{\pgf@xa-\nw}
\def\pgf@yaa{\pgf@y+\nw}
\pgfpoint{\pgf@xaa}{\pgf@yaa}
}
\anchor{south}{\south}
\anchor{north}{\north}
\anchor{east}{\east}
\anchor{west}{\west}
\backgroundpath{% this is new
% store lower right in xa/ya and upper right in xb/yb
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
% construct main path
\pgfkeysgetvalue{/tikz/rectangle with rounded corners north west}{\pgf@rectc}
\pgfsetcornersarced{\pgfpoint{\pgf@rectc}{\pgf@rectc}}
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
\pgfkeysgetvalue{/tikz/rectangle with rounded corners north east}{\pgf@rectc}
\pgfsetcornersarced{\pgfpoint{\pgf@rectc}{\pgf@rectc}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfkeysgetvalue{/tikz/rectangle with rounded corners south east}{\pgf@rectc}
\pgfsetcornersarced{\pgfpoint{\pgf@rectc}{\pgf@rectc}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
\pgfkeysgetvalue{/tikz/rectangle with rounded corners south west}{\pgf@rectc}
\pgfsetcornersarced{\pgfpoint{\pgf@rectc}{\pgf@rectc}}
\pgfpathclose
}
}
\pgfdeclareimage[width=1.4em]{uniheader}{\meta/config/images/logo}
\pgfdeclareimage[width=2.8em]{uniheadertitle}{\meta/config/images/logo}
\setbeamertemplate{blocks}[shadow=false]
\setbeamercovered{transparent}
\beamer@headheight=0.1\paperheight
\setbeamercolor*{Title bar}{fg=unibablueI}
\setbeamercolor*{Location bar}{fg=unibablueI,bg=white}
\setbeamercolor*{frametitle}{parent=Title bar}
\setbeamercolor*{block title}{bg=unibablueI,fg=white}
\setbeamercolor*{block body}{bg=unibagrayV,fg=black}
\setbeamercolor*{block title alerted}{bg=nounibaredII,fg=white}
\setbeamercolor*{block body alerted}{bg=unibaredV,fg=black}
\setbeamercolor*{block title example}{bg=unibayellowII,fg=black}
\setbeamercolor*{block body example}{bg=unibayellowV,fg=black}
\setbeamercolor*{normal text}{bg=white,fg=black}
\setbeamercolor*{alerted text}{fg=nounibaredII}
\setbeamercolor*{section in head/foot}{fg=unibablueI}
\setbeamercolor*{item}{fg=unibablueI, bg=unibagrayV}
\usecolortheme[named=unibablueI]{structure}
\setbeamerfont{section in head/foot}{size=\tiny,series=\normalfont}
\setbeamerfont{frametitle}{size=\large}
\setbeamertemplate{title page}{
\begin{tikzpicture}[remember picture,overlay]
\node[
anchor=south east,
draw=unibablueV,
thin,
fill=unibablueV,
shape=rectangle with rounded corners,
minimum height=\paperheight-.2cm, minimum width=\beamer@sidebarwidth-.2cm,
rectangle with rounded corners north west=0pt,
rectangle with rounded corners south west=0pt,
rectangle with rounded corners north east=18pt,
rectangle with rounded corners south east=0pt,
] at ($(current page.south east)+(-.1,.1)$) (b) {};
\draw[anchor=north east] node(logo) at ($(b.north east)+(.15,.15)$) { \pgfuseimage{uniheadertitle} };
%\draw[unibablueI] node(uniba) [below of=logo, anchor=center]{\scriptsize\unibastring};
\end{tikzpicture}
\vskip-0.3\beamer@headheight
\begin{beamercolorbox}[sep=8pt]{institute}
\usebeamerfont{institute}\insertinstitute
\end{beamercolorbox}
\vskip2em\par
\begin{beamercolorbox}[sep=16pt]{title}
\usebeamerfont{title}\inserttitle\par%
\ifx\insertsubtitle\@empty%
\else%
\vskip0.25em%
{\usebeamerfont{subtitle}\usebeamercolor[fg]{subtitle}\insertsubtitle\par}%
\fi%
\end{beamercolorbox}%
\vskip1em\par
\begin{beamercolorbox}[sep=16pt]{date}
\usebeamerfont{date}\insertdate
\end{beamercolorbox}\vskip-0.5em
\begin{beamercolorbox}[sep=16pt]{author}
\usebeamerfont{author}\insertauthor
\end{beamercolorbox}
\vfill
}
\setbeamertemplate{frametitle}
{
\ifx\insertframesubtitle\empty
\vskip+0.1cm
\usebeamerfont*{frametitle}\insertframetitle
\vskip+0.15cm
\else
\usebeamerfont*{frametitle}\insertframetitle
\vskip+0.1cm
\hskip+0.5cm\usebeamerfont*{framesubtitle}\insertframesubtitle
\vskip+0.15cm
\fi
}
%\setbeamertemplate{headline}
%{
% \vskip -\beamer@headheight
% \linethickness{0pt}
% \framelatex{
% \begin{beamercolorbox}[wd=\paperwidth,ht=\beamer@headheight]{Title bar}
% \usebeamerfont{section in head/foot}
% %\insertsectionnavigationhorizontal{0pt}{\hskip0.22cm}{}%
% \end{beamercolorbox}}
%}
\setbeamertemplate{footline}
{
\begin{tikzpicture}[remember picture, overlay]
\draw[thick, unibablueI] ($(current page.south west)+(.1,0.37\beamer@headheight)$) -- ($(current page.south east)+(-.1,0.37\beamer@headheight)$);
\end{tikzpicture}
\linethickness{0pt}
\framelatex{
\begin{beamercolorbox}[leftskip=0.2cm, rightskip=0.2cm, wd=\paperwidth,ht=0.35\beamer@headheight,sep=0.05cm]{Location bar}
\usebeamerfont{section in head/foot}%
\begin{tikzpicture}[remember picture, overlay]
\node[anchor=south west] at ($(current page.south west)+(.1,0)$){\insertshorttitle \ | \insertshortauthor \ | \insertshortinstitute};
\node[anchor=south] at (current page.south){\ifgit\gitMarkFormat{\gitMarkPref\,\textbullet{}\,\gitMark}\fi};
\node[anchor=south east] at ($(current page.south east)+(-.1,0)$){\insertframenumber/\inserttotalframenumber};
\end{tikzpicture}
\end{beamercolorbox}}
}
\setbeamertemplate{sidebar canvas \beamer@sidebarside}[vertical shading]
[top=white,bottom=white]
\setbeamertemplate{sidebar \beamer@sidebarside}
{
\begin{tikzpicture}[remember picture,overlay]
\node[
anchor=south east,
draw=unibablueV,
thin,
fill=unibablueV,
shape=rectangle with rounded corners,
minimum height=\paperheight-.2cm, minimum width=\beamer@sidebarwidth-.2cm,
rectangle with rounded corners north west=0pt,
rectangle with rounded corners south west=0pt,
rectangle with rounded corners north east=18pt,
rectangle with rounded corners south east=0pt,
] at ($(current page.south east)+(-.1,.1)$) (b) {};
\draw[anchor=north east] node(logo) at ($(b.north east)+(.15,.15)$) { \pgfuseimage{uniheadertitle} };
\end{tikzpicture}
\vskip12em%
\hskip1em\insertverticalnavigation{\beamer@sidebarwidth}%
\vfill
\ifx\beamer@sidebarside\beamer@lefttext%
\else%
\usebeamercolor{normal text}%
\llap{\usebeamertemplate***{navigation symbols}\hskip0.1cm}%
\vskip2pt%
\fi%
%
\ifx\beamer@sidebarside\beamer@lefttext%
\defbeamertemplate*{sidebar right}{sidebar theme}
{%
\vfill%
\llap{\usebeamertemplate***{navigation symbols}\hskip0.1cm}%
\vskip2pt}
\fi
}

View File

@ -1,16 +1,16 @@
%Meta info %Meta info
%Necessary Information %Necessary Information
\author[C\&F]{Clemens, Franz} \author[clkl]{Clemens}
\title{IoT Night} \title{IoT Night $v1.1$}
\subtitle{S stands for security} \subtitle{S stands for security\\C stands for completeness\\V stands for verified contents\\E stands for electrical safety\\F stands for fair working conditions\\U stands for unharmed bits }
%The day of the presentation %The day of the presentation
\date{\today} \date{\today}
%Optional Information %Optional Information
\subject{IoT ESP8266} \subject{IoT ESP8266 ESP32}
\keywords{iot esp8266} \keywords{iot esp8266 esp32}
\institute[WIAI]{Fachschaft WIAI} \institute[wiai.de]{Fachschaft WIAI}
\titlegraphic{\includegraphics[width=13mm,height=13mm]{image/logo}} \titlegraphic{\includegraphics[width=13mm,height=13mm]{image/logo}}

View File

@ -1,6 +1,9 @@
@misc{pinmap, @misc{pinmap,
url={https://www.roboburada.com/public/assets/ESP8266/pinmap.png} url={https://www.roboburada.com/public/assets/ESP8266/pinmap.png}
} }
@misc{pinmap32,
url={https://lastminuteengineers.com/esp32-arduino-ide-tutorial/}
}
@misc{esp8266, @misc{esp8266,
url={http://www.c-sharpcorner.com/article/blinking-led-by-esp-12e-nodemcu-v3-module-using-arduinoide/} url={http://www.c-sharpcorner.com/article/blinking-led-by-esp-12e-nodemcu-v3-module-using-arduinoide/}
} }
@ -8,10 +11,14 @@
url={https://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html} url={https://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html}
} }
@misc{node-dht, @misc{node-dht,
url={https://www.mikrocontroller.net/topic/389850}} url={https://www.losant.com/blog/getting-started-with-the-esp8266-and-dht22-sensor}}
@misc{node-led, @misc{node-led,
url={https://www.pinterest.de/pin/658088564269958262/}} url={https://www.pinterest.de/pin/658088564269958262/}}
@misc{node-button, @misc{node-button,
url={https://alexbloggt.com/esp8266-pushover/}} url={https://alexbloggt.com/esp8266-pushover/}}
@misc{mp-interrupt, @misc{mp-interrupt,
url={{https://docs.micropython.org/en/latest/esp8266/reference/isr_rules.html}}} url={{https://docs.micropython.org/en/latest/esp8266/reference/isr_rules.html}}}
@misc{bmemod,
url={{https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/blob/master/MicroPython_BUILD/components/micropython/esp32/modules_examples/bme280.py}}}
@misc{espbme,
url={{https://randomnerdtutorials.com/esp32-web-server-with-bme280-mini-weather-station/}}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

View File

@ -0,0 +1,11 @@
\documentclass[11pt,a4paper]{article}
\usepackage[top=0cm,bottom=0cm]{geometry}
\usepackage{graphicx}
\begin{document}
\noindent
\includegraphics[width=.85\textwidth]{images/pinmap}\\
\includegraphics[width=.85\textwidth]{images/pinmap}\\
\includegraphics[width=.85\textwidth]{images/pinmap}
\end{document}

View File

@ -79,27 +79,6 @@ compress
\newcommand{\icon}[1]{\pgfimage[height=1em]{#1}} \newcommand{\icon}[1]{\pgfimage[height=1em]{#1}}
\section*{}
\phantomsection
\begin{frame}{First things first}\framesubtitle{Hardwareausgabe}
\begin{itemize}
\item Verfügbare Sets: 20
\item Reserviert: ~19
\item Kosten: \EUR{8} pro Set
\begin{itemize}
\item Bank of WIAI
\item \url{https://www.paypal.me/clkl/8}
\item Cash
\end{itemize}
\end{itemize}
\begin{figure}[H]
%\centering
%\flushright
\includegraphics[width=.3\textwidth]{qr}
\label{img:qr}
\end{figure}
\end{frame}
\begin{frame}{Content} \begin{frame}{Content}
\tableofcontents \tableofcontents
\end{frame} \end{frame}
@ -107,24 +86,36 @@ compress
%%%%%%%%%% Content starts here %%%%%%%%%% %%%%%%%%%% Content starts here %%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{ESP8266} \section{ESP Microcontroller}
\subsection{Hardware} \subsection{Hardware}
\begin{frame}{ESP8266} \begin{frame}{ESP*}
ESP8266
\begin{itemize} \begin{itemize}
\item 80 MHz, 64 kB RAM (Code), 96 kB RAM (Daten) \item 80 MHz, 64 kB RAM (Code), 96 kB RAM (Daten)
\item 4 MB Flashspeicher \item 4 MB Flashspeicher (extern)
\item Ardunio-kompatibel \item Ardunio-kompatibel
\item Open Source Hardware \item Open Source Hardware
\item Billige China-Klone :) \item Wlan
\end{itemize}
ESP32
\begin{itemize}
\item 160/240 MHz, 520 kB RAM (Daten)
\item Dualcore!
\item 4 MB Flashspeicher (extern)
\item Ardunio-kompatibel
\item Open Source Hardware
\item Wlan, Bluetooth 4.2, BLE, Ethernet (Treiber)
\end{itemize} \end{itemize}
\image{.6\textwidth}{esp8266}{ESP8266 + NodeMCU v3 \cite{esp8266}}{img:esp}
\end{frame} \end{frame}
\begin{frame}{ESP8266 - Pins} \begin{frame}{ESP8266 - Pins}
\image{.6\textwidth}{pinmap}{ESP8266 Pins \cite{pinmap}}{img:pins} \image{.6\textwidth}{pinmap}{ESP8266 Pins \cite{pinmap}}{img:pins}
\end{frame} \end{frame}
\begin{frame}{ESP32 - Pins}
\image{\textwidth}{ESP32-Development-Board-Pinout}{ESP32 Pins \cite{pinmap32}}{img:pins}
\end{frame}
\subsection{Software} \subsection{Software}
\begin{frame}{ESP8266} \begin{frame}{Programmierung}
\href{http://nodemcu.com/index_en.html}{NodeMCU} \href{http://nodemcu.com/index_en.html}{NodeMCU}
\begin{itemize} \begin{itemize}
\item Open Source Firmware \item Open Source Firmware
@ -137,19 +128,21 @@ Cooler: \href{https://micropython.org/}{MicroPython}
\item Frei \& Open Source \item Frei \& Open Source
\item Einige Funktionalität eingeschränkt (z.B. Multithreading) \item Einige Funktionalität eingeschränkt (z.B. Multithreading)
\item Verscheidene Boards/Controller unterstützt: PyBoard, ESP32, \dots \item Verscheidene Boards/Controller unterstützt: PyBoard, ESP32, \dots
\item Doku: \url{http://docs.micropython.org/en/latest/esp8266/index.html} (\url{http://iot.wiai/doc}) \item Doku: \url{https://docs.micropython.org/en/latest/esp8266/quickref.html} bzw. \url{https://docs.micropython.org/en/latest/esp32/quickref.html}
\end{itemize} \end{itemize}
Lowlevel: C, Arduino Studio Lowlevel: C, Arduino Studio
\end{frame} \end{frame}
\section{Setup} \section{Setup}
\subsection{Tools} \subsection{Tools}
\begin{frame}{Tools}\framesubtitle{Alle Downloads unter \url{http://iot.wiai/}} \begin{frame}{Tools}
Linux Linux
\begin{itemize} \begin{itemize}
\item Debian, Gentoo (testing): \texttt{\{apt install,emerge\} esptool picocom} \item Debian, Gentoo (testing): \texttt{\{apt install,emerge\} esptool picocom}
\item Ubuntu: \texttt{pip3 install esptool \&\& apt install picocom}
\item \texttt{adduser \$USER dialout} \item \texttt{adduser \$USER dialout}
\item Alternative: Docker (bin/docker): \textit{docker-compose run esp esptool} \item neuer Login (sudo su \$USER)
%\item Alternative: Docker (bin/docker): \textit{docker-compose run esp esptool}
\end{itemize} \end{itemize}
Windows Windows
\begin{itemize} \begin{itemize}
@ -159,32 +152,46 @@ Windows
\end{itemize} \end{itemize}
\item \texttt{pip install esptool} \item \texttt{pip install esptool}
\item \url{https://www.chiark.greenend.org.uk/~sgtatham/putty/download.html} \item \url{https://www.chiark.greenend.org.uk/~sgtatham/putty/download.html}
\item CH340G Treiber: \url{http://www.wch.cn/download/CH341SER\_ZIP.html} \item CH340G Treiber: \url{https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers}
\end{itemize} \end{itemize}
Mac Mac
\begin{itemize} \begin{itemize}
\item Homebrew (\url{https://brew.sh}) installieren + \texttt{brew install python3 \&\& pip install esptool} \item Homebrew (\url{https://brew.sh}) installieren
\item \texttt{brew install python3 \&\& pip install esptool}
\end{itemize} \end{itemize}
Offline pip: \textit{pip install -f http://iot.wiai/webrepl/}%TODO: --no-index?
\end{frame} \end{frame}
\subsection{Firmware} \subsection{Firmware}
\begin{frame}{Firmware}\framesubtitle{Alle Downloads unter \url{http://iot.wiai/}} \begin{frame}{Firmware ESP8266}
Windows-Spezial: Windows-Spezial:
\begin{itemize} \begin{itemize}
\item Portbezeichner: Gerätemanager $\rightarrow$ Serielle Geräte (COM+LPT) $\rightarrow$ COM$X$ \item Portbezeichner: Gerätemanager $\rightarrow$ Serielle Geräte (COM+LPT) $\rightarrow$ COM$X$ (z.B. COM12)
\item python -m esptool
\end{itemize} \end{itemize}
Flashen: Flashen:
\begin{itemize} \begin{itemize}
\item \url{https://micropython.org/download\#esp8266} %TODO: WIAI-link \item MicroPython Download: \url{https://micropython.org/download\#esp8266} (esp8266-20190125-v1.10.bin)
\item[*nix] \texttt{esptool.py --port /dev/ttyUSB0 erase\_flash} \item[*nix] \texttt{esptool -{}-port /dev/ttyUSB0 erase\_flash}
\item[win] \texttt{python -m esptool --port COM12 erase\_flash} \item[win] \texttt{python -m esptool -{}-port COM12 erase\_flash}
\item[*nix] \texttt{esptool.py --port /dev/ttyUSB0 --baud 460800 write\_flash --flash\_size=detect 0 esp8266-20170823-v1.9.2.bin} \item[*nix] \texttt{esptool -{}-port /dev/ttyUSB0 -{}-baud 460800 write\_flash -{}-flash\_size=detect 0 esp8266-20190125-v1.10.bin}
\item[win] \texttt{python -m esptool --port COM12 --baud 460800 write\_flash --flash\_size=detect 0 esp8266-20170823-v1.9.2.bin} \item[win] \texttt{python -m esptool -{}-port COM12 -{}-baud 460800 write\_flash -{}-flash\_size=detect 0 esp8266-20190125-v1.10.bin}
\item reset \item reset
\end{itemize} \end{itemize}
\end{frame} \end{frame}
\begin{frame}{Firmware ESP32}
Windows-Spezial:
\begin{itemize}
\item Portbezeichner: Gerätemanager $\rightarrow$ Serielle Geräte (COM+LPT) $\rightarrow$ COM$X$ (z.B. COM12)
\end{itemize}
Flashen:
\begin{itemize}
\item MicroPython Download: \url{https://micropython.org/download\#esp32} (esp32-20190128-v1.10-15-gdeb67569f.bin)
\item[*nix] \texttt{esptool -{}-chip esp32 -{}-port /dev/ttyUSB0 -{}-baud 460800 write\_flash -z 0x1000 esp32-20190128-v1.10-15-gdeb67569f.bin}
\item[win] \texttt{python -m esptool -{}-chip esp32 -{}-port COM12 -{}-baud 460800 write\_flash -z 0x1000 esp32-20190128-v1.10-15-gdeb67569f.bin}
\item Während dessen wild auf Boot drücken...
\item reset
\item Troubleshooting: Evtl. \texttt{esptool.py} verwenden
\end{itemize}
\end{frame}
\subsection{REPL} \subsection{REPL}
\begin{frame}{Serielle Konsole} \begin{frame}{Serielle Konsole}
@ -192,8 +199,9 @@ Flashen:
\begin{itemize} \begin{itemize}
\item \texttt{picocom -b 115200 /dev/ttyUSB0} \item \texttt{picocom -b 115200 /dev/ttyUSB0}
\item $n$ beherzte \textit{<ENTER>}-Drücke \item $n$ beherzte \textit{<ENTER>}-Drücke
\item Docker: \texttt{docker-compose run esp} (evtl. TTY anpassen) %\item Docker: \texttt{docker-compose run esp} (evtl. TTY anpassen)
\item[exit] Ctrl-a Ctrl-x \item[exit] Ctrl-a Ctrl-x
\item Alternativ: screen, \dots
\end{itemize} \end{itemize}
Windows: Windows:
\begin{itemize} \begin{itemize}
@ -214,7 +222,7 @@ Windows:
\subsection{WLAN} \subsection{WLAN}
\begin{frame}[fragile]{WLAN}\framesubtitle{Put the I in IoT} \begin{frame}[fragile]{WLAN}\framesubtitle{Put the I in IoT}
\begin{lstlisting}[caption={Descriptive Caption Text},label=DescriptiveLabel] \begin{lstlisting}[caption={Wifi Setup},label=DescriptiveLabel]
import network import network
sta_if = network.WLAN(network.STA_IF) sta_if = network.WLAN(network.STA_IF)
ap_if = network.WLAN(network.AP_IF) ap_if = network.WLAN(network.AP_IF)
@ -222,7 +230,7 @@ ap_if = network.WLAN(network.AP_IF)
ap_if.active(False) ap_if.active(False)
sta_if.active(True) sta_if.active(True)
sta_if.connect('SSID', 'SECRET') # TODO: setup sta_if.connect('wiaiot', 'wiaiotoiaiw')
sta_if.isconnected() sta_if.isconnected()
sta_if.ifconfig() sta_if.ifconfig()
\end{lstlisting} \end{lstlisting}
@ -234,18 +242,20 @@ import webrepl_setup
\end{lstlisting} \end{lstlisting}
\begin{itemize} \begin{itemize}
\item \textit{import webrepl\_setup} \item \textit{import webrepl\_setup}
\item reset/start webrepl (\textit{import webrepl \& webrepl.start()}) \item WebREPL einrichten (\textit{import webrepl \& webrepl.start()})
\item visit \url{http://iot.wiai/webrepl/} or \url{http://micropython.org/webrepl/} \item WebREPL Client \url{http://micropython.org/webrepl/}
\item enter your ESP's IP (\textit{sta\_if.ifconfig()}) \& connect \item IP des ESP's für WebSocket verwenden (\textit{sta\_if.ifconfig()})
\item Datei Up-/Download (z.B. für main.py)
\end{itemize} \end{itemize}
\end{frame} \end{frame}
\subsection{Init} \subsection{Init}
\begin{frame}[fragile]{main.py} \begin{frame}[fragile]{main.py}
Wird beim starten ... gestartet Wird beim starten \dots gestartet
\begin{lstlisting}[caption={main.py},label=mainpy] \begin{lstlisting}[caption={main.py},label=mainpy]
def connect_wifi(ssid, passphrase): from secrets import SSID, PASS
def connect_wifi(ssid=SSID, passphrase=PASS):
#TODO ;) #TODO ;)
pass pass
@ -258,40 +268,40 @@ setup()
\end{lstlisting} \end{lstlisting}
\end{frame} \end{frame}
\subsection{Exkurs: Flask-Server} \subsection{Exkurs: Grafana}
\begin{frame}[fragile]{Gegenseite: Flask} \begin{frame}[fragile]{Gegenseite: InfluxDB + Grafana}
\begin{lstlisting}[caption={C\&C Server},label=cnc]
from flask import Flask, request \begin{lstlisting}[caption={Collection Server (docker-compose)},label=cnc]
app = Flask(__name__) version: "3"
@app.route("/") services:
def hello(): influxdb:
return "Hello ESP8266!" image: influxdb:1.7-alpine
@app.route("/id/<id:id>", methods=['GET','POST'])
def log(id): grafana:
app.logger.info("%s was here and delivered '%s'", id, request.data.decode("utf8")) image: grafana/grafana:5.4.3
networks:
- traefik_net
- default
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik_net"
- "traefik.http.frontend.rule=Host:iot.uni.clkl.de"
\end{lstlisting} \end{lstlisting}
Starten:
\begin{itemize}
\item[!] pip install Flask
\item python server.py
\item[||] docker-compose up (server.py in src/)
\item[||] FLASK\_APP=server.py flask run
\end{itemize}
\end{frame} \end{frame}
\begin{frame}[fragile]{Daten übertragen} \begin{frame}[fragile]{Daten übertragen}
\begin{lstlisting}[caption={HTTP Requests},label=http] \begin{lstlisting}[caption={HTTP Requests},label=http]
import urequests import urequests
host = "http://your.host.ip.here:5000" host = "http://iot-db.uni.clkl.de"
response = urequests.get(host) #response = urequests.get(host)
print(response)
import machine import machine
board_id = int.from_bytes(machine.unique_id(), 'little') board_id = int.from_bytes(machine.unique_id(), 'little')
payload = '{"board": "{id}"}'.format(id=board_id) data = "machine_id,user=<you>,other_data=foobar value=" + str(board_id)
json_header = {'Content-Type': 'application/json'} post_url = "{host}/write?db={db}".format(host=host, db="ids")
post_url = "{host}/id/{id}".format(host=host, id=board_id) urequests.post(post_url, data=data)
urequests.post(post_url, data=data, headers=json_header)
\end{lstlisting} \end{lstlisting}
\end{frame} \end{frame}
@ -338,7 +348,7 @@ pin.irq(trigger=machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING, handler=callba
\end{lstlisting} \end{lstlisting}
\end{frame} \end{frame}
\subsection{Sensoren} \subsection{Sensoren}
\begin{frame}[fragile]{Sensoren} \begin{frame}[fragile]{DHT22}
\image{.35\textwidth}{nodemcu-dht22}{DHT22 \cite{node-dht}}{img:dht} \image{.35\textwidth}{nodemcu-dht22}{DHT22 \cite{node-dht}}{img:dht}
\begin{lstlisting}[caption={Sensoren},label=senors] \begin{lstlisting}[caption={Sensoren},label=senors]
import dht import dht
@ -349,16 +359,36 @@ d.temperature()
d.humidity() d.humidity()
\end{lstlisting} \end{lstlisting}
\end{frame} \end{frame}
\begin{frame}[fragile]{BME280}
\image{.25\textwidth}{esp-bme}{BME 280 \cite{espbme}}{img:bme}
Modul auf ESP hochladen: bem280.py \cite{bmemod}
\begin{lstlisting}[caption={Sensoren},label=senors]
import bme280
import machine
i2c=machine.I2C(scl=machine.Pin(26),sda=machine.Pin(25))
bme=bme280.BME280(i2c=i2c)
bme.values
\end{lstlisting}
\end{frame}
\subsection{Interrupts} \subsection{Interrupts}
\begin{frame}{Here be dragons} \begin{frame}{Interrupts}
\framesubtitle{Here be dragons}
\begin{itemize} \begin{itemize}
\item Z.B. Callbacks von Tastern \item Z.B. Callbacks von Tastern
\item pausieren main \item pausieren main
\item dürfen keinen Speicher allozieren \item dürfen keinen Speicher allozieren
\begin{itemize}
\item[\checkmark] \textit{alarm = True \#only with previously allocated variable!}
\item[\checkmark] \textit{counter = counter + 1}
\item[\checkmark] \textit{interrupts[2] += 1}
\item[X] \textit{events.append(Interrupt())}
\item[X] \textit{}
\end{itemize}
\item Emergency exception buffer: \textit{micropython.alloc\_emergency\_exception\_buf(100)} \item Emergency exception buffer: \textit{micropython.alloc\_emergency\_exception\_buf(100)}
\end{itemize} \end{itemize}
\cite{mp-interrupt} Siehe Doku :) \cite{mp-interrupt}
\end{frame} \end{frame}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%