home-assistant.github.io/blog/2016/07/28/esp8266-and-micropython-part1/index.html
2017-05-01 13:58:02 +00:00

306 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ESP8266 and MicroPython - Part 1 - Home Assistant</title>
<meta name="author" content="Fabian Affolter">
<meta name="description" content="Using MicroPython on ESP8266 based devices and Home Assistant.">
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/">
<meta property="fb:app_id" content="338291289691179">
<meta property="og:title" content="ESP8266 and MicroPython - Part 1">
<meta property="og:site_name" content="Home Assistant">
<meta property="og:url" content="https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/">
<meta property="og:type" content="article">
<meta property="og:description" content="Using MicroPython on ESP8266 based devices and Home Assistant.">
<meta property="og:image" content="https://home-assistant.io/images/blog/2016-07-micropython/social.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@home_assistant">
<meta name="twitter:title" content="ESP8266 and MicroPython - Part 1">
<meta name="twitter:description" content="Using MicroPython on ESP8266 based devices and Home Assistant.">
<meta name="twitter:image" content="https://home-assistant.io/images/blog/2016-07-micropython/social.png">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet">
<link href="/atom.xml" rel="alternate" title="Home Assistant" type="application/atom+xml">
<link rel='shortcut icon' href='/images/favicon.ico' />
<link rel='icon' type='image/png' href='/images/favicon-192x192.png' sizes='192x192' />
</head>
<body >
<header>
<div class="grid-wrapper">
<div class="grid">
<div class="grid__item three-tenths lap-two-sixths palm-one-whole ha-title">
<a href="/" class="site-title">
<img width='40' src='/demo/favicon-192x192.png'>
<span>Home Assistant</span>
</a>
</div>
<div class="grid__item seven-tenths lap-four-sixths palm-one-whole">
<nav>
<input type="checkbox" id="toggle">
<label for="toggle" class="toggle" data-open="Main Menu" data-close="Close Menu"></label>
<ul class="menu pull-right">
<li><a href="/getting-started/">Getting started</a></li>
<li><a href="/components/">Components</a></li>
<li><a href="/docs/">Docs</a></li>
<li><a href="/cookbook/">Examples</a></li>
<li><a href="/developers/">Developers</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/help/">Need help?</a></li>
</ul>
</nav>
</div>
</div>
</div>
</header>
<div class="grid-wrapper">
<div class="grid grid-center">
<div class="grid__item two-thirds lap-one-whole palm-one-whole">
<article class="post">
<header>
<h1 class="title indent">ESP8266 and MicroPython - Part 1</h1>
<div class="meta clearfix">
<time datetime="2016-07-28T04:00:00+00:00" pubdate data-updated="true"><i class="icon-calendar"></i> July 28, 2016</time>
<span class="byline author vcard"><i class='icon-user'></i> Fabian Affolter</span>
<span><i class='icon-time'></i> six minutes reading time</span>
<span>
<i class="icon-tags"></i>
<ul class="tags unstyled">
<li>ESP8266</li>
<li>How-To</li>
<li>Micropython</li>
</ul>
</span>
<a class='comments'
href="#disqus_thread"
>Comments</a>
</div>
</header>
<p><img src="/images/blog/2016-07-micropython/micropython.png" style="clear: right; border:none; box-shadow: none; float: right; margin-bottom: 12px;" width="200" />
The first release of Micropython for ESP8266 was delivered a couple of weeks ago. The <a href="http://docs.micropython.org/en/latest/esp8266/esp8266_contents.html">documentation</a> covers a lot of ground. This post is providing only a little summary which should get you started.</p>
<p>Until a couple of weeks ago, the pre-built MicroPython binary for the ESP8266 was only available to backers of the Kickstarter campaign. This has changed now and it is available to the public for <a href="https://micropython.org/download/#esp8266">download</a>.</p>
<a name="read-more"></a>
<p>The easiest way is to use <a href="https://github.com/themadinventor/esptool">esptool.py</a> for firmware handling tasks. First erase the flash:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>sudo python esptool.py --port /dev/ttyUSB0 erase_flash
esptool.py v1.0.2-dev
Connecting...
Erasing flash <span class="o">(</span>this may take a <span class="k">while</span><span class="o">)</span>...
</code></pre>
</div>
<p>and then load the firmware. You may adjust the file name of the firmware binary.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>sudo python esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size<span class="o">=</span>8m 0 esp8266-2016-07-10-v1.8.2.bin
esptool.py v1.2-dev
Connecting...
Running Cesanta flasher stub...
Flash params <span class="nb">set </span>to 0x0020
Writing 540672 @ 0x0... 540672 <span class="o">(</span>100 %<span class="o">)</span>
Wrote 540672 bytes at 0x0 <span class="k">in </span>13.1 seconds <span class="o">(</span>330.8 kbit/s<span class="o">)</span>...
Leaving...
</code></pre>
</div>
<p>Now reset the device. You should then be able to use the <a href="http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/repl.html#getting-a-micropython-repl-prompt">REPL (Read Evaluate Print Loop)</a>. On Linux there is <code class="highlighter-rouge">minicom</code> or <code class="highlighter-rouge">picocom</code>, on a Mac you can use <code class="highlighter-rouge">screen</code> (eg. <code class="highlighter-rouge">screen /dev/tty.SLAB_USBtoUART 115200</code>), and on Windows there is Putty to open a serial connection and get the REPL prompt.</p>
<p>The <a href="http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/repl.html#webrepl-a-prompt-over-wifi">WebREPL</a> work over a wireless connection and allows easy access to a prompt in your browser. An instance of the WebREPL client is hosted at <a href="http://micropython.org/webrepl">http://micropython.org/webrepl</a>. Alternatively, you can create a local clone of their <a href="https://github.com/micropython/webrepl">GitHub repository</a>. This is neccessary if your want to use the command-line tool <code class="highlighter-rouge">webrepl_cli.py</code> which is mentionend later in this post.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>sudo minicom -D /dev/ttyUSB0
<span class="c">#4 ets_task(4020e374, 29, 3fff70e8, 10) </span>
WebREPL daemon started on ws://192.168.4.1:8266
Started webrepl <span class="k">in </span>setup mode
could not open file <span class="s1">'main.py'</span> <span class="k">for </span>reading
<span class="c">#5 ets_task(4010035c, 3, 3fff6360, 4)</span>
MicroPython v1.8.2-9-g805c2b9 on 2016-07-10; ESP module with ESP8266
Type <span class="s2">"help()"</span> <span class="k">for </span>more information.
<span class="gp">&gt;&gt;&gt; </span>
</code></pre>
</div>
<p class="note">
The public build of the firmware may be different than the firmware distributed to the backers of the Kickstarter campaign. Especially in regard of the <a href="http://docs.micropython.org/en/latest/esp8266/py-modindex.html">available modules</a>, turned on debug messages, and alike. Also, the WebREPL may not be started by default.
</p>
<p>Connect a LED to pin 5 (or another pin of your choosing) to check if the ESP8266 is working as expected.</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">machine</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">pin</span> <span class="o">=</span> <span class="n">machine</span><span class="o">.</span><span class="n">Pin</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">machine</span><span class="o">.</span><span class="n">Pin</span><span class="o">.</span><span class="n">OUT</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">pin</span><span class="o">.</span><span class="n">high</span><span class="p">()</span>
</code></pre>
</div>
<p>You can toogle the LED by changing its state with <code class="highlighter-rouge">pin.high()</code> and <code class="highlighter-rouge">pin.low()</code>.</p>
<p>Various ESP8266 development board are shipped with an onboard photocell or a light dependent resistors (LDR) connected to the analog pin of your ESP8266 check if you are able to obtain a value.</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">machine</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">brightness</span> <span class="o">=</span> <span class="n">machine</span><span class="o">.</span><span class="n">ADC</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">brightness</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</code></pre>
</div>
<p>Make sure that you are familiar with REPL and WebREPL because this will be needed soon. Keep in mind the password for the WebREPL access.</p>
<p>Read the <a href="http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/network_basics.html">instructions</a> about how to setup your wireless connection. Basically you need to upload a <code class="highlighter-rouge">boot.py</code> file to the microcontroller and this file is taking care of the connection setup. Below you find a sample which is more or less the same as shown in the <a href="http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/network_basics.html#configuration-of-the-wifi">documentation</a>.</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="k">def</span> <span class="nf">do_connect</span><span class="p">():</span>
<span class="kn">import</span> <span class="nn">network</span>
<span class="n">SSID</span> <span class="o">=</span> <span class="s">'SSID'</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="s">'PASSWORD'</span>
<span class="n">sta_if</span> <span class="o">=</span> <span class="n">network</span><span class="o">.</span><span class="n">WLAN</span><span class="p">(</span><span class="n">network</span><span class="o">.</span><span class="n">STA_IF</span><span class="p">)</span>
<span class="n">ap_if</span> <span class="o">=</span> <span class="n">network</span><span class="o">.</span><span class="n">WLAN</span><span class="p">(</span><span class="n">network</span><span class="o">.</span><span class="n">AP_IF</span><span class="p">)</span>
<span class="k">if</span> <span class="n">ap_if</span><span class="o">.</span><span class="n">active</span><span class="p">():</span>
<span class="n">ap_if</span><span class="o">.</span><span class="n">active</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">sta_if</span><span class="o">.</span><span class="n">isconnected</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">'connecting to network...'</span><span class="p">)</span>
<span class="n">sta_if</span><span class="o">.</span><span class="n">active</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="n">sta_if</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">SSID</span><span class="p">,</span> <span class="n">PASSWORD</span><span class="p">)</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">sta_if</span><span class="o">.</span><span class="n">isconnected</span><span class="p">():</span>
<span class="k">pass</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Network configuration:'</span><span class="p">,</span> <span class="n">sta_if</span><span class="o">.</span><span class="n">ifconfig</span><span class="p">())</span>
</code></pre>
</div>
<p>Upload this file with <code class="highlighter-rouge">webrepl_cli.py</code> or the WebREPL:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>python webrepl_cli.py boot.py 192.168.4.1:/boot.py
</code></pre>
</div>
<p>If you reboot, you should see your current IP address in the terminal.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">&gt;&gt;&gt; </span>Network configuration: <span class="o">(</span><span class="s1">'192.168.0.10'</span>, <span class="s1">'255.255.255.0'</span>, <span class="s1">'192.168.0.1'</span>, <span class="s1">'192.168.0.1'</span><span class="o">)</span>
</code></pre>
</div>
<p>First lets create a little consumer for Home Assistant sensors state. The code to place in <code class="highlighter-rouge">main.py</code> is a mixture of code from above and the <a href="/developers/rest_api/">RESTful API</a> of Home Assistant. If the temperature in the kitchen is higher than 20 °C then the LED connected to pin 5 is switched on.</p>
<p class="note">
If a module is missing then you need to download it from the <a href="https://github.com/micropython/micropython-lib">MicroPython Library overview</a> and upload it to the ESP8266 with <code class="highlighter-rouge">webrepl_cli.py</code> manually.
</p>
<div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="c"># Sample code to request the state of a Home Assistant entity.</span>
<span class="n">API_PASSWORD</span> <span class="o">=</span> <span class="s">'YOUR_PASSWORD'</span>
<span class="n">URL</span> <span class="o">=</span> <span class="s">'http://192.168.0.5:8123/api/states/'</span>
<span class="n">ENTITY</span> <span class="o">=</span> <span class="s">'sensor.kitchen_temperature'</span>
<span class="n">TIMEOUT</span> <span class="o">=</span> <span class="mi">30</span>
<span class="n">PIN</span> <span class="o">=</span> <span class="mi">5</span>
<span class="k">def</span> <span class="nf">get_data</span><span class="p">():</span>
<span class="kn">import</span> <span class="nn">urequests</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'{}{}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">URL</span><span class="p">,</span> <span class="n">ENTITY</span><span class="p">)</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">'x-ha-access'</span><span class="p">:</span> <span class="n">API_PASSWORD</span><span class="p">,</span>
<span class="s">'content-type'</span><span class="p">:</span> <span class="s">'application/json'</span><span class="p">}</span>
<span class="n">resp</span> <span class="o">=</span> <span class="n">urequests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">URL</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
<span class="k">return</span> <span class="n">resp</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">'state'</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="kn">import</span> <span class="nn">machine</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="n">pin</span> <span class="o">=</span> <span class="n">machine</span><span class="o">.</span><span class="n">Pin</span><span class="p">(</span><span class="n">PIN</span><span class="p">,</span> <span class="n">machine</span><span class="o">.</span><span class="n">Pin</span><span class="o">.</span><span class="n">OUT</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">int</span><span class="p">(</span><span class="n">get_data</span><span class="p">())</span> <span class="o">&gt;=</span> <span class="mi">20</span><span class="p">:</span>
<span class="n">pin</span><span class="o">.</span><span class="n">high</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">pin</span><span class="o">.</span><span class="n">low</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">TypeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">TIMEOUT</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Get the state of {}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">ENTITY</span><span class="p">))</span>
<span class="n">main</span><span class="p">()</span>
</code></pre>
</div>
<p>Upload <code class="highlighter-rouge">main.py</code> the same way as <code class="highlighter-rouge">boot.py</code>. After a reboot (<code class="highlighter-rouge">&gt;&gt;&gt; import machine</code> and <code class="highlighter-rouge">&gt;&gt;&gt; machine.reboot()</code>) or power-cycling your physical notifier is ready.</p>
<p>If you run into trouble, press “Ctrl+c” in the REPL to stop the execution of the code, enter <code class="highlighter-rouge">&gt;&gt;&gt; import webrepl</code> and <code class="highlighter-rouge">&gt;&gt;&gt; webrepl.start()</code>, and upload your fixed file.</p>
</article>
<section id="disqus">
<h3 class="indent title">Comments</h3>
<div id="disqus_thread" aria-live="polite"><noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript></div>
</section>
</div>
<aside id="sidebar" class="grid__item one-third lap-one-whole palm-one-whole">
<div class="grid">
<section class="aside-module grid__item one-whole lap-one-half">
<h1 class="title delta">About Home Assistant</h1>
<ul class="divided">
<li>
Home Assistant is an open-source home automation platform running on Python 3. Track and control all devices at home and automate control.
</li>
<li><a href='/getting-started/'>Get started with Home Assistant</a></li>
<li><a href='/demo/'>Try the online demo</a></li>
<li><a class="twitter-follow-button" href="https://twitter.com/Home_Assistant">Follow Home Assistant on Twitter</a></li>
<li><div class="fb-like" data-href="https://www.facebook.com/homeassistantio/" data-layout="standard" data-action="like" data-size="small" data-show-faces="true" data-share="false"></div></li>
</ul>
</section>
<div id="fb-root"></div>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.async=true;js.src='//platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<script>(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(d.getElementById(id)){return;}js=d.createElement(s);js.id=id;js.async=true;js.src="//connect.facebook.net/en_US/all.js#appId=338291289691179&xfbml=1";fjs.parentNode.insertBefore(js,fjs);}(document,'script','facebook-jssdk'));</script>
<section class="sharing aside-module grid__item one-whole lap-one-half">
<h1 class="title delta">Share this post</h1>
<a href="//twitter.com/share"
class="twitter-share-button"
data-via="home_assistant"
data-related="home_assistant"
data-url="https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/"
data-counturl="https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/" >Tweet</a>
<div class="fb-share-button" style='top: -6px;'
data-href="https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/"
data-layout="button_count">
</div>
<div class="g-plusone" data-size="standard"></div>
</section>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<section id="recent-posts" class="aside-module grid__item one-whole lap-one-half">
<h1 class="title delta">Recent Posts</h1>
<ul class="divided">
<li class="post">
<a href="/blog/2017/05/01/home-assistant-on-raspberry-pi-zero-in-30-minutes/">Home Assistant on a Pi Zero W in 30 minutes</a>
</li>
<li class="post">
<a href="/blog/2017/04/30/hassbian-1.21-its-about-time/">HASSbian 1.21 - It's about time isn't it</a>
</li>
<li class="post">
<a href="/blog/2017/04/25/influxdb-grafana-docker/">Setting up InfluxDB and Grafana using Docker</a>
</li>
<li class="post">
<a href="/blog/2017/04/24/hardware-contest-2017/">Hardware Contest 2017</a>
</li>
<li class="post">
<a href="/blog/2017/04/22/ikea-tradfri-spotify/">Home Assistant 0.43: IKEA Trådfri, Spotify and our iOS app is live</a>
</li>
</ul>
</section>
</div>
</aside>
</div>
</div>
<footer>
<div class="grid-wrapper">
<div class="grid">
<div class="grid__item">
<div class="copyright">
<a rel="me" href='https://twitter.com/home_assistant'><i class="icon-twitter"></i></a>
<a rel="me" href='https://facebook.com/homeassistantio'><i class="icon-facebook"></i></a>
<a rel="me" href='https://plus.google.com/110560654828510104551'><i class="icon-google-plus"></i></a>
<a rel="me" href='https://github.com/home-assistant/home-assistant'><i class="icon-github"></i></a>
<div class="credit">
Contact us at <a href='mailto:hello@home-assistant.io'>hello@home-assistant.io</a>.<br>
Website powered by <a href='http://jekyllrb.com/'>Jekyll</a> and the <a href='https://github.com/coogie/oscailte'>Oscalite theme</a>.<br />
Hosted by <a href='https://pages.github.com/'>GitHub</a> and served by <a href='https://cloudflare.com'>CloudFlare</a>.
</div>
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">home-assistant.io</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
</div>
</div>
</div>
</div>
</footer>
<script>
var _gaq=[['_setAccount','UA-57927901-1'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
<script>
var disqus_shortname = 'home-assistant';
// var disqus_developer = 1;
var disqus_identifier = 'https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/';
var disqus_url = 'https://home-assistant.io/blog/2016/07/28/esp8266-and-micropython-part1/';
var disqus_script = 'embed.js';
(function () {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/' + disqus_script;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}());
</script>
</body>
</html>