{"id":592,"date":"2019-02-18T19:22:20","date_gmt":"2019-02-18T19:22:20","guid":{"rendered":"http:\/\/wp.spoton.cz\/?p=592"},"modified":"2019-02-18T19:22:20","modified_gmt":"2019-02-18T19:22:20","slug":"not-so-bad-temperature-meter-using-esp8266-and-a-dht11","status":"publish","type":"post","link":"https:\/\/spoton.cz\/index.php\/2019\/02\/18\/not-so-bad-temperature-meter-using-esp8266-and-a-dht11\/","title":{"rendered":"Not so bad temperature meter. Using ESP8266 and a DHT11"},"content":{"rendered":"\n<p>In case you are a nut case and want everything monitored and under control, as I do, you NEED a temperature and humidity monitoring device that is at least semi-reliable, throwable, checkable, cheap and ugly as fuck. <\/p>\n\n\n\n<p>Also, the results can be seen here: <a href=\"https:\/\/bastart.spoton.cz\/temphumi\/\">https:\/\/bastart.spoton.cz\/temphumi\/<\/a> and especially, the graphing for battery state (3rd graph from top): <a href=\"https:\/\/bastart.spoton.cz\/status\/\">https:\/\/bastart.spoton.cz\/status\/ <\/a><\/p>\n\n\n\n<p>Search no more, as you have found it, read on and relive the ecstatic feelings of designing an ass-ripping ultra portable ESP8266 powered temperhumi meter for a couple [f|b]ucks. <\/p>\n\n\n\n<!--more-->\n\n\n\n<h2>Da parts.<\/h2>\n\n\n\n<p>When it comes to hardware selection, it was an obvious choice. What better a device to find than an ESP8266-12F in it&#8217;s all bare guts sticking out. The DHT11 is very inprecise, but cheap and easy to work with. Also, with every unit manufactured &#8211; a polar bear dies. Go get &#8217;em. For the other stuff, a few capacitors, some resistors etc&#8230; <\/p>\n\n\n\n<p>Heck, I shall put a list of all that shit for this MOFO project just here:<\/p>\n\n\n\n<ul><li>ESP8266-12E\/F<\/li><li>DHT11, or even the more advanced DHT22 would work, I assume<\/li><li>battery case for 3x AAA sized batteries (1.2V NiMh preferred)<\/li><li>self-made PCB &#8211; more on that later<\/li><li>2x10k, 1x2k7 resistors<\/li><li>1x 100nF, 1x10uF capacitors<\/li><li>couple pin headers, if you want to have it fancy (DIN 2.54mm)<\/li><li>want a case? Get a case then<\/li><\/ul>\n\n\n\n<h2>Da code.<\/h2>\n\n\n\n<p>As nobody cares about the hardware part, let&#8217;s look at the software part. My choice of language to fit this non-demanding and stupidly ugly project &#8211; YEAH! Python. Micro Python that is, as this small thing runs on these small things (i.e. uPython runs on ESP8266). No interrupts, no memory allocations, nothing of the stuff that grown-ups do with microprocessors.<\/p>\n\n\n\n<p>Alright, alright, you expect a chunk of code, copy paste it and move on. Well, here you go then. **slab**<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import dht\nimport machine\nimport utime\nimport urequests\nimport network\nimport json\nimport esp\nfrom flashbdev import bdev\n\n\"\"\"\nVariables\n--------------------------------------------------------------------------------\n\"\"\"\n# Do we want to measure internal or external? VCC \/ ADC\nADC_MODE_VCC = 255\nADC_MODE_ADC = 0\n# Network credentials pulled from inet.conf residing on the FS\n# options check\npossible_opts = ['ssid', 'pass', 'ip', 'netmask', 'gw', 'destination', 'dns']\n# Let's set location, will be set as a tag in influx\n_LOCATION_TYPE = \"Tea\"\n# INFLUX config - can be part of the config file, no?\n_INFLUX_HOST = '192.168.8.15' \n_INFLUX_PORT = '8086'\n_INFLUX_DB = 'indb'\n_INFLUX_USER = 'pi'\n_INFLUX_PASS = 'password'\n\n\n\"\"\"\nFunctions\n--------------------------------------------------------------------------------\n\"\"\"\n\ndef set_adc_mode(mode):\n    # Switch between internal and external ADC. Returns if restart is needed\n    # Mode up in variables\n    sector_size = bdev.SEC_SIZE\n    flash_size = esp.flash_size() # device dependent\n    init_sector = int(flash_size \/ sector_size - 4)\n    data = bytearray(esp.flash_read(init_sector * sector_size, sector_size))\n    if data[107] == mode:\n        # flash is already correct; nothing to do\n        return False\n    else:\n        data[107] = mode  # re-write flash\n        esp.flash_erase(init_sector)\n        esp.flash_write(init_sector * sector_size, data)\n        print(\"ADC mode changed in flash; restart to use it!\")\n        return True\n\ndef check_wake_state():\n    # check if the device woke from a deep sleep\n    if machine.reset_cause() == machine.DEEPSLEEP_RESET:\n        print('woke from a deep sleep')\n    else:\n        print(machine.reset_cause())\n    utime.sleep_ms(10)\n\ndef deep_sleep(sleep_minutes):\n    sleep_ms = sleep_minutes * 60 * 1000\n    rtc = machine.RTC()\n    rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)\n    rtc.alarm(rtc.ALARM0, sleep_ms)\n    machine.deepsleep()\n\ndef read_network_config():\n    config_dict = {}\n    try:\n        with open('inet.conf', 'r') as conf_handler:\n            config = conf_handler.readlines()\n            for item in config:\n                tmp_list = item.split(\"=\")\n                option = tmp_list[0].strip()\n                if len(tmp_list) == 2 and option in possible_opts:\n                    value = tmp_list[1].strip()\n                    config_dict.update({option: value})\n                else:\n                    pass\n    except Exception as e:\n        print(\"WARNING: Errors in INFRA config, still going for AP\")\n        return False\n    print(config_dict)\n    return config_dict\n\ndef set_up_infra(_SSID, _PASS, _TIMEOUT):\n    sta = network.WLAN(network.STA_IF)\n    ap = network.WLAN(network.AP_IF)\n    print(\"Disabling AP\")\n    ap.active(False)\n    print(\"Activating INFRA\")\n    sta.active(True)\n    sta.isconnected() # False, it should be # Comments by Yoda\n    print(\"Connecting to infra\")\n    sta.connect(_SSID, _PASS)\n    connection_tout = _TIMEOUT\n    print(\"Let's wait for the network to come up\") # Hopefully not indefinitely\n    # That's why we have a nice timeout, so it does not drain the batt on con\n    while not (sta.isconnected()):\n        if connection_tout &gt; 0:\n            print(\"Trying... {} more times\".format(connection_tout))\n            utime.sleep_ms(500)\n            connection_tout = connection_tout - 1\n        else:\n            print(\"Out of retrys while waiting for network, going to sleep\")\n            utime.sleep_ms(500)\n            return False\n    network_config = sta.ifconfig()\n    return network_config\n\n\"\"\"\nNetwork configuration section\n--------------------------------------------------------------------------------\n\"\"\"\ntry:\n    net_config = read_network_config()\n    if net_config:\n        net_conf_result = set_up_infra(net_config[\"ssid\"],\n                                       net_config[\"pass\"],\n                                       10)\n    else:\n        print(\"ERROR: cannot read from inet.conf file\")\n    utime.sleep_ms(100)\n    if net_conf_result:\n        print(\"Connected:\")\n        print(\"  IP: {}\".format(net_conf_result[0]))\n        print(\"  MASK: {}\".format(net_conf_result[1]))\n        print(\"  GW: {}\".format(net_conf_result[2]))\n        print(\"  DNS: {}\\n\".format(net_conf_result[3]))\n    else:\n        print(\"WARNING: Network config not done\")\nexcept Exception as e:\n    print(\"ERROR: Network configuration failed with: {}\".format(e))\nprint(\"Network section done\")\n\n\"\"\"\nMeasure temperhumi\n--------------------------------------------------------------------------------\n\"\"\"\nprint(\"getting the temperature here\")\nd1 = machine.Pin(5, machine.Pin.IN)\ntry:\n    local_dht = dht.DHT11(d1)\n    local_dht.measure()\n    temperature = local_dht.temperature()\n    humidity = local_dht.humidity()\n    print(\"T: {}\".format(temperature))\n    print(\"H: {}\".format(humidity))\nexcept Exception as e:\n    print(\"ERROR: Temp measurement: {}\".format(e))\n    temperature = 255\n    humidity = 255\n\n\"\"\"\nMeasure battery\n--------------------------------------------------------------------------------\n\"\"\"\nprint(\"Setting ADC mode here\")\nset_adc_mode(ADC_MODE_VCC)\nvcc = machine.ADC(1)\nval = vcc.read()\nutime.sleep(2)\nbattery = vcc.read()\n\n\n\"\"\"\nData send\n--------------------------------------------------------------------------------\n\"\"\"\nif net_conf_result:\n    post_str = \"http:\/\/{}:{}\/write?db={}&amp;u={}&amp;p={}\"\n    post = post_str.format(_INFLUX_HOST,\n                           _INFLUX_PORT, \n                           _INFLUX_DB,\n                           _INFLUX_USER,\n                           _INFLUX_PASS)\n    data_str = \"usense,type={_type} humidity={_humi} \\n \" + \\\n                \"usense,type={_type} temperature={_temp}\\n \" + \\\n                \"usense,type={_type} battery={_batt}\"\n    data = data_str.format(_type=_LOCATION_TYPE,\n                           _humi=humidity,\n                           _temp=temperature,\n                           _batt=battery)\n    print(data)\n    try:\n        result = urequests.post(post, data=data)\n    except Exception as e:\n        print(\"ERROR: Data send 'urequest': {}\".format(e))\n        # Go to sleep, cause why the fuck not\n        deep_sleep(28)\n    print(result.text)\nelse:\n    print(\"WARNING: Not sending data, as infra is not available\")\n# Sleep, deep. You earned it\ndeep_sleep(28)\n<\/pre>\n\n\n\n<p>So you want a better guide to the hardware part, eh? Wait for it and hold my beer&#8230;<\/p>\n\n\n\n<h2>How to put it together<\/h2>\n\n\n\n<p>You might want to read a couple articles first. namely <a href=\"http:\/\/wp.spoton.cz\/2017\/11\/21\/bricking-and-flashing-esp-01s-8266\/\">http:\/\/wp.spoton.cz\/2017\/11\/21\/bricking-and-flashing-esp-01s-8266\/<\/a> to see how to flash an ESP and <a href=\"http:\/\/wp.spoton.cz\/2017\/11\/29\/micropython-on-esp-01-8266\/\">http:\/\/wp.spoton.cz\/2017\/11\/29\/micropython-on-esp-01-8266\/<\/a> on how to setup micropython on an ESP.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In case you are a nut case and want everything monitored and under control, as I do, you NEED a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":59,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,5,8],"tags":[15,37,40,42,65,66,90,94,99],"_links":{"self":[{"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/posts\/592"}],"collection":[{"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/comments?post=592"}],"version-history":[{"count":0,"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/posts\/592\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/media\/59"}],"wp:attachment":[{"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/media?parent=592"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/categories?post=592"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spoton.cz\/index.php\/wp-json\/wp\/v2\/tags?post=592"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}