Created
October 28, 2019 23:44
-
-
Save miguelgrinberg/80973081596f1069057ec6668142be15 to your computer and use it in GitHub Desktop.
Example code from my "MicroPython Heats My Home" presentation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DHT22_PIN = 4 # D2 pin / GPIO4 | |
LED_PIN = 2 # D4 pin / GPIO2 | |
WIFI_ESSID = 'your-wifi-network-name' | |
WIFI_PASSWORD = 'your-wifi-password' | |
INTERVAL = 5 * 60 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dht [82/128] | |
import machine | |
import network | |
import utime as time | |
import urequests as requests | |
import config | |
def wifi_connect(): | |
"""Connect to the configured Wi-Fi network.""" | |
sta_if = network.WLAN(network.STA_IF) | |
if not sta_if.isconnected(): | |
print('connecting to network...') | |
sta_if.active(True) | |
sta_if.connect(config.WIFI_ESSID, config.WIFI_PASSWORD) | |
while not sta_if.isconnected(): | |
time.sleep(1) | |
print('network config:', sta_if.ifconfig()) | |
def get_current_time(): | |
"""Obtain the current Unix time. | |
Note that because the ESP8266 does not have a clock, I make a call to the | |
World Time API to obtain the current time. | |
""" | |
response = requests.get( | |
'http://worldtimeapi.org/api/timezone/Etc/UTC') | |
if response.status_code != 200: | |
raise RuntimeError('Cannot get current time!') | |
return response.json()['unixtime'] | |
def get_temperature(): | |
"""Obtain the current temperature reading from the DHT22 sensor. | |
The returned temperature is in degrees Celcius. | |
""" | |
d = dht.DHT22(machine.Pin(config.DHT22_PIN)) [43/128] | |
d.measure() | |
return d.temperature() | |
def boosted(now): | |
"""Returns True if the heating is currently running, or False if it is | |
not. | |
The current Unix time must be passed as the now argument. | |
To avoid making frequent calls into the heating controller, each time the | |
heating is boosted, a boost.dat file is written with the end time of the | |
boost. | |
""" | |
boost_until = 0 | |
try: | |
with open('boost.dat', 'rt') as f: | |
boost_until = float(f.read()) | |
except OSError: | |
return False | |
return boost_until > now | |
def boost(now): | |
"""Initiate a 30 minute heating boost. | |
The current Unix time must be passed as the now argument. | |
The end time for this boost is recorded in the boost.dat file. | |
""" | |
# Note that this request must be changed to the proper one for your | |
# heating controller | |
response = requests.post('https://httpbin.org/status/200', | |
json={'foo': 'bar'}) | |
if response.status_code != 200: | |
raise RuntimeError('Could not issue boost!') | |
with open('boost.dat', 'wt') as f: | |
f.write(str(now + 30 * 60)) | |
[4/128] | |
def thermostat(temp, now): | |
"""Returns True if the heating needs to run, or False if not. | |
The current temperature must be passed in the temp argument. | |
The current Unix time must be passed in the now argument. | |
This function uses a simple logic to determine a target temperature for | |
the current time of day. If the current temperature is below the target, | |
then it returns True to indicate that the heating must be started. | |
""" | |
current_hour = int(now % (24 * 60 * 60) / (60 * 60)) | |
target_temp = 19 if 7 <= current_hour < 22 else 17 | |
boost = temp < target_temp | |
print('Target Temp = {}C Boost = {}'.format(target_temp, boost)) | |
return boost | |
def show_error(): | |
"""Blink the ESP8266 LED a few times to indicate that an error has | |
occurred. | |
""" | |
led = machine.Pin(config.LED_PIN, machine.Pin.OUT) | |
for i in range(5): | |
time.sleep(0.5) | |
led.on() | |
time.sleep(0.5) | |
led.off() | |
led.on() | |
def deep_sleep(): | |
"""Put the ESP8266 board into deep sleep mode for the configured length | |
of time. | |
At the end of the deep sleep period the board will reboot. | |
""" | |
rtc = machine.RTC() | |
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) | |
rtc.alarm(rtc.ALARM0, config.INTERVAL * 1000) | |
machine.deepsleep() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
from heat import wifi_connect, get_current_time, get_temperature, boosted, \ | |
boost, thermostat, show_error, deep_sleep | |
try: | |
wifi_connect() | |
now = get_current_time() | |
temp = get_temperature() | |
print('[{}] Temp = {}C'.format(now, temp)) | |
if not boosted(now) and thermostat(temp, now): | |
boost(now) | |
except Exception as exc: | |
sys.print_exception(exc) | |
show_error() | |
deep_sleep() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment