If you want to control electronic devices, e.g. a relay or motor, you can do it with MicroPython with an ESP8266 and browser. Normally you would program an ESP8266 with Arduino, but C ++, which Arduino uses, is not always the easiest programming language for beginners to learn.
MicroPython is much easier to program in. In addition, it is a great way to use Python code on a microcontroller, such as an ESP8266 or ESP32, to basically control all the electronic components you want from your computer running Jupyter Notebook in a browser. If you are new to MicroPython, check out our previous guides on how to use it with a microcontroller; one covers creating rogue access points, while the other talks about programming an MCU over Wi-Fi.
Our example scenario
To help you show how MicroPython, an MCU and Jupyter Notebook can be used together to control electronic components, we use an installation that is normally very difficult to do in Arduino but very simple in MicroPython.
On a board, we have our ESP8266 paired with a D1Mini, which is connected to a relay switch. A relay is an electronic switch that is similar to the single-pole wall switches found in many of your rooms. When we send a power signal, it is turned on or off. There is a 9-volt battery connected, which will turn on the engine whenever we want it to.
What you need
These are the basics, but once you have your D1 Mini connected to the bread slice, with the relay connected, connect the relay to the GPIO pins and connect a 9V battery to the motor.
On your computer:
Step 1: Identify the correct serial port
Connect your ESP8266 to your computer and then run one of the commands below to see what serial address it is. If you disconnect the MCU to another USB port later, it may have a different serial address.
On a Linux computer:
~$ dmesg | grep tty /dev/cu.Bluetooth-Incoming-Port /dev/cu.SOC /dev/cu.wchusbserial14630 /dev/cu.MALS /dev/cu.usbserial-14630
On a Mac:
~% ls /dev/cu.* /dev/cu.Bluetooth-Incoming-Port /dev/cu.SOC /dev/cu.wchusbserial14630 /dev/cu.MALS /dev/cu.usbserial-14630
From my results from Linux and macOS it would be /dev/cu.wchusbserial14630. If you see two serial ports, always use the one with “wch” in it. To be sure if it is your ESP8266, you can disconnect it, restart the command, and then reconnect it to the same USB port and restart it.
To find the serial address in Windows, you need to open Device Manager and find the COM port under “Ports (COM & LPT).” We will not show any of the Windows steps below, so if you are using Windows and can not find out the process, look up the comments and we will try to steer you in the right direction.
Step 2: Download the latest MicroPython binary
If you already have MicroPython installed on your microcontroller, as if you were following one of our previous guides, you can skip down to step 4. Otherwise, you will need MicroPython on the MCU.
Download the latest firmware based on the card you are using. Visit the MicroPython download page, find your card and download the file. Below you will find quick links to the downloads for ESP8266 and ESP32. When selecting your board, select the .bin file for the latest stable release.
Step 3: Delete the board
Erase the card so that there are no problems when flashing MicroPython to it. Use the following command and replace my serial port with the serial on your ESP.
~$ esptool.py --port /dev/cu.wchusbserial14630 erase_flash esptool.py v2.8 Serial port /dev/cu.wchusbserial14140 Connecting.... Detecting chip type... ESP8266 Chip is ESP8266EX Features: WiFi Crystal is 26MHz MAC: 2c:f4:32:4b:07:83 Uploading stub... Running stub... Stub running... Erasing flash (this may take a while)...
Step 4: Flash MicroPython
If you are now using an ESP8266 microcontroller, run the following to flash MicroPython to it. Replace the .bin file at the end with the MicroPython binary you downloaded.
~$ esptool.py --port /dev/cu.wchusbserial14630 --baud 460800 write_flash --flash_size=detect 0 /Users/kali/Downloads/esp8266-20191220-v1.12.bin esptool.py v2.8 Serial port /dev/cu.wchusbserial14630 Connecting.... Detecting chip type... ESP8266 Chip is ESP8266EX Features: WiFi Crystal is 26MHz MAC: 2c:f4:32:4b:07:83 Uploading stub... Running stub... Stub running... Changing baud rate to 460800 Changed. Configuring flash size... Auto-detected Flash size: 4MB Flash params set to 0x0040 Compressed 617880 bytes to 402086... Wrote 617880 bytes (402086 compressed) at 0x00000000 in 9.6 seconds (effective 514.5 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin...
If you are using an ESP32, run the following instead. Replace the .bin file at the end with the MicroPython binary you downloaded.
~$ esptool.py --chip esp32 --port /dev/cu.wchusbserial14630 write_flash -z 0x1000 /Users/kali/Downloads/esp32-idf3-20191220-v1.12.bin
After flashing, confirm that it worked with the following command. If the outcome is similar, you’re fine. If you do not see anything, strike Get on a few more times to force it into action.
~$ screen /dev/cu.wchusbserial14630 115200 MicroPython v1.12 on 2019-12-20; ESP module with ESP8266 Type "help()" for more information. >>>
Step 5: Install Jupyter Notebook
Now we need to have Jupyter Notebook on our computer, the web application we use to have direct control over motors, relays, sensors and other components. If you already have it installed, skip to step 6 to get the kernel. Otherwise, upgrade your pipe installation:
~$ python3 -m pip install --upgrade pip Collecting pip Downloading pip-20.1.1-py2.py3-none-any.whl (1.5 MB) |████████████████████████████████| 1.5 MB 935 kB/s Installing collected packages: pip Successfully installed pip-20.1.1
Then install Jupyter Notebook with:
~$ python3 -m pip install jupyter Collecting jupyter Using cached jupyter-1.0.0-py2.py3-none-any.whl (2.7 kB) Collecting notebook Using cached notebook-6.0.3-py3-none-any.whl (9.7 MB) Collecting qtconsole Downloading qtconsole-4.7.5-py2.py3-none-any.whl (118 kB) |████████████████████████████████| 118 kB 907 kB/s Collecting ipykernel Downloading ipykernel-5.3.3-py3-none-any.whl (120 kB) |████████████████████████████████| 120 kB 11.7 MB/s Collecting ipywidgets Using cached ipywidgets-7.5.1-py2.py3-none-any.whl (121 kB) Collecting nbconvert Using cached nbconvert-5.6.1-py2.py3-none-any.whl (455 kB) Collecting jupyter-console Using cached jupyter_console-6.1.0-py2.py3-none-any.whl (21 kB) Requirement already satisfied: nbformat in /usr/lib/python3/dist-packages (from notebook->jupyter) (5.0.7) Requirement already satisfied: tornado>=5.0 in /usr/lib/python3/dist-packages (from notebook->jupyter) (5.1.1) Collecting Send2Trash Using cached Send2Trash-1.5.0-py3-none-any.whl (12 kB) Requirement already satisfied: jupyter-core>=4.6.1 in /usr/lib/python3/dist-packages (from notebook->jupyter) (4.6.3) Collecting jupyter-client>=5.3.4 Downloading jupyter_client-6.1.6-py3-none-any.whl (108 kB) |████████████████████████████████| 108 kB 2.2 MB/s Requirement already satisfied: traitlets>=4.2.1 in /usr/lib/python3/dist-packages (from notebook->jupyter) (4.3.3) Collecting prometheus-client Downloading prometheus_client-0.8.0-py2.py3-none-any.whl (53 kB) |████████████████████████████████| 53 kB 1.9 MB/s Requirement already satisfied: ipython-genutils in /usr/lib/python3/dist-packages (from notebook->jupyter) (0.2.0) Collecting pyzmq>=17 Downloading pyzmq-19.0.1-cp38-cp38-manylinux1_x86_64.whl (1.1 MB) |████████████████████████████████| 1.1 MB 9.9 MB/s Requirement already satisfied: jinja2 in /usr/lib/python3/dist-packages (from notebook->jupyter) (2.10.1) Collecting terminado>=0.8.1 Using cached terminado-0.8.3-py2.py3-none-any.whl (33 kB) Requirement already satisfied: pygments in /usr/lib/python3/dist-packages (from qtconsole->jupyter) (2.3.1) Collecting qtpy Using cached QtPy-1.9.0-py2.py3-none-any.whl (54 kB) Requirement already satisfied: ipython>=5.0.0 in /usr/lib/python3/dist-packages (from ipykernel->jupyter) (7.13.0) Collecting widgetsnbextension~=3.5.0 Using cached widgetsnbextension-3.5.1-py2.py3-none-any.whl (2.2 MB) Collecting testpath Using cached testpath-0.4.4-py2.py3-none-any.whl (163 kB) Requirement already satisfied: mistune<2,>=0.8.1 in /usr/lib/python3/dist-packages (from nbconvert->jupyter) (0.8.4) Collecting pandocfilters>=1.4.1 Using cached pandocfilters-1.4.2.tar.gz (14 kB) Collecting bleach Downloading bleach-3.1.5-py2.py3-none-any.whl (151 kB) |████████████████████████████████| 151 kB 1.3 MB/s Collecting entrypoints>=0.2.2 Using cached entrypoints-0.3-py2.py3-none-any.whl (11 kB) Collecting defusedxml Using cached defusedxml-0.6.0-py2.py3-none-any.whl (23 kB) Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/lib/python3/dist-packages (from jupyter-console->jupyter) (3.0.5) Requirement already satisfied: python-dateutil>=2.1 in /usr/lib/python3/dist-packages (from jupyter-client>=5.3.4->notebook->jupyter) (2.8.1) Collecting ptyprocess; os_name != "nt" Using cached ptyprocess-0.6.0-py2.py3-none-any.whl (39 kB) Requirement already satisfied: pexpect in /usr/lib/python3/dist-packages (from ipython>=5.0.0->ipykernel->jupyter) (4.6.0) Requirement already satisfied: webencodings in /usr/lib/python3/dist-packages (from bleach->nbconvert->jupyter) (0.5.1) Requirement already satisfied: packaging in /usr/lib/python3/dist-packages (from bleach->nbconvert->jupyter) (20.3) Requirement already satisfied: six>=1.9.0 in /usr/lib/python3/dist-packages (from bleach->nbconvert->jupyter) (1.14.0) Building wheels for collected packages: pandocfilters Building wheel for pandocfilters (setup.py) ... done Created wheel for pandocfilters: filename=pandocfilters-1.4.2-py3-none-any.whl size=7856 sha256=d120576d72839490baf2013615ee01ad685c9e81b3a8f3068b4597432d8a6b36 Stored in directory: /home/kali/.cache/pip/wheels/f6/08/65/e4636b703d0e870cd62692dafd6b47db27287fe80cea433722 Successfully built pandocfilters Installing collected packages: pyzmq, jupyter-client, ipykernel, Send2Trash, testpath, pandocfilters, bleach, entrypoints, defusedxml, nbconvert, prometheus-client, ptyprocess, terminado, notebook, qtpy, qtconsole, widgetsnbextension, ipywidgets, jupyter-console, jupyter Successfully installed Send2Trash-1.5.0 bleach-3.1.5 defusedxml-0.6.0 entrypoints-0.3 ipykernel-5.3.3 ipywidgets-7.5.1 jupyter-1.0.0 jupyter-client-6.1.6 jupyter-console-6.1.0 nbconvert-5.6.1 notebook-6.0.3 pandocfilters-1.4.2 prometheus-client-0.8.0 ptyprocess-0.6.0 pyzmq-19.0.1 qtconsole-4.7.5 qtpy-1.9.0 terminado-0.8.3 testpath-0.4.4 widgetsnbextension-3.5.1
And upgrade the Juypter client:
~$ pip3 install --upgrade jupyter_client Requirement already up-to-date: jupyter_client in ./.local/lib/python3.8/site-packages (6.1.6) Requirement already satisfied, skipping upgrade: jupyter-core>=4.6.0 in /usr/lib/python3/dist-packages (from jupyter_client) (4.6.3) Requirement already satisfied, skipping upgrade: traitlets in /usr/lib/python3/dist-packages (from jupyter_client) (4.3.3) Requirement already satisfied, skipping upgrade: python-dateutil>=2.1 in /usr/lib/python3/dist-packages (from jupyter_client) (2.8.1) Requirement already satisfied, skipping upgrade: tornado>=4.1 in /usr/lib/python3/dist-packages (from jupyter_client) (5.1.1) Requirement already satisfied, skipping upgrade: pyzmq>=13 in ./.local/lib/python3.8/site-packages (from jupyter_client) (19.0.1)
Step 6: Install Jupyter Notebook MicroPython Kernel
We need to install the MicroPython kernel for Jupyter Notebook now. We can download it from Jupyter MicroPython Kernel GitHub repo with:
~$ git clone https://github.com/goatchurchprime/jupyter_micropython_kernel.git Cloning into 'jupyter_micropython_kernel'... remote: Enumerating objects: 340, done. remote: Total 340 (delta 0), reused 0 (delta 0), pack-reused 340 Receiving objects: 100% (340/340), 108.88 KiB | 1.25 MiB/s, done. Resolving deltas: 100% (240/240), done.
Then install it on Python3 with (use sudo if something goes wrong):
~$ pip3 install -e jupyter_micropython_kernel Obtaining file:///home/kali/jupyter_micropython_kernel Requirement already satisfied: pyserial>=3.4 in /usr/lib/python3/dist-packages (from jupyter-micropython-kernel==0.1.3) (3.4) Requirement already satisfied: websocket-client>=0.44 in /usr/lib/python3/dist-packages (from jupyter-micropython-kernel==0.1.3) (0.53.0) Installing collected packages: jupyter-micropython-kernel Running setup.py develop for jupyter-micropython-kernel Successfully installed jupyter-micropython-kernel
Now install the kernel in Jupyter:
~$ python3 -m jupyter_micropython_kernel.install Installing IPython kernel spec of micropython /home/kali/jupyter_micropython_kernel/jupyter_micropython_kernel/install.py:29: DeprecationWarning: replace is ignored. Installing a kernelspec always replaces an existing installation k.install_kernel_spec(td, 'Micropython', user=user, replace=True, prefix=prefix) ...into /home/kali/.local/share/jupyter/kernels/micropython
Jupytes should now be ready to work with MicroPython.
Step 7: Open Jupyter Notebook
To open the Jupyter Notebook web interface, use:
~$ jupyter notebook
If you installed Jupyter Notebook in your local, use this instead:
Or add export PATH = $ PATH: ~ / .local / bin to your ~ / .bashrc file and try jupyter again.
You may need to enter your password before opening it. Afterwards, you should see an interface as below open in a browser.
Step 8: Open a MicroPython Jupyter Notebook
To create a MicroPython file, click “New” and select “MicroPython – USB” as the type of document to be created.
Now we should be in an empty Jupyter notebook. We can add cells to run with the plus (+) button and then run cells with the play button to see how our code runs. Before we can do that, however, we need to add a cell to connect.
Step 9: Check your engine from the web
In your Jupyter Notebook MicroPython file, use the following for the first block and make sure you use your serial port instead of mine. When it says “Done” when it starts connecting, you can continue.
%serialconnect to --port=/dev/cu.wchusbserial14630 --baud=115200
Now, in our second block, let’s create a little task to turn the engine on and off. First, make sure you are importing from the machine import pin and from the time import sleep. Then define the value of “engine” as 1 or TRUE to turn it on and 0 or Fake to turn it off. For “sleep” I use 0.2 seconds for how long it will run when activated. You can press “Run” to see it in action.
from machine import Pin from time import sleep motor = Pin(5, Pin.OUT) motor.value(1) sleep(0.2) motor.value(0) sleep(0.2)
You can also use .on() or .of() to control the pin:
motor.on() sleep(0.2) motor.off() sleep(0.2)
If you want to loop things, we can start using different Python data structures that are really fun, short and simple, and that do not require any of what Arduino IDE does. So let’s see if we can just turn the engine on and off ten times in a row:
from time import sleep for i in range(10): motor.on() sleep(0.5) motor.off() sleep(0.5)
If you want to stop your code, you can always press the stop icon, and if it just keeps going, you can press it to cancel it and be able to send in a new code
If you are a beginner or someone who already knows a little Python, MicroPython is probably the best way to get started with electronics from your laptop – spinning motors, glowing lasers and doing all sorts of other interesting things.
Want To Get Into The Gift Basket Business? Jump your career with hat hacking with our training package for premium ethical hacking 2020 from the new Null Byte store and get over 60 hours of training from professional ethical hacking.
Buy now (90% off)>