Electronics & MicroPython© with ESP32©: 80 Complete Projects


243 79 52MB

English Pages [600] Year 2024

Report DMCA / Copyright

DOWNLOAD PDF FILE

Table of contents :
Electronics
& MicroPython©
with ESP32©:
Recommend Papers

Electronics & MicroPython© with ESP32©: 80 Complete Projects

  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
File loading please wait...
Citation preview

Electronics & MicroPython© with ESP32©: 80 Complete Projects

© 2024 Gregorio Chenlo (@arquiteutis)

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Index (v2) Dedicated Introduction Other titles by the author Copyright

6 7 14 16

1.-HARDWARE • Box of the ESP32© • Heat sinks • Power supply • Connection cables • The ESP32© module 1. SOC 2. USB controller 3. USB 4. BOOT 5. Regulator 6. Antenna 7. GPIO

18 21 22 22 22 22 24 24 24 24 24 24 24

2.-SOFTWARE • Installation of Python© & ESPTool© • Thonny© MicroPython© Editor

26 27 29

3.-MICROPYTHON • The interpreter Thonny© • The art of programming • Structure of a program • Importing libraries • Comments • Parameters & variables • Type of data 1. Numerical data 2. Logical data 3. Characters 4. Time 5. Lists 6. Dictionaries • Input & output • Operators 1. Mathematical operators

31 33 38 39 45 47 48 49 49 50 50 51 52 53 55 57 57

2

Electronics & MicroPython© with ESP32©: 80 complete projects

Logical operators Comparator operators Bit operators Character operators Assignment and inclusion operators Flow control 1. If conditional 2. While loops 3. For loops User functions Predefined functions 1. Functions with lists and strings 2. Functions with numbers and strings 3. Functions with dictionaries Files 1. Using MicroPython© 2. Using Thonny© 3. Using the file manager Error control Command summary 2. 3. 4. 5. 6.



• •



• •

4.-EXERCISES • Basic Electricity • ESP32© GPIO usage • E1: Turn on/off an LED • E2: SOS signal with LED • E3: DC10EGWA© level indicator • E4: JQC3F© on/off relay • E5: KSK-1A66© reed switch • E6: OS25B10© photo switch • E7: LED management with a button • E8: ESP32© internal data • E9: ESP32© internal watchdog • E10: Connect the ESP32© to WiFi • E11: Scan WiFi with ESP32© • E12: Analog to Digital Converter • E13: Digital to Analog Converter • E14: Wav generator with DAC • E15: KY-006© passive buzz & DAC • E16: DAC and *.wav files • E17: DHT11/22© double sensor • E18: DS18B20© temperature sensor • E19: KY-106© RGB LED on/off

59 60 61 62 64 66 66 68 72 74 78 78 79 80 82 82 83 83 87 90 95 96 100 103 112 116 120 126 133 137 148 150 156 160 163 169 174 183 188 194 200 208 3

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • 4

E20: E21: E22: E23: E24: E25: E26: E27: E28: E29: E30: E31: E32: E33: E34: E35: E36: E37: E38: E39: E40: E41: E42: E43: E44: E45: E46: E47: E48: E49: E50: E51: E52: E53: E54: E55: E56: E57: E58: E59: E60: E61:

RGB LED and PWM Fan and ESP32© temperature L293D© DC motor control SG90© servo control ESP32© internal clock DS1302© external clock Web server BLE Bluetooth ESP32© internal timer KY-040© rotary encoder Frequency meter with 7555© HC-SR501© motion sensor HLK-LD2410C© human presence sensor ESP32© and TTP223© touch sensors 49E© Hall sensor 44E© Hall switch MF52AT© NTC thermistor sensor Switch with thermistor KY-033© line detector ERD29© laser diode TCS3200© colors sensor KY-032© obstacle sensor 1838B© infrared receiver Remote control with infrared SW-200D© tilt sensor SW-18010P© vibration sensor MAX-4466© sound sensor HC-SR04© ultrasound sensor GL5539© photoresistor sensor TIL-78© fire sensor MQ-2 gas and smoke sensor SKU-500© rain sensor Scan I2C bus BMP280© barometric sensor YB-GS07381© water pressure sensor GY-271© magnetic sensor OV7670© camera sensor COM90133P© joystick HW-209© logic level converter MQ135© air quality sensor Alternating current sensor Send email with ESP32©

215 227 234 242 248 253 259 272 277 287 296 302 306 312 319 325 329 335 339 345 349 354 359 363 368 372 375 380 386 390 394 396 400 404 408 413 418 422 427 429 433 436

Electronics & MicroPython© with ESP32©: 80 complete projects

• • • • • • • • • • • • • • • • • • •

E62: E63: E64: E65: E66: E67: E68: E69: E70: E71: E72: E73: E74: E75: E76: E77: E78: E79: E80:

Home Automation with IFTTT© NO-IP© remote management ADXL345© accelerometer MPU6050© gyroscope PCF8574© GPIO extender SH1106© OLED screen PCM5102© I2S player Simultaneous ESP32© execution 74HC595© 8 LED manager SMA42056© 6 segments display 4x7 segment cascade display LCD1602© I2C display LCD1602© display with PCF8574© ILI9341© TFT display RC522© RFID reader Angeek© SPI uSD memory Samiore© mp3 player 4x4 matrix keyboard MAX7219© LED matrix display

441 451 456 462 469 475 482 489 494 500 505 511 516 523 530 537 554 559 563

5.-ADDITIONAL SOFTWARE • IPscanner Home© • iCircuit© • Wokwi© • KingstVIS© • OpenHantek© • chatPGT©

570 571 572 573 574 575 576

6.-MORE INFORMATION • Python2© vs Python3© • Interruptions managed by the ESP32© • IFTTT© • Home Assistant© and ESPHome© ◦ Home Assistant© installation ◦ ESPHome© installation • MB-102© power supply • Eagle© • Bibliography • Glossary of terms • Thanks

577 578 582 583 585 587 588 591 592 593 595 600

⊝⊝⊝ 5

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Dedicated to my Son

For decades I was dreaming, wishing to know how you'd be, waiting for you, how long your hair would be. And when you were finally born, you looked me in the eyes, held my finger tight, and we became friends forever, from this first light. I was with you, helping you grow older, listening and reading your mind, getting stronger, shoulder to shoulder. You're unique, having you is worth it, you always surprise me, nothing compares to you, you're what I love most, a part of me true. I no longer have you, many will say that I fell no sorrow, obviously they're wrong, I'll always be with you, in any world, dear and admired Son, through every morrow. The more you grow, the higher up I lose you, wait for me and forgive me if I'm so slow, remember, I'll always carry you inside, wherever I go. We have our talks, the good and the bad, of course it unites us, making us whole, it helps and encourages us to continue, both glad and sad. I'm very proud of you, I tell you little, I'll always be what you need, my friend, believe me, it's what I feel, a love that will never end.

⊝⊝⊝

6

Electronics & MicroPython© with ESP32©: 80 complete projects

INTRODUCTION

W

hen I published my first book “Home Automation with Raspberry©, Google© and Python©: an useful and fun Home Automation project”, www.amazon.com, both in Spanish and English, I received several comments from readers encouraging me to write another book for beginners in the use of micro controllers such as the Raspberry©, Arduino© or ESP32© as a basis for the creation of small projects development exercises, which will be explained step by step, more slowly, in more detail, more easily, etc. how to use an ESP32©, starting from scratch and adding elements from less to more complexity: LED, buttons, sensors, sounds, switches, controllers, Home Automation devices, access from the Web, voice control, IFTTT©, server Web, etc. Th e fi r s t b o o k d e s cr i b ed h ow t o us e t he Raspberry© to create a specific and complete Home Automation project with multiple sensors (temperature, humidity, thermostat with geolocation, power supply failures, garage door status sensor, air toxicity in the garage, ringing the main door bell, presence sensors, gas leaks, fire and smoke detector, flood, Internet connection status, buttons, etc.), multiple actuators (lighting, raising/lowering of blinds, system status LED, acoustic and voice signals, watchdog barking simulation, relays, gas and water valves, electronic control by “watchdog”, etc.). The book also included intelligent control algorithms (repetitive processes, routines, scenes, etc.), use of application integrators and devices from various manufacturers, such as IFTTT©, or even bidirectional management of the entire system using voice, broadcasting, with a natural language, using Artificial Intelligence (AI) included in an assistant such as Google Home© or Alexa©. 7

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Therefore, in response to this proposal from the readers of my first books, I have decided to write this one and it aims to help the beginner reader to acquire general basic knowledge about Electronics and particulars in the use of an ESP32© to be able to use their management potential of various electronic devices, Home Automation, etc. There are already several publications on the market that pursue similar objectives to this one, especially in English, but they tend to be very theoretical, boring, too concise, without sufficient depth, without explaining the reasons of each item, oriented to very complex projects that on many occasions they only apply to very specific solutions and do not help a solid learning process which allows the development of one's own project. On the contrary, no specific closed project is developed in this book, but small projects or exercises that consolidate knowledge are explained in depth so that a beginner and enthusiast of selflearning and self-development is able to implement their own ideas that will surely be new and creative, unpublished and excellent. In this sense, this book contains a first part where the basic concepts necessary to have the hardware (choice of the ESP32©, GPIO details, modules, components, etc.) and the software (firmware loading, instructions, configuration, update, IP assignment, remote access, system startup, devices startup, MicroPython© editing and management software, etc.) necessary to start a recreational training activity around Electronics managed with an ESP32©. The second part of the book includes some practical exercises, 80 with detailed solutions and almost 400 proposed for the reader to design, develop and experiment on their own, to strengthen the formation of basic theoretical concepts and with increasing complexity exercise by exercise. Each exercise describes the objective pursued, the necessary components and the theory, hardware and 8

Electronics & MicroPython© with ESP32©: 80 complete projects

software, essential to understand the concepts and achieve the objective, in addition all of this written in a language that pursues entertainment and fun for the reader, with graphics, diagrams, formulas, photos, etc. that facilitate a greater understanding of all the concepts used. The third part includes a list of additional software (applications for the ESP32©, computer, mobile phone and tools), which help improve the project development process, pre-testing, documentation, ESP32© advance features, search for technical resources, etc., making the entire process much simpler, easier, more affordable and friendly. Today, fans of these technologies are very fortunate that in recent decades the development of consumer electronic systems has been drastically promoted, the ease of access to new technologies by anyone interested, the proliferation of electronic devices of all types (controllers, sensors, actuators, applications, integrators, voice assistants, etc.), the lowering of these systems that make the price no longer a problem for their use. To all of the above, we must add the “democratization” in the use of Artificial Intelligence (both software and specific devices, personal assistants, etc.), the great ease of access to information provided by the Internet (search engines, training content, free dissemination of information, explanatory videos, manuals, discussion fo r um s , g r o up s , n e tw o r ks , AI , d ow n lo a di n g of information by manufacturers and users, tutorials, etc.), application and device integration software (type “If this then that” or IFTTT©) etc. what they do with all this is that there is no excuse not to face and dedicate a few hours to training in this technology, considering the process as a formal and structured training but also, and very important, as part of a hobby or time dedicated to entertainment. With all these factors, the emergence of Electronic and computer systems has been promoted, at a very low cost or even free, associated with the 9

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

needs of digitalization, learning, personal de ve l op m en t , l e is u re , ho b bi es , en t er t ai n me n t, training, self-development, etc., that have completely eliminated the barriers to entry so that anyone, of any age and with any type of knowledge, wants to get started in this world. In addition to everything mentioned in relation to electronic devices in particular and hardware in general, the Python© programming language has burst onto the market for years and with increasing force, with application in multiple facets of the industry and even in our daily lives. This language, in its version adapted to micro controllers called MicroPython©, will allow us to extract, in a pleasant and simple way, the most out of the ESP32© to be able to carry out multiple interesting, useful and fun projects. We will go into all the details of the MicroPython© programming environment later, but we could anticipate that this programming language is a new and special version of the already very famous Python3©, designed specifically for micro controllers and embedded systems, that is, systems that include integrated processors in other larger systems. With MicroPython© we will learn Python© and we will be able to run scripts written in this language on cheap, easily available devices with limited resources, such as development boards such as ESP32©, STM32©, etc. We can quickly and easily program micro controllers using a high-level language, which facilitates the development of projects for hobbyists, teachers, students and professionals in Electronics, Computer Science, Home Automation, entertainment, training, R&D, etc. We will be able to use MicroPython© to automate the home, control electronic devices, robotics, data acquisition and prototyping IoT (Internet of Things) products. MicroPython© has an active community that contributes libraries and resources to expand its functionality and compatibility with different devices and hardware types. 10

Electronics & MicroPython© with ESP32©: 80 complete projects

Basic questions about Python©, MicroPython© and ESP32© often arise, such as the following, which this book solves: •

Did they give you an ESP32© and you don't know what to do with it?: This book explains, in detail, what basic hardware and software you need so that you can use your ESP32© with MicroPython© as a training language or for the development of various projects. You can easily learn to write programs in this great language, learn the basic commands one by one, load libraries already tested by other users, enjoy multiple examples so that you can finally design and control your own projects.



Would you like to know how to use the MicroPython© programming language to build a simple project and you have no idea where to start?: this book teaches you basic MicroPython© from scratch, explains in detail the structure of a program, the various instructions, the import of external libraries, the design of functions, error control, etc. and how to create simple programs, without complications, easy to follow and all this in a pleasant and fun environment.



Do you already have an ESP32©, already know something about Python© and would like to get more out of it?: this book guides you how you can enhance your knowledge and develop more complete and complex projects with professional tools, WAV and MP3 sounds, WiFi connection or Bluetooth, Home Automation integration with IFTTT©, Web servers, network file sharing, etc.



Do you like Electronics and its integration with Home Automation but you don't know how to do it?: in this book you have the opportunity to learn to program in MicroPython©, use an ESP32© to control that Electronics and enhance the project with multiple exercises. 11

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Exercise in MicroPython©, whether basic or advanced, can be done by reading a command book, browsing a website, an online course, etc., but all of this is pure theory and difficult to assimilate. It is much more effective for your training to perform the exercises as described in this book, that is, to exercise the learning on a real and not a virtual hardware platform, for example an ESP32©. With the method proposed here we can check how the code we have written really “runs”, how well or badly the small programs we have designed behave and therefore review instantly and live, the topics that you and only you need. Finally, this book pursues the training, entertainment and development of the reader, therefore it does not include any “turnkey” project or “plug & play” service, on the contrary, it seeks to make the path followed be the driving force of the training objective and personal development and not the destination of the trip. To do this, both the 80 already solved exercises or projects are included, as well as another 400 proposed and unsolved exercises, therefore "have a good trip" and I hope that after reading the book, or part of it, you have acquired, for on the one hand, some basic knowledge that will serve as an impetus to fly in this world, where MicroPython© and ESP32© are the springboards and on the other hand you have spent a time of entertainment in which the process of trial and error is the foundation of a solid learning. Important: t o e d i t t h e e x e r c i s e s i t i s preferable that yourself use the Thonny© editor (or another one) to create or modify a MicroPython© script, you will gain practice in writing, indentation, error correction, maintenance, etc. and you will fix the theoretical knowledge acquired much better. For your convenience, in the Python© section of my blog indicated below, you will find the complete scripts for the exercises on: 12

Electronics & MicroPython© with ESP32©: 80 complete projects

https://gregochenlo.blogspot.com/ In this blog you also find more information about my books. In the Python© section of the blog you will also find two folders (Spanish and Italian) that include mo re t ha n 50 c om p le t e P y th o n© exercises described in detail that deal with the use of multiple sensors and actuators based on basic Electronics controlled with a Raspberry© and you will also find most of the exercises in this book.

These exercises are fully explained in my already mentioned books and whether you have them or not, you can use them to practice Python© and MicroPython©, learn functions, guide projects, etc. I recommend viewing and putting into practice the ones that interest you the most.

⊝⊝⊝

13

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

OTHER TITLES BY THE AUTHOR “Domótica con Raspberry©, Google© y Python©” (Ed-1) “Domótica con Raspberry©, Google© y Python©” (Ed-2) “Domótica con Raspberry©, Google© y Python©” (Ed-3) “Home Automation with Raspberry©, Google© & Python©” “Electrónica divertida con Raspberry©” “Elettronica divertente con Raspberry©” “Electrónica y Domótica con Raspberry©” “Python© con Raspberry© y Google©” “MicroPython© con ESP32©” “Electrónica y MicroPython© con ESP32©” “400 Ejercicios Resueltos de Física Universitaria” “400 Solved Exercises of University Physics” “400 Esercizi Risolti di Fisica Universitaria” “400 Problemas Resolvidos de Física Universitaria” “Ejercicios de Física 1: Cálculo Vectorial” “Ejercicios de Física 2: Mecánica Clásica” “Ejercicios de Física 3: Mecánica de Fluidos” “Ejercicios de Física 4: Calorimetría y Termodinámica” “Ejercicios de Física 5: Campo Eléctrico y Magnético” “Ejercicios de Física 6: Corriente Continua y Alterna” “Algebra y Análisis en Carreras Universitarias” “50 Poesías sin Título” “Pescando Tiburones” “Pescando Squali” “Snooker fácil” “Superar los Problemas de Próstata” “Porra de Próstata” “Prostata Infiammata”

⊝⊝⊝ 14

Electronics & MicroPython© with ESP32©: 80 complete projects

15

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

COPYRIGHT©

T

he author of this book is Gregorio Chenlo, who reserves the rights that the Law grants him in each region or country where this book is published.

This book, in its 1st edition, was published in October 2024 and the copyright that Spanish & USA Law grants it, applies from the moment of its publication. All rights reserved. Total or partial reproduction of this work is not permitted. With the © symbol next to each product, logo, idea, etc., we want to indicate respect for the possible brands, owners and suppliers of hardware, software, etc., described here, so it could be recognized that all of them are possibly registered trademarks and potentially have the rights that the Law may grant them. The author is not an expert on this subject and does not have the information or does not know if any of them are subject to any type of copyright or other rights that would prevent him from using them as a reference in this book. All of them are extracted from the Google© public browser, so it is understood that their use is completely public to use them, at least as a reference, in works similar to this one. On the other hand, it is stated that the system detailed here is used and is intended only for use in the particular home environment, training and/or recreational use, as it is written, without any commercial pretension, without any guarantee and declining all the responsibility that readers, other people, third parties, companies, etc., may carry out 16

Electronics & MicroPython© with ESP32©: 80 complete projects

on their own and for the use of all or part of the information described here. Although everything described in this book has been sufficiently implemented and tested, any responsibility is also declined for incorrect or not exactly identical operation of the various components, both hardware and software. Finally, indicate that the various public sources used, Web, etc., are attached, reaffirming the rights that may correspond to them and declining any type of responsibility, guarantee, etc., as a consequence of the inaccuracy, variation or disappearance of these sources of information.

⊝⊝⊝

17

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

1.-HARDWARE

A

s we have already mentioned, we are going to carry out Electronics exercises using an ESP32© that we will program with MicroPython©, therefore our scripts will run in real life with that micro controller so we need to know its hardware in some depth and that is what we will do in this first chapter of this book. There are several options to perform these code tests. We could use a PC©, MAC©, hardware simulator to practice, but I have believed that it is much more interesting to use a physical ESP32© that, due to its low price and availability of technical information, we can dedicate “full time” to this task. There are various types and models of ESP32© and above all multiple modules (ESP32© with voltage regulator, WiFi, Bluetooth, USB interface, pins, etc.) on the market that can be used for this project. Until now, the legendary ESP8266© dominated the market, but I recommend using the ESP32©, which is much more powerful, with more and better hardware, a very low price and also very easy to find on the market. There are also various modules and it will be up to the reader to choose the one they want to use based on their current but, above all, future needs. The price of all ESP32© models and all modules with ESP32© is very low, therefore my recommendation is to use a module, with all the components and with 38 pins since it incorporates more GPIO. 18

Electronics & MicroPython© with ESP32©: 80 complete projects

Below we can see a brief comparison of the basic parameters of the most interesting ESP32© modules currently available. Element

ESP32©

ESP32-S2©

ESP32-C3©

ESP32-S3©

CPU

Xtensa©

Xtensa©

RISC-V©

Xtensa©

Cores

1-32bits

1-32bits

1-32bits

2-32bits

Hz

240MHz

240MHz

160MHz

240MHz

RAM

520kB

320kB

400kB

512kB

Ext RAM

16MB

1GB

16MB

1GB

WiFi

2.4GHz

2.4GHz

2.4GHz

2.4GHz

Bluetooth

V4.2 BLE

-

V5.0

V5.0

ADC

2x12bit

2x12bit

2x12bit

2x12bit

DAC

2x8bit

2x8bit

-

-

Timers

4x64bit

4x64bit

2x54bit

4x54bit

Sensor ºF

-

1

1

1

Touch

10

14

-

14

Hall

1

-

-

-

GPIO

34

43

22

45

SPI

4

4

3

4

UART

3

2

2

3

I2C

2

2

1

2

I2S

2

1

2

2

PWM

16

8

6

8

The manufacturer of the ESP32©, Espressif©, has all the information on its website and also a very useful comparison tool, but the price of all versions is very similar, therefore my recommendation is to choose one of the most complete unless the dimensions are a limitation of use. As can be seen, we have multiple options for the ESP32© controller to which we must additionally add multiple options if we use a module and therefore the 19

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

options are very wide. In this book, an ESP32© has been used in a WROOM C3 module that has the following characteristics and that each reader can decide to use according to their needs.

20



A module from the manufacturer XTVTX© that includes a SOC (System on Chip) with: ESP32-S2©, 320KB RAM, 4MB Flash, WiFi and Bluetooth chip and a small printed circuit board with everything we need.



Two buttons: RESET which restarts the ESP32© micro controller and BOOT which is generally necessary to load new firmware, this last button can be used as a general purpose button when connected to GPIO0.



Micro USB port to power the ESP32© module at +5V and internally the board regulator transforms it into +3.3V. Let us remember that all GPIO pins and other connection protocols can only be connected to signals of +3.3V maximum. If this voltage is exceeded, the ESP32© or any of the elements of the SOC or module will burn out. There are ESP32© modules, which use USB-C ports for power and others have other USB ports (micro USB or USB-C) for connecting other devices.



The module has 38 pins with various functions described below, listing them from pin 1 to 38.



+3.3V: output pin of this voltage when the module is powered by micro USB or VIN or module power input pin at +3.3V. This pin does not provide more than 200mA-250mA.



RESET: connection input pin to reset the micro controller, performing the same function as the RESET button.



GPIO (GPIOXX): pins configurable as general purpose inputs/outputs (some are input only and some are output only).

Electronics & MicroPython© with ESP32©: 80 complete projects



GPIO (ADCXX): configurable as analog to digital converters or ADC. Although there are multiple ADC inputs, internally there is only one operational 12bit ADC, whose input can be selected by software.



GPIO (DACXX): configurable as digital to analog converters or DAC. The ESP32© has two independent 8bit DAC.



GPIO (TOUCHX): configurable as touch sensors that can be used as inputs.



GND: ground pins required for proper power.



GPIO (RXX-TXX): intended for asynchronous serial communication or UART, in this case 3 independent UART are available.



GPIO (FLASHXX): for updating, programming and maintaining the internal firmware of the ESP32©.



VIN: +5V input to power the ESP32© module as an alternative to the micro USB port.



GPI O ( VS PI ): us ed in sy nc hr ono us se ri al communication of the SPI port intended for communications, for example, with screens, memories, etc.



GPIO (I2CXXX): for high-speed serial communication between devices and integrated circuits over an I2C bus.

contact

Depending on the ESP32© module model chosen, we will need some additional components, which we will see in detail below: 1. Box for the ESP32©: Depending on the use we give

to our project, we will need a box or not. If we are only going to use the ESP32© to learn Electronics, MicroPython© and with a few peripherals (sensors or actuators) we will not need any box, it is enough to place the ESP32© 21

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

module on a breadboard or even with some cables inserted or soldered on the pins that we are going to use is more than enough. 2. Heat

sinks: The ESP32© is a low-performance, very low-consumption micro controller and therefore will not need generally active or passive coolers. There is an exception and that is when we power the module through the VIN pin with a high voltage (always lower than +7V) and in that case the internal +3.3V voltage regulator of the module can heat up moderately.

3. Power supply: This is a very important element

because we need it to be as stable as possible so that there is no loss of information in our scripts or deterioration of the hardware. It is best to power the module through the micro USB or USB-C port with a stabilized +5V charger and let the module make the conversion to the working +3.3V of the ESP32©. In this book the module has been connected to the USB port of a MAC© from where all the programming has been carried out without any problem. In any case, let's consider that each GPIO can only safely supply a maximum of 40mA with a limit of 250mA for the maximum total current supplied by the ESP32©. See annex with more information. 4. Connection cables: We will need the micro USB or

USB-C connection cable for power the PC or MAC, as well as connection cables, for example, the ESP32© to a breadboard. In learn only MicroPython©, we will corresponding USB cable. 5. The

and data from Dupont© type if we connect principle, to only need the

ESP32© module: The ESP32© printed circuit board includes multiple components, as we see in the following figure, but we are interested in those discussed below.

22

Electronics & MicroPython© with ESP32©: 80 complete projects

In this book, an ESP32© WROOM3-32 module has been used and described because it has, at the time of writing, very acceptable performance, 38 pins configurable with all types of communication ports, very easy to obtain, at a reasonable very small price and with infinite information on the Internet. This ESP32© has a dual-core ESP32-D0WDQ6© processor, type MCU LX6©, these cores can be activated separately, an UART type CP2102© and a DEV KIT C configuration that allows compatibility with multiple already designed projects. The board has WiFi and Bluetooth low consumption or BLE, its own MAC address and an LED connected to the UART I/O port and manageable in the GPIO01. The WiFi IP address is set by software, the CPU clock speed is configurable between 80-240MHz. The GPIO provide up to 40mA output, the DAC only 14mA and has the SPI, UART, I2C, I2S, 1-Wire©, Touch, etc. protocols. The firmware loading is automatic and in general does not require pressing the BOOT button on the board that we had mentioned.

23

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

24



SOC: The SOC (System On Chip) resides in this metal package, that is, the ESP32© CPU, the RAM and a WiFi and Bluetooth controller.



USB Controller: This chip allows the ESP32© to communicate with the outside world through a micro USB or USB-C port. In general there are two types of this controller: the CP2102© which is square and the CH340C© which is rectangular, personally I prefer the CP2102© for being more reliable and with drivers that are easier to obtain.



USB: Here we will connect the micro USB or USB-C charger if the module is already configured, the firmware loaded and the programs installed and therefore we do not need data or a USB, charging and data cable, to connect it to the computer from where we are going to work with MicroPython© and the ESP32©.



BOOT: T h i s b u t t o n, i n c o rp o r a t e d i n t o th e module's printed circuit board, is usually used to load the initial firmware of the ESP32© or also as a general purpose button. In the latter case, in most modules, this button is configured as GPIO0 and we can use it by controlling it with our software.



Regulator: As we have already mentioned, the ESP32© uses +3.3V for its internal operation and for the control of all GPIO. When powering the module with a +5V USB cable, the system requires a +3.3V voltage regulator.



Antenna: This component allows 2.4GHz WiFi and Bluetooth BLE (low consumption) communication between the ESP32© and the rest of the devices.



GPIO: Finally, the module has 38 pins where the GPIO are accessible, that is, input and output ports that are configurable by software and that allow us to directly connect multiple devices: sensors, components, actuators, etc. but also

Electronics & MicroPython© with ESP32©: 80 complete projects

us e i ts pi n s, in di vi du a ll y o r i n gr ou ps (communications protocols SPI, I2C, I2S, 1Wire©, UART, parallel, etc.), to be able to carry out exercises and small projects. In this book we will see how to use this connector from MicroPython©. In any case, handle the module with care, avoiding touching the GPIO pins with metal parts. In short, we need hardware elements whose use will depend on the objective of the current project and the future that we want to give to our system, however, to learn basic Electronics and MicroPython©, it is enough with a basic ESP32© module, the USB cable power supply, a breadboard where the module and components, sensors, actuators, etc. that are necessary, can be located.

Finally, since the maximum output current of a GPIO cannot exceed 40mA, this current must be limited with the corresponding resistors if necessary. The DAC converter provides a maximum output current of 14mA, so i ts ou tp ut mus t b e l im it ed w it h a 220 Ω resistance or equivalent and which we will see in detail in each exercise.

⊝⊝⊝

25

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

2.-SOFTWARE Logically, in addition to the hardware that we have already detailed, we need a software environment (the ESP32© does not have an operating system or any factory firmware pre loaded) to interact with the hardware comfortably and some basic applications to access the various functions that we want our ESP32© to perform in each of the Electronics with MicroPython© exercises that we develop. Therefore, in this section we will see the topics discussed below and that will help us to comfortably access all the software and hardware functions of the ESP32© so that later, programming in basic MicroPython© is as efficient as possible. Software required to run MicroPython©: •

Installation of Python© and ESPTool©.



MicroPython© Thonny© editor.

At the end of the book we also include other additional software that helps us a lot to build electronic projects using an ESP32©.

⊝⊝⊝

26

Electronics & MicroPython© with ESP32©: 80 complete projects

*Installation of Python© & ESPTool© For the MicroPython© environment works properly on our ESP32©, we must install a version of Python© on the computer, higher than 3.0. We do the following in Windows© or MAC©: PYTHON© INSTALLATION: Go to www.python.org and do: [download] [macOS] or [windows, use option 64] Latest Python 3 Release - Python 3.12.1 Follow the instructions on the screen, locate the APP in the application bar and check the installed version from Terminal or CMD with: python –version. INSTALL ESPTool©: Enter to Terminal and execute the commands: sudo pip3 install --upgrade pip sudo pip install esptool Test the installation of ESPTool© with: esptool.py INSTALL DRIVER OF THE CP2102© CHIP: Enter the CP2102© driver manufacturer's website, that is, www.silabs.com, and access to: [download] [mac] or [windows], if necessary give permissions to the driver installation in [security]. For MAC© we can see the installed driver from t h e t e r m i n a l w i t h t h e c o m m a n d : ls /dev/tty.*, displaying the installed device: /dev/cu.SLAB_USBtoUART. For Windows©, the driver can be located in the traditional device manager window. 27

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

DELETE THE ESP32©: E n t e r Terminal o r CMD and use the following command, it is quite long, check carefully that it is written correctly: esptool.py --chip esp32 --port /dev/tty. SLAB_USBtoUART erase_flash If everything similar will appear:

is

ok,

the

following

text

or

Chip is ESP32-D0WD-V3 (review v3.0) Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None Crystal is 40MHz MAC: [the MAC of your ESP32©] INSTALL NEW FIRMWARE: We now have everything almost ready, we just need to install the firmware on the ESP32© so that we can program it in MicroPython© and the good news: all the steps carried out so far do not have to be repeated (unless there are errors...). Access the Web www.micropython.org/download and: [esp32/wroom] and download, for example: v1.22.1(2024-01-05).bin (ESP32_GENERIC20240105-v1.22.1.bin) Copy it to the command path and from Terminal: esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 460800 write_flash -z 0x1000 ESP32_GENERIC-20240105-v1.22.1 Review the command carefully and wait for the new firmware to be loaded into the ESP32©... and that's it!!!!. If there is an error in the previous step, review the commands, repeat the operation and if necessary, search for help on the Web, there is plenty available.

⊝⊝⊝ 28

Electronics & MicroPython© with ESP32©: 80 complete projects

*Thonny© MicroPython© Editor To write, test, load into the ESP32© and execute MicroPython© scripts we need a programming editor. There are multiple programming environment editors: simple, complex, light, heavy, with or without aids, adapted or not to the hardware, etc. After seeing several programming editors: IDLE©, PyCharm©, Visual Studio Code©, Thonny©, etc. my proposal for this basic level of Electronics with MicroPython© using the ESP32© hardware is the Thonny© editor because it is very easy to obtain, install, understand, run, debug, etc. To install www.thonny.org, instructions on place and run it

Thonny© we access the Web: we can download it following the the screen, place it in a suitable directly. We make:

1. We

enter on [preferences] and use the MicroPython© interpreter (ESP32©) and select in [Port or WebREPL] the driver installed in the previous section, for example, CP2102 USB...

2. We open [file] [new program] and we can write a

MicroPython© script in *.py format, which we can save both on the computer and in the internal memory of the ESP32©. 3. To run a script we press the [run] button and

stop it with [stop]. At first times we will make many mistakes but the MicroPython© editor or interpreter, Thonny©, will give us enough clues to detect and correct code errors, logically it will not help us with the algorithm's own errors. Be patient. 29

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

4. We

can stop most of the scripts by pressing +, previously placing the cursor in the console or lower window. From the console we can also restart the ESP32©, by software, by pressing +.

5. If we want to access the ESP32© via WiFi instead

of a USB cable connection, we must power the module with a charger or battery and from the Thonny© console enable WebRPL with the import webrepl_setup command, activating it with [E] a n d d e a c t i v a t i n g i t w i t h [D]. I f i t i s activated, we must assign a password of 8 characters. In [preferences] [interpreter], we must also activate WebREPL with ws://[IP]:8266/ where [IP] is the IP address of the ESP32© and the password is the one created previously. Finally we will have to restart the ESP32© and activate the WiFi, but to do this we need to run a specific MicroPython© script that we will see later in some exercise. To access to the ESP32© we will do so from a browser with http://[IP]:8266/ and the previous password, being able to view the execution of any script located in the module or executing it from the console by importing it with import [script].

6. If

we want a script to be executed when the ESP32© starts, for example the script that connects the module to the WiFi, we must save this script in the ESP32© memory within the boot.py script or within main.py.

To get started in this book I recommend using the physical connection to the computer via USB cable, this way we will have everything we need closer, being able to control it much more easily. Once we master the language and the hardware we will be able to use the WiFi connection without any problem.

⊝⊝⊝ 30

Electronics & MicroPython© with ESP32©: 80 complete projects

3.-MICROPYTHON©

W

e have seen the ESP32©, the necessary hardware and the Thonny© programming environment to start using MicroPython©, but before starting to program we have to know what is Python© in general and MicroPython© in particular, how they works and how we can get the most out of them doing hundreds of Electronics exercises. Python© in general and MicroPython© in particular are a modern, powerful, widely used, easy to implement programming languages, which have multiple libraries or additional programs already tested and debugged, with manuals of all kinds, hundreds of tutorials, forums, online courses, books, millions of users, very easy integration with other systems and projects, which integrates and manages perfectly with the ESP32© hardware, etc. In this book we will use the most current version of MicroPython© and therefore the changes in the writing are included: way of importing libraries, need for parentheses in print() statements, exceptions management, etc. and also some functions already integrated as well as a multitude of libraries already tested by thousands of users that will allow us to manage our Electronics projects more comfortably. Comment before continuing that MicroPython© is an interpreted programming language, that is, once the code is written, a program must be used to interpret it, line by line, and translate it, at run time, into the machine language, that is, to the CPU language of the ESP32© module. 31

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

This condition of interpreted language has the advantage that the script code is much easier for us Humans to read, but its execution is slower because the code must be interpreted, that is, it must be translated every time the program is executed, line by line, to the internal language of the machine, that is, of the ESP32© CPU. On the other hand, a compiled language such as C++© or Java©, are much more difficult for Humans to understand, but they are translated once into the machine language and then the machine executes them much faster than an interpreted language. In our case, both the program editor, the interpreter, and the MicroPython© debugger are carried out through the Thonny© interpreter software, which we will see below.

⊝⊝⊝

32

Electronics & MicroPython© with ESP32©: 80 complete projects

*The interpreter Thonny© As we have already mentioned, to start using MicroPython© in our exercises, we need an interpreter that will translate and execute our code, transferring it to the language of the machine we are using, in our case an ESP32©. For greater convenience on our part, we can add the Thonny© icon to the computer's application bar (MAC© or Windows©) so that, just by pressing it, it opens directly. To do this we do the following and logically it also helps us add icons from other applications or utilities of the operating system or even personal applications that execute a Python© script that we have designed. Once version 4.1.4 of the Thonny© interpreter for Python3.10© has been started, we access the main screen, where we can basically enter commands directly into the console, open already created MicroPython© files [*].py, edit, etc.

33

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

At the bottom is another window that is the console, that is, where the inputs or outputs of the script are shown and where we can also interact directly with the ESP32© in MicroPython© by writing at the prompt [>>>]. Try the following: >>>a = 5 >>>print(a) >>>5 This is a very simple example where we have created a variable called a, we have assigned it the integer value 5 and we have displayed its value on the screen. Many times we will need to test complex functions without having to write and debug a specific program, for example, try this: >>>a,b = 'Happy 2024','Birthday' >>>print(a[:6] + b + a[5:]) >>>Happy Birthday 2024 In general, in this book we are almost never going to use MicroPython© in this way because we will lose what we have written, we will only go to the Thonny© console in very specific cases to see how a specific command behaves. We will use programs or scripts that we are going to save in files with the extension [*].py and that we will invoke later to modify, execute and save them again to use when we need. Like all languages in the real or virtual world, writing well implies following rules and here it is no different, we will use a writing protocol for our scripts whenever we can. This protocol is defined under the PEP8© standard that contemplates the following basic rules but, in this book, I have decided to add an “aesthetic” component that helps to arrange the information on the screen in a more visual and readable way. 1. Indentation:

Use 4 spaces for each level of indentation. In general, do not use tabs as they can be misinterpreted by MicroPython©.

34

Electronics & MicroPython© with ESP32©: 80 complete projects

Adequate indentation is not an aesthetic issue, it is absolutely crucial in MicroPython© as it structures the commands in blocks, establishing a specific order of execution. 2. Line length: Try to limit lines of code to 80

characters to make it easy to read in most editors and screens. Thonny© allows us to divide a long line into several lines automatically. 3. Whitespace:

Use whitespace consistently to improve the readability of mathematical operations, logic, variable assignment, etc. Do not place spaces at the end of lines of code and use blank lines appropriately to separate functions and logical blocks.

4. Names:

Use self-descriptive names for the variables and follow the general convention of all variables in lowercase with underscores between words and all constants in uppercase letters, in any case do not use excessively long or complex names.

5. Comments: Add comments when necessary to explain

complicated code fragments or to provide additional information about the purpose of the code. The comments may seem obvious but they are not obvious to all readers or for us at all times. Comments start with #.

6. D o c s t r i n g s :

Include docstrings or selfexplanatory text to describe the purpose and functionality of functions, classes, modules and the script itself. This helps generate documentation automatically. Use # to comment out lines and text delimited with '''example''' for long texts.

7. Imports:

Group import statements into three sections: standard MicroPython© imports, thirdparty imports, and local imports. Separate these sections with a blank line. Also

briefly

comment

on

the

purpose

of

each 35

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

imported library using #. 8. Script

structure: Organize your code into functions and classes for easy maintenance and reuse. Use the block if __name__ == "__main__": to execute the main code when the script is executed directly and especially when the script is very long or complex.

Let's see a summary of the many most useful Thonny© commands, they are very intuitive, try them: Command

Description

[File]

operations with script [*.py]

[Open]

open a existing script [*.py]

[Recent files] open recent scripts [Save] [Save as]

save a script save current script with other name

[Close]

close without saving the opened script

[Exit]

exit Thonny©

[Edit]

edit [*.py] script

[Indent]

format specific areas of the script

[Preferences] Thonny© interpreter configuration [Help]

help on using Thonny©

[View]

events, plotter, variables, etc.

[Change] [Go to line] [Packages]

change text in open script goes to a specific line in the script load MicroPython© libraries

As we can see, only some of the most used Thonny© options for a basic start have been explained, but their use is very simple and intuitive. In Thonny©'s own help [Help] or on the Internet there is enough information to work with all the exercises in this book. In addition to the specific examples for each 36

Electronics & MicroPython© with ESP32©: 80 complete projects

concept, in each of the explanations, we will see a multitude of specific examples for each phase of programming and thus be able to better establish all the theoretical concepts. An attempt has also been made, as far as possible, to have a common thread between all the exercises proposed and with a degree of incremental complexity between all of them. In this way we do not lose the training thread between exercise and exercise and we consolidate progress with a solid base and increasingly complex and powerful concepts. The necessary concepts are gradually introduced with fair and essential theoretical explanations, with more than 40 examples, more than 90 proposed exercises and in the end 80 complete and solved projects and 400 proposed ones. The topics to be discussed in the following chapters have been classified in the following order: • • • • • • • • • • • • • • •

The art of programming Structure of a program Importing libraries Comments Parameters and variables Type of data Input and output Operators Flow control User functions Predefined functions Files Error control Command summary Complete exercises

⊝⊝⊝

37

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*The art of programming Purist professional programmers may not agree with what I am going to say in this chapter, but I believe that it is the basis for ensuring that any training started on MicroPython© is continued to the end and is not abandoned because it is complicated, tedious and bored. The trick is to think that programming in general and programming in MicroPython© in particular is like an Art, that is, each one has their own method and although we have to respect the rules of the language so that the system understands us, so that the ESP32© execute the necessary commands, so that the script achieves the intended objective, etc., it is essential that we feel comfortable with our own “art of programming”, that we use the instructions that we best understand, with which we feel comfortable and proud even if they are not as efficient as possible. There was a time in computing when super efficient and minimalist codes prevailed in order to take advantage of the limited memory of the devices. At this time, the speed of execution of the code itself also took precedence since the speed of the hardware was very poor. Nowadays we have an ESP32© internal memory with sufficient capacity and hardware with more than enough power for what we are going to practice at our level, therefore we must orient our art of programming towards other objectives, especially towards ease of reading by ourselves and by others, both now and in the future.

⊝⊝⊝ 38

Electronics & MicroPython© with ESP32©: 80 complete projects

*Structure of a program Regardless of our creativity and “our art to program”, what is evident is that we must respect the MicroPython© programming rules, the basic structure of a program and the PEP8© rules already mentioned. In general, the basic structure of a basic MicroPython© program, at our initial level, can consist of the following sections and in the order discussed. We could make multiple changes on our scripts: change the order, delete some sections and add others but, at our level, it is very important that we maintain a fixed structure so that we do not forget any important section and have a regular structure, easy to interpret and read at all times. 1. 2. 3. 4. 5. 6.

Title, description and parameters Import of libraries Data and variables Functions Main body Error management

We will look at each of the previous points in detail in the next chapters, however we are going to detail them a little more to understand what we are talking about and have an initial global vision. 1.-TITLE, DESCRIPTION AND PARAMETERS The title and description of our MicroPython© program is very important to be clear at a glance what its main objective is, what its inputs are and what its most important outputs are.

39

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Let's look at our first example of a MicroPython© program or script, for this we will use the following instructions in Thonny©: • •

[File] [New Program] or by pressing: [File] [Save as] [This computer] p_exercises.py

In this way we will have created the MicroPython© program p_exercises.py in the directory of the selected computer. Now the program is empty but we will add interesting things, which we can modify, expand, delete, etc. subsequently. Let's add an important instruction: # -*- coding: utf-8 -

# Special characters

This instruction will guarantee that our program includes, in the comments, content of variables, strings, etc., special characters such as accents, symbols, etc. In many versions of MicroPython© this instruction is not necessary as it is included in the editor configuration, test it to ensure its necessity. Now we will add the following: ########################### # MODULE: p_exercises.py # Our first MicroPython© example # INPUTS: none # OUTPUTS: none ########################## [File] [Save] or by pressing: The program does not do anything yet but it will do so as we add data, commands, operators, functions, etc., be patient. We can run the program with the [Run] option or the Thonny© button, but it won't do anything at all, logically, we haven't incorporated commands yet. Except for the special instruction indicated at the beginning, everything that begins with #, the program will interpret as a comment and will not do 40

Electronics & MicroPython© with ESP32©: 80 complete projects

anything with it. If we wanted to make a comment with many lines, we can delimit them with ''' at the beginning and at the end. Let's see that we have added some ### that the only thing they do is delimit parts of the program. We will use them every time we want to highlight a part: the library import body, the data, the functions, the main body of the program, etc. We can use these characters or others, but always the first one on the left must be # to indicate that it is a comment and not an instruction. We have also included the name of the program with a brief description of what it does, the inputs it uses and the outputs, at the moment nothing at all. 2.-IMPORT OF LIBRARIES In our program we are going to use other MicroPython© programs or libraries already written by third parties and that have been sufficiently tested so that we can use them with confidence and for free. For example, the time library will allow us to calculate the time elapsed between two moments in our program, the current hour, minutes, seconds, etc. Let's add the library import body and the time import to our program with: #--------------------------#IMPORT OF LIBRARIES BODY #--------------------------import time # Time control 3.-DATA AND VARIABLES In MicroPython© we can use fixed data that we can conveniently store with a name and also variables, that is, data that will change during the course of the program. Let's use easy-to-understand names, for example, name instead of x_name%12 or age instead of f_age_if%18, etc. 41

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Let's add the following to our script: #--------------------------#DATA & VARIABLES BODY #--------------------------name = 'John' # Variable assignment age = 20 # We can add spaces We have created the name data and we have assigned it the value John. It is important to see that John is a data, not a variable and therefore it has to be enclosed in single or double quotes. Try not putting them on, run the program with and see that the error appears: Traceback (most recent call last): File "", line 4, in NameError: name 'John' isn't defined • •

In the error message we see interesting things: The line where the error is, 4 The error: John is not defined. 4.-FUNCTIONS

To make a program easier to understand, easier to maintain, simpler to debug and above all so that it does not have repeated and inefficient code, we will often use functions created by ourselves and we will invoke them every time it is necessary. Let's add the following code to the exercise: #--------------------------#FUNCTIONS BODY #--------------------------def see(x): # Function see() global age # Global variable age edad += 1 # age increment print(x + ' is ' + str(edad) + ' old') print(time.localtime()[3:5]) We have created a function called see() that includes the parameter x, that is, the function see() operates on the variable that we pass to it in x. 42

Electronics & MicroPython© with ESP32©: 80 complete projects

When, later, see(x) is invoked, it will be executed: the age data is a data defined outside the function see(x), 1 is added to it, the result is stored again in age, it is displayed on the screen that the variable x has such years and the hour and minutes at the time of program execution. Let's try to run the program with we will see that it does nothing, why?...it does nothing because, although the function see() is defined, we are not invoking it, that is, we are not saying anywhere that this function should be executed. We are going to do it in the next part of our program. 5.-MAIN BODY Let's add the next component to our program, the main body with: #--------------------------#MAIN BODY #--------------------------if __name__=='__main__': # Script start see(name) # Call function see() T h e if __name__=='__main__': s t a t e m e n t i s reserved and indicates that this is where the instructions in the main body of the program begin. We also see that the instructions see(name) and those of def see(x): are shifted to the right. This displacement is called indentation or bleeding and is very very important in MicroPython© as it indicates which instructions are included in each action. In our case, the execution of the see(name) function is included in the main body of the program and both global, age += 1 and print() are included in the see(x) function. Try to eliminate this indentation or bleeding, we will see that the program behaves in an unexpected way. Many errors made when writing a MicroPython© script occur for this reason. 43

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

6.-ERRORS MANAGEMENT Finally we will add to the main body a group of instructions to manage possible errors in the execution of the program. Error handling is often used when the script invokes hardware functions that may not be available. For example, sending an email may be unavailable if we do not have an Internet connection at the time of running our script. Let's add the following instructions to our code within the main body: #--------------------------#MAIN BODY #--------------------------if __name__=='__main__': try: see(name) except Exception: print('ERROR') raise

# # # # # #

Script start Try action see() function Is there an error? Indicate it Display error

The function see(name) will be executed, but if an error occurs, the program flow is resumed by the except system function and the message 'ERROR' will be printed. Try changing the age += 1 instruction to age = 1/0, an error will be generated for dividing 1 by 0. Also try commenting with # or uncommenting the raise instruction, see what happens. We already have the first MicroPython© script, it doesn't do much, we will expand it as we learn more commands, operators, functions, etc.

⊝⊝⊝

44

Electronics & MicroPython© with ESP32©: 80 complete projects

*Importing libraries To complete some of the MicroPython© modules discussed in this book, we need your own MicroPython© or third-party libraries already configured and sufficiently tested without us having to develop them again from the beginning. These libraries make our scripts more powerful, complete and even efficient. The most used in the exercises in this book are indicated below and are related to system functions, GPIO, communication buses, Wi-Fi network, Bluetooth, sensors, actuators, displays, external RTC, memory cards, mathematical functions, Web servers , multitasking, etc. Library

Description

utime

Time data, hour, minutes, etc.

utime

Precise time control

ntptime

RTC synchronization server

Pin

GPIO control

esp32

ESP32© internal data

DAC

Digital to analog management

ADC

Analog to digital management

PWM

Pulse width modulation signals manager

TouchPad

Touch GPIO control

Timer

Hardware timer management

network

WiFi connection management

usocket

Web server connection manager

urequests

Web request manager

ubinascii

Binary to ACII converter

45

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Library

Description

uasyncio

Multitasking process manager

ramdom

Handling random numbers

array

Data buffer management

ir_rx.nec

Infrared remote control

SoftI2C

I2C data bus manager

I2S

I2S music bus manager

SPI

SPI data bus manager

dht

DHT11© temperature sensor control

onewire

1-Wire© bus management

lcd1602

Display LCD1602© control

lcd_api

PCF8574© bus extender manager

i2c_lcd

Display LCD1602© with I2C control

ili9341

TFT Display ILI9341© control

ds18x20

DS18B20© temperature sensor manager

sh1106

OLED display SH1106© control

ds1302

External RTC DS1302© control

ds1307

External RTC DS1307© control

BLE

Bluetooth BLE connection manager

BME280

BMP280© barometer controller

hmc5883l

GY-271© magnetic sensor controller

mfrc522

RFID RC522© card reader management

max7219

Matrix LED controller

uos

System functions

sdcard

SD and micro SD memory manager

dfplayermini Control of mp3 player modules

⊝⊝⊝

46

Electronics & MicroPython© with ESP32©: 80 complete projects

*Comments As we have already seen, we can add comments to each line of code to note what objective it pursues, but it is very important to add comments in the following sections, especially to be able to read the code more easily both at the time of its construction and after a certain time has passed. If the code is also going to be read by other people, all the more reason we should make all the necessary comments. • • • • • • •

Title of the program: pursued objective, its main inputs and outputs. Import body: brief description of each library. Data and variables: what we are going to store in each of them and what they are for. Functions: what they pursue, main inputs and outputs. Main body: what objective it pursues and what main functions it performs. Error control: What happens if an expected error or an unforeseen error occurs. Etc.: whenever necessary. # ''' “””

for one line comments comments ''' for multiple lines or comments “”” for multiple lines.

EXERCISES: • • •

Add comments to p_exercises.py Try with # and ''' See what happens using: ''' comment “””

⊝⊝⊝

47

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Parameters & variables To perform calculations, enter and display results on the screen, make decisions, transfer data to functions, etc. we are going to need to create parameters and variables. We will call parameters data that remains fixed throughout the script, for example our name, our age, the size of a window, etc. We will call variables data that vary depending on calculations, algorithms, etc. Both parameters and variables are assigned with t h e = symbol and must have a name that clearly identifies what objective it pursues but without being too extensive so that it is easy to handle and cannot have accents, etc. For example: MY_NAME YOUR_NAME john_age peter_age name

= = = = =

'John' 'Peter' 21 25 MY_NAME

# Name assignment # Ages assignment # Variable assignment

Note that spaces can be added between the parameter or variable name and the = sign and that constants are usually written in capital letters. Note that name=MY_NAME does not assign the text 'MY_NAME' to the variable name, it assigns the content o f t h e c o n s t a n t MY_NAME t o t h e v a r i a b l e name, therefore it is as if we assigned name = 'John'. EXERCISES: • • •

Assign to YOUR_NAME the text Julia Assign the name variable to YOUR_NAME Assign Pedro's age to john_age

⊝⊝⊝ 48

Electronics & MicroPython© with ESP32©: 80 complete projects

*Type of data MicroPython© handles many types of data that are already established in the system and that we are going to see in this section, but it also handles other types of data, which we could create and define, called objects, for example, we could define what cities are, what are cars, etc. what characteristics they have and what functions they perform, but we are not going to see them in this book because they go beyond the concepts of a basic MicroPython© course. We can highlight the following types of basic data, later we will see how we can operate with each of them. 1.-NUMERICAL DATA Numerical data are the easiest to understand and refer to the numbers that we usually use and that we could classify into: • • •

integers: both negative and positive, for example: 2, 3, -2, 1000, etc. real: or also called floating point with all types of decimals, for example: 2.5, 3.0, -2.01, 1e3, etc. complex: with integer or real components, for ex a m p le : 4+5j, 4.0-5.01j, etc. Due to its complexity, we will not see this last type of numerical data in this book.

EXAMPLES: john_age john_weight margin total negative

= = = = =

21 68.1 .001 1e2 -.100

# # # # #

Integer Real Real Real 1e2=1x10^2=100 Real

49

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

EXERCISES: • • •

Assign a negative integer value to temperature. Assign a floating point value to the integer name variable, is it possible?, is it appropriate?. Assign 13 to x which is a real parameter. 2.-LOGICAL DATA

Logical data, also called Boolean, are those that admit only the values true or false or in MicroPython© the values True or False and are widely used to perform logical operations or make simple decisions. EXAMPLES: repeat = True not_repeat = False print(repeat, not_repeat)

# Logical data True # Logical data False # Display data

EXERCISES: • • •

Assign the variable called value the logical value 'False' including the quotes, analyzes the impact of the quotes. Now assign the value True to the value variable, without including the quotes, and describe the difference with the previous exercise. How are both cases different?. Look closely at how Thonny© interprets them when writing them. 3.-CHARACTERS

Characters are text strings of various sizes, which may include letters (upper or lower case or both), numbers, special characters, etc., which are grouped and delimited between single (') or double (“) quotes and which can be used to manage names, text sequences, etc. 50

Electronics & MicroPython© with ESP32©: 80 complete projects

EXAMPLES: city_name book_name number quotes

= = = =

'Los Angeles' 'MicroPython© Exercises' ”123456” 'between ”quotes”'

EXERCISES: • • •

Assign the value “2” to the variable númbèr. what happens?...the variable names cannot have accents. Assigns the character value '3' to the variable text, i n c l u d i n g t h e s i n g l e q u o t e s , w h a t happens?... we can make text = ”'3'” Test with text = '”3”'. 4.-TIME

In reality, the time data type is a numeric data type of the real or floating point type, which includes all chronological information: year, month, day of the week, day, hour, minute, second, etc. and that each of its components can be translated into integers with the corresponding conversion function. There are many ways to manage time variables in MicroPython©, only some examples are discussed here. In any case, to manage the time variables we must import the corresponding libraries since they are not included in Thonny©. The most used libraries are: import time import RTC

# Time library # Internal ESP32© clock library

EXAMPLES: Add the following instructions to our program p_exercises.py, run it with and observe the results of each added instruction. 51

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

hour_1 = time.localtime() # Assign time data hour_2 = time.localtime()[0] # Assign the year print(hour_1) # Display data print(hour_2) We can see that various information about the time variables can be displayed with different functions. Let's see more cases, add the following code and we can visualize the time elapsed between two instructions: now_1 = time.time() now_2 = time.time() print(now_2-now_1)

# Assign time 1 # Assign time 2 # Display calculations

Add the following code and see how we can separately manage the current year, month, day, hour, minute and second: now_x = time.localtime() print(now_x[:3]) print(now_x[3:6])

# View date, test [0:3] # View time

EXERCISES: • • •

Display with print() the text type variable hour='ss:mm:hh' and just below it the value of the current seconds, minutes and hour. Assign the numeric variable now_x the value of seconds. Change [x:y] and view it. Try the previous exercise with both time.localtime() a n d time.time(). What is the fundamental difference?. 5.-LISTS

Lists and also dictionaries, which we will see later, are very interesting types of data, very useful and that can help us save and manage data in a grouped, related and very simple, very interesting way. It's very important to know this type of data well, because they are widely used. 52

Electronics & MicroPython© with ESP32©: 80 complete projects

A list is assigned in the following way: list = [e_1,...,e_n], where list[] is the name that we assign to this variable list and e_1,...,e_n are all the elements that make up this list, from the first element, 1, to the last element, n, grouped with [] and separated by commas. EXAMPLES: Let's add to our program p_exercises.py the definition or assignment of the following lists[] with the following contents: names = ['John', 'Julia', 'Peter'] ages = [39, 50, 10] surnames = [['J1', 'J2'],['A1', 'A2'],['P1', 'P2']] print(names, ages) print(surnames) In the previous examples we can see that the elements of a list[] can be of all types: characters, numbers, even other lists[] or the empty list: list = [], etc. EXERCISES: • • •

Try viewing the list example = ['a', b, 'c'] what happens?, does an error appear?, why?, how is this error resolved?. Display the list example = ['a, 'b', 'c'] what happens?, how is the error resolved?. Generates, for example, the list today = [] but containing the current year, day and month as elements. 6.-DICTIONARIES

Dictionaries are similar to lists but each element of the dictionary is made up of a pair of data: a key and a value. The components of each pair are separated by : and the elements are separated by commas and grouped with {}. 53

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

A dictionary is assigned as follows: dictionary = {key_1:value_1,...,key_n:value_n}, where dictionary is its name, key_1 is the first key, value_1 is its first value until key_n is the last key and value_n is its last value. T h e m a i n d i f f e r e n c e b e t w e e n list[] a n d dictionary{} is that in the latter we can directly access each data through the use of keys. EXAMPLES: Try adding to p_exercises.py and see how the definitions and displays of the following dictionaries behave: addresses = {'Greg':'USA', 'Julia':'Italy'} weights = {'Greg':60, 'Julia':50, 'Peter':80} print(addresses['Greg'], weights['Greg']) weights['Greg'] = 90 print(addresses['Greg'], weights['Greg']) We can see how a dictionary data is accessed or changed through its key. In the operators chapter we will see many more functions. EXERCISES: •

C r e a t e t h e variables{} dictionary with the variables one, two, three and the numerical values 1, 2, 3. Previously assign each variable its value and display the variables{} dictionary.



In the previous point, modify the values of each numerical data by its double, accessing to variables{} key by key.



Changes data of variables{} to a logical data, the 2-element string[] and the hour.

⊝⊝⊝

54

Electronics & MicroPython© with ESP32©: 80 complete projects

*Input & output In order to advance our knowledge of basic MicroPython©, we will need to provide our programs with additional data in a comfortable way and without having to change the code every time some data changes. That is, we need to be able to have input data or variables and also be able to display data and variables as output elements. We will see the most basic data input and output formats included in Thonny©: direct display in the console through print() statements of our code or with the Thonny© plotter tool. Keyboard data entry is performed, in its most basic version of MicroPython©, with the instruction t y p e variable = input('name'), where variable is a variable where the input will be loaded and 'name' is a text that summarizes the content of the input loaded into the variable variable. If we want to give a certain format to the input data, for example, if we want the input data to be an integer, we have to use functions that we will see later, for example the int() function. EXAMPLES: See what happens with an integer like 3, a real number like 3.8, a variable like x or a text like 'text' in the following code: while True: try: x = int(input('x=')) print(x) except: print('Incorrect data')

# # # # # #

Infinite loop Try the following Capture integer data It display them If there's an error It indicates

55

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Later we will see more cases of flow control such as the while True: statement, which, in this case, performs an infinite loop since the True variable is always true and the try:...except: couple controls possible errors. For data output we have used the print() command which supports some variants such as: name = 'Ana' # Assign name age = 20 # Assign age print('%s is %d years old.'%(name,age)) # Substitution Specifically, with the print output we can use data format substitutions such as: Type

Description

Examples

%s

Text strings

'My list: %s'%list[x]

%d

Integer data

“I'm %d years old”%age

%f

Real data

'I weight %f kg'%weight

%.nf

Real data decimals

w i t h n 'You weight %.1f'%70

EXERCISES: •

Eliminate the try:...except: pair and explain the errors that occur if we do not enter an integer value in the input() statement.



Repeat the previous exercise, but with the function x=float(input('x=')). What happens if we now enter the value 3.8?, and 3,789?.



Include this part in the see() function and define the variable x to present its value if requested in the input() statement.

⊝⊝⊝

56

Electronics & MicroPython© with ESP32©: 80 complete projects

*Operators Finally something interesting is going to happen in our example p_exercises.py, why?..., well now we are going to use operators that make controlled changes in all types of variables and therefore we are going to be able to create algorithms, that is, codes that use inputs and these operators or operations to create new outputs that could again be inputs for other algorithms, etc. Let's look at some operators. 1.-MATHEMATICAL OPERATORS They are the best known operators, for example: Operator

Description

Examples

a+b

Add the variables a and b

1+2=3

a-b

Subtract a and b

1-2=-1

a/b

Divides a by b

a%b

Calculate remainder a by b

5%2=1

a//b

Gets the integer a by b

5//2=2

a**b

Raise a to b

3**2=9

4/2=2.0 4/3=1.33333 4./3=1.3333

These are the basic mathematical operators commonly used in all areas but, if we want to use more advanced ones, we will have to use predefined functions in MicroPython© or invoke additional libraries, for example, with the following library: import math. With these libraries we can calculate the square root, the factorial, trigonometric functions, random numbers, exponentials, logarithms, etc. 57

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Add the following example to our p_exercises.py program: import math print(math.cos(90)) print(math.sqrt(2))

# Import library # Display the cosine of 90 # Display square root of 2

Important: l e t ' s n o t e t h a t m a t h e m a t i c a l operations between integers always obtain a real decimal number, which is why the result of 2/2=1.0. Let us be very attentive to these types of issues because unexpected results often occur, if we are used to other versions of Python©, in our mathematical calculations that are integrated into the MicroPython© code. If we want to get the exact result as a real number or floating point number, it is not necessary for any of them to be real or floating, for example: 4/3 = 4.0/3 = 4/3. = 4.0/3.0 = 1.333333. EXERCISES: •

• •



58

D e f i n e t h e v a r i a b l e s : Divisor, dividend, quotient, remainder and verify, with an example and using the operators // and %, that it is true that: Divisor = dividend * quotient + remainder. Try integers and real numbers, what happens?. Use the trigonometric mathematical functions included in the math library: sin(x) and cos(x) and check that cos 2 (x )+sin2 (x )=1. Apply the Pythagorean Theorem and calculate the hypotenuse, H of an equilateral triangle knowing that C_1=3, C_2=4 and that the formula of such H =√ C_1 2+C_22 . theorem is the famous: Defines the function hypotenuse(x,y) t h a t calculates the hypotenuse of a right triangle with sides the variables x and y and that have been previously entered by keyboard. Present the result and the sides. Why is the hypotenuse always a floating point number?.

Electronics & MicroPython© with ESP32©: 80 complete projects

2.-LOGICAL OPERATORS Logical operators are used with the True and False variables that we have seen and are basically used to make quick decisions based on previous results of conditions, functions, variable states, etc. It is important to know how they work as they affect the flow of the program, etc. Operator

Description and

Examples

a and b

Returns True both True

if a

are

True and False=False

a or b

Returns True b is True

when either a or

True or False=True

not a

Returns the opposite of a

b

not True=False

EXAMPLES: a,b = True,False c = not a d = not b print(a and b and c) False print(a or b and c) True print(a or b or d) True We can use & instead of

# Assign variables # Deny variables # Display operations # Display others # Display others and, & | instead of or.

The previous result may have surprised us because in the second case we would expect False and the program returns True. This is because the operators not, and, or have that priority in that order and therefore in a or b and c, b and c is executed first as if we had typed or (b and c). Try (a or b) and c and we will see that instead of True coming out the initially expected False comes out. This same priority happens with *, /, +, -, etc. Therefore, on this occasion and in the rest of the operators and functions, if we have doubts about the priorities, we use parentheses (...) in the operations that we need to be executed first. 59

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

EXERCISES: •

• •

With the previous data calculate: a or not b and d not (a or d) and b not a & not d | c&d Display all the possible options with a and b and a or b. Use the not operator if necessary. Check with an example if the famous Morgan's Laws are fulfilled, that is: not(a & b) = not a or not b not(a | b) = not a and not b 3.-COMPARATOR OPERATORS

These operators are very well known, they are used in many areas of programming and everyday life. They are simple symbols that compare two arguments, one to the left and other to the right, and return a True or False value after the comparison. These operators are usually used to control the flow of a program depending on whether or not a condition is met, so that certain instructions, functions, etc. are executed. Let's look at several examples: Operator

Description

Examples

a > b

True if a is greater than b

2>1 is True

a < b

True if a is less than b

3 and < operators can be combined with = like >= , = 'France' # Greater than Could the comparison operator > be used to establish an alphabetical order with character strings?. Try comparisons between lists, for example: [1,3] > [1,2] and dictionaries, for example: {1:2} > {1:3}. MicroPython© does not support the direct comparison of dictionaries but it does support the comparison of lists. Use the time.localtime() function and also the time.time() function and check with a comparator if the time increases or decreases between instructions of our program. Try it on console and see how time evolves. 4.-BIT OPERATORS

On some occasions, especially if we want to manage electronic hardware from MicroPython© (for example using the GPIO port of our ESP32©), or we want to filter some type of information encoded in a bit of a variable or perform binary calculations, we will need operate in binary and manage bits directly. We are not going to explain binary notation or translations from binary to decimal or hexadecimal and vice versa in this book (see it on the Internet, there's a lot of information), but we are going to summarize some operations of this type. In the following examples we consider the following binary numbers: a=100 (4 in decimal) and b=111 (7 in decimal). We can assign binary numbers in MicroPython© in the following ways: a=int('100',2) a=0b100

# a is the binary 100 in base 2 or # a is the binary 100 61

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Operator

Description (bit per bit)

Examples

a & b

a and b operation

a&b=0b100

a | b

a or b operation

a|b=0b111

a>>n

Shift n bits from a to right

a>>2=0b1

aTimer activated...') # Configure hardware timer (Timer(0) here) timer = Timer(0) # Number (#) can't be negative # Timer 0 calls function() every T_IRQ useconds timer.init(period=T_IRQ, mode=Timer.PERIODIC, callback=function) # Main program try: # Errors control while True: print('Green-', end='') # Without line break led1.on() # Green on time.sleep(T_ACT) led1.off() # Green off print('Red-', end='') # Without line break led2.on() # Red on 278

Electronics & MicroPython© with ESP32©: 80 complete projects

time.sleep(T_ACT) led2.off()

# Red off except: print('\nProgram completed') # Line break led1.off() # Both LED off led2.off() timer.deinit() # Stops timer 2. TIMER SOFTWARE

On this occasion we will implement two software timers similar to the exercise proposed above and that will perform similar tasks. Note the difference in the construction of the timer made with negative values. The number of timers created is not specifically limited and will depend on the amount of ESP32© memory available, etc. The script is similar to the previous one but we define two timers: timer_0, which calls funcion_0() that presents a counter and timer_1, which calls funcion_1() that presents the RTC time of the ESP32© adjusted to the local time and formatted appropriately. ############################ # E028_TIMER2_SW.PY: Two software timers manager # INPUTS: IRQ timer time and LED activation time # OUTPUTS: Timer1, timer2, LED polling message ############################ import time # Timing manager # Timer, GPIO, RTC management from machine import Timer, Pin, RTC import ntptime # RTC update led1 = Pin(26, Pin.OUT) # Green LED led2 = Pin(27, Pin.OUT) # Red LED led1.off() # Green off led2.off() # Red off T_ACTI = 1 # Activation LED time in seconds T_IRQ0 = 4000 # Tiempo IRQ timer_0 en m seconds T_IRQ1 = 10000 # Tiempo IRQ timer_1 en m seconds local = 2 # Local hour counter = 1 # Timer_0 counter # I update the RTC of the ESP32© from the Internet ntptime.settime() # Function to be executed when timer_0 is triggered 279

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

def function_0(_): # Must have an argument global counter print(f'-->[{counter}] Timer_0 activated...') counter+=1 # Function to execute when timer_1 is triggered def function_1(_): rtc = RTC() # Get RTC data year, month, day, weekday, hour, minute, second, subsecond = rtc.datetime() hour = hour + local # Adjusts local hour # Display hour, minutes and seconds print("Hour: {:02}:{:02}:{:02}".format(hour, minute, second)) # Configure two software timers (negative values) timer_0 = Timer(-1) # Display Timer_0 activated timer_1 = Timer(-2) # Display RTC data # Timer 0 calls function_0() every T_IRQ0 m seconds timer_0.init(period=T_IRQ0, mode=Timer.PERIODIC, callback=function_0) # Timer 1 calls function_1() every T_IRQ1 m seconds timer_1.init(period=T_IRQ1, mode=Timer.PERIODIC, callback=function_1) # Main program print('2 TIMER MANAGER') try: # Errors control while True: print('Green-', end='') # Without line break led1.on() # Green on time.sleep(T_ACTI) led1.off() # Green off print('Red-', end='') # Without line break led2.on() # Red on time.sleep(T_ACTI) led2.off() # Red off except KeyboardInterrupt: print('\nProgram completed') # Line break led1.off() # Both LED off led2.off() timer_0.deinit() # Stops both timer timer_1.deinit() 3. HARDWARE TIMER WITH LA1010©

To consolidate the timer exercises with ESP32© and see that we can generate pulses of any type (within the limitations of the ESP32©) and see them in the LA1010© analyzer, or another, we created the following script that includes the management of 3 hardware timer. 280

Electronics & MicroPython© with ESP32©: 80 complete projects

We import the machine libraries to control the GPIO and the timer (0, 1 and 2), we assign the 3 GPIO (25, 26 and 27) as output and specify the pulse times in milli seconds (adjust consistently with the LA1010© sampling). We define the function pulse_x() where the pulse is generated for each GPIO, we configure the 3 timers with the activation period, the operating mode and the function that each one calls and finally, in the main loop, if there is an error we present it, being able to finish the script and stop the 3 timers. In the analyzer we observe the 3 pulses generated in the probes that we have called Timer_0, Timer_1 and Timer_2 and we compare them with a reference 20Hz PWM signal.

281

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

We can adjust various pulse timings in the script, both the total time, the HIGH time and the LOW time and observe with the LA1010© how they behave. With this system we can generate some types of pulses but they do not have the precision of a PWM signal nor the waveform that can be created with a digital to analog converter. Keep in mind that times created with time or utime libraries can interfere with timers, especially if the timers are software type. Practice with the LA1010© the trigger option with rising edge, HIGH, falling edge and LOW. Likewise, test how defining a sample volume and sampling frequency in the LA1010© affects the exercise. ############################ # E028_TIMER3_HW_LA1010.PY: Three hardware timers # INPUTS: Interruption timing # OUTPUTS: 3 pulses to display on LA1010© ############################ from machine import Pin, Timer import time

# GPIO and Timer

sig0 = Pin(25, Pin.OUT) sig1 = Pin(26, Pin.OUT) sig2 = Pin(27, Pin.OUT)

# Signal 0 # Signal 1 # Signal 2

T_I0 = 1 T_I1 = 2 T_I2 = 3

# Timer_0 interruption in ms # Timer_1 interruption in ms # Timer_2 interruption in ms

# Function to be executed when timer_0 is triggered def pulse_0(_): # Must take 1 argument sig0.on() # Generate pulse in GPIO25 sig0.off() # Function to be executed when timer_1 is triggered def pulse_1(_): sig1.on() # Generate pulse in GPIO26 sig1.off() # Function to be executed when timer_2 is triggered def pulse_2(_): sig2.on() # Generate pulse in GPIO27 sig2.off() 282

Electronics & MicroPython© with ESP32©: 80 complete projects

# Timer 0 calls pulse_0() every T_I0 ms # Hardware timer: positive numbers or 0 Timer(0).init(period=T_I0, mode=Timer.PERIODIC, callback=pulse_0) # Timer 1 calls pulse_1() every T_I1 ms Timer(1).init(period=T_I1, mode=Timer.PERIODIC, callback=pulse_1) # Timer 2 calls pulse_2() every T_I2 ms Timer(2).init(period=T_I2, mode=Timer.PERIODIC, callback=pulse_2) # Main program starts here print(f'Timer initiated in: try: print('INITS 3 TIMER IN while True: time.sleep(.1)

{sig0}-{sig1}-{sig2}') # Error control 3 GPIO OF ESP32...') # Main loop simulation

except Exception as e: print(f'Error: {e}')

# If there's an error # Display it

except KeyboardInterrupt: # If + is pressed print('Timers stopped...') Timer(0).deinit() # Stop 3 timers Timer(1).deinit() Timer(2).deinit()

⊝⊝⊝

283

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E141: Two timers. Add to the first script with a timer, a second timer, called timer_1, which is activated every 10 seconds, which displays the internal temperature and time of the ESP32©, which must be previously updated from the Internet. •E142: Timer and LED. Create a script that flashes a couple of LED at every hour on the hour. Keep in mind that the hardware or software timers of the ESP32© do not have this option directly, therefore we will have to create a timer that checks the RTC of the ESP32© for polling and acts accordingly. •E143: Timer with ONE_SHOT. Design a MicroPython© script that uses a timer with the ONE_SHOT option and that is activated when there is an alarm, for example, the internal temperature of the ESP32© rises above a preestablished limit. When the alarm goes on, 2 options will be presented: ignore the alarm, which will stop the script, or activate the alarm again, which will request a new reference level and activate the timer's ONE_SHOT option again. •E144: 4 timers, 2 hardware and 2 software. Create a program in MicroPython© for ESP32© that uses 4 timers (2 hardware and 2 software), with four different functions: on/off an LED, read the state of a button as if it were by IRQ and present its state, send a email with the temperature of the ESP32© and send an SMS indicating that there is an alarm (see subsequent exercises if necessary). Decide why and what type of timer (hardware or software) is best for each function. 284

Electronics & MicroPython© with ESP32©: 80 complete projects

•E145: Timer vs IRQ. Use a periodic timer to read the state of a button and use an IRQ to read the state of another button, see how both situations work and determine which is the most convenient (response, consumption, CPU usage, simplicity, bounces, etc.) to manage keystrokes and why. •E146: Timer and DHT11© double sensor. Implement a MicroPython© script that uses a hardware timer on the ESP32© to read data from a DHT11© double sensor every 10 seconds and display it on the console while the main loop changes colors on an RGB LED. •E147: Timer and ADC. Create a script that uses a software timer to perform analog readings with an Analog-to-Digital Converter (ADC) every 5 seconds. Display the results in the console and make them accessible via the Web. Simulates analog data with an ESP32© GPIO touch sensor or a traditional button. •E148: NO-IP© and remote sensor. Design a system that uses a hardware timer to collect data from a remote sensor (for example, a potentiometer) and send this data to a IP using the NO-IP© dynamic DNS service, (see later exercises) or via from the local network, without using NO-IP©. •E149: Timer and remote display. Develop a program that uses a hardware timer to take readings from a specific sensor. These readings and the time at which they are taken must be visible remotely on a Web with local or global access. The script will be started or stopped by voice commands on a Google Home© assistant (see later exercises). •E150: Hardware vs software timer. Create a script where a hardware and timers are used to blink an LED using Analyze the advantages and disadvantages of and propose specific practical cases where convenient to use each timer mode.

a software a button. both cases it is more

285

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

•E151: Timer with RGB LED. Create timers that manage basic colors of an RGB LED, visualize with the LA1010© the pulses that reach the LED, practice modifying the parameters of the timers and those of the LA1010©. •E152: RGB LED with push button and IRQ. Connect a push button to the ESP32© and configure an interrupt (IRQ) to detect its pushes. Each time the button is pressed, a timer is activated that generates flashes on a certain LED. Visualize the blinks with the LA1010©. •E153: Timer and scanning of WiFi networks. Use a timer to scan the available WiFi networks periodically. When detecting a network, it will activate an LED whose GPIO will be displayed with the LA1010©. •E154: WiFi scanning and Web server. Add to the previous exercise that the ESP32© is activated as a Web server so that when we access it we can view the list of detected WiFi networks. •E155: Timer and passive buzz. Connect the passive buzz to a GPIO of the ESP32© and generate an audible signal using a hardware timer that varies the tone of the signal when using a button. Use the LA1010© to view the generated pulses, change the trigger if necessary. •E156: LED control with DAC. Use the ESP32©'s Digital-Analog Converter (DAC) to generate a signal that changes the brightness of an LED. Connect the GPIO to the LA1010© and see how an analog signal affects a digital analyzer, modifying the time base. Try a timer to create the LED brightness pulse and also change the trigger value on the LA1010©. Explain what happens when we visualize these pulses.

⊝⊝⊝ 286

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 29: KY-040© Rotary Encoder In this exercise we will see what a rotary encoder is, such as the KY-040© or similar, how to program it and how to integrate it, in a simple way, into any of the previous exercises. A rotary encoder is nothing more than a sensor that encodes the angular position of a rotary knob on a device, for example: the volume control or station search of a car radio, the air conditioning control, the microwave selector or a modern washing machine, the Thermomix© control, the mouse scroll, etc. In this way, these sensors measure angle, angular velocity, direction of rotation, length, position, acceleration, etc. When used, an integrated circuit inside sends a series of electronic pulses, which allows a script to increase or decrease a variable, change pages, raise/lower a window with the computer mouse, regulate sounds, change temperatures, change parameters, etc. 287

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

The KY-040© rotary encoder also incorporates a push button, so that we will have a compact device with multiple functions. Therefore, a rotary encoder, or signal decoder is a very useful and very interesting sensor device to integrate into one of our exercises or our projects. There encoders:

are

basically

two

types

of

rotary



Absolute: In them the encoder indicates the current position of the selector, therefore they behave like angle transducers.



Relative or incremental: In them the indicates the movement of the selector.

encoder

Most rotary encoders have 5 pins and physically perform 3 basic functions: left turn, right turn, and on/off by pressing the push button. There are many models on the market, here we have used the Keyes© KY-040© model or similar, with the following pins: Pin Signal 1 2

GND

Function Ground

+3.3V Power supply

3

SW

Normally open (NO) terminal of push button switch, connect to GND

4

DT

0 (LOW) means that the knob turns

5

CLK

0 clockwise, 1 counterclockwise

Here we will test both the switch function, SW pin connected to GPIO25 of the ESP32©, and the “right, left” function, DT and CLK pins connected to GPIO32 and GPIO35 respectively. We will also connect 2 LED to display direction of rotation of the rotary encoder.

288

the

Electronics & MicroPython© with ESP32©: 80 complete projects

In idle state the decoder is with DT=H. If any rotation occurs, DT goes to state L and if CLK=L the rotation is cl o ck w is e an d if CLK=H, the rotation is counterclockwise.

On the other hand, if SW=L indicates that the button has been pressed and if SW=H, the button is at rest.

289

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

If at any time the rotary encoder button is pressed again, both LED turn off, the counter is reset and the system is positioned in its initial state. Both the button pin (pin_SW) and the data pin (pin_DT) are controlled by IRQ, in this way the response of the script is immediate and “bouncing” of the buttons is avoided. In the script we import the machine libraries to control the decoder logic and time to control the operation times and we define the pins to use with the following diagram: ROTARY DECODER CONNECTIONS KY04©

ESP32©

Observations

1

GND

GND

Ground

2

+3.3V

+3.3V

Power supply

3

SW

GPIO25

Pushbutton

4

DT

GPIO32

Spin detection

5

CLK

GPIO35

Direction of rotation

In rest state pin_DT is in HIGH state and when going down to LOW state, if pin_CLK is in LOW, the rotation is to the right (clockwise direction) and if it is in HIGH state, the rotation is to the left (counterclockwise direction). When the SW_pin, connected to GPIO25, goes from HIGH to LOW, it indicates to the ESP32© that the button has been pressed. A red LED is also added to GIPO27 and a green LED to GPIO26. Global variables are defined to control the counter, decoder states, increment/decrement step. Th e setup() function is defined where the pins for the LED are initialized as output and the decoder pins as input for the ESP32©. 290

Electronics & MicroPython© with ESP32©: 80 complete projects

The managements for the button and data are created as inputs treated by interruption when going from HIGH to LOW level and that point to the clear() and spinning() functions respectively. T h e spinning() function that controls the decoder logic, the direction of rotation, the counter and the activation of the LED is detailed with the algorithm described above. The clear() function is defined that turns off the LED and indicates the use of the decoder, the loop() function that represents a main loop of the script and in which any other function could be integrated. Finally we have the stop() function that stops the keyboard program and turns off the LED. In the LA1010© analyzer, the DAT (pin_DT) and CK (pin_CLK) signals are defined in addition to a PWM signal that, as always, serves as a reference. In this case, the vertical marks A1-A2 and also B1-B2 have been added to more easily compare the states between DAT and CK. •Right turn: In this case, when the DT_pin goes LOW it indicates that a turn has been initiated and since the CLK pin is at LOW, the turn has been made to the right. When the turn is made to the right, the script increments the counter by the previously defined step, turns on the green LED and turns off the red LED and displays it on the console. •Left turn: Now, when the DT_pin goes from HIGH (rest) to LOW it indicates that a turn has been initiated and since the CLK_pin is at HIGH, the turn has been made to the left. When the turn is made to the left, the script decrements the counter by the previously defined step, turns off the red LED and turns on the green LED and displays it on the console. We can see the logical levels discussed in both cases in the LA1010© analyzer. 291

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Right turn (CLOCKWISE) When DAT=LOW CK goes from HIGH to LOW

Left turn (COUNTERCLOCKWISE) When DAT=LOW CK goes from LOW to HIGH

292

Electronics & MicroPython© with ESP32©: 80 complete projects

############################ # E029_ROTARY_DECODER.PY: Rotary decoder # INPUTS: Decoder rotation and push button status # OUTPUTS: Turn counter and LED ############################ '''KY-040© ESP32© Observations ----------------------------------------1 GND GND Ground 2 +3.3V +3.3V Power supply 3 SW GPIO25 Pushbutton 4 DT GPIO32 Spin detection 5 CLK GPIO35 Spin direction''' from machine import Pin # GPIO management import time # Timing control # Definition of GPIO in the ESP32© pin_DT = 32 # GPIO32 DT o data pin_CLK = 35 # GPIO35 CLK o clock pin_SW = 25 # GPIO25 SW o pushbutton led_r = 27 # GPIO27 Red LED led_v = 26 # GPIO26 Green LED # Global Variables counter = 0 # Spin counter last_state_CLK = 0 # Las state of CLK step = 1 # +/- counter change = False # Change spin direction # Initial configuration function def setup(): # LED out and off for pin in [led_r, led_v]: Pin(pin, Pin.OUT).value(0) # Input pins configuration Pin(pin_DT, Pin.IN) Pin(pin_CLK, Pin.IN) # Pin_SW/DT inputs, pull-up and IRQ falling edge Pin(pin_SW, Pin.IN, Pin.PULL_UP).irq(trigger=Pin. IRQ_FALLING, handler=clear) Pin(pin_DT, Pin.IN, Pin.PULL_UP).irq(trigger=Pin. IRQ_FALLING, handler=spinning) # Function handles the rotation of the rotary encoder def spinning(_): # An argument must be added global counter, last_state_CLK, change # Read the current status of CLK current_state_CLK = Pin(pin_CLK).value() # CLK if last_state_CLK==0 and current_state_CLK==1: counter=counter-step # Decrement print('COUNTERCLOCKWISE spin') Pin(led_r).value(1) # Red LED on Pin(led_v).value(0) # Green LED off 293

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

if last_state_CLK==1 and current_state_CLK==1: Pin(led_r).value(1) if change: # Change spin print('COUNTERCLOCKWISE spin') change = not change # Avoid repeat text counter=counter-step if last_state_CLK==1 and current_state_CLK==0: counter=counter+step # Increment print('CLOCKWISE spin') Pin(led_r).value(0) # Red LED off Pin(led_v).value(1) # Green LED on if last_state_CLK==0 and current_state_CLK==0: Pin(led_v).value(1) if not change: # Change spin print('CLOKWISE spin') change = not change # Avoid repeat text counter=counter+step print('counter = %d' % counter) last_state_CLK=current_state_CLK # Update #Function handles reset push button interrupt def clear(_): # An argument must be added global counter, change change = not change # Reset flag print('\n' * 20) # Blank lines for cleaning Pin(led_r).value(0) # Red LED off Pin(led_v).value(0) # Green LED off print('ROTARY DECO CONTROL WITH PUSH BUTTON') print('Turn knob or press button...') counter = 0 # Reset counter print('Counter = %d' % counter) # Main loop def loop(): #print('\n' * 20) # Blank lines for cleaning print('Turn knob or press button...') while True: time.sleep(0.01) # Main loop simulation # For stop the program def stop(): Pin(led_r).value(0) # Red LED off Pin(led_v).value(0) # Green LED off # Main input point to the program if __name__ == '__main__': print('\n' * 20) # Blank lines for cleaning print('ROTARY DECO CONTROL WITH PUSH BUTTON') setup() # Initial configuration try: loop() # Call to main loop except KeyboardInterrupt: stop() # Stop the program

⊝⊝⊝ 294

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E157: RGB LED control with rotating deco. Develop a script that uses a rotary decoder to control an RGB. Turning the decoder clockwise increases the value of a color, and counterclockwise decreases the value. The push button will turn the LED on/off. Try an RGB dictionary that scrolls, in both directions, when we turn the rotary decoder. •E158: Temperature with ADC and rotating deco. Write a script for ESP32© that uses the rotary decoder to adjust the settings (measurement scale) of a temperature sensor connected to the ESP32© ADC converter. •E159: Timer, PWM and rotary decoder. Develop an adjustable timer using the decoder. Use PWM to control an LED, and turning the decoder sets the timer time that should be displayed on the console. Pressing the button starts the timer. •E160: Analog signal with DAC and decoder. Create a script that uses the rotary decoder to adjust the frequency of an analog signal generated by the ESP32© Digital-Analog Converter (DAC) and make it audible on a passive buzz. Pressing the button switches between different waveforms: square, sine and triangular. •E161: RTC control with rotary decoder. Develop an adjustable clock using a decoder. Turns and presses will set the RTC time and date. There will also be a hardware timer that will flash a red LED every 5 seconds.

⊝⊝⊝

295

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 30: Frequency meter with 7555© In this exercise we are going to build a frequency meter with a 7555© circuit, which is a timer with the same functionalities as the famous NE555©, but since it uses CMOS technology, it can be powered at +3.3V and therefore we can connect it directly to our ESP32© without any problem. It will be a test frequency meter and not very precise (it measures frequencies between 30Hz and 20kHz), since to improve it would be necessary to have very well calibrated components, with very little tolerance and temperature compensation, connected to a precision power source, etc. but in any case the exercise is valid to practice with these elements. We are going to use the 7555© integrated circuit, which is a timer or pulse generator (from 0 to +3.3V), very low cost, easy to obtain, which can be used in multiple exercises and which can basically be configured in three very interesting modes: Monostable: if the input of the circuit is activated, its output changes for a while and returns to the initial state, that is, the system has 1 state. Bistable: when the input of the circuit is activated, its output changes its state and does not return to the initial state until the input is activated again, therefore the circuit has 2 states. 296

Electronics & MicroPython© with ESP32©: 80 complete projects

Astable: When the input of the circuit is activated, its output periodically changes between the initial and final state, therefore generating a square wave that varies between the 2 states. This last configuration is the option that we are going to use in this exercise to generate a square wave, of a certain frequency and that we will later measure with the ESP32© using a GPIO controlled by IRQ and a simple script. We need the following components (others with other values can be used to obtain another output frequency): 1 2 2 1

7555 © 100nF 10k Ω 1k Ω

timer capacitors resistors resistor

The pins of the 7555©, totally equivalent to the NE555© (+5V), are as follows: [1] [2] [3] [4] [5]

[6] [7] [8] • • • •

GND or 0V. trigger or lower comparator. output: 0 or +3.3V. reset: active at +3.3V. control: change the trigger levels or also comparison levels.

threshold: upper comparator. discharge: capacitor discharge. power: between +2V and +18V. Other interesting features of the 7555©: Very low consumption of 80 μ A. High frequency, up to 1MHz. Timing range from seconds to hours. Wide temperature range from -25ºC to 85ºC.

And the circuit diagram in astable mode that we will use is the following: 297

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

If we test it with the iCircuit© application, we observe how a wave similar to a “square” wave of the frequency calculated with: f=

1 ln(2)∗C2∗( R1+2∗R2)

where:

ln(2)=0.69315 (Neperian Logarithm) −7 C2=100nF= 10 F. R1=R2= 10K Ω, therefore: f=

1 ≡481Hz 0,693∗10 ∗(104 +2∗104 ) −7

The frequency measured with the script is 488Hz and we can observe it on an oscilloscope.

298

Electronics & MicroPython© with ESP32©: 80 complete projects

To carry out the measurement with the ESP32© we count, through the GPIO12, the pulses generated by the 7555© for a certain time, for example 1 second, and using the IRQ method. The frequency f will be the result of dividing the number of pulses by the specific time selected. We can try with various values of R1, R2 and C2, see the generated frequencies and the measurement provided by our frequency meter. In t h e MicroPython© script we i m p o r t t h e machine and time libraries to control the GPIO and the times respectively. We configure the GPIO12 as input and define global variables that we are going to use for the pulse counter, counting time, separation between readings and previous frequency. We define the function pulse_counter() which is called by the IRQ on the rising edge generated by the square wave of the 7555© when entering through the GPIO12. We define the function frequency_meter(), which calculates the frequency f by dividing the number of pulses counted by IRQ by the time [wait]. Finally we write the main loop of the script that presents the frequency generated by the 7555© whenever there is a value change. It also incorporates stopping the script when pressing + from the console. 299

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

############################ # E030_FRECU_7555.PY: Frequency meter with 7555 timer # INPUTS: GPIO12 and wait times # OUTPUTS: Measured frequency ############################ from machine import Pin # GPIO manager import time # Timing management # Pins configuration pin_input = 12 # GPIO frequency meter input pin = Pin(pin_input, Pin.IN) # Global variables pulses = 0 wait = 1 reading = 2 frec_ant = 0

# # # #

Pulses counter Calculus time Time between readings Previous frequency

# Pulses counter function def pulse_counter(_): # Must have an argument global pulses pulses += 1 # Increments counter # Configure pulse counter by IRQ pin.irq(trigger=Pin.IRQ_RISING, handler=pulse_counter) # Function to measure frequency def frequency_meter(wait): global pulses, frequency pulses = 0 # Reset counter time.sleep(wait) # Wait for a while num_pulses = pulses # Counted pulses frequency = num_pulses / wait # Frequency f print(f'Calculate frequency in GPIO {pin_input}') try: while True: frequency_meter(wait) if frequency != frec_ant: print(f'Measured frequency: {frequency}Hz') frec_ant = frequency time.sleep(reading) except KeyboardInterrupt: print('Frequency meter stopped...')

⊝⊝⊝

300

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E162: Variable frequency. Add to the previous circuit, in series with resistor R1, a 50k Ω potentiometer P (variable resistance) and measure the frequency generated with various positions of P. See that we could vary it between 180Hz and 480Hz, perform the corresponding calculations with the previous formula. •E163: Control start/stop. Perform a start and stop control of the pulse ̄ R , setting it generation of the 7555© using its pin to LOW with a GPIO of the ESP32©, protecting this GPIO with a resistor if necessary. •E164: Monostable mode. Search the web how to configure the 7555© in monostable mode and initiate a pulse from an ESP32© GPIO. Add an LED to the output and observe how its state changes. Calculate the pulse time with the components, resistors and capacitors already seen. •E165: Bistable mode. Use the same circuit but configuring the 7555© as bistable mode. It also calculates theoretically and with the frequency meter created with the ESP32© all the timings generated. •E166: Generate PWM with 7555© and with ESP32©. Using only the previous circuit and without using the ESP32©, manage the brightness of an LED by modifying the Duty Cycle of the 7555© between predefined margins. Check if the PWM logic is positive or negative. Generate a PWM wave in a GPIO of the ESP32© and compare both, for example, with the oscilloscope.

⊝⊝⊝ 301

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 31: HC-SR501© Motion Sensor In this exercise we will see how to use a simple but very powerful motion sensor such as the well-known HC-SR501© or equivalent. A motion sensor is a passive infrared radiation (PIR) sensor that detects the movement of objects that emit heat and is used in Home Automation projects and electronic devices that detect motion.

• • • •

• • • • • •

The basic features of the HCSR501© or equivalent are: Power supply at +5V. +3.3V output compatible with the ESP32©. It has two potentiometers to configure the sensitivity adjustment (from 3 to 7 meters) and the switching time (0.5-200s). Trigger adjustment bridge: single or retriggerable. The sensor connections are very simple: GND GND of the ESP32©. OUT Digital output 0 to +3.3V. VDC +5V. Switching time setting. Sensitivity adjustment. Jumper L (single trigger), H (retriggerable).

The switching time indicates how long the OUT output is at H after motion is detected, the sensitivity setting allows us to indicate the minimum distance at which motion is detected, and the jumper 302

Electronics & MicroPython© with ESP32©: 80 complete projects

can be used so that the OUT output is at H for a period of time. Single switching time or retrigger every time motion is detected.

In this exercise we have connected the sensor to GPIO14 and an LED connected to GPIO25 to indicate when motion is detected. In the script we import the machine and time l i b r a r i e s t o control the GPIO and control times. The OUT pin of the PIR is configured as an input for the ESP32© and the LE D a s a n o ut p u t, i n it i a l ly t u rn i n g i t o f f. Additionally, the management variables are defined. The functions turn led_off() are added, which turns off the LED after a certain time has elapsed, c o n t r o l l e d b y t h e Timer(0), a n d t h e f u n c t i o n detect_motion(), which when detecting movement, checking the status of OUT, increases a counter, presents the message detection, turns on the LED and starts a one-shot timer that invokes the led_off(). 303

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Finally, in the main body of the script, the d e t e c t i o n f u n c t i o n detect_motion() is called periodically. If we press + the program stops, turning off the LED and stopping the Timer(0). ############################ # E031_MOTION_SENSOR.PY: HC-SR501© motion sensor # INPUTS: Motion detected by sensor # OUTPUTS: LED and messages on screen ############################ from machine import Pin, Timer import time # Pines configuration pin_sensor = 14 # Motion sensor pin pin_led = 25 # Red LED t_time = 2000 # Timer time in m seconds counter = 0 # Activation counter # Configure sensor in input and output LED motion_sensor = Pin(pin_sensor, Pin.IN) red_led = Pin(pin_led, Pin.OUT) red_led.off() # LED off # LED off function def led_off(_): # Must include an argument global counter red_led.off() # Red LED off print('LED off...') counter = 0 # Start activation counter # Motion detection function def detect_motion(): global counter if motion_sensor.value() == 1: # Detected counter+=1 # Activation counter goes up print(f'[{counter}], Motion detected!') red_led.on() # LED on # Timer turns off LED [t_time] m seconds Timer(0).init(period=t_time, mode= Timer.ONE_SHOT, callback=led_off) print('HC-SR501© MOTION SENSOR') print('Approach the sensor...') # Main loop to scan sensor status try: while True: detect_motion() time.sleep(.5) # Wait .5s between scans except KeyboardInterrupt: print('Program completed...') red_led.off() # LED off Timer(0).deinit() # Timer stop

⊝⊝⊝ 304

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E167: Sensor controlled by IRQ. Use the previous script but modify what is necessary so that the motion detection is controlled by IRQ instead of by polling with the detect_motion() function. •E168: Motion detection and relay. Create a script that controls a motion sensor by IRQ and two control LED. If motion is detected, activate a relay to turn on an electrical load, such as a lamp simulated by another LED. •E169: Servo, push button and motion sensor. Configure a servo motor connected to the ESP32© and monitor, by IRQ, the state of a button to control the movement of the servo manually. If movement is detected with the HC-SR501 sensor, move the servo to a predetermined position that will be reset with the push button. •E170: DS18B20© sensor, detector and relay. Use a motion detector so that when activated, the room temperature is read using the DS18B20© sensor. If the temperature exceeds a predefined threshold, activate a relay simulating being connected to a fan. •E171: RGB LED, ADC and motion sensor. Read the value of a potentiometer with ADC and change the color of an RGB LED by PWM when necessary. If motion is detected with the sensor, the color of the RGB LED changes automatically depending on the time the sensor is triggered, for example in traffic light mode: green, yellow and red.

⊝⊝⊝ 305

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 32: HLK-LD2410C© Human Presence Sensor In this exercise we will see a much improved option for a motion sensor, it is a human presence sensor, that is, a sensor that detects movement but also detects presence and therefore, although people who are within the area of the sensor are completely “still”, the sensor also detects them, making their use much more comfortable and reliable. We will use the HLKLD2410C© presence sensor, it is a simple and cheap human presence sensor that uses 24GHz microwave radar technology to detect the presence of people in a certain area. Presence sensors are capable of detecting subtle movements and can penetrate through materials such as plastic, wood, etc., making them suitable for home security and automation applications. These human presence sensors are widely used in automatic lighting systems, security systems, access control systems and multiple other devices that require precision and reliable motion and presence detection. 306

Electronics & MicroPython© with ESP32©: 80 complete projects

The HLK-LD2410C© allows multiple adjustments to be made to adapt to the needs of each project, highlighting the following fundamental characteristics: • • •





Plug and play, easy assembly, only needs power, very easy to set up. The detection distance between 0.75 and 6 meters configurable. Wide detection angle, coverage up to ±60 degrees. Accurate identification within its range, supporting detection range division, and eliminating out-of-range interference. It has an APP that allows Android©, with version LD2410C©, to connect via Bluetooth. There is also an application for Windows©. It has two TX and RX pins that allow connection, via UART, to the ESP32©. With these three options we can configure multiple operating parameters of this wonderful sensor. Its si ze is mi ni ma l, su pp or tin g v ar io us installation methods such as ceiling hanging or wall hanging. Avoid obstacles close to the sensor. Power supply: +5V and 200mA, therefore we should NOT connect it to the ESP32©. It has an OUT output that is activated at HIGH when detection occurs. This output is +3.3V and therefore we can connect it to a GPIO of the ESP32©. Remember that the GND of the sensor and the GND of the micro controller must be connected.

We can use the ESP32©, through the UART connection, to configure the parameters of this sensor but I recommend using the HLKRadarTool© APP available on Android©. Once installed, we activate Bluetooth on our mobile. We start the APP and the device HLKLD2410_C90B© or similar will appear. If we click on the name, we will have two screens where, in the first one we see a traffic light that tells us if there is movement, static presence (with an indication of the distance in cm) or neither of the two. 307

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

The default Bluetooth connection password is HiLink, which we can easy modify in the application. In the first window of the APP we can see if the detection is motion, static or without detection, as well as four graphs where we can view the evolution of the movement, the static detection, the detection range and the luminosity level. In the first two graphs we can see the target sensitivity levels that we can configure in the second window. In the second window we can see the firmware version and with the option to update it, the minimum shooting distance, the password change, the duration of the output pulse, the sensitivity of the light sensor, the detection level HIGH or LOW (e.g. interesting if we want to connect a relay to the OUT pin), the connection speed, the target sensitivity levels depending on the distance, etc.

308

Electronics & MicroPython© with ESP32©: 80 complete projects

If we wanted to configure the sensor from the ESP32©, we could connect the TX and RX pins to two GPIO of the micro controller and use the ld2410.py library. Remember to load it into the ESP32© memory and pass the UART parameters. In this exercise we are going to configure the sensor via Bluetooth and connect it to the ESP32© in on/off mode as the same as we did with the infrared motion sensor and using the same script, therefore we will connect the OUT pin of the sensor to GPIO14 and an LED to identify the detection on the GPIO26. When the sensor detects movement or presence, the OUT output goes to HIGH (also configurable to LOW in the APP) and with it the GPIO14 of the ESP32©, which will indicate the detected movement and turn on the LED in the GPIO26.

⊝⊝⊝ 309

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E172: Presence sensor and relay. Add to the previous circuit a relay connected to a GPIO of the ESP32© and change the script so that when movement is detected the relay is activated. Try doing the same by directly connecting the relay to the OUT pin of the sensor without using the ESP32©. Please note that the relay may have reverse logic. Take advantage of the +5V power supply to power the sensor and the +3.3V output to power the relay. Do not power the presence sensor from the ESP32©. •E173: Presence sensor and PWM. Design a system that uses the LD2410© presence sensor and an ambient light sensor or LDR connected to the ESP32© ADC or software simulation, to control the light intensity of a lamp. When motion is detected with the presence sensor and the ambient light is low, gradually increase the light intensity using the PWM signal. When no motion is detected for a set period of time, gradually reduce the light intensity until it turns off completely. •E174: Alarm with presence sensor and DAC. Create an alarm system using the presence sensor and a buzzer. When motion is detected with the LD2410© human sensor, activate an audible alarm on the buzzer using the analog signal generated by a DAC converter. The intensity of the alarm sound may vary depending on the distance detected by the presence sensor. •E175: Position control with Design an automatic door uses a servo motor to open and human presence sensor to approaches the door. 310

servo and RTC. opening mechanism that close the door. Use the detect when someone

Electronics & MicroPython© with ESP32©: 80 complete projects

Additionally, program the system to automatically close the door at certain times of the day using information from the external RTC, such as at dusk. •E176: Activity with presence sensor and RTC. Develop an activity recording system that uses the LD2410© human presence sensor to detect the presence of people in a room. Add a DS18B20© high precision temperature sensor and record the ambient temperature at the time of detection. Store all information in a circular data file on the ESP32© and use the external RTC to also record the date and time of each motion detection. Implement an algorithm to send, at a certain time or using a hardware time, a report for each day by email. Finally, create an acoustic alarm using PWM or DAC with a passive buzzer and sends a message via SMS when a certain presence and/or temperature control algorithm indicates it.

⊝⊝⊝

311

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 33: ESP32© and TTP223© Touch Sensors In this exercise we will see a very interesting sensor, easy to use, widely used in everyday life and which is a touch sensor that detects, without any mechanical part and using the conductivity of the human body, when we touch it with a finger. These sensors have multiple advantages traditional buttons that we could summarize as: • • • •



over

They are intuitive: They offer a very easy-touse user interface, as they allow completely direct interaction with your fingers. Greater precision: They allow precise, detailed and reliable entry. Adaptability: They adapt to various shapes and sizes, making them ideal for a variety of devices and applications. Durability: Touch sensors, since they do not have moving mechanical components susceptible to wear, are much more durable than traditional input devices. Ease of cleaning: In several clean environments, such as medical or industrial applications, touch sensors are easy to clean and disinfect, being airtight and with completely smooth surfaces.

For all these reasons and others, tactile sensors are widely used in human activities that require finger presses: elevator buttons, control panels, traffic lights, automotive, ATM, household appliances, etc. 312

Electronics & MicroPython© with ESP32©: 80 complete projects

Luckily, the ESP32© has special GPIO that can be configured as touch input pins, that is, pins that activate HIGH when touched with a finger. This allows the use of buttons to be implemented in a very simple way since hardly any additional hardware is needed. The ESP32© WROOM C3 has 10 GPIO with this function, therefore we can implement several buttons to perform multiple functions. In this exercise we will use an ESP32© touch sensor, this is a cable connected to GPIO32 and two LED, in GPIO26/27 that will alternate as the touch sensor is touched. It is important that we adjust the sensor threshold and for this it is convenient to read the values of GPIO32, which will be defined as touch with tactile_pin= TouchPad(Pin(32)) and will be read with tactile_pin.read(). In our case, the values exceed 670 when the pin is at rest, dropping to 80 when held with two fingers, having to experiment until finding the appropriate value, in this case 300.

313

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

If we do not have GPIO available with the touch function, we can use an external touch sensor such as the TTP223© or similar. This external touch sensor has an activation zone that attacks a special circuit necessary to amplify and stabilize the signal that the human body captures and that generates an on/off type digital signal. The amplifier circuit used, whi ch requir es high sensitivity and gain, is the TTP223-BA6© or equivalent. Basically it is a set of cascade transistors that amplify, stabilize and selfregulate the very low voltage provided by the human body by acting as an antenna. In the schematic of the amplifier circuit we can see how the TTP223© touch sensor attacks pin 1 of the TTP223BA6© amplifier circuit with the capacitor C1 acting as a high-pass filter and after amplifying the signal, the Q output is activated that attacks the GPIO32 of the ESP32© and that, in this example, we must configure it as an input instead of configuring it as a touch sensor. Resistor R0 powers the LED that indicates that there is current in the circuit, R1 does the same with D1, R2 acts as a pull-up of Q and C2 stabilizes the +3.3V line. By default, the TOG signal activates the “Toggle” function, that is, the Q states (HIGH and LOW) alternate with each press. 314

Electronics & MicroPython© with ESP32©: 80 complete projects

In the MicroPython© script to control the internal touch sensor of the ESP32©, the utime libraries are imported for the management of control times and machine for the control of the GPIO and touch sensor. The touch GPIO are started as touch input and the LED as output, turning on the green LED, turning off the red LED, deleting the console, presenting the script start message and defining the minimum sensitivity already mentioned for the sensor to trigger. The touch sensor is read with the call to tactile_pin.read() by polling and to avoid flashing of the LED, caused by multiple readings, it is checked that the pin value is within a range and at various times. Finally, a waiting time is used between readings that we must adjust, the corresponding exceptions that may occur are controlled, and the script can be stopped by pressing + in the console.

315

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

############################ # E033_TACTILE_SENSOR_POL.PY: Touch sensor management # Scanning touch sensor in GPIO32 by polling # INPUTS: Touch sensor status # OUTPUTS: GPIO26 green and GPIO27 red alternation ######################### import utime # Time management from machine import Pin, TouchPad # GPIO and touch # Pins configuration tactile_pin = TouchPad(Pin(32)) # Touch green_led = Pin(26, Pin.OUT) # Green LED red_led = Pin(27, Pin.OUT) # Red LED green_led_state = True # Green LED current status green_led.on() red_led.off() print('\n' * 50) # 50 lines to clean screen print('ESP32© INTERNAL TOUCH SENSOR CONTROL') print('Touch the sensor...') sen = 300 # Touch sensitivity, change if desired # Read sensor status and update LED def led_update(): global green_led_state # Used outside tactile_value = tactile_pin.read() # First reading utime.sleep_ms(100) # Wait to avoid errors new_tactile_value = tactile_pin.read() # Second # See if it is touched if tactile_value< sen and new_tactile_value< sen: print('\n' * 50) # Clean console if green_led_state: green_led.off() # Green LED of red_led.on() # Red LOD on print('Red') green_led_state = False else: green_led.on() # Green LED on red_led.off() # Red LED off print('Green') green_led_state = True print('Touch the sensor...') try: while True: # Stop with + led_update() utime.sleep_ms(200) # Time between reading except KeyboardInterrupt: print('\n' * 50) # Clean console print('Program completed.') finally: # Turns off both LED when exiting the loop green_led.off() red_led.off()

⊝⊝⊝ 316

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested Exercises: •E177: Touch interruption reading. The touch pins of the ESP32© do not support direct control by interruptions generally but we can simulate touch interruptions with normal interruptions generated periodically by a timer or by polling. Design a MicroPython© script similar to the previous one but that reads the GPIO configured as touch when a timer interrupt is generated. Use the following function: # Timer that calls function every second. timer = Timer(0) timer.init(period=1000, mode=Timer.PERIODIC, callback=upload_led) •E178: Reading DHT11© and touch pins. Develop a MicroPython© script that uses a DHT11© dual sensor to measure temperature and humidity, and also include tactile reading, using several pins to control the display of separate results and a third to convert the read temperature into various measurement scales. •E179: Brightness control with touch and PWM. Create a program that uses touch pins to adjust the brightness of an LED in increasing vs decreasing order, using PWM signals, by pressing touch pins. •E180: Signal generation with DAC and touch. Build a MicroPython© script for ESP32© that uses several special touch pins to control the generation of analog signals through a digital-to-analog converter (DAC). Use different frequencies and/or waveforms (square, sine, etc.) depending on the touch input. Also use a passive buzz to listen to the audible frequencies generated. 317

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

•E181: Monitoring inputs with touch pins. Develop a program that reads multiple analog inputs (use polling since internally we only have 1 ADC) using several inputs configured as ADC (potentiometer, push button, etc.). Use touch pins to select the corresponding analog input and an LED to indicate which of the ADC is active. Finally, we can see several types of Touch sensors that can be used with the ESP32©. Important: If we use the ESP32© with a battery, we must touch GND with another finger for the GPIO touch to work.

⊝⊝⊝ 318

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 34: 49E© Hall Sensor Continuing with the sensor exercises, in this case we will see a not very wellknown but quite interesting sensor. This is the sensor of magnetic materials based on the Hall Effect, that is, the generation of an electric current when charges are separated inside a conductor, through which a current circulates in the presence of a magnetic field, that is, a normal magnet. This sensor is widely used in electric current detectors, speed meters, proximity sensors, positioning, limit switches, etc. The sensor used in this exercise is similar to the 49E© (linear response) and we can use it within a module that incorporates the Hall sensor and also an additional circuit that allows two signals to be obtained: an analog signal AO (Analog Output) that proceeds directly from the 49E© sensor and a digital signal DO (Digital Output) of the on/off type that we can use, for example, as activation for an IRQ. 319

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

We will manage the analog output AO with an analog-digital converter (ADC) to know the value of the magnetic signal and the digital output DO of the Hall sensor, which is treated by a comparator and linear amplifier type LM393©, is connected to a GPIO of the ESP32© read by polling or by IRQ. The module seen incorporates an LM393© type operational amplifier that acts as a comparator, providing a fully digital DO signal, depending on the analog output AO of the 49E© and a reference value controlled by a potentiometer. W i t h t h e p o t e ntiometer 10k Ω P, we can adjust the comparison level between the comparator input 1IN- (Hall sensor) and the input 1IN+ (reference P) and therefore select whether the LED D1 and the digital output DO are activated with (N)orth or (S)outh poles. Resistors R0 and R1 limit the current of the LED and R2 is a pull-up to stabilize the 1OUT output of the LM393© amplifier and the GPIO32 input. Some previous versions of the ESP32©, not all, have an internal Hall sensor included in the main chip and accessible through the esp32 library but it is not very reliable, which is why it has been removed in more ESP32© recent versions. To control the 49E© sensor with its module, we will make a MicroPython© script where we will connect the digital output DO of the module to GPIO32, the analog output AO to the ADC converter in GPIO34 and we will add two LED: green in GPIO26 and red one in GPIO27 that will act of magnet polarity indicators. 320

Electronics & MicroPython© with ESP32©: 80 complete projects

When DO is activated, controlled by IRQ, a message will be displayed on the console, when the North pole (N) approaches, the green LED will be activated and with South or (S) the red LED and the value captured by the analog-digital converter (ADC) will also be presented. When the sensor rests, without detecting anything, the theoretical output value of the ADC will be the average value (M) of the scale (0-4,095), that is, a value close to 2,048 but here it's 1,900. When approaching the North pole (N), this ADC value will rise above the average value (M), depending on the value of the magnetic field of the approximate material and if we approach the South pole (S), this value will fall below the average value (M). We will add North values, for less than 1,800. factors: sensor temperature, etc.

some configurable thresholds for the example greater than 1,900 and South These thresholds depend on multiple type, power supply calibration,

321

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

In the script, the machine and time libraries are imported to control the GPIO, the ADC and the timing. The GPIO of the AO and DO signals coming from the Hall sensor and the GPIO for controlling the LED are defined, as well as the ADC thresholds that define the North pole and South pole of the magnet that activates the sensor (configure as needed). The ADC is configured by specifying the GPIO34, 12 the 12-bit resolution and therefore 2 =4,096 levels and the extension of the default measurement range from 0-1V to 0-3.3V. T h e sensor() function is established that controls the IRQ call and where the ADC is read and depending on its value and the predefined thresholds, the messages of the detected poles are presented and the corresponding LED are activated. Finally, the control IRQ is defined for the input to the ESP32© through the GPIO32 and by the transition from HIGH to LOW (falling) configurable by hardware with the potentiometer P. The start messages and a while True: loop are added which simulates the main body of the script which is controlled, as always, by the error handler and the console shutdown. ############################ # E034_HALL_SENSOR.PY: 44E© Sensor Hall with AO and DO # Hall sensor scanning on GPIO34 by IRQ # INPUTS: Hall sensor status AO and DO # OUTPUTS: North GPIO26 green and South GPIO27 red ######################### from machine import Pin, ADC import time

# GPIO & ADC control # Timing management

# Pines configuration pin_ao = Pin(34) # Analog AO pin_do = Pin(32, Pin.IN, Pin.PULL_UP) # Digital DO with 10k pull-up pin_led_green = Pin(26, Pin.OUT) # North pole pin_led_red = Pin(27, Pin.OUT) # South pole

322

Electronics & MicroPython© with ESP32©: 80 complete projects

# Detection thresholds north = 1900 # Top: North pole south = 1800 # Bottom: South pole hall_ant = 10 # Previous state of the Hall (not 0) # ADC configuration adc = ADC(pin_ao) adc.width(ADC.WIDTH_12BIT) adc.atten(ADC.ATTN_11DB)

# ADC reading # Resolution of 12 bits # 0-3.3V (default 0-1V)

# Change sensor status by IRQ def sensor(_): # Include an argument global hall_ant analog = adc.read() # Management of % variation greater than 2% if abs(analog-hall_ant)/hall_ant*100 > 2: if analog > north: print(f'NORTH Pole detected! {analog}') pin_led_green.off() # Green LED of pin_led_red.on() # Red LED on if analog < south: print(f'SOUTH Pole detected! {analog}') pin_led_green.on() # Green LED on pin_led_red.off() # Red LED off hall_ant=analog # IRQ for DO, sets to LOW and calls sensor() pin_do.irq(trigger=Pin.IRQ_FALLING, handler=sensor) print('SENSOR HALL 49E©') print('Approach a magnet...') # Main program loop try: while True: time.sleep(.1) # Simulates main body except KeyboardInterrupt: pin_led_green.off() # Green LED of and pin_led_red.off() # stop IRQ pin_do.irq(handler=None) print('Program completed...')

⊝⊝⊝ 323

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E182: LED control with Hall switch and PWM. Design a program for ESP32© that turns on an LED using a Hall sensor as an on/off switch, using DO. Use a PWM signal to control the intensity of the LED brightness within pre-established ranges. •E183: Timer with Hall sensor. Create a hardware timer on the ESP32© that is activated and deactivated using a Hall sensor. When activated, the timer must count for a specified period and then trigger an action, such as lighting an LED or sounding a buzzer. •E184: Event registration with RTC and Hall. Implement an event registration system that saves the date, time and levels at which a magnetic field is detected by the Hall sensor. Use the internal RTC to obtain the accurate timestamp and will be preupdated from the Internet and adjusting the necessary local variables. •E185: Servo control with Hall sensor. Design a system that controls a servo motor. When a magnetic field is detected with the Hall sensor. The servo must move to a specific position pre-configured by the console and when no magnetic field is detected, the servo must return to its initial rest position. •E186: Analog generator with DAC and Hall. Create an analog wave generator that produces simple waveforms using a DAC. Use the Hall sensor to start, stop or change the type of wave generated by the DAC.

⊝⊝⊝ 324

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 35: 44E© Hall Switch In this exercise we will see the use of a Hall sensor that has a digital switch on/off output (SIG or DAT), which is activated at LOW and therefore acts as a normal switch. As on other occasions, we will use a simple module, which includes the 44E© sensor and other components for its correct operation, as well as a 3 pin connector: SIG (on/off output), VCC (+3.3V) and GND. In the Hall switch circuit, LED D1 lights up when the circuit is supplied with +3.3V power, LED D2 lights up when the sensor conducts current when detecting a magnetic material, resistor R3 acts as a pull-up at +3.3V and R1, R2, as usual, limit the current that flows through both LED to protect them. 325

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

The output of the Hall switch (DAT or SIG, on/off type only) is connected through GPIO32 of the ESP32© and GPIO26/27 manage the status of two green and red LED respectively. The DAT or SIG output of the Hall switch is of the “open collector” type, that is , i t in te rn a ll y h a s a transistor that can be connected to +3.3V with a pull-up and allow the DAT output to be connected directly to the GPIO32 of the ESP32 © without voltage level adapters. The differences between the 49E© and 44E© Hall sensors are fundamental: the 49E© Hall sensor provides a n analog signal through its pin 3 that must be treated with an ADC or a comparator, while the 44E© Hall sensor provides a digital signal, of the on off type, which can be connected to a GPIO of the ESP32© to determine its HIGH or LOW value. The MicroPython© script begins with the import of the utime and machine libraries for timing control, switch GPIO and LED. The definition of control variables is also added and the green LED starts to turn on, with messages inviting us to bring a magnet close to the Hall switch. The led_update() function controls the state of the LED and messages based on the state of the Hall switch in pin_hall.value() which is activated at LOW as we have already mentioned (reverse logic). As we can see, this management is done by polling within a while...True: loop and in the main loop of the script the previous function is called, a waiting time between readings is controlled, which we must adjust according to our needs and finally, the corresponding error control and script interruption are included, which, if applicable, will turn off the LED as usual. 326

Electronics & MicroPython© with ESP32©: 80 complete projects

############################ # E035_HALL_SWITCH.PY: Hall Switch 44E© # Hall switch scanning on GPIO32 by polling # INPUTS: Hall switch status # OUTPUTS: GPIO26 green and GPIO27 red alternation ######################### import utime # Time management from machine import Pin # GPIO control # Pins configuration hall_pin = Pin(32, Pin.IN) # Hall switch green_led = Pin(26, Pin.OUT) # Green LED red_led = Pin(27, Pin.OUT) # Red LED # Current LED status (starts green) green_led_state = True green_led.on() red_led.off() print('\n' * 50) # Clear screen print('44E© HALL SWITCH CONTROL') print('Approach a magnet to the Hall switch') # Read switch status and update LED def led_update(): global green_led_state # Used out of function hall_value = hall_pin.value() # Read switch if hall_value == 0: # Detects a magnetic field print('\n' * 50) # Clear display print('Magnet detected...') if green_led_state: # Acts as a flag green_led.off() # Green LED off red_led.on() # Red LED on print('Red') green_led_state = False # Avoid bounces else: green_led.on() # Green LED on red_led.off() # Red LED off print('Green') green_led_state = True # Avoid bounces print('Approach a magnet to the Hall switch') try: while True: # Can be stopped with + led_update() utime.sleep_ms(300) # Wait between reading except KeyboardInterrupt: print('\n' * 50) # Clear display print('Program completed.') finally: # Turns off both LED when exiting the loop green_led.off() red_led.off()

⊝⊝⊝ 327

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E187: PWM wave generation with Hall switch. Create a system that generates a PWM wave on a specific pin of the ESP32©. Use a Hall switch to control the frequency of the PWM wave, which should increase or decrease depending on the detection of a magnetic field. •E188: Hall switch and push button. Implement a program that uses a Hall switch, managed by IRQ, to detect a magnetic field. When a magnetic field is detected, an LED will light and an interrupt for a push button will be activated. By pressing this button, the status of the switch will be displayed on the console. •E189: Servo control with Hall switch and RTC. Design a system that controls a servo motor by bringing a magnet close to a Hall switch. Use the RTC to record the date, time, Hall switch status, and angle applied to the servo motor to a file. Refreshes the file every 20 seconds. •E190: Watchdog, Hall switch and timer. Create a program that uses a Hall switch to detect a magnetic field. If no field is detected for a specific period of time, the ESP32© Watchdog will stop powering based on a timer that will restart the program from scratch. •E191: Hall switch and rotary decoder. Create a system that moves a servo arm based on the state detected by a Hall switch and the value entered through a rotary decoder. All data will be recorded to a file along with the RTC time.

⊝⊝⊝ 328

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 36: MF52AT© NTC Thermistor Sensor A thermistor is basically a resistance whose value varies with temperature, therefore we can use it as a thermometer to measure temperatures within predefined ranges. There are two types of thermistors: • Those that have a negative temperature coefficient, called NTC, that is, as the temperature detected in its environment rises, the resistance of the NTC decreases in a logarithmic (non-linear) manner. • Those with a positive temperature coefficient, called PTC, in which the opposite happens and the resistance increases exponentially (also non-linear) with temperature. In our case we will use an NTC type thermistor, similar to the MF52AT©, which has a resistance of 10k Ω at 25ºC and a variation between the detected temperature T and its resistance R with logarithmic variation, so for example, at 0ºC its resistance is R=98k Ω and at 50ºC is from R=3,6 k Ω. 329

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

In this exercise, like others already seen with other sensors, we w i ll u s e a m o d ul e t ha t includes the thermistor and also some control resistors and some status LED. We will process the output of the module, SIG, with the ADC converter of the ESP32©. When the temperature near the NTC thermistor rises, its resistance drops and we can detect this variation through the GPIO32 of our ESP32©. As always, on the NTC sensor module, LED D0 indicates power, resistors R0 and R1 limit the LED currents, and R2 and R3 are pull-up to stabilize all signals. In the script we import the time and machine libraries to control timing, pins and ADC. We define the minimum and maximum values for alarm control and configure the ADC in the GPIO32, adjusting the converter to support a greater dynamic range, allowing inputs from 0 to +3.3V (by default it only supports 0 to 1V as we already know). We create the function read_temperature() that reads the analog value of the thermistor, we create the function convert_temperature(), where we use a linear function (it should be logarithmic), which converts volts into ºC adjusted and limited to the maximums and minimums established by the ADC and finally we define the main loop where alarms, the presentation of the measured temperature and the time between readings are managed. 330

Electronics & MicroPython© with ESP32©: 80 complete projects

############################ # E036_THERMISTOR_SENSOR.PY: ADC with Thermistor # INPUTS: ADC in GPIO32 between 0 and +3.3V # OUTPUTS: ADC in ºC and GPIO26/27 LED green_red ############################ import time from machine import Pin, ADC

# Timing manager # GPIO management

# Configure temperature control LED led1=Pin(26, Pin.OUT) # Green LED led2=Pin(27, Pin.OUT) # Red LED led1.off() # Green LED off led2.off() # Red LED off # Temperature alarm thresholds (adjust) temp_min = 24.0 # Green temperature temp_max = 26.0 # Red temperature # Pin ADC configuration pin_thermistor = 32 adc = ADC(Pin(pin_thermistor)) # Set the ADC range to 0-3.3V (default 0-1V) adc.atten(ADC.ATTN_11DB) # Read thermistor values def read_temperature(): adc_value = adc.read() # Read ADC value # Convert ADC value to temperature temperature = convert_temperature(adc_value) if temp_min < temperature < temp_max: led1.on() # Correct temperature led2.off() # Green on else: led1.off() # Wrong temperature led2.on() # Red on print('Temperature Alarm: {:.2f} °C'.format(temperature)) return adc_value, temperature # Convert temperature between limits def convert_temperature(adc_value): # Converting thermistor value to temperature # ADC and temperature inverse temperature_min = 20 # Minimum ADC temperature 331

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

temperature_max adc_value_min adc_value_max adjust

= = = =

40 0 4095 .8

# # # #

Maximum ADC temperature Minimum expected ADC Maximum expected ADC Calibration value

# Inverted and adjusted linear conversion temperature = (temperature_max – (temperature_max - temperature_min) * (adc_value - adc_value_min) / (adc_value_max - adc_value_min)) * adjust return temperature # Main loop of the script def main(): try: while True: value, temperature = read_temperature() print("Temperature: {:.2f} °C".format(temperature)) time.sleep(1) # Wait between reading except KeyboardInterrupt: led1.off() led2.off() print("Program completed...") if __name__ == "__main__": print('\n'*20) print('TEMPERATURE READING BY THERMISTOR') main()

⊝⊝⊝

332

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E192: Nonlinear thermistor. In the previous exercise, a linear conversion of the ADC reading to temperature was carried out, but the thermistors do not present a linear behavior (both PTC and NTC). For this example use a curve for a typical NTC where the resistance varies with temperature with the formula: 2

where T is the 1 /T =a+b∗ln(R)+c∗ln (R), temperature in Kelvin, R is the resistance in Ohm and a, b, c are manufacturer-dependent coefficients.

and

Use, for example, −8 c=9.9∗10 .

−3

a=1.4∗10 ,

b=2.37∗10

−4

Remember that T is in Kelvin, search the Web to find out how to convert it to Fahrenheit or Celsius degrees. •E193: Thermistor with analog comparator. To complete this exercise, use a sensor module that contains an NTC thermistor and an analog comparator, so that when a certain reference temperature is reached (selected with a small potentiometer) the comparator is triggered, activating a digital output that we can capture with a GPIO, see next exercise. Implement this function, with the corresponding control messages, in a MicroPython© script similar to the previous one. •E194: Periodic temperature reading. Set a hardware timer on the ESP32© to take temperature sensor readings every 10 seconds using an NTC thermistor. 333

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Display the temperature and uses an LED to indicate that the temperature is within or outside a range. •E195: Temperature monitoring on the Web. Display the temperature detected with an NTC thermistor sensor module, read from the analog-digital converter (ADC), on a Web page hosted on the ESP32© that acts as a server. Configure the NO-IP© application (see other exercises), to access the Web page from anywhere outside the home. •E196: Voice temperature control. Create a routine with IFTTT© (see subsequent exercises) that allows us to implement voice control to request the ESP32© to perform a temperature measurement using an NTC thermistor sensor with ADC expressing the result on several scales. The values obtained must be saved in a file, together with the date and time captured from an external RTC, previously Internet updated, and these values will also be presented on a specific website hosted on the ESP32©. To ensure ADC readings, they must be accompanied by flashing LED and corresponding error checks.

⊝⊝⊝

334

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 37: Switch with Thermistor Likewise as seen with the Hall switch, in this exercise we also have the option of using a switch module with thermistor and that has two outputs: the digital output, DO, which is activated based on the comparison, carried out by the LM393© with a reference level and the AO output, coming from the sensor and that we can treat with the ADC procedure. The control circuit is similar to that of the Hall sensor switch, that is, as the ambient temperature rises, the NTC decreases its resistance and therefore the 1INinput activates the LM393© comparator in relation to the reference signal 1IN+ set by the P potentiometer. Once this situation is established, the digital output, DO, is activated to LOW by circulating current through D1 and activating the GPIO32 of the ESP32©. 335

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

In parallel, through the AO output we can see the value of the temperature provided by the thermistor, using an analog-digital converter (ADC). The connection to the ESP32© is similar to that of the Hall switch, we use GPIO34 to measure the analog signal AO with the ADC and we connect the digital output of the switch, DO, to the GPIO32 to treat it as a detection signal by polling or by IRQ. In this case, we will make a very simple script to poll only the output of the thermistor switch, that is, the digital output DO that is connected to GPIO32. We can vary the reference or trigger level of the LM393© comparator by adjusting the potentiometer P and/or changing the temperature and therefore the resistance of the NTC thermistor of the module. At the beginning of the script, we load the usual utime and machine libraries for timing control and GPIO for the DO switch input and the output for the LED. We start with the LED green, clean the console and present informative messages. The update_led() function flashes the LED in the event that the digital signal DO is activated at LOW (inverse logic), presenting the corresponding messages. The main loop of the script calls this function by polling and can be interrupted by console by pressing +, in which case the LED turn off. ############################ # E037_THERMISTOR_SWITCH.PY: DO thermistor management # Switch scanning on GPIO32 by polling # INPUTS: Thermistor status # OUTPUTS: Blink GPIO26 green and GPIO27 red ######################### import utime from machine import Pin

# Time management # GPIO control

# Pins configuration pin_DO = Pin(32, Pin.IN) green_led = Pin(26, Pin.OUT)

# Thermistor switch # Green LED

336

Electronics & MicroPython© with ESP32©: 80 complete projects

red_led

= Pin(27, Pin.OUT)

# Red LED

# Current LED status (starts green) green_led_state = True green_led.on() red_led.off() print('\n' * 50) # Clear display print('SWITCH CONTROL WITH THERMISTOR') print('Put your hand close to the thermistor...') print('...or turn the potentiometer...') # Read DO switch and update LED def update_led(): global green_led_state # Out of function ntc_value = pin_DO.value() # Switch reading if ntc_value == 0: # Look if DO is on print('\n' * 50) # Clear display print('Switch with activated thermistor...') if green_led_state: # Acts like a flag green_led.off() # Green LED off red_led.on() # Red LED on print('Red') green_led_state = False # Avoid bounces else: green_led.on() # Green LED on red_led.off() # Red LED off print('Green') green_led_state = True # Avoid bounces print('Put your hand close to the thermistor') print('... or turn the potentiometer...') try: while True: # Can be stopped with + update_led() utime.sleep_ms(300) # Wait between reading except KeyboardInterrupt: print('\n' * 50) # Clear display print('Program completed.') finally: green_led.off() # LED off red_led.off()

⊝⊝⊝ 337

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E197: NTC switch with IRQ. Use the same circuit as the previous exercise but change the management of the DO digital signal from polling to IRQ. •E198: NTC and ADC switch. Add the thermistor temperature value reading using the ADC connected to GPIO34 similar to the Hall sensor exercise. The DO signal will be treated by IRQ and when it is activated the temperature value, in degrees Celsius, will be read linearly. •E199: NTC logarithmic. Change the NTC reading with the ADC from linear to logarithmic as discussed in the thermistor sensor exercise. Save the NTC values each time the DO switch is tripped, varying the position of the P potentiometer and/or modifying the ambient temperature near the thermistor. These values will be saved in a file, along with the time updated with the ESP32© internal RTC. •E200: NTC and servo. Add to the previous exercise a servo and an algorithm that moves the servo a number of degrees depending on the temperature within pre-established thresholds. •E201: Multiple temperatures. Create a periodically updated file containing the updated RTC timestamp and temperatures from multiple sources: logarithmically adjusted NTC, internal to the ESP32©, and external from a DS18B20© sensor. Activates LED based on a temperature table.

⊝⊝⊝ 338

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 38: KY-033© Line Detector A line detector or follower is a sensor that distinguishes the reflectance of a line, for example a line drawn on paper, a line painted on a road, etc. In this sense, this sensor or similar is interesting to apply in robotics, automation, automotive, counters, etc. Because with this detector we can follow a certain line, not cross it, count crossed lines, etc. The line follower discussed here, for example the KY-033©, consists of two elements: an emitter and an infrared light receiver included in a package that detect when all, one or none of the two elements is on the line to be detected. These elements, transmitter and receiver, require an additional circuit that amplifies the signal and provides an on/off type output, which is set to LOW when it is detected that the sensor is on a line. Let's remember that the sensor's emitting diode is emitting infrared light continuously as long as it receives power. When the sensor is outside a line (light zone) the photo transistor receives infrared light from the emitter reflected in that light zone and begins to conduct and therefore the 1IN+ input of the comparator goes to LOW and the 1OUT output and the GPIO32 input go to LOW so D2 lights up. 339

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

When the sensor is on a line (dark area) the photo transistor does not receive light, as it is absorbed by the line, so the 1IN+ input of the LM393© comparator amplifier is at HIGH, the 1OUT output and therefore the GPIO32 input of the ESP32© is at HIGH and so D2 does not light up.

340

Electronics & MicroPython© with ESP32©: 80 complete projects

In the module, resistor R1 limits the current of LED D1 that lights up when power is applied to the circuit, R2 limits the current that crosses the reference adjustment potentiometer R3, R4 acts as a pull-up for 1IN+, R5 adjusts the current that circulates for the infrared emitter, R6 limits the current of LED D2, R7 is a pull-up for the GIPO32 and C1 and C2 act as a filter. In the script we import time and machine for time and GPIO control, we define the functions: setup() with the assignment of GPIO and variables, see() for LED and message state changes, loop() for polling the detector on the GPIO32 and stop() to stop the script, turning off the LED and displaying the corresponding messages. ############################ # E038_LINE_DETECTOR.PY: Line detector by polling # INPUTS: Line crossing in GPIO32 # OUTPUTS: Line crossing and LED indicator ######################### import time from machine import Pin # Pins configuration def setup(): global state_a, line_pin, green_led, red_led line_pin = Pin(32, Pin.IN) # Detector green_led = Pin(26, Pin.OUT) # Green LED red_led = Pin(27, Pin.OUT) # Red LED state_a = 1 # Previous state # Update detected status def see(x): if x == 1: red_led.on() # green_led.off() # print('To the left...') else: red_led.off() # green_led.on() # print('To the right...')

Red LED on Green LED off Red LED off Green LED on

341

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

# Read the detector by polling def loop(): global state_a state_n = line_pin.value() if state_n != state_a: see(state_n) state_a = state_n time.sleep(0.1)

# # # # #

Read the status Change state Show new one Update state Wait a while

# Stop keyboard script def stop(): green_led.off() red_led.off() print('Program completed') # Main loop of the program if __name__ == '__main__': setup() # Star GPIO and variables print('\n'*50) # Clear display print('LINE DETECTOR KY-033©') print('Testing line detector...') try: while True: loop() # Run main loop except KeyboardInterrupt: stop() # Stop program with +

⊝⊝⊝

342

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E202: Line follower, LED and push button. Design a program in MicroPython© for ESP32© that uses a line follower of the type KY-033© or similar, controlled by IRQ, so that, when the line follower detects a line, it turns on an array of LED up to a certain level according to a pre-established algorithm with a 3-level table. Finally, integrate a push button already seen in other exercises and managed by interruption (IRQ), to stop the tracking of lines when the push button is pressed. •E203: Servo control with line follower. Create a program that uses a KY-033© line follower to follow a predefined route created by drawing curves on a piece of paper. Integrates a servo motor that rotates in reverse depending on the signal from the line follower. Use a timer to periodically poll the line follower instead of using IRQ. •E204: Wave generation and line follower. Develop a script in MicroPython© that uses a line follower to control the generation of analog waves using the DAC (digital-to-analog converter) of the ESP32©. Experiment with different waveforms: sinusoidal, square, triangle, saw, etc. and different frequencies and duty cycle, according to the signals detected by the line follower. •E205: RGB LED, line follower and RTC. Create a MicroPython© program for ESP32© that uses a KY-033© line follower or similar to detect a given path. 343

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Integrate an RGB LED to change the color of the LED depending on the state of the line follower and record in a file the date and time of the internal RTC of the ESP32©, updated over the Internet, as well as the state of the line follower and the applied values to the RGB LED. The recording in the file must be circular, that is, when recording 20 lines, it must start recording the first one again. •E206: Follower and speed control. Design a MicroPython© program for ESP32© that uses a KY-033© line follower or similar to follow a line drawn on a piece of paper with a black marker. Integrate a DC motor with PWM speed control and a servo with rotation control. Use the line follower to adjust the speed and direction of the motors according to the detected trajectory. Design an algorithm so that the motor decreases the speed if nothing is detected and changes the servo angle if crossing to the right or left of the line is detected.

⊝⊝⊝

344

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 39: ERD29© Laser Diode IMPORTANT: DO NOT LOOK AT THE LASER DIRECTLY In this exercise we will use a low power laser diode (5mW), that is, a diode that emits coherent light, of a specific frequency therefore of a specific color, created by the emission of electronically stimulated radiation. It is a low-power laser but it should NOT be focused on the eyes as it can cause irreversible damage. The author of this book declines any responsibility derived from possible damages caused by this or any other optical or electronic element described in this book. The coherence of the laser light allows us to focus on a small point and conveniently direct it as if it were a pointer. Other higher power lasers are used for other industrial purposes, here we will use it only for training reasons to emit pulses based on some algorithm implemented in a program. The circuit is very simple, since we only need to connect it to the GPIO32 that powers it directly, creating the necessary pulses. The program example generates approximately, respecting the times, the Morse code of the international SOS distress signal, that is: ...---... 345

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

To make it as realistic as possible, the script takes into account all the necessary relative times, that is, of a dot, a dash, the separation between signs, the separation between letters, the separation between words, etc. The script is simple, it imports the usual machine and time libraries to control the GPIO and the times, it defines the timing of the elements: point, line, space between pulses, space between letters and space between words, it assigns each element a number and thereby generates the list text[] with all the necessary sequence. T h e setup() function is defined with the association of the GPIO, the loop() function where the text[] list is traversed and acts with each component, the stop() function that stops the script by turning off the laser and the LED that act visual signal so we don't have to look directly at the laser. ############################ # E039_LASER.PY: Laser SOS emitter # INPUTS: SOS elements list # OUTPUTS: Laser and LED visualization ######################### from machine import Pin import time

# GPIO management # Timing control

# SOS elements dot = .3 # Morse dot line = dot*3 # Morse line space_pulse = dot # Space pulse letter_pulse = dot*3 # Letter pulse word_space = line*4 # Word space text = [0,2,0,2,0,3,1,2,1,2,1,3,0,2,0,2,0,4]

(0) (1) (2) (3) (4) # SOS

# GPIO start def setup(): global laser, green_led, red_led laser = Pin(32, Pin.OUT) # Laser green_led = Pin(26, Pin.OUT) # Green LED red_led = Pin(27, Pin.OUT) # Red LED

346

Electronics & MicroPython© with ESP32©: 80 complete projects

# Laser on/off activation (inverse logic) def loop(): for x in text: # Scan text[] if x==0: # Is a dot? laser.off() red_led.on() time.sleep(dot) laser.on() red_led.off() if x==1: # Is a line? laser.off() red_led.on() time.sleep(line) laser.on() red_led.off() if x==2: # Space pulse? time.sleep(space_pulse) if x==3: # Letters pulse? time.sleep(letter_pulse) if x==4: # Words space? time.sleep(word_space) # Stop script def stop(): print ('Program finished, Laser off') laser.off() # Laser off red_led.off() # LED off green_led.off() # Main body of the script if __name__ == '__main__': # setup() # green_led.on() print('SOS WITH LASER') print('Transmitting code...') try: while True: loop() # except KeyboardInterrupt: # stop()

Program start here Start GPIO

SOS loop Stop script

⊝⊝⊝ 347

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E207: Laser and servo with ESP32©. Simulate the physical connection between the laser and a servo arm, so that based on the seconds of the ESP32©'s internal RTC, activate the laser and moves the servo arm a certain turn making the laser point at various objects. The position of the objects can be defined in the dictionary positions{object:position}. •E208: Laser and DAC with ESP32©. Connect the laser to a GPIO with digital-toanalog conversion (DAC) capability and check whether changing the output level activates the laser or not. Modify the SOS signal generation script so that the DAC does it. •E209: Laser and PWM signal. Connect the laser to an ESP32© GPIO that can generate a square wave, using variable duty cycle PWM technology and see how it affects the luminosity of the laser. Add a Hall sensor whose output, treated by the ESP32©, acts proportionally on the duty cycle of the PWM signal and therefore on the possible luminosity of the laser (it is not a linear device).

⊝⊝⊝

348

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 40: TCS3200© colors sensor In this exercise we will see a very curious and interesting sensor, it is a colors sensor, that is, a sensor that is capable of detecting and even measuring the basic colors of an object. The TCS3200© sensor or similar, has 4 white LED that directly illuminate a nearby object and an 8x8 pixel sensor that detects the light reflected by the basic color components of this object and outputs a sq u a re w a ve o f 50 % d ut y c y cl e a nd f r eq u e n cy proportional to the intensity of a certain color. For a better measurement of the signal associated with a basic color with the ESP32© GPIO, the output frequency on the OUT pin can be scaled by several factors with the S0 and S1 inputs according to the attached table. This sensor, which actually behaves as an intensity converter of a certain color of light at a frequency, has 8x8 photodiodes: 16 have a red filter (R), 16 green (G), 16 blue (B) and another 16 without filter that can be selected according to the table: 349

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Therefore, we can select the applied filter by connecting S2 and S3, for example, to GPIO26 and GPIO32 respectively and measure with 3 test objects (red, green and blue) how the frequency decreases on the OUT pin of the TCS3200© sensor. Other colors will be combinations of the RGB values. We also could connect S0 and S1 to the GPIO of the ESP32© but it is not recommended because the frequencies provided by the sensor in the 20% and 100% configurations are too high for the ESP32© (more than 25kHz), so we can set S0=L and S1=H and work with 2%. See pin table.

350

Electronics & MicroPython© with ESP32©: 80 complete projects

In the MicroPython© script we import machine and time as always, we define the number of CYCLES for calculating the frequency, the setup() function that defines the filter pins S2 and S3 and the OUT frequency output. W e d e f i n e t h e f u n c t i o n measures() t h a t calculates the frequency according to the time it takes to perform CYCLES counted by the MicroPython© object out.irq() that defines an interruption on the OUT pin (GPIO34) by passing from HIGH to LOW (falling) and where lambda p:None is a callback argument activated by this IRQ and that allows us to count the number of cycles. Finally, the duration of the CYCLES is counted and converted into frequency. In this measures() function we also see how s2 and s3 are changed depending on the color filter to be used (red, green, blue, none). Finally, the setup() function is activated to configure the GPIO and a while True: loop is performed where the frequencies for each filter are measured and presented and a condition is proposed, which must be adjusted based on the conditions of each case, to the combinations of frequencies for each color and in this way the approximate basic color is obtained. For other colors we will obtain a certain combination of these frequencies. ############################ # E040_COLOR_SENSOR.PY: Color sensor TCS3200© # INPUTS: Basic colors RGB # OUTPUTS: Frequency and color detected ############################# from machine import Pin # GPIO management import time # Timing control ''' # Pins definition out frequency # Frequency output s2 s3 filter # Filter select -------------L L Red L H Blue H L NO filter H H Green ''' CYCLES = 50 # GPIO configuration

# Frequency cycles counter

351

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

def setup(): global s2, s3, out # Global variables s2 = Pin(26, Pin.OUT) # S2 s3 = Pin(32, Pin.OUT) # S3 out = Pin(34, Pin.IN, Pin.PULL_UP) # OUT # Measures frequency (S2, S3, color) def measures(v2, v3, color): print('Measuring: ' + color) s2.value(v2) # Activate the filter s3.value(v3) time.sleep(0.3) # Wait for the chip start = time.ticks_ms() # Get star time for _ in range(CYCLES): # Cycles counter out.irq(lambda p: None, Pin.IRQ_FALLING) while out.value() == 1: # Wait on LOW pass while out.value() == 0: # Wait on HIGH pass duration = time.ticks_diff(time.ticks_ms(), start) / 1000 # Duration frequency = int(CYCLES / duration) # Hz return frequency # Main body of the script setup() # Pins configuration print('TCS3200© COLOR SENSOR') print('Approach an objet to the sensor...') try: while True: # Colors read cycle red = measures(False,False,'Red') # Red green = measures(True, True, 'Green') # Green blue = measures(False,True, 'Blue') # Blue white = measures(True, False,'White') # White print(f'RGB: {red}:{green}:{blue}') # Hz # Adjust conditions as ambient light, etc. # Proposal of 2% frequency (S0=L y S1=H)) if red > 1000 and green < 800 and blue 400 and blue200: print('BLUE OBJECT') elif red > 1000 and green > 800 and blue>800: print('WHITE object or none') else: print('Unknown color') except KeyboardInterrupt: print('Finished...')

⊝⊝⊝ 352

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E210: Color sensor and relay. Design a system, based on ESP32©, that automatically controls the lighting of a room using the TCS3200© color sensor and a relay to turn a lamp on and off based on the intensity of the detected light of a given color. The script will present appropriate messages. •E211: Temperature and color sensor. Create a device that monitors ambient temperature and humidity using a DHT11© as well as the internal temperature of the ESP32©. If these three variables exceed a certain limit, measure the color detected by the TCS3200© sensor and if it is red send an email with all the necessary data. •E212: TCS3200© sensor and WiFi connection. Take data from the frequencies detected by the color sensor, record them in a file along with the date and time of the updated RTC and using WiFi, send them by email every 10 readings. •E213: Color sensor and wave generator. Implement an audio signal generator using the ESP32© DAC and the TCS3200© color sensor to modulate the frequency and amplitude of the generated audio signals, creating interesting sound effects or programmed melodies based on the color detected and set into colors{color:freq}. •E214: Color, RGB and PWM sensor. Build a device that reads a basic color with the color sensor and reproduce it on an RGB LED using PWM signals. Extend the exercise to non-basic colors from a predefined color table.

⊝⊝⊝ 353

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 41: KY-032© Obstacle Sensor This time we will see an obstacle sensor of the KY032© type or similar, which actually consists of three parts: • • •

An electrical pulse generator. An infrared pulse emitter. An infrared signal receiver.

The emitter constantly sends pulses of infrared light generated by a 7555© type oscillator configured in astable mode (frequency generator). When these pulses bounce off an obstacle (not very far) and are captured by the receiver, an alarm is activated. The detection distance of the infrared receiver depends on the power of the emitter, the reflectance of the obstacle, the characteristics of the medium that intervenes between the emitter and receiver, the sensitivity of the receiver, etc. The pulse generator signal (7555© timer or similar) is amplified by a PNP type transistor similar to the S8550© whose gain factor can be regulated with a potentiometer, regulating the base current, through R7, or regulating the supply current through the collector with the variable resistor R4, this allows regulating the obstacle detection distance. 354

Electronics & MicroPython© with ESP32©: 80 complete projects

This sensor therefore requires a control circuit that is a little more complicated than the ones we have seen so far but easy to understand. Let's see each part:

Oscillator: This is the timer already seen 7555© (a NE555© CMOS) in astable oscillator configuration where the oscillation frequency is determined by: f=

1 1 = ±46KHz log (2)∗C3∗( R5 +2∗R6 ) 0.693∗10−9∗(103 +2∗15∗10 3 )

C1 and C2 act as stabilizers and the signal generated by the 7555© comes out through the OUT pin. Emitter: T h e si g n a l f r o m O U T a t t ac k s t h e PN P transistor S8550© which acts as a signal amplifier used by the emitter D3 (an infrared diode) and which can be regulated with the 1k Ω R4 potentiometer. R3 limits the current that crosses the transistor when the potentiometer is at minimum resistance and R7 limits the base current of the transistor. 355

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Receiver: This is an infrared photodiode (BPV10NF© or similar) that captures the infrared beam sent by the emitter and that has bounced off the obstacle. When this sensor detects the bounced signal, it sets GPIO34 to GND (reverse logic) and activates LED D1. R1 and R2 limit the current to the LED and D2 lights to indicate that the circuit is powered. We will also use a Dual LED that will flash red to indicate the presence of the obstacle and will remain green otherwise. This LED is managed by software with GPIO26 (green) and GPIO27 (red) as we usually do. The script is similar to that of the line detector and others that present the status of a sensor with an on/off type digital output. The time control and GPIO libraries are imported, the sensor and LED pins and global variables are defined. T h e setup() function initializes the GPIO, the look() function analyzes the sensor output and acts on the LED, and the loop() function simulates the main body of a script that includes the control of the obstacle sensor by polling. Finally, the stop() function is presented that stops the script and the main body that calls setup() a n d loop() within an error and stop control. ############################ # E041_OBSTACLE_SENSOR.PY: KY-032© obstacles sensor # INPUTS: Obstacle detected in GPIO32 # OUTPUTS: Message and LED in GPIO26/27 ############################# import time from machine import Pin

# Timing management # GPIO control

pin_v pin_r pin_s pins state counter

# # # # # #

356

= = = = = =

26 27 32 (pin_r, pin_v) True 0

Green LED Red LED Sensor input Pins list Control flag Obstacles trace

Electronics & MicroPython© with ESP32©: 80 complete projects

# Start GPIO def setup(): global pin_s # Sensor output pin_s = Pin(pin_s, Pin.IN) for p in pins: # LED output led = Pin(p, Pin.OUT) led.value(0) # LED off # Check sensor status due to polling def look(): global state, counter counter += 1 # Obstacles trace print(f'[{counter}]: Obstacle detected...') if state: # Change LED states Pin(pin_r, Pin.OUT).on() # Red LED on Pin(pin_v, Pin.OUT).off() # Green LED off else: Pin(pin_v, Pin.OUT).on() # Green LED on Pin(pin_r, Pin.OUT).off() # Red LED off state = not state # Main loop of the script def loop(): while True: if not pin_s.value(): look() time.sleep_ms(100)

# Inverse logic # Sensor status # Simulate script

# Stop script def stop(): for p in pins: Pin(p, Pin.OUT).off() # LED off print('\nProgram completed.') # Script starts here if __name__ == '__main__': print ('OBSTACLES SENSOR CONTROL') setup() print('Approach an obstacle to the sensor...') try: loop() # Polling loop except KeyboardInterrupt: stop() # Stops script

⊝⊝⊝ 357

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E215: Servo control and obstacle sensor. Design a MicroPython© script to control a servo motor based on the detection of an obstacle. When an obstacle is detected, the servo rotates a certain angle and when the detection is completed, the servo returns to its initial position. •E216: Activate a relay with obstacle sensor. Use an obstacle sensor to detect the presence of a nearby object. When detected, a relay is activated that can control any electrical device connected to it, such as a lamp or a motor (for example, simulate it with an LED). •E217: Line and obstacle sensor. Use a line sensor and an obstacle sensor to follow a line parallel to a wall. The obstacle sensor must detect the wall permanently and if not, it will indicate it with an LED. •E218: Temperature, thermistor obstacles. Use an obstacle sensor along with a thermistor to measure ambient temperature. When an obstacle is de t e ct e d , t h e s c r ip t a dj u s ts t he s p ee d o f a thermistor-controlled fan to prevent overheating of the environment. •E219: RGB LED and proximity of an obstacle. Use an obstacle sensor and a color sensor to detect the proximity of an object of a certain basic color. Change the RGB color depending on the color and/or obstacles detected.

⊝⊝⊝

358

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 42: 1838B© Infrared Receiver In this exercise we will see how to use an infrared receiver as a detector, that is, NOT as a code reader (we will see this later), only as a sensor that activates a signal when detecting an infrared signal coming from any infrared emitter (remote television, decoder, etc.) For this we will use the 1838B© infrared receiver or equivalent, with an additional circuit very similar to that used in the rest of the sensors already seen.

When the 1838B© detects an infrared signal, it passes its pin 1 to GND and therefore D2 conducts and the GPIO32 detects the LOW level (reverse logic) where R2 is a pull-up to +3.3V. 359

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

LED D1 lights up when power is detected, resistors R1 and R3 control the maximum current that circulates through LED D1, D2 and through the sensor, and C1 activates the +3.3V signal filter. In our example, every time the infrared sensor detects a signal of this type, coming from a TV remote control, air conditioning, etc., it will activate and act on a Dual LED, causing it to alternate between the red and green LED with each infrared signal received. The script is very simple and similar to other sensor exercises seen previously in which the sensor situation is reviewed by polling. ############################ # E042_INFRARED_RECEIVER.PY: 1838B© sensor # INPUTS: Signal detected in GPIO32 # OUTPUTS: Message and LED in GPIO26/27 ############################# import time from machine import Pin

# Timing control # GPIO management

pin_v pin_r pin_s pins state counter wait

# # # # # # #

= = = = = = =

26 27 32 (pin_r, pin_v) True 0 .1

Green LED Red LED Sensor input Pins list Control flag Obstacle trace Wait between presses

# GPIO start def setup(): global pin_s # Sensor output pin_s = Pin(pin_s, Pin.IN) for p in pins: # Output LED led = Pin(p, Pin.OUT) led.value(0) # LED off # Check sensor status due to polling def look(): global state, counter counter += 1 # Signals trace print(f'[{counter}]: IR signal detected...') 360

Electronics & MicroPython© with ESP32©: 80 complete projects

if state: Pin(pin_r, Pin.OUT).on() Pin(pin_v, Pin.OUT).off() else: Pin(pin_v, Pin.OUT).on() Pin(pin_r, Pin.OUT).off() state = not state # Main loop of the script def loop(): while True: if not pin_s.value(): look() time.sleep(wait)

# Change LED status # Red LED on # Green LED off # Green LED on # Red LED off

# Inverse logic # Look sensor status # Wait presses

# Script stop def stop(): for p in pins: Pin(p, Pin.OUT).off() # LED off print('\nProgram completed.') # Script starts here if __name__ == '__main__': print ('INFRARED SENSOR CONTROL') setup() print('Send a signal to sensor...') try: loop() # Polling loop except KeyboardInterrupt: stop() # Stop script

⊝⊝⊝

361

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E220: Relay with IR remote control. Use the infrared or IR receiver to receive signals from a TV remote control. Set the ESP32© to act as a relay switch, turning an electrical device (such as a lamp) on or off each time a button on the remote control is pressed. Add the corresponding delays between switches. •E221: Servo control with remote control. Use the IR receiver to detect signals from a remote control. Program the ESP32© to control the position of a servo motor according to the signal received from the remote control. •E222: Change RGB color with an IR control. Use the IR receiver to capture on/off signals from an IR remote control. Program the ESP32© to change the color of an RGB LED in a predefined sequence in the sequences{step:color} dictionary. •E223: Hall sensor reading via IR. Connect a Hall sensor to the ESP32© and use the IR receiver to receive signals from a remote control. Modify the script so that it reads the Hall sensor values every time a button is pressed on the remote control, and displays these values on the console. •E224: Motor control via IR and PWM. Connect a motor to PWM and use the IR receiver to receive signals from a remote control. Program the ESP32© to adjust the motor speed according to the received signals in an increment and decrement sequence established in a dictionary.

⊝⊝⊝

362

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 43: Remote Control with Infrared As promised, in this exercise we will see how we can receive and manage infrared signals, sent by an infrared remote control or “command”, and received and decode them with the ESP32© with a MicroPython© script. There are multiple controls and protocols and for simplicity in this exercise we will see the Sunfounder© infrared control or similar.

The Sunfounder© remote uses, among others, the NEC© infrared transmission protocol, which is basically summarized in the following steps: •

Sequence: The data frame in the NEC© protocol consists of a header, an 8-bit command, the complement of the 8-bit command, and a termination bit.



Header: The data header is composed of a 9ms start gap (start mark to LOW) followed by a 4.5ms pulse (start pulse to HIGH) with reverse logic. 363

Gregorio Chenlo Romero (gregochenlo.blogspot.com)



Data bit: Each data bit is represented by a sequence of two pulses: a 560µs mark followed by a 560µs gap to represent a 0 bit, or a 560µs mark followed by a 1.68ms gap to represent a 1 bit. This notation is with reverse logic.



Command: Commands are usually 8 bits long, transmitted from the most significant bit to the least significant bit.



Command complement: The command complement is simply the inverse of the command bits and is used to verify data integrity.



Termination: After transmission of the command and its complement, a long pulse (mark) followed by a long blank (space) is sent to indicate the end of the frame.

We will maintain the same connection of the infrared receiver module already seen in the previous exercise, that is, +3.3V, GNG and SIG connected to the GPIO32. We will also use the green and red LED that will alternate when pressing the “Mode” key. For the script we need the ir_rx library that we will download from the Sunfounder© website with which we will have to upload the ir_rx folder to the ESP32© from which we will use the nec.py and __init__.py files only, we will also add the following script: ############################ # E043_INFRARRED_REMOTE.PY: 1838B© infrared sensor # INPUTS: Signal detected in GPIO32 # OUTPUTS: Key pressed # IMPORTANT: Needs Sunfounder© ir_rx.nec and remote ############################# import time from machine import Pin from ir_rx.nec import NEC_8 pin_ir = Pin(32, Pin.IN) pin_v = Pin(26, Pin.OUT) pin_r = Pin(27, Pin.OUT) 364

# # # # # #

Timing management GPIO control Remote control library Infrared receiver Green LED Red LED

Electronics & MicroPython© with ESP32©: 80 complete projects

# Received key codes codes = { 0x16: "0", 0x0C: 0x08: "4", 0x1C: 0x52: "8", 0x4A: 0x07: "EQ", 0x0D: 0x44: "Play/Pause",0x43: 0x45: "On/Off", 0x47:

"1", "5", "9", "U/SD", "FF", "Mute",

0x18: 0x5A: 0x09: 0x19: 0x40: 0x46:

"2",0x5E: "3", "6",0x42: "7", "+",0x15: "-", "Repeat", "RW", "Mode"}

# ir_rx.nec library error codes errors = {"BADSTART" : 'Invalid initial pulse', "BADBLOCK" : 'Wrong block', "BADREP" : 'Repeat', "OVERRUN" : 'Excess data', "BADDATA" : 'Wrong data', "BADADDR" : 'Wrong address'} # Flow control data flag = True # LED control flag tmp = .1 # Polling time # Errors control def see_error(data): if data in errors: print(errors[data]) else: print('Unknown error')

# There's error # There's no error

# Processes received data def process(data, address, control): global flag # LED control if data < 0: # Data waiting pass else: # Received data print(f'Received key: {codes[data]}') if codes[data] == 'Mode': if flag: pin_r.on() # Red LED on pin_v.off() # Green LED off else: pin_r.off() # Red LED off pin_v.on() # Green LED on flag = not flag # Change led status

365

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

ir = NEC_8(pin_ir, process)

# NEC© protocol instance

# Shows possible errors ir.error_function(see_error) # Polling reading loop print('REMOTE CONTROL IR NEC© PROTOCOL') print('Press a key on the remote') try: while True: time.sleep(tmp)

# Simulate script

except KeyboardInterrupt: print('Program completed...') ir.close() # Receiver off As an example of the NEC© IR transmission protocol, when transmitting a “1” the following sequence can be seen in the logic analyzer:

We can see the start at LOW of 9ms (space between marks A1 and A2) with the header 0x00, the device address 0xFF, the command 0x0C corresponding to key 1 and the complement of the command 0xF3 to verify the integrity of the transmission.

⊝⊝⊝

366

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E225: Control of an LED array with IR control. Connect an infrared receiver to the ESP32© and configure it to receive codes from an infrared remote control. Use the IR command numbers to control the number of array LED activated. •E226: Control of a servo with an IR command. Connect a servo and program the infrared receiver to receive signals from an IR controller. Use the received codes to control the position of the servo according to states{code:rotation}. •E227: Activation of a relay with an IR command. Connect a relay to the ESP32© and configure the infrared receiver to receive codes from a controller. Use the correct codes received to activate or deactivate the relay. •E228: LED modulation with PWM and IR. Connect an LED to the ESP32© and configure the infrared receiver to receive codes from a controller. Use the received codes to modulate the light intensity of the LED using PWM. Each button on the controller can be associated with a different LED brightness level predefined with data{button:brightness}. •E229: Infrared emitter. Set the GPIO32 as an output to use the IR module as an infrared emitter and send the code '2' by sending the sequence: [start, 0x00, 0xFF, 0x18, 0xE7]. Respect the timing for start and the corresponding 0 and 1 of each command. Could we control a simultaneous transmitter and receiver with the ESP32©?, why?.

⊝⊝⊝

367

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 44: SW-200D© Tilt Sensor Another way to control an LED or any type of output is by using some type of additional sensor. In this exercise we will see how to use a tilt sensor or “tiltswitch”, for example the SW200D©. It is a mechanical sensor that is not very precise or very fast but easy to use, cheap and that detects a certain angle of inclination. It consists of a small cylinder with a small sphere inside that, when tilted, makes the sphere roll and this activates a mechanical contact, being able, for example, to detect the rotation or overturning of an object, movement, impact, anti-theft alarms, industrial processes, etc. The inclination sensor or tilt-switch sensor, in most cases, is usually accompanied by a very simple electronic control circuit like the one attached. In this circuit, R0 and R1 control the current through LED D0 (power indicator) and LED D2 (activation indicator). 368

Electronics & MicroPython© with ESP32©: 80 complete projects

When we tilt the tilt-switch sensor its built-in switch sets GPIO32 to GND and therefore D2 lights up. There are more precise tilt-switch sensor circuits by incorporating integrated circuits that act as comparators and assign more reliable states to the switch. The activation of the tilt-switch is what we will capture with the ESP32© and by software, we will activate a red or green LED based on an algorithm. Logically it could be actuated with a relay, an amplifier or any other type of actuator. As we said, this sensor is not very precise, later we will see a very precise three-axis accelerometer, although more difficult to manage. To control this simple sensor we will use one of the scripts already seen previously that also controlled other on/off type sensors and that include green and red LED for visual control of the activation of the sensor. This script will also be useful for subsequent exercises that include on/off type sensors like this one. ############################ # E044_TILT_SENSOR.PY: SW-200D© sensor # INPUTS: Detected signal in GPIO32 # OUTPUTS: Message and LED in GPIO26/27 ############################# import time # Timing management from machine import Pin # GPIO control pin_v = pin_r = pin_s = pins = state = counter wait =

26 27 32 (pin_r, pin_v) True = 0 .1

# # # # # # #

Green LED Red LED Sensor input Pins list Control flag Motion trace Wait between events

# GPIO start def setup(): global pin_s # Sensor output pin_s = Pin(pin_s, Pin.IN) 369

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

for p in pins: # Output LED led = Pin(p, Pin.OUT) led.value(0) # LED off # Check sensor status due to polling def look(): global state, counter counter += 1 # Motion trace print(f'[{counter}]: Tilt detected...') if state: # Change LED status Pin(pin_r, Pin.OUT).on() # Red LED on Pin(pin_v, Pin.OUT).off() # Green LED off else: Pin(pin_v, Pin.OUT).on() # Green LED on Pin(pin_r, Pin.OUT).off() # Red LED off state = not state # Script main loop def loop(): while True: if not pin_s.value(): look() time.sleep(wait)

# Inverse logic # Check sensor status # Wait for motion

# Stops script def stop(): for p in pins: Pin(p, Pin.OUT).off() # LED off print('\nProgram completed.') # Script starts here if __name__ == '__main__': print ('TILT SENSOR CONTROL') setup() print('Move the sensor...') try: loop() # Polling loop except KeyboardInterrupt: stop() # Stops the script

⊝⊝⊝

370

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E230: Relay control with tilt sensor. Use a tilt sensor to detect the movement of an object. Connect a relay to the ESP32© and program the micro controller to activate the relay when the tilt sensor detects a movement and deactivate it when it detects the next. Manage the sensor by IRQ instead of polling. •E231: Buzzer and tilt sensor. Connect a tilt sensor to the ESP32© and an active buzzer. Program the ESP32© with MicroPython© to activate the buzzer when the tilt sensor detects an inclination and deactivate it when it detects the next one. Repeat the exercise with a passive buzzer managed by the ESP32© DAC. •E232: PWM generation and tilt sensor. Connect a tilt sensor to the ESP32© and an RGB LED. Program the micro controller, with a MicroPython© script, so that the movement of the tilt sensor modifies the color of the LED using PWM. •E233: Servo control with tilt sensor. Connect a tilt sensor to the ESP32© and a servo motor. Program the micro controller to move the servo in one direction or another depending on the number of inclinations detected. As the tilt detection is performed, the state of an LED array changes and the sound of a buzz is modified using PWM.

⊝⊝⊝

371

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 45: SW-18010P© Vibration Sensor A variant of the tilt switch is the vibration, spring or impact switch. When a vibration or impact of a certain energy occurs, the spring makes contact with an internal element of the switch, activating its output. In this exercise we will see a vibration sensor, of the on/off type, similar to the SW-18010P© or equivalent, which also requires a simple additional control circuit like the one in the attached figure and very similar to other sensors. In this circuit, the LED diode D0 lights up when power is supplied to the circuit and the LED D1 lights up when the vibration switch detects a movement or an impact, as it sets the GPIO32 to GND (LOW). Resistors R0 and R1 limit the current that circulates through LED D0 and D1 respectively, resistor R2 acts as a pull-up of the GPIO32 input to stabilize its level when the sensor is not activated and capacitor C1 filters the high frequency signals normally generated by the 372

Electronics & MicroPython© with ESP32©: 80 complete projects

vibration switch, avoiding false activations (which we can also reinforce its suppression by software). When GPIO32 is LOW it will detect vibration (reverse logic). To complete the exercise, we add a Dual LED so that when the vibration or impact is detected, the red LED turns on, in the next vibration the green LED turns on and the red turns off and so on as if it were a “flip-flop” circuit type or bistable (two-state circuit). For the MicroPython© script, we will use the same or similar one seen in the previous tilt sensor exercise.

⊝⊝⊝ 373

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E234: Vibration event log. Connect a vibration sensor to the ESP32© and design a MicroPython© script to detect vibration events and record the date and time of each event in a file that is updated by a hardware timer. •E235: Temperature and vibration sensors. Connect a vibration sensor and a DHT11© sensor to the ESP32©. Program the micro controller to activate the DHT11© sensor and read and display temperature and humidity when a vibration is detected. •E236: Vibration and color sensors. Connect a vibration sensor and a color sensor to the ESP32©. Program the micro controller so that when it detects a certain color it checks, by polling, the status of a vibration sensor. •E237: Infrared control and vibration sensor. Connect a vibration sensor and an infrared receiver to the ESP32©. Add an action algorithm based on both sensors. Perform programming so that the date, time, state of the vibration sensor, key pressed on the infrared remote control, and output of the algorithm are stored in a file. •E238: Timed events with vibration. Connect a vibration sensor to the ESP32© and program it to initiate timed events when a vibration is detected and using the time and date of the internal RTC of the ESP32© previously updated from the Internet. Save all data to a file.

⊝⊝⊝

374

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 46: MAX-4466© Sound Sensor The sensor that we are going to see in this exercise is very common in homes, very well known and widely used in multiple devices. It is a microphone that translates the pressure of sound waves into analog electrical signals that we will capture and convert with the ADC converter. In our case we will use the MAX-4466© or similar, which is a sound sensor, that is, a microphone based on an electrostatic capacitor that generates a small current when activated by the acoustic pressure exerted by sound. This sensor requires a highgain, low-noise amplification circui t, su ch as the L M358© operational amplifier, and an additional control circuit like the fo llowi ng, an d sin ce it provides an analog signal, we will connect it to the ESP32© ADC analog-digital converter. We will read the ADC quickly to capture all the information from the sensor, but we must know that to capture a frequency f we must read the ADC at least 2*f (Shannon Theorem) and with high f values the ESP32© is limited. For sounds of a certain level and medium frequencies we should not have any problems. 375

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

The microphone, upon receiving sound pressure, generates through C1, R4 and together with R3, a variable analog voltage that is amplified by the LM358©, which comes out through 1OUT and attacks the GPIO32 configured as ADC. R1 and R2 generate an intermediate point between +3.3V and GND that serves as a reference to the 1INinput for the LM358© comparator (an adjustment potentiometer could have been used). C4 acts as a filter, R5 controls the gain of the circuit and finally R0 limits the current of the LED that lights up if the set is powered. When there is no ambient sound, the SIG signal (GPIO32) is close to 2V and when the volume increases it drops to 0V (inverse logic), we must also take into account that the ADC of the ESP32© is 12 bits, 12 therefore it has 2 =4,096 levels that we will convert to voltage levels between 0 and +3.3V. The script converts the analog value generated by the LM358© comparator (0 to +3.3V) into digital values between 0 and 4,095 depending on the sound pressure applied to the sound sensor or microphone. 376

Electronics & MicroPython© with ESP32©: 80 complete projects

The digital value is displayed on the screen and on the Thonny© plotter. A minimum sound threshold is defined and when it is exceeded, the red LED is briefly activated. When the excess sound disappears, the green LED is activated. The green and red LED are managed by GPIO26 and GPIO27 respectively. In the script we import the usual machine and time libraries, configure the GPIO, adjust the ADC threshold to 0-3.3V and define the parameters. The adc_read() function reads the range 0-4,095 and converts it into volts in the range 0-3.3V and finally the main body of the script adjusts values to see them well on the Thonny© plotter and if the value exceeds a threshold it turns on the red LED. ############################ # E046_SOUND_SENSOR.PY: MAX-4466© microphone # INPUTS: ADC in GPIO32 between 0 to +3.3V # OUTPUTS: ADC read in volts GPIO27/26 LED ############################ from machine import Pin, ADC import time

# GPIO and ADC manager # Timing management

# ADC pin configuration pin_adc = 32 adc = ADC(Pin(pin_adc)) # Set the ADC range to 0-3.3V (default 0-1V) adc.atten(ADC.ATTN_11DB) # Configure the pins for the LED green_led = Pin(26, Pin.OUT) red_led = Pin(27, Pin.OUT) # Script parameters t_read = .0001 # Time between reading alarm = 2.2 # Alarm level # Performs analog reading from 0 to +3.3V # The ADC is 12 bits therefore 2^12=4,096 levels def adc_read(): adc_value = adc.read() # Level to volts conversion voltage = (adc_value / 4096) * 3.3 return voltage

377

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

# Script main body green_led.on() print('SOUND SENSOR MAX-4466©') print('Speak close to the microphone...') try: while True: value = adc_read() * 2 # Plotter view ok print('Sound: ', value) # Plotter trace if value < alarm: # Alarm level red_led.on() # Red LED on time.sleep(.01) red_led.off() time.sleep(t_read) # Between reading except KeyboardInterrupt: print('Script completed...') green_led.off() # LED off red_led.off() adc = None # ADC release

⊝⊝⊝ 378

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E239: Sound intensity and timing. Design a system that uses an analog sound sensor to measure the intensity of ambient sound every 5 minutes using an ESP32© hardware timer. Save the data of each measurement in a file for later analysis. •E240: LED, rotary decoder and sound. Connect a rotary decoder and LED to the ESP32©. Program the micro controller to change the LED intensity based on the sound intensity measured by the sound sensor and use the rotary decoder to adjust the system sensitivity. •E241: Audible presence alarm. Create an alarm system that activates when a sound above a predefined threshold is detected using the analog sound sensor. Use an additional presence sensor to deactivate the alarm when motion is no longer detected in the room. •E242: Ambient temperature and sound. Implement a system that measures room temperature using a thermistor and captures sound intensity. Records both sets of data and the internal RTC date and time. •E243: Laser activation based on sound. Create a system that turns on a laser when sound above a certain level is detected using the analog sound sensor. Use a hardware timer to turn off the laser 2 seconds later.

⊝⊝⊝

379

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 47: HC-SR04© Ultrasound Sensor In this exercise we will see one of the funniest and most interesting devices (sensor and receiver) in this book since it is widely used to measure distances (robots, toys, parking, access, etc.) with a very acceptable precision and using ultrasound as physical measurement element. The device used is the HC-SR04© module, or equivalent, which has an emitter and a 40kHz ultrasonic sensor. Ultrasounds travel in the air at a speed of 343.2meters/second, therefore, by sending that sound towards an object and calculating the time it takes to go and return, we can easily calculate the distance r between the ultrasonic emitter and object as follows:

distance(r)=speed∗time=

343,2 ∗100∗time 2

The distance r is in centimeters, the time is the total in seconds, from the emission to the reception of the sound and is divided by 2 as it is the round trip time from the sender to the receiver. 380

Electronics & MicroPython© with ESP32©: 80 complete projects

The connection of this device ESP32© is very simple since the already includes all the necessary elements and also the adaptation of

to the GPIO of the ultrasonic sensor electronic control logic levels.

Our example only needs, in this case, GPIO33 for the emitter [trig], GPIO32 for the receiver [echo], GND and a +3.3V power supply. The MicroPython© script will have a loop that will periodically send a certain ultrasound pulse, receive the echo of that pulse, calculate the elapsed time, do the calculations and present the distance in cm (change if is necessary) on the console, doing: 1. Set

the [trig] or GPIO33 signal to LOW for at least 0.2s to stabilize the ultrasound emitter. the [trig] signal to HIGH for 10 μ s (microseconds) and then lower it to LOW. When performing this operation, the HC-SR04© automatically sends 8 ultrasound pulses with a non-audible frequency of 40kHz and places the [echo] signal at HIGH, this is when we must start the response time countdown.

2. Raise

381

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

3. The output [echo] remains at HIGH until the echo

signal of the ultrasound sent and bounced off the object is received. At this moment it goes to LOW, which is when we must stop the elapsed time counting timer.

4. Knowing

the elapsed time (round trip between sensor and object to be measured) and the speed of sound in the environment of use of the HCSR04© sensor, we can calculate the distance r between the sensor and the object with sufficient precision.

In the script, the machine and time libraries are imported, the pins for [trig] (emitter) in GPIO33 and [echo] (receiver) in GPIO32 are defined, the speed of sound in air is considered, which, to be precise, will depend of temperature, ambient humidity and atmospheric pressure. It is specified that the [trig] pin is an output and that the [echo] pin is an input, the function distance_measure() is d e f i n ed , w h i c h b a s i c a ll y activates the HC-SR04© to emit the ultrasonic pulses and receive them, the time elapsed between these two events is recorded by the ESP32© which, with the corresponding calculations, transforms them into cm (centimeters) and presents them on the console. In the LA1010© logic analyzer, we observe the 10 μs pulse from LOW to HIGH on the [trig] pin, the transition to HIGH of the [echo] signal, which is when the HC-SR04© sensor sends the 8x40kHz pulses and the time it takes for these pulses to reach the obstacle, bounce back and be captured again by the HC-SR04© receiver and which has been marked on the analyzer between points A1 and A2. Taking into account the total time elapsed between the sending of the pulses and their reception and dividing it by two (round and return trip), in the example about 26.6ms and assuming a speed of sound in ambient air of 344.6m/s (depends on temperature, humidity, pressure, etc.), we will have a distance r between the HC-SR04© sensor and the obstacle of 4.58m. 382

Electronics & MicroPython© with ESP32©: 80 complete projects

############################ # E047_ULTRASOUND.PY: Ultrasonic measurement HC-SR04© # INPUTS: Speed of sound in air # OUTPUTS: Distance r, in centimeters ############################ from machine import Pin import time

# GPIO management # Timing control

# Output pins (trigger) and input (echo) echo = Pin(32, Pin.IN) # Arrival pulse trig = Pin(33, Pin.OUT) # Output pulse # Sound speed in air in m/s speed = 344.6 # Depending on temperature, humidity... # Measure the distance r def distance_measure(): trig.value(0) # time.sleep(.2) # trig.value(1) # time.sleep_us(10) trig.value(0)

with the HC-SR04© sensor Start the HC-SR04© Do not go below .2 seconds Sensor gives 8x40kHz pulses

383

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

while echo.value() == 0: pass start_pulse=time.ticks_us()

# Wait for echo = 1

while echo.value() == 1: pass end_pulse=time.ticks_us()

# Wait for echo = 0

# Start counter

# End counter

# Calculate the delay in microseconds delay = time.ticks_diff(end_pulse, start_pulse) # Calculate distance in centimeters (all trip) distance_centimeters = delay * speed / 2 / 10000 # Divide 1e6/100=1e4 to cm print (delay) print("Distance: {} centimeters".format (distance_centimeters)) # Main loop print('DISTANCE METER WITH HC-SR04©') print('Point the sensor at the object to be measured') try: while True: distance_measure() time.sleep(2) except KeyboardInterrupt: print('Completed...')

⊝⊝⊝

384

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E244: Distance measurement with LED indicator. Use an HC-SR04© to measure distances to an object, turning on a green LED if the distance is less than a predetermined threshold and a red LED if it is greater. The distances will be previously entered and validated by the console and the measurements will be carried out periodically using an ESP32© hardware timer. •E245: LED control proportional to distance. Measures the distance to an object using an HCSR04© sensor and adjusts the intensity of an LED proportionally to the measured distance using PWM. •E246: Distances and rotary encoder. Use an HC-SR04© to measure distances and use a rotary decoder to change the measurement scale presenting it in meters, inches, feet and yards. •E247: Generation of tones according to distance. Use an HC-SR04© sensor to measure the distance to an object and simultaneously generate an audible tone whose frequency is inversely proportional to the measured distance similar to a car parking distance meter. Use the DAC of the ESP32© to generate the tone. •E248: Distance, temperature and humidity. Use the distance meter and the DHT11© double sensor to measure feet, degrees and % humidity. Previously define a dictionary with various tuples containing various environments. If all the values contained in a tuple are exceeded, a red LED will light up following a certain algorithm.

⊝⊝⊝

385

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 48: GL5539© Photoresistor Sensor Just as the microphone detects sounds, the photoresistor, such as the GL5539© or similar, modifies its internal resistance inversely depending on the amount of visible light it receives, therefore we can build a light sensor and transform its analog output to digital and process it with the ADC of ESP32©. As with all other sensors, we need a control circuit to be able to take full advantage of the photoresistor and adapt its signals to the ADC converter. When visible light hits the photoresistor, that is, the sensor, its resistance decreases and when the light stops hitting, that resistance increases (through a non-linear law and dependent on the brand and model of the sensor). Therefore, in the GPIO32 we have a variable voltage between +3.3V and GND (approximately) that will generate a value between 4,095 and 0 in the ADC converter respectively. Resistor R1 limits the current that crosses the sensor and acts as a pull-up for the GPIO32 and R0 limits that of diode D0, which is activated by the circuit power supply. 386

Electronics & MicroPython© with ESP32©: 80 complete projects

Finally, with the GPIO26 and GPIO27 we will make the red and green LED blink (by software) respectively when the light detected by the photoresistor exceeds a threshold, that is, when the GPIO32 drops below a predefined level and they will remain fixed otherwise.

The script is similar to that of the sound sensor, the same libraries and the same structure are used, only changing the timing between readings and the alarm values, which we will adjust based on the voltage levels provided by the photoresistor. Likewise, to visualize data, we will use the plotter function available in the main menu of the Thonny© programming environment. ############################ # E048_PHOTORESISTOR.PY: GL5539© photoresistor and ADC # INPUTS ADC in GPIO32 between 0 to +3.3V # OUTPUTS: ADC in volts GPIO27/26 LED green/red ############################ from machine import Pin, ADC # GPIO and ADC manager import time # Timing management 387

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

# ADC pin configuration pin_adc = 32 adc = ADC(Pin(pin_adc)) # Set the ADC range to 0-3.3V (default 0-1V) adc.atten(ADC.ATTN_11DB) # Configure the pins for the LED green_led = Pin(26, Pin.OUT) red_led = Pin(27, Pin.OUT) # Script parameters t_read = .5 # Time between reading alarm = .6 # Alarm level # Performs analog reading from 0 to +3.3V # The ADC is 12 bits therefore 2^12=4,096 levels def adc_read(): adc_value = adc.read() # Level in volts voltage = (adc_value / 4096) * 3.3 return voltage # Script main body green_led.on() print('GL5539© PHOTORESISTOR') print('Lights up the photoresistor...') try: while True: value = adc_read() * 2 # Plotter display print('Light: ', value) # Plotter trace if value < alarm: # Alarm level red_led.on() # Red LED on time.sleep(.1) red_led.off() # Red LED off time.sleep(t_read) # Between reading except KeyboardInterrupt: print('Script completed...') green_led.off() # LED off red_led.off() adc = None # Release ADC

⊝⊝⊝ 388

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E249: Light intensity control with PWM. Connect a photoresistor to the ESP32© and an LED. Use the analog value of the photoresistor to control the brightness intensity of the LED using PWM. As the ambient light changes, the LED brightness will automatically adjust. •E250: Alarm, vibration and photoresistor. Design a security system using a vibration sensor and a photoresistor. When vibration is detected, the ESP32© should check the ambient light with the photoresistor. If it is dark (low visible light level), it will trigger an alarm using a buzzer or flashing a Dual LED. •E251: Infrared lights and ambient light. Set up a system that automatically adjusts the brightness of a series of infrared lights using a photoresistor. When the ambient light is low, the ESP32© will increase the intensity of the infrared lights, and vice versa. Use PWM for expansion. •E252: Servo, line detection and photoresistor. Use a servo motor and a line sensor to simulate a small follower robot. The photoresistor will detect ambient light and the ESP32© will adjust the speed or direction of the servo motor based on the light to follow a line on the ground. •E253: Analog signals, DAC and ambient light. Use the photoresistor to control a DAC. It generates an analog signal proportional to the ambient light intensity and generates an audible sound in a passive buzz. Record the data to a file along with the ESP32© RTC date and time.

⊝⊝⊝ 389

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 49: TIL-78© Fire Sensor A fire sensor or flame sensor basically consists of a device that detects the infrared radiation produced by combustion in the spectrum of 700-1,000nm. There are other similar sensors that also detect certain chemical substances. The one we are going to use in this exercise is a TIL-78© phototransistor or equivalent, which detects the infrared radiation produced by flames. Like all other sensors, the phototransistor also needs a control circuit based on the LM393© comparator amplifier that we have already seen in other exercises.

390

Electronics & MicroPython© with ESP32©: 80 complete projects

When hot light, causes it depending received.

infrared light, coming from a flame or a hits the base of the phototransistor Q1, it to conduct a certain amount of current, on the energy of that infrared light

This current is captured, on the one hand, by the GPIO32 input of the ADC converter, which will translate it to digital levels from 0 to 4,095, and on the other hand, by the 1IN+ input of the LM393©, which compares it with the 1IN- reference level ( a d j u s t a b l e w i t h t h e 10k Ω potentiometer), making the 1OUT (DO) output activate or not the GPIO35, which we will treat as an interruption in our program. Finally, GPIO26 and GPIO27 make the usual Dual LED blink. Resistors R2 and R3 act as a pull-up at +3.3V, R0 and R1 limit the current of diodes D0 and D1 respectively and C0, C1 and C2 filter any possible interference that may occur. In our script we will capture, on the one hand, the analog value (AO) of the phototransistor, translate it to digital in the ADC converter and display it on the console and on the plotter and on the other hand, when DO generates an interrupt in the ESP32© by the GPIO32, the program executes a function that flashes the LED several times. ############################ # E049_FIRE_SENSOR.PY: TIL-78© fire sensor with ADC # INPUTS: ADC In GPIO32 and DO (on/off) in GPIO35 # OUTPUTS: ADC read in volts and GPIO27/26 LED ############################ from machine import Pin, ADC import time

# GPIO and ADC control # Timing management

# ADC pin configuration pin_adc = 32 adc = ADC(Pin(pin_adc)) 391

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

# Set the ADC range to 0-3.3V (default 0-1V) adc.atten(ADC.ATTN_11DB) # Configure the pins for the LED and DO green_led = Pin(26, Pin.OUT) red_led = Pin(27, Pin.OUT) # DO with 10k pull-up pin_do = Pin(35, Pin.IN, Pin.PULL_UP) # Script parameters t_read = .5 # Time between reading t_blink = .1 # Blink time # Performs analog reading from 0 to +3.3V # The ADC is 12 bits therefore 2^12=4,096 levels def adc_read(): adc_value = adc.read() # Voltage to level voltage = (adc_value / 4096) * 3.3 return voltage # Blink red LED def blink(_): # Add an argument for _ in range(2): # 2 repetitions red_led.on() time.sleep(t_blink) red_led.off() time.sleep(t_blink) # Fire interruption, activated at LOW # that calls the blink() function pin_do.irq(trigger=Pin.IRQ_FALLING, handler=blink) # Script main body print('TIL-78© FIRE SENSOR') print('Approach a flame to the sensor...') try: while True: value = adc_read() * 2 # Plotter display print('Flame: ', value) # Plotter trace time.sleep(t_read) # Between reading except KeyboardInterrupt: print('Script completed...') green_led.off() # LED off red_led.off() adc = None # Release ADC

⊝⊝⊝ 392

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E254: Fire alarm, sensor and timer. Create a fire detection system that uses a flame sensor. When a flame is detected, it activates an audible or visual alarm for a period of time specified by a timer. •E255: Lighting control, distance sensor. Design an intelligent outdoor lighting system that is activated by a relay when detecting flames and adjusts its intensity using a photoresistor. In addition, use an ultrasonic distance sensor to modify the intensity of the light according to the proximity of nearby people and controlled by certain algorithm. •E256: System shutdown with Hall and flames. Implement a security system to automatically turn off electrical devices, connected to a relay, in case of flame detection. Use a Hall switch to detect if a door is open and disables the devices if flames are detected while the door is open. •E257: Internal temperature and flame sensor. Create a security system that measures the temperature of the ESP32© and the presence of flames. If the internal temperature exceeds a threshold or flames are detected, send a notification via email. •E258: Fire extinguishing and flame sensor. Design a simulated fire suppression system that uses an ultrasonic meter to determine the proximity of a possible burning moving object. When the object is at a dangerous distance and the flame sensor indicates fire, automatically activate a sprinkler system or a simulated fire extinguisher.

⊝⊝⊝ 393

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 50: MQ-2© Gas and Smoke Sensor A gas and smoke detector is a sensor that consists of semiconductors sensitive to a certain amount and type of gas that varies its resistance, so that if we transform this analog effect into digital we will observe how its values rise as a greater amount of gas is detected. In this exercise we will use the MQ-2© sensor or a similar one that detects: liquefied petroleum gas, smoke, alcohol vapor, propane, hydrogen, methane and carbon monoxide. This sensor has an approximate consumption of 1w, therefore, it must be taken into account when powering it that we must do it with an external power source and never directly with the ESP32©, in addition this gas and smoke sensor needs to reach a certain operating temperature and reaches its optimal state after about 24 hours, however a few minutes are enough to test it in this exercise. The MQ-2© sensor requires an activation and amplification circuit similar to those already seen with the LM393© famous comparator. When the MQ-2© sensor detects any type of gas already mentioned, it varies the analog signal AO that attacks the ADC of the ESP32© through the GPIO32. 394

Electronics & MicroPython© with ESP32©: 80 complete projects

The LM393© amplifier compares this AO signal with a threshold set by the variable resistor RS (which serves us as a calibration element), so that the 1OUT or DO output is activated at LOW when the gas is detected and the set threshold is exceeded. The DO output acts with GPIO35, which is treated in the script by interruption, initiating the alarm process for detected gas. D0 lights up when the circuit is powered and D2 when gas is detected. Resistors R0 and R2 limit the current through the LED, R3 is a pull-down to GND and C1 filters interference and micro variations in DO output. The script is the same as that of the fire sensor, it presents the level of gas or smoke detected on the Thonny© console and plotter and when GPIO35 detects the interruption alarm, it launches a function that makes the Dual LED blink, presenting the alarm in console and activates an intermittent acoustic signal.

⊝⊝⊝

395

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 51: SKU-500© Rain Sensor A rain sensor, for example the SKU-500© or similar, is an electronic device that consists of two elements, the sensor element itself that detects the presence of humidity in water droplets, by electrical conductivity, light reflection, volume meter, etc. and a control element that adapts the signal generated by the sensor to the appropriate electrical levels and that generates an analog signal proportional to the detected humidity and a digital, on/off type, that indicates the presence of rain. In our case we will use a sensor that has a plate with very close tracks that when wet conduct a small current and an el ec tr on ic c on tr ol e le me nt based on the LM393© chip that includes two operational amplifiers comparators and we will only use one. The LM393© operational amplifier compares the signal from the sensor with a reference value adjustable by a potentiometer, amplifies the comparison and extracts the two analog AO and digital DO outputs already mentioned. 396

Electronics & MicroPython© with ESP32©: 80 complete projects

The AO analog output coming directly from the sensor and which is not very precise, we will connect it to the GPIO32 and process it with the ADC converter and with the help of the ESP32©, we will be able to see on the console and on the plotter a measurement of the volume of rain or humidity that affects the sensor. We can use the DO digital output as an on/off alarm by connecting it directly to the GPIO35 and treating it by IRQ. For the proper functioning of the LM393© comparator we also need a series of basic components so that the complete circuit would be like the previous one and with the following operation: The rain sensor sends the analog signal AO to one of the inputs (1IN+) of the LM393© comparator, the other input (1IN-) comes from the midpoint of the potentiometer R3 which acts as an manually adjustable reference value. The output (1OUT) of the comparator acts as a rain detection on/off signal DO and is captured by the GPIO35 and processed by the MicroPython© script. Additionally, the analog signal AO is connected to GPIO32, which will be processed by the ADC of the ESP32©. 397

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

R5+D1 and C2 act and R2 are is detected

indicate when the circuit is powered, C1 as filters for possible interference. R1 pull-up and R4+D2 are activated when rain and the DO output goes to GND.

With the rain sensor dry, we adjust the potentiometer R3 until LED D2 turns off, this indicates that the digital output DO is at HIGH, without detecting rain, since 1IN- is less than 1IN+. When the sensor gets wet, 1IN+ is less than 1IN- and therefore the digital output DO is activated, illuminating LED D2 and activating GPIO35 on the Raspberry© (reverse logic). We can use the same script as the one used in the smoke sensor and the fire sensor with some small adjustments to the texts and variables.

⊝⊝⊝ 398

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E259: Fire alarm with sensor and relay. Use a fire sensor with digital output to detect the presence of fire. When fire is detected, activate a relay to activate an audible alarm with active buzz and a visual alarm with an array of LED. •E260: Smoke, temperature with DHT11 and RGB LED. Create a system that uses a smoke sensor and a DHT11© to monitor both the presence of smoke and the ambient humidity and temperature. Use an RGB LED with PWM to visually indicate the current situation: green for normal conditions, yellow for warning and red for smoke alarm. •E261: Irrigation, water sensor and relay. Build an automatic plant watering system that uses a water sensor with digital output to detect low levels of moisture in the soil. When potting soil dryness is detected, activate a relay to turn on a water pump and water the plants. Simulate what is necessary and save events to a file also using the RTC of the ESP32© •E262: Emergency, rain, fire and LED array lights. Create an emergency lighting system for fire and rain situations. Use a fire and a rain sensor with digital output to detect fire and/or rain to activate an array of LED and a servo according to an algorithm. •E263: Remote alarm control with IR command. Design an alarm system that can be activated and deactivated remotely using an IR infrared remote control. The system should include fire, smoke and rain/water sensors to detect different types of emergencies and activate the alarm as necessary.

⊝⊝⊝ 399

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 52: Scan I2C Bus In future exercises we are going to use very interesting devices that need a fast, efficient and easy to manage communication protocol. One of these protocols that is implemented in the ESP32© is the I2C (Inter-Integrated Circuit) bus and is characterized by the following: •

Master/slave: The ESP32© functions as both master and slave on this bus. As a master, it can control multiple slave devices, this mode is what we will use in this book to get the ESP32© to manage multiple elements. As a slave, it can respond to commands sent by another master device like another ESP32© (not very efficient).



Topology: The I2C bus is a bidirectional serial communication bus that uses only two signal lines: SDA (Serial Data Line) and SCL (Serial Clock Line). SDA is used for data transfer between master and slave. Data is transmitted sequentially in 8-bit packets. Both, master and slave devices, can send and receive data through this line. SCL (Serial Clock Line) is used always to synchronize data transfer on the bus. The master generates clock pulses on this line to indicate when the data on the SDA line is ready to be read or written.



400

Adjustable baud rates: The ESP32© supports baud rates up to 400kHz in Standard mode and up to 1MHz in Fast mode.

Electronics & MicroPython© with ESP32©: 80 complete projects



Multi Master Support: The I2C bus on the ESP32© can support multiple master devices connected simultaneously, allowing for greater flexibility in network configuration. We will not use this configuration here.



Configurable Pins: Several but not all GPIO pins of the ESP32© can be easy configured as SCL (clock) and SDA (data) pins to connect I2C devices.



Support for standard I2C devices: The ESP32© I2C bus is compatible with a wide variety of standard I2C devices available on the market. See the following table whit several examples of I2C interesting devices.



Device detection capability: The ESP32© has the ability to scan the I2C bus to detect connected devices and their addresses.

We will start with this last point, that is, we will make a script that will help us detect the devices connected to the I2C bus by analyzing all the possibilities of 7-bit addresses (0 to 128 or 0x08 to 0x77), which, in the in most cases, they are either defined by the device manufacturer or are selectable, within a range, using a jumper or switch. The MicroPython© script imports the Pin, SoftI2C and time libraries for managing the GPIO, I2C bus and time management. Assigns GPIO21 for the SDA pin and GPIO22 for the SCL pin of the I2C bus and activates the i2c instance where these GPIO are specified. The function scan_i2c() is created that tries to write to an empty buffer of a certain address of the I2C bus. If this writing does not give an error, it means that this address exists, otherwise it jumps to the next one, going through all the possible 7-bit addresses. Finally, the script stops if + pressed or all addresses have been traversed.

is

401

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

############################ # E052_SCAN_I2C.PY: I2C bus scan # INPUTS: SDA GPIO21 and SCL GPIO22 # OUTPUTS: I2C devices found ############################ from machine import Pin, SoftI2C # Pin, I2C management import time # Timing control #GPIO SDA sda_pin = scl_pin = zero =

and SCL of ESP32© 21 # Adjust according to hardware 22 # Adjust according to hardware True # Control flag

# SoftI2C objet configuration i2c = SoftI2C(sda=Pin(sda_pin), scl=Pin(scl_pin)) # Searches all possible I2C addresses (7bits) def scan_i2c(): global zero for i in range(128): time.sleep(0.05)# Pause between samples try: # Try current address i2c.writeto(i, b'') print("Device found on: 0x{:02X}".format(i)) zero = False except OSError: print('.', end='') pass print('\nScan completed....') # Script main body print('I2C BUS SCANNING...') try: scan_i2c() except KeyboardInterrupt: if zero: print('No I2C device found...') print('Scan completed...') Also try: print(i2c.scan()), what happened?. There are I2C devices of all types on market, here I discuss some interesting examples: 402

the

Electronics & MicroPython© with ESP32©: 80 complete projects

Device

Description

LCD1602©

Display LCD 16x2

PCF8574©

GPIO extender

ADS1115©

External ADC with 4x16bit modules

PCA9685PW© Controller with 16 PWM outputs MCP23017©

Expander with 16 inputs/outputs

BME280©

Temperature, humidity and pressure sensor

SI5351A©

External RTC

INA219©

Power consumption monitor

VL530X©

Laser distance meter

CCS811©

CO gas and organic compounds sensor

TCA9548A©

8-port I2C bus multiplexer

GY-271©

Digital compass

DHT20©

Humidity and temperature sensor

ADXL345©

Accelerometer

MPU6050©

Gyroscope

SH1106©

OLED 128x64 display

⊝⊝⊝

403

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 53: BMP280© Barometric Sensor In this exercise we will use a barometric pressure sensor widely used in smartphones and smartwatches such as the BMP280© or equivalent. It is a high-precision, lowcost, low-consumption barometric pressure and temperature sensor and since barometric pressure varies with altitude, it can also be used as an altimeter (from -500m to +9,000m). The BMP280© sensor requires, if is possible, a high precision +3.3V voltage regulator and 10k Ω pull-ups to stabilize I2C communication. To facilitate the exercise we will use the HW-611© module that includes the BMP280© chip, the pull-up resistors, some capacitors that act as filters and the connection pins: VCC (+3.3V), GND, I2C (SCL and SDA) and two SPI bus pins (CSB and SDO) that we will not use in this exercise since we are only going to use the I2C bus. Among the basic characteristics of the BMP280© precision barometer we can highlight the following: 404

Electronics & MicroPython© with ESP32©: 80 complete projects

1. Pressure and Temperature: The BMP280© is a high-

2.

3.

4.

5. 6.

7.

8.

precision digital sensor that measures both atmospheric pressure and ambient temperature. The BME280© also measures humidity. Communication: It can communicate with the micro controller through a standard I2C interface or an SPI interface as we have seen. The I2C address of the BMP280© is usually 0x76 at the factory. Pressure Range: It has a wide atmospheric pressure measurement range, from 0.2966 to 1.0851 atmospheres. Precision and Resolution: It offers high precision in measuring atmospheric pressure, with an accuracy of up to ±1 hPa. Temperature Range: It can measure temperature in the range of -40°C to +85°C. Power Consumption: It has low power consumption, making it suitable for applications that operate with limited power sources or batteries. Compact Size: The BMP280© is very compact and easy to integrate into electronic projects and embedded systems. Altitude Variations: Offers compensation for altitude variations, making it useful in applications such as drone navigation and digital altimeters.

For our MicroPython© script we will connect the BME280© sensor to the I2C bus, that is, to the SCL and SDA pins and we will use the BME280.py library that we will download from the Web and upload to the ESP32© through the Thonny© main menu. To use the I2C bus we will connect the SCL pin to GPIO22 and the SDA pin to GPIO21 and thus include them in the definition of the i2c instance. We refer to the BME280 class included in the BME280.py library that must be loaded into the ESP32© memory. Finally, in a loop we will read the temperature that it will give us in ºC and the pressure that it will provide in hPa (hecto Pascals) and we will change it to mBar (milli Bars). The equivalence between hecto Pascals and milli Bars is 1hPa=1mBar=0.0145psi. 405

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

############################ # E053_BAROMETER.PY: BMP280© barometer # INPUTS: Sensor data # OUTPUTS: Temperature in ºC and Pressure in mBar ############################ from machine import Pin, SoftI2C # GPIO & I2C manager import time # Timing control try: import BME280 # BMP280© library except: print('Load the BME280© library into the ESP32©') # GPIO mapping for i2c i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=10000) # Main loop of the script print('BMP280© SENSOR CONTROL') print('Approach object to measure temperature...') try: bme = BME280.BME280(i2c=i2c) while True: temp = bme.temperature #hum = bme.humidity # For BME280© pres = bme.pressure[:-3]+'mBar' # hPa to mBar print(f'Temperature: {temp[:-1]}ºC ', end='') #print(f'Humidity: {hum}') # For BME280© print(f'Pressure: {pres}') time.sleep(2) except KeyboardInterrupt: print('Script Completed') except: print('I2C bus error')

406

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E264: Barometer sensor and LED. Add a dual LED to the previous exercise. The green LED should turn on when the script starts and the barometer is detected on the I2C bus, scanning the range 0x70 to 0x77. Use, for example, the i2c.scan() MicroPython© internal function. The red LED will turn on when a previously defined temperature threshold is exceeded. This alarm can be canceled with a button IRQ control. •E265: Water level control. Use an ultrasonic sensor to measure the water level in a tank. Use the BMP280© to offset ultrasonic sensor readings based on current atmospheric pressure by adjusting a sound speed table. Use a relay to simulate filling water if the tank is empty. •E266: Climate control system. Use the BMP280© to measure temperature and atmospheric pressure. Design an algorithm that adjusts the temperature in a room using a simulated heating system with an LED connected to the DAC. •E267: Infrared remote control. Implement an infrared remote control using an infrared remote device and an IR receiver. Use the BMP280© to monitor ambient temperature and barometric pressure. Program several buttons on the IR remote to display the temperature in ºC and ºF, the pressure in mBar, mmHg and psi, the updated time of the RTC, the internal temperature of the ESP32©, the IP of the WiFi connection and the value of a connected ADC to a reference potentiometer.

⊝⊝⊝

407

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 54: YB-GS07381© Water Pressure Sensor This sensor, YB-GS07381©, consists of a liquid pressure detector (admits water, oil, diesel and natural gas) that is embedded in a G1/4” size stainless steel metal thread that we can connect, with some adapter, to our sanitary installation. With this sensor we will be able to see if the pressure of the sanitary water in our home exceeds minimum and maximum limits and the system will notify us if they are exceeded, being able to cut off the supply with an electro valve. There are several models of this sensor depending on the maximum pressure that we want to control, so for example, for a normal home we can use the 0-100psi (pounds per square inch) version which is equivalent to about 0-7.14bar and which adapts to the average pressure of a home, which is usually between 3 and 5bars or 43 to 73psi. The sensor has an output cable with 3 wires: +5V (red), GND (black) and data (green or blue). This data signal is analog and varies between 0.5V-4.5V, which we will have to convert into digital (levels from 0 to 4,095) using the ADC converter of the ESP32©, therefore the sensor and converter assembly cannot be very far from the micro controller. As we see, the output of this sensor exceeds +3.3V, therefore, we must use a voltage adapter such as a voltage divider similar to the following. 408

Electronics & MicroPython© with ESP32©: 80 complete projects

To convert the output of the water pressure sensor (0.5V-4.5V) to the ADC of the ESP32© (0V-3.3V) we can use a voltage divider built with two resistors, for example one 10k Ω connected between the GPIO of the ADC and the pressure sensor output (VCC) and another 20k Ω connected between the GPIO of the ADC and GND. Do the corresponding calculations to confirm it. If the distance between the pressure sensor and the ESP32© is insurmountable, we can use a second ESP32© close to the main one (the cost is low) and share information through file sharing via WiFi. In the script we import the Pin and ADC libraries to control the LED and the ADC that we connect to the GPIO34 and that we configure to accept 0-3.3V input values. We define GPIO26 and GPIO27 for the green and red LED respectively. We will use green for normal operation and red for when there is excess pressure that we set, for example, at 5bars. We define the function adc_read() that reads the value of the analog-digital converter or ADC (measurement range: 0-4,095) and converts it into pressure (measurement range: 0-7.14bars) which we format to 2 decimal places. In the main loop of the program we read the ADC in a loop and present either the normal value or the alarm value if a certain maximum is exceeded. In parallel, we use the LED as a visual trace to follow the state of the sensor. Finally we can stop the script with +. ############################ # E054_WATER_PRESSURE.PY: Water pressure sensor & ADC # INPUTS: ADC in GPIO34 between 0 to +3.3V # OUTPUTS: ADC in bars GPIO27/26 LED green/red ############################ from machine import Pin, ADC # LED & ADC control import time # Timing management 409

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

# ADC pin configuration adc = ADC(Pin(34)) # Set the ADC range to 0-3.3V (default 0-1V) adc.atten(ADC.ATTN_11DB) # Configure the pins for the LED green_led = Pin(26, Pin.OUT) red_led = Pin(27, Pin.OUT) # Parameters wait = .5 p_alarm = 5

# Wait between reading # Alarm pressure

# Analog reading from 0 to +3.3V and controls the LED # Voltage divider converts (0 to +5V) to (0 to +3.3V) # The ADC is 12 bits therefore 2^12=4,096 levels # Water pressure range: 0-7.14bars def adc_read(): adc_value = adc.read() pressure = round((adc_value / 4096) * 7.14, 2) return pressure # Script main body print('YB-GS07381© WATER PRESSURE SENSOR') print('Try turning on and off a water faucet...') try: while True: value = adc_read() # Control LED according to input threshold if value > p_alarm: # Alarm pressure print('ATTENTION: excessive pressure') green_led.off() # Green LED off red_led.on() # Red LED on else: red_led.off() # Red LED off green_led.on() # Green LED on print(f'Water pressure: {value}bars') time.sleep(wait) # Space between readings except KeyboardInterrupt: print('\nClose reading.') green_led.off() # LED off red_led.off() 410

Electronics & MicroPython© with ESP32©: 80 complete projects

The complete circuit with the water pressure sensor, voltage divider, start and alarm display LED and the ESP32© is similar to the following:

Calculate how many watts the voltage divider consumes assuming that the input current to the ESP32© ADC is neg li gi bl e. W e c an ad d a relay, connected to a GPIO that activates an electro val ve to cl os e t he wat er supply if necessary.

⊝⊝⊝

411

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E268: Water pressure monitoring. Uses the pressure sensor to measure domestic water pressure and displays the real-time values on the ESP32© Web server along with the appropriately updated RTC date and time. •E269: RGB lighting according to water pressure. Connect an RGB LED to the ESP32© and use the water pressure sensor to adjust the LED color using PWM and a predefined color table. •E270: Servo based on water pressure. Connect a servo motor to the ESP32© and use the pressure sensor to control the position of the servo. Define pressure ranges for different servo positions and have the servo move based on the pressure, simulating the opening or closing of the valve. •E271: Archived and plotted pressure data. Configure the ESP32© to record domestic water pressure data to a file at regular intervals. Activate the Thonny© plotter to display a graph based on the pressure values. •E272: DHT11© double sensor and BMP280© barometer. Combine the domestic water pressure sensor with a temperature and humidity sensor (such as the DHT11©) and create a complete environmental monitoring system. The data from both sensors must be read, together with the RTC date and time, and recorded cyclically in a file on the ESP32©.

⊝⊝⊝

412

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 55: GY-271© Magnetic Sensor In this exercise we will use the GY-271© magnetic sensor incorporated into the HW-246© module, which is a device that allows detecting magnetic fields in three axes (X: up vs down, Y: left vs right and Z: back vs forward) in the space. This sensor is also known as three-axis electronic compass or three-axis magnetometer, which uses the HMC5883L© chip or equivalent which is a high-precision, lowpower consumption three-axis magnetometer sensor. The GY-271© sensor can be used for various applications, such as navigation, positioning, orientation detection, metal detection, measurement of magnetic fields in industrial environments, etc. The GY-271© sensor provides magnetic field data in the form of digital values, which can be read and processed by a micro controller, such as the ESP32©, through a I2C communication protocol. These digital values represent the strength of the magnetic field in each of the three axes (X, Y, Z), allowing the relative orientation of the sensor to be determined with respect to the Earth's magnetic field or other surrounding magnetic fields. Connect it as follows: 413

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

We will use the scan_i2c.py script already seen to know the I2C address that the manufacturer has assigned to the GY-271© sensor and we will be able to verify that it is the hexadecimal address 0x1E. To know the address of the sensor on the I2C bus we can also use the i2c.scan() MicroPython© instruction, which returns the decimal address of the I2C devices connected to the bus. Once the address of the sensor on the I2C bus is known, the script uses the hmc5883l library that we must download from the Web and install it in the ESP32© memory. We will invoke the HMC5883L class of that library, specifying the GPIO of the SDA pins in GPIO21 and SCL in GPIO22. We could also use the DRDY interrupt signal which is set to HIGH when there is new data in the sensor. With this class, we can obtain the following parameters: •

X, Y, Z: These values represent the magnetic field strength in the X, Y and Z axes which are arranged horizontally in the plane of the surface and vertically up or down. This data makes it possible to detect nearby magnetic objects or for navigation.



Heading: The "heading" or direction calculated by the sensor represents the orientation of the magnetic field in relation to the north-south axis, in other words, it indicates where the X axis of the sensor is pointing in terms of the North direction. This value is usually expressed in degrees or radians, where 0 degrees or 0 radians generally represents the magnetic north. Heading can be used to implement an electronic compass that indicates the direction in which the device is pointing.

414

Electronics & MicroPython© with ESP32©: 80 complete projects

If we connect, by example, the LA1010© analyzer to the I2C bus we will see the exchange of information with the ESP32© through the SDA pin and the clock signals in SCL.

############################ # E055_MAGNETIC_SENSOR.PY: GY-271© magnetic sensor # INPUTS: SDA GPIO21 and SCL GPIO22 # OUTPUTS: Relative orientation X, Y, Z ############################ from machine import Pin, SoftI2C # GPIO and I2C from hmc5883l import HMC5883L # Sensor control from time import sleep # Timing management # Configure I2C and sensor class i2c = SoftI2C( sda=Pin(21), scl=Pin(22)) sensor = HMC5883L(sda=Pin(21), scl=Pin(22)) # Scan devices on I2C bus def scan(): print('Scanning I2C bus...') devices = i2c.scan() # Devices list if len(devices) == 0: print('No devices found') else: print('Sensor found on: ', end='') for dis in devices: print(hex(dis)) # Hexadecimal address 415

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

# Script main body print('GY-271© MAGNETIC SENSOR') print('Rotate the sensor in all 3 axes...') scan() # Sensor address try: while True: x, y, z = sensor.read() # Field intensity # Values formatted with 1 decimal print(f'X: {x:.1f}, Y: {y:.1f}, Z: {z:.1f}', end=' ') guide = sensor.heading(x,y) # Values formatted with 2 decimals print(f"Guide: {guide[0]:.2f}º {guide[1]:.2f}'") sleep(1) except KeyboardInterrupt: print('Script completed...') except: print('Sensor error...')

⊝⊝⊝ 416

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises •E273: Magnetic orientation measurement. Use the GY-271© sensor to measure magnetic orientation and view the data on a Web server. Users could access the server from their devices to view real-time guidance. Use HTML code to view data. •E274: Control of a relay with compass. Use the guidance provided by the GY-271© sensor to control a relay. Activate the relay when the orientation points approximately South and deactivate it when it points approximately North. Connect a servo whose rotation simulates a compass. •E275: Compass, rain sensor and barometer. Combine the GY-271© sensor with a rain sensor and the BMP280© barometer to create a weather monitoring system. Use the rain sensor to detect humidity and the barometer to measure atmospheric pressure. Save all data to a file. •E276: Sound and compass sensor. Use the GY-271© sensor together with a sound sensor to detect loud sounds. Set the system to issue an alert when the sound level exceeds a threshold and the magnetic orientation is within a predefined threshold. •E277: Orientation control for a vehicle. Implement an orientation control system for a possible vehicle using the GY-271© sensor and a line follower. For example, we could simulate a vehicle that can move in a specific direction based on the magnetic orientation detected by the sensor and/or following a line.

⊝⊝⊝ 417

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercises 56: OV7670© Camera Sensor In this exercise we will connect the OV7670© camera to the ESP32©, which, even though it is a camera with complex connections (proprietary I2C, parallel data bus and control signals), has the great advantage of being an ultracheap camera that can be used to capture still images and low-resolution videos. The basic characteristics of this camera can be summarized as: • • • •

• • • 418

OV7670© Sensor: Small size OmmiVisión© sensor, +3.3V power supply, VGA format. Connection: SCCB control bus compatible with I2C and 8-bit parallel bus to obtain the frame, sampling, format and resolution. Image: VGA 640x480 up to 30 frames/second, configurable image quality and transmission. Processing: Gamma curves, white balance, saturation, chroma, image stabilization, noise removal, automatic black level calibration, color control, saturation, hue, gamma, sharpness, etc. Formats: RawRGB to RGB (GRB4: 2:2, RGB565/ 555/444), YUV (4:2:2) and YCbCr (4:2:2). Resolution matrix 640X480 pixels. Power: +3.3V and consumption 60mW at 15fps and only 20uA in idle state. Optics: 1/6”, 25º angle, 30fps, 46dB.

Electronics & MicroPython© with ESP32©: 80 complete projects

The camera requires the SCCB bus, a proprietary version of the I2C bus but not 100% compatible, for configuration and control, the 8-bit parallel bus (D0...D7) for data transfer between the camera and ESP32© and other pins. (VS, HS, PCLK, MCLK, RST and PWNN) for camera hardware control. The SDA and SCL pins must have +3.3V 10k Ω pull-up resistors to stabilize the signals and make them reliable. These resistors are not included (*). Important: Due to the complexity of the necessary MicroPython© script and the absence of libraries for this specific device (there are for Arduino©), this exercise only describes the camera and its possible connection to the ESP32©. We will use the connections: VSYNC (Vertical Sync): Start and end of a frame in the video signal. HSYNC (Horizontal Sync): Start and end of each line of pixels in the video signal. PCLK (Pixel Clock): Each pulse of this clock indicates a new pixel available to be read. MCLK (Master Clock): Clock for the internal operation of the camera, video signal generation and image processing. RST (Reset): Useful to initialize the camera before starting image capture. PWDN (Power Down): Puts the camera into a low power state or to turn it off completely. 419

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Important: For the correct operation of the camera, the external master clock MCLK must have a typical frequency of 20MHz that we could generate with an ESP32© GPIO configured for PWM but it is too high a frequency for this micro controller. With a 4.7MHz signal we can obtain acceptable but unreliable data over time. As we can see, this exercise is a bit “cumbersome” because of having to connect so many cables and because of the difficulty of finding a simple MicroPython© library developed and tested for this camera. A small script is attached where communication with the camera is achieved to read and write to its registers using I2C, but synchronization with the horizontal and vertical signals does not seem feasible with a MicroPython© script running on an ESP32©. ############################ # E056_CAMERA.PY: OV7670© camera (test only) # INPUTS: SCCB (I2C) proprietary bus # OUTPUTS: Addresses, registers ############################ from machine import Pin,SoftI2C,PWM from time import sleep # GPIO sda = scl = mclk = dire =

of the 21 22 32 0x21

# GPIO, I2C, PWM # Timing control

camera # SCCB SDA I2C data # SCCB SCL I2C clock # MCLK Master clock # Camera address

# PWM on MCLK, essential for its operation pwm_pin = PWM(Pin(mclk), freq=4700000) # Not down # I2C communication (*) i2c = SoftI2C(sda=Pin(sda), scl=Pin(scl)) # Scan available I2C addresses def detect(): try: i2c.writeto(dire, b'') 420

Electronics & MicroPython© with ESP32©: 80 complete projects

print(f'Camera connected on: {hex(dire)}') except: print('Camera not detected...') # Read a register def read_register(register): i2c.writeto(dire, bytearray([register])) response = i2c.readfrom(dire, 1) # Read one byte print(f'Command: {hex(register)} -> {hex(response[0])}') # Writes the data to the register and reads it def write_register(register, data): i2c.writeto_mem(dire, register, bytearray([data])) read_register(register) # Main program try: detect() sleep(.1) read_register(0x0A) read_register(0x0B) read_register(0x1C) read_register(0x1D) write_register(0x55, 0x00) write_register(0x56, 0x40) except: print('Error in camera...') finally: pwm_pin.deinit()

# # # # # #

Product ID MSB Product ID LSB Brand ID MSB Brand ID LSB Bright to 0 Contrast to 40

# Stop MCLK

⊝⊝⊝

421

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 57: COM90133P© Joystick I think it is not necessary to explain what a Joystick is because we have all used it at some point (game consoles, remote-controlled toys, drones, etc.) but they are also used in industry (excavators, elevators, airplanes, medicine, etc.)

In its basic and totally analog version, like the COM90133P©, it is made up of a package that c o n t a i n s t w o 10k Ω potentiometers (variable resistors) located at 90º and that measure the position of a control on two axes: X (RVX) and Y (VRY ) and one or more pushbuttons (SW on the Z axis) that are activated by pressure. This Joystick must also be connected to +3.3V and GND. A specific position of the Joystick is a specific combination of the X, Y and Z values, therefore, by translating the ohm or voltage values into position values with an ADC, we will know at all times how that Joystick is located. 422

Electronics & MicroPython© with ESP32©: 80 complete projects

In this exercise we will connect the Joystick to the ESP32© ADC analog-digital converter that will convert the analog variables X, Y to digital variables (between 0 and 4,095) that we can use to act with any other type of device. We will connect the output of the SW button to the GPIO14 of the ESP32©, which we will manage by polling. For its correct operation, the Joystick requires a very simple and easy to understand control circuit. The signal from the SW button has a pull-up to +3.3V to stabilize it, so that when we press the SW button it is set to LOW and D1 lights up. We will detect this change by polling. D0 lights up when powering the Joystick circuit. R0 and R1 l i m i t t h e c ur r e n t flowing through LED D0 and D1. The X, Y signals go from the Joystick to the ADC analog digital converter directly into GPIO32 and GPIO35 respectively. In the script we will use the Thonny© “plotter” function to display the variables limits, we have to use the adc.atten(ADC.ATTN_11DB) instruction to enable these limits since, by default, the ADC measurement is limited to the 0-1V range. On the other hand, let us remember that the ADC of the ESP32© is 12bit and therefore it will give us 12 2 =4,096 values, from 0 to 4,095, with the rest position of the joystick being at (2048,2048) theoretically, in practice this is not the case because the qualities of the Joystick, ADC, power supply, etc.

423

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

The script imports the Pin, ADC and utime libraries, defines the configuration of the X axis in GPIO32, Y axis in GPIO35 and the selection switch, SW, in GPIO14. Specify the function read_joystick(pin), which will read the corresponding pin, adjust the reading value to +3.3V maximum and return the reading. The main loop reads X and Y in the DAC and the switch directly in the GPIO14 by polling and presents these values in a formatted way. To view the joystick values graphically, we can use the plotter built into Thonny© by accessing it from: [menu] [view plotter].

############################ # E057_JOYSTICK.PY: Read values X, Y, SW of Joystick # INPUTS: Joystick position # OUTPUTS: Plotter X, Y values ############################ 424

Electronics & MicroPython© with ESP32©: 80 complete projects

from machine import Pin, ADC import utime

# GPIO and ADC control # Timing management

# Pins configuration pin_x = Pin(32, Pin.IN) pin_y = Pin(35, Pin.IN) pin_s = Pin(14, Pin.IN)

# X position # Y position # Pushbutton on/off

# Joystick initial position x_init = y_init = 2048 s_init = 0

# Medium point # SW not pressed

# Read analog value from Joystick def read_joystick(pin): adc = ADC(pin) # Activate ADC in pin adc.atten(ADC.ATTN_11DB) # Range 0 to 3.3V return adc.read() # ADC reading # Script main body print('JOYSTICK CONTROL') print('Move and/or press the controller...') try: while True: value_x = read_joystick(pin_x) # X position value_y = read_joystick(pin_y) # Y position value_s = pin_s.value() # SW pressed # View X, Y, S values if they change if value_x != x_init or value_y != y_init or value_s != s_init: print("X:", value_x, "Y:", value_y, "Switch:", value_s) x_init = value_x y_init = value_y s_init = value_s utime.sleep_ms(50) # Wait between reading except KeyboardInterrupt: print('Program completed...')

⊝⊝⊝ 425

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E278: Joystick and RGB LED. Combines the reading of a joystick and the color variation of an RGB using the X and Y variables for the color change by PWM and the joystick switch to turn off the RGB completely. Also use the plotter. •E279: Joystick and ultrasonic meter. Implement a script in MicroPython© that reads the Joystick values (X and Y axis) and displays the position on the ESP32© console. Combine this with the reading from an ultrasonic meter to display the distance measured when the joystick switch is pressed. Defines a calculation algorithm with the X and Y positions and the distance to simulate a right or left turn with a two-color LED. •E280: Analog signal generation with DAC. Create a script that uses the ESP32© digital-toanalog converter, DAC, to generate an analog signal. Control the amplitude and frequency of the signal using the Joystick connected to the ESP32© to dynamically change its output. We can view the signal generated on the plotter. •E281: Timer and Joystick with LED. Design a script that uses a hardware timer to control an LED. Use the joystick to adjust the LED flashing frequency. Experiment with different timing intervals to achieve various visual effects. •E282: Joystick data recording with RTC. Create a script that logs the joystick values along with RTC data updated from the Internet to a trace file.

⊝⊝⊝ 426

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 58: HW-209© Logic Level Converter Sometimes we will need to change the electronic logic levels between digital devices in a simple and uncomplicated way, that is, we will need to adapt the voltages offered by one device, for example the +5V to the +3.3V offered by another and vice versa. Typical examples are the different digital logic levels provided by the usual Arduino©, Raspberry©, ESP32©, etc. controllers or those provided by some devices such as sensors, actuators, interfaces, controllers, displays, integrated circuits, etc. This conversion of voltage levels and digital logic levels is essential to avoid damage to the circuits. To make this change in digital logic levels we will use the level converter or level shifter, which basically consists of a c i r cu i t w i t h a transistor and appropriate control resistors, allowing bidirectional conversion, at high speed and in a simple way. In the circuit LV1 is the low signal level (for example +3.3V), HV1 is the high signal level (for example +5V), LV is the low level power source (+3.3V) and HV is the high level power source (+5V). 427

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

An example of a m o d u l e t h a t i n t egrates up to 8 digital logic level converters is the HW209© module where we must connect VCCA to +5V source, VCCB to +3.3V source, GND, the AX pins to the high level signal and the BX pins to the low level signal. The conversion is bidirectional, high speed and digital levels. Remember that these converters are digital, they are not suitable for converting analog levels as they are not linear devices and introduce multiple distortions. For analog level converters we have already seen simple voltage dividers. Finally, comment that with this type of converter we could adapt the voltage levels between UA R T , G P IO , I 2C , S PI p or t s of v a ri o u s m i c ro controllers that use different voltages in their GPIO and logically with sensors and actuators from different manufacturers with different voltage protocols in their communications. In the following exercises we will see examples of use of this type of digital logic level converters used to adapt voltage levels provided by sensors to those used by the GPIO of the ESP32©.

⊝⊝⊝

428

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 59: MQ135© Air Quality Sensor The MQ135© is an electro-chemical sensor, in a metal encapsulation, that measures air quality by varying its internal resistance depending on the concentration of the gas to which it is exposed. In this case it is also a small module that includes all the elements already connected: sensor, sensitivity potentiometer, status LED, connectors, etc. This sensor, for example, could be placed in the garage of the home and detect excessive concentrations of harmful gases ( CO 2 , NH 3 , NO, etc.), produced by the accumulation of vehicle exhaust gases in a usually closed environment like a garage. We could also install it in other rooms of the home such as the kitchen, fireplace area of the living room, etc. We must consider that: 1. Important:

This module requires a +5V power supply with a minimum consumption of about 140mA to preheat the sensor and its digital and analog outputs are +5V. Take this “high” consumption into account to connect it to a suitable power source. It is not possible to power it from the internal source or through the ESP32© directly. 429

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

2. AOUT: Analog output that we could connect to a

GPIO of the ESP32© with ADC analog-digital conversion capacity. This output varies between 0 and +5V, therefore we need a voltage divider to avoid damaging the ESP32©.

3. DOUT: On/off type digital output at +5V that we

must connect to a GPIO of the ESP32© using a logic level converter like the one already seen.

4. Reverse

logic operation: DOUT=LOW indicates toxic gas alarm, DOUT=HIGH indicates no toxic gas alarm.

5. Mini green LED ON: the sensor is powered. 6. Mini red LED ON: there is an alarm due to poor

air quality.

7. I t

has an adjustable trimmer (mini potentiometer) to regulate the sensitivity of the sensor and avoid false alarms. To adjust, turn it and see how the red LED is.

8. Due to the consumption of the sensor (140mA), we

will connect it to the external power supply MB102© already mentioned in other exercises.

9. We

will use the HW-209© digital logic level converter or equivalent, which uses several BSS138© Mosfet transistors and 10kΩ resistors to adapt the +5V output to the necessary +3.3V.

We will build a script that uses the GPIO27 to capture the DOUT logic level coming from the MQ135© sensor and that we have previously converted with the logic level converter from 0-5V to 0-3.3V. In order to use the AOUT output we must use a voltage divider to adapt the analog level. I will not tire of commenting that +5V signals should not be connected to the GPIO of the ESP32©. Any signal input to the GPIO that exceeds +3.3V will burn out the circuitry on the board. 430

Electronics & MicroPython© with ESP32©: 80 complete projects

A good way to avoid this situation is to use this logic level converter and isolator or an special isolator circuit with an optocoupler that acts as a total electrical separation between the ESP32© and the outside. The MicroPython© script that we can use is the same as that of the infrared sensor, tilt sensor, vibration sensor, etc. in which the on/off signal of the corresponding sensor is detected. We will have to select the appropriate GPIO, the type of logic (direct or reverse), the timing, the messages, the algorithm, etc.

⊝⊝⊝

431

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Suggested exercises: •E283: Air quality sensor, ADC and IRQ. Modify the commented script so that it controls the digital output DOUT of the sensor by IRQ instead of polling and also adds the management of the analog output AOUT using a voltage divider and a GPIO with ADC of the ESP32©, shows the activation of a alarm and its value. Why can't we connect AOUT to a logic level converter?. •E284: Environmental quality sensor. Include fire, smoke and humidity sensors (rain sensor) in the previous exercise and use the ADC converter of the ESP32©, with the appropriate level converters, to read the analog values of all of them, record them in a file along with data of the RTC and launch the corresponding alarms. •E285: Air quality and alarms. Configure the ESP32© as a Web server where we can view the air quality level and the air quality alarm status. In addition to recording all the relevant information in a file, send these alarms to a predefined email. •E286: Air quality, LED array and relay. Add to the previous exercise an LED array where the level of air quality is displayed and in case of alarm activate a relay that sounds a passive buzz, controlled by PWM, and simulate with a servo the opening of a door to force ventilation. •E287: MQ135© and BLE sensor. Add to the previous exercise some Bluetooth buttons that allow, from a mobile phone, to know the status of each ambient sensor mentioned.

⊝⊝⊝ 432

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 60: Alternating Current Sensor On this occasion we will build a sensor that will act as an interface with circuits where there is an AC voltage of up to 250V and we want to know if they are active or not. To do this we can use an already integrated AC sensor module such as the ZMPT101B© that gives us a sinusoidal voltage from 0 to +3.3V proportional to the 250V alternating signal for which this sensor has a small transformer, a voltage divider and a comparator of the LM358© type that shifts the alternating signal to a positive sinusoidal signal from 0 to +3.3V. An alternative option to this is to build ourselves an alternating current sensor that will give us an on/off type signal from 0 to +3.3V when there is or is not AC voltage in a certain circuit. To do this we will use the following circuit or equivalent that we have simulated with iCircuit© application:

433

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Basically the circuit consists of a voltage reducer composed of a resistor and a capacitor in series, which attack a diode bridge that converts the alternating voltage of 220V into DC and which attacks an optocoupler, represented by a relay and a transistor, all of this simulated with iCircuit©. At the output of the optocoupler we will have an on/off signal, with inverse logic, that is, when 220V is detected the GPIO goes from HIGH to LOW and vice versa and that can directly attack a GPIO of the ESP32© simulated with an LED. The voltage reducer is composed of a resistor vs capacitor pair of the 220Ω+470nF type, with a total Z=220+6k8j Ω impedance (complex notation), to reduce the input current of the optocoupler to less than 30mA. To calculate these values we will use: 2

(power of an ordinary resistor) P=i R=1/ 4w R=220Ω . and with i=30mA maximum, we have: On the other hand, for the capacitor, use: −3

C=I /(2 π fV )=(30∗10 )/(2 π∗50∗220)=470nF • • • •

I: f: V: if C:

where:

maximum current that passes through it, 30mA. frequency of the electrical network, 50Hz. mains voltage, 220V (change to 235V or other, applicable). capacitor capacity, 470nF (nano farads).

Choose a capacitor for more than 500V and change from 50Hz to 60Hz for America or other areas. Finally, the total impedance Z is the resistance plus the impedance of the capacitor C which is 1 Z C= calculated with: and therefore: 2πf C R

Z =R+Z C =R+ 434

1 1 =220+ Ω −9 2 π fC 2 π∗50∗470∗10

Electronics & MicroPython© with ESP32©: 80 complete projects

With this we will have to:

Z =220+6k8j Ω.

The B250C/1000V© bridge rectifier or equivalent is composed of 4 diodes in a “Wheatstone Bridge” configuration that converts the 220V alternating current into a direct current voltage suitable for the optocoupler. The 1.5uF/35V capacitors are made of tantalum and prevent random jumps of the 4N35© type opto coupler, which is activated with each alarm by turning its output to LOW. The 10MΩ resistance at the base of the phototransistor, at the input of the optocoupler, prevents noise and fixes its sensitivity. Finally we add pairs of 1uF, 100nF capacitors and a 10kΩ attack pull-up to each GPIO of the ESP32©. With all this, the circuit diagram would be the following and we could replicate it for each 220V voltage sensor that we need to control.

The MicroPython© script that we can use is very similar to that used with the infrared sensor, tilt sensor, vibration sensor, etc. in which the on/off signal of the corresponding sensor is detected. We must select the appropriate GPIO, the type of logic, direct or inverse depending on whether we want to detect the alternating current or its absence, the timing, the messages, the algorithm, etc.

⊝⊝⊝

435

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 61: Send email with ESP32© On many occasions we will need to send data from the ESP32© to an email address, for example, at the end of the day the ESP32© will send a file with the data captured from various sensors and/or actuators. This function is very useful for tracking variables, errors, turning devices on and off, sending alarms, the status of sensors and actuators, etc. In order to use this function, we must have a series of parameters such as the following examples and which we must adjust with our data. • • • • • •

Email origin: Password: Destine: Subject: Body: Annex:

[email protected] mypassword [email protected] ESP32© Temperature and pressure file.txt

In this script, the file.txt located on the ESP32© is sent from the address [email protected], with the access password mypassword, to the address [email protected], with the subject ESP32© and the body of the e-mail Temperature and pressure. The script uses an need an IMAP type server that are detailed on the to help us with the MicroPython© script. 436

SMTP type email server, if we we would have to make changes Internet. We can use chatGPT© configuration and with the

Electronics & MicroPython© with ESP32©: 80 complete projects

I n t h e s c r i p t , t h e usocket libraries are imported for communication on the server and ubinascii to perform binary vs ASCII conversions. The main parameters of the source SMTP server that we are going to use are configured, the send_email() function is defined that uses the source, subject, body and attachment data. This function connects to the server, performs authentication, creates the email, attaches the attachment and sends it to the indicated recipient, controlling the necessary messages and errors. ############################ # E061_EMAIL.PY: Send ESP32© file by e-mail # INPUTS: File, origin, destine of e-mail # OUTPUTS: Send [file.txt] # IMPORTANT: Server must be of the SMTP type ############################ import usocket as socket # Server communications import ubinascii, time # Convert Binary-ACII & time # E-mail configuration USERNAME = '[email protected]' # Origin PASSWORD = 'mypassword' # Change destine = '[email protected]' # Destination subject = 'ESP32©' # Subject body = 'Temperature and pressure' # Body annex = 'file.txt' # Annex # SMTP server SMTP_SERVER = "smtp.myserver.com" SMTP_PORT = 25 # Typical for no encrypted SMTP # Send email with attached attachment def send_email(to, e_subject, e_body, file_path): response = "" # Save error messages try: sock = socket.socket() sock.connect(socket.getaddrinfo(SMTP_SERVER, SMTP_PORT)[0][-1]) print('Server connected') # Authenticate to the SMTP server sock.send(b"EHLO esp32\r\n") time.sleep(0.1) # Pause response += sock.recv(256).decode('utf-8') sock.send(b"AUTH LOGIN\r\n") time.sleep(0.1) # Pause response += sock.recv(256).decode('utf-8') sock.send(ubinascii.b2a_base64(USERNAME. encode()).strip() + b'\r\n') time.sleep(0.1) # Pause response += sock.recv(256).decode('utf-8') 437

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

sock.send(ubinascii.b2a_base64(PASSWORD .encode()).strip() + b'\r\n') time.sleep(0.1) # Pause auth_response = sock.recv(256).decode('utf -8').strip() response += auth_response if not auth_response.startswith("235"): print('Error, check e-mail credentials') return print('Wrong credentials') # Send the email with the attached attachment sock.send("MAIL FROM:\r\n".format (USERNAME).encode()) sock.send("RCPT TO:\r\n". format(to).encode()) sock.send(b"DATA\r\n") # Send message headers and body sock.send("From: {}\r\n".format(USERNAME) .encode()) sock.send("To: {}\r\n".format(to).encode()) sock.send("Subject: {}\r\n".format(e_subject) .encode()) sock.send("Content-Type: multipart/mixed; boundary=\"boundary\"\r\n\r\n".encode()) sock.send("--boundary\r\n".encode()) sock.send("Content-Type: text/plain\r\n\r\n{}" .format(e_body).encode()) sock.send("\r\n--boundary\r\n".encode()) sock.send("Content-Type: application/ octet-stream; name=\"{}\"\r\n".format(file_path) .encode()) sock.send("Content-Disposition: attachment; filename=\"{}\"\r\n\r\n".format(file_path).encode()) # Read the content of the annex to attach it with open(file_path, "rb") as file: sock.send(file.read()) sock.send("\r\n—boundary--\r\n.\r\n" .encode()) time.sleep(1) # Minimum send time print('Message sent') except OSError as e: print('Sent error:', e) finally: # Close the connections sock.send(b"QUIT\r\n") sock.close() send_email(destine, object, body, annex)

⊝⊝⊝ 438

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E288: Joystick and e-mail. Extend the Joystick exercise to send by e-mail a file with the X, Y coordinates and status of the push button, to an address once an hour. Integrate in the same script the creation of joy.txt file from the Joystick movement data, a hardware timer that controls the time change and the sending of the e-mail with the attached file. •E289: Environmental monitoring. Use the DHT11© dual temperature and humidity sensor to measure both ambient temperature and humidity and set a timer to take measurements every certain time interval, store them in a file and send them by email. The file will include time, ambient temperature, humidity, internal temperature of the ESP32© and status of a touch button. •E290: Water level with ultrasonic sensor. Si mu la t e w it h a M i cr oP yt h on © s c ri pt t he measurement of the water level in a tank using an ultrasonic sensor connected to the ESP32©. Configure a hardware timer to perform periodic measurements every hour and save the results in a file that will be sent by email twice a day. In tests, use tighter and/or more comfortable times. •E291: Light control with DAC. Use a MicroPython© script and the ESP32© digital analog converter (DAC) to control the intensity of an LED light based on the internal temperature of the ESP32©, also implement a timer to periodically read that temperature and send an email report with the changes in the same by request from an HTML or Bluetooth button. 439

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

•E292: Voltage monitoring with ADC. Connect a voltage divider, created by 2 resistors to an analog input pin (ADC) to measure the voltage of a battery. Keep in mind that for the maximum battery voltage we must have a maximum of +3.3V at the ADC input. Add a timer to perform periodic measurements of that voltage, store the results in a file, and email them as a periodic battery status report. •E293: Temperature alarm system. Use the temperature sensor (e.g. thermistor) to measure the ambient temperature, set a maximum and minimum temperature threshold and a timer to periodically check if the temperature exceeds the predefined ranges, in which case an alert email will be sent attaching a log file with measurements.

⊝⊝⊝

440

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 62: Home Automation with IFTTT© In this script we have a very interesting example of integrating the ESP32© as a basic Home Automation controller that starts with a Web action, that is, with a Webhook and the IFTTT© integrator interprets and executes an action with a specific Home Automation device. To carry out this task, that is, to be able to interact with Home Automation devices, we have two methods, the “difficult” method and the “easy” method. The “difficult” method would try to get each API, that is, each MicroPython© application that runs on the ESP32© and that can interact, via WiFi or Bluetooth, with each of the Home Automation devices. This option is quite difficult because for many devices there are no libraries designed for MicroPython©, or they are complex or difficult to integrate into the ESP32©. The “easy” method consists of relying on software that integrates applications and devices of various kinds, and what is more difficult, even from various manufacturers that use different protocols and operating specifications. There are various integrators on the market, this book uses IFTTT©, “If This then That”, which is simple, cheap, with free options, and above all with th e po s si b i li t y o f in t e gr a ti n g mu l ti p le H o me Automation devices from various companies. 441

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Comment that, in general, today each Home Automation device has an APP that allows its control, schedule, creation of scenes, dependence on events, etc. but what is interesting is being able to implement algorithms that relate these devices and this is where IFTTT© comes in. In the following example, a script has been created that can execute an IFTTT© function to interact with various devices: Tao© infrared lights with Broadlink©, Samsung© TV, Yamaha© audio amplifier, HP© printer, touch screens with Sonoff© , Raspberry©, electronic markers, Apple© devices, Wiz© aroma diffusers, Sonoff© Christmas lights, coffee maker, Tadoº thermostat, sending SMS, file backup, etc. As we can see, we can interact in a simple way with multiple devices of multiple models and brands. The script describes a summary of an example list of Webhooks or actions IFTTT©, imports the urequests library requests, includes the IFTTT© personal will later see how to achieve.

operation as to use with to send Web key that we

The ifttt() function is defined, which executes the Webhook in which the Web request is constructed and the server's response is controlled by controlling the corresponding errors. As we can see, this script is very simple and brief and does not require knowing the hardware and operation of each of the Home Automation components or devices that make up our home. IFTTT© includes many brands of devices and these examples include: Broadlink© devices that are controlled by infrared, Sonoff© WiFi switches, Wiz© WiFi lights and switches, Tadoº thermostat, SMS with any telecom operator, Dropbox storage ©, etc. In order to use IFTTT© we have to follow the following steps in detail but on the Web there is a lot of documentation and examples of how IFTTT© is used. At the end of the book there is an annex with more information.

442

Electronics & MicroPython© with ESP32©: 80 complete projects

• •

• •

Sign up at www.ifttt.com (free or Pro). Create a Webhook, give it a [webhook] name and act on a device with: [ifttt] [create] [webhook] [receive a web request] [event name] [create trigger] [then that...] [device] [options] [create action] [continue] [finish]. Obtain the key [key] from IFTTT© with: [profile] [my services] [webhooks] [documentation] [your key is:]. Run the Webhook with: https://maker.ifttt.com/trigger/ [webhook]/with/key/[key] or: curl -X POST https://maker.ifttt.com/trigger /[webhook]/with/key/[key] Examples for MicroPython© on ESP32©:

urequests.post('https://maker.ifttt.com/trigger/' +printer_on+'/with/key/'+123) Webhook colors_on/off

Action

Device

On/off Broadlink©

Description Colored lamp

tv_lounge_toggle On/off Broadlink©

Lounge TV

audio_toggle

On/off Broadlink©

Lounge audio

spotlight_on

On

Broadlink©

RF spotlight on

spotlight_off

Off

Broadlink©

RF spotlight off

printer_on/off

On/off Sonoff©

Printer switch

screen_on/off

On/off Sonoff©

HDMI screen switch

home_auto_on/off On/off Sonoff©

Raspberry© switch

wizlounge_on/off On/off Wiz©

Light and sockets

chameleon_red

On

Chameleon in red

apple_on/off

On/off Apple©

Apple TV©

sunrise_on/off

On/off Smartlife©

Sunrise light

diffuser_on/off

On/off Smartlife©

Diffuser color spray

send_sms

Send

SMS

Alarm to mobile

log_dropbox

Add

Dropbox©

Add file.log

Tadoº

Thermostat mode

tado_on/off/auto Mode

Wiz©

443

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

############################

# E062_IFTTT.PY: Activate a device using IFTTT© # INPUTS: Webhook name and [my IFTTT© key] # OUTPUTS: Server activation and response ############################ ''' WEBHOOK EXAMPLES (ESP32© STARTS A WEBHOOK) --------------------------------------------------NAME ACTION DEVICE DESCRIPTION --------------------------------------------------colors_on/off on/off Broadlink© Lamp tv_lounge_toggle on/off Broadlink© Lounge TV audio_lounge_toggle on/off Broadlink© Amplifier spotlight_on on Broadlink© RF spotlight printer_on/off on/off Sonoff© Switch screen_on/off on/off Sonoff Raspberry© wizlounge_on/off on/off Wiz© Light and plug chameleon_red on Wiz© Red light on apple_on/off on/off Apple© Apple TV© sunrise_on/off on/off Smartlife© Sunrise light diffuser_on/off on/off Smartlife© Diffuser spray tado_on/off/auto on/off Tado© Thermostat send_sms send SMS Send alarm log_dropbox add Dropbox© Add file ''' import urequests # Web request management key_ifttt ='[my IFTTT© key]' # Webhooks IFTTT© key # Invoke the IFTTT© Webhook def ifttt(webhook): try: response = urequests.post('https://maker.ifttt.com/ trigger/'+webhook+'/with/key/'+key_ifttt) if response.status_code == 200: print(response.text) print('Webhook activated: '+webhook) else: print('Server error: '+response. status_code) except: print('Webhook error: '+webhook) # Examples: ifttt('colors_off') # Turn off colored lamp ifttt('tado_auto') # Active Tadoº thermostat mode 444

Electronics & MicroPython© with ESP32©: 80 complete projects

To complete this exercise we will do the reverse management of the previous exercise, that is, the ESP32© in server mode, will receive an IFTTT© Webhook request from various events and will be able to act accordingly: indicating it on the console, acting with devices or even generating other Webhooks to act, via IFTTT©, with other Home Automation devices. For all of the above, we can add to our project a Home Automation algorithm for interaction between sensors and actuators and with this we can build a simple Home Automation system that is very easy to maintain. In that script we define 4 devices and 8 actions, for example, it is best to define a table like the following: Name

Origin

Device

Event

Action

score_on/off Board

eWelink©

On/off LED, color

color_on/off Lamp

Wiz©

On/off LED, color

print_on/off Printer

Ewelink©

On/off LED, color

tado_away tado_home

Tadoº

Modo

Tadoº

LED, color, printer on/off

In the script we include a general description of operation indicating the name of the event generated in IFTTT©, the origin, the hardware device that generates it, the type of event and the action that this script will perform with that event. This is where the options are endless and we must specify which Home Automation algorithm we want to be carried out in our ESP32© with this information, the internal information (time, temperature, variables, etc.) and the algorithm that we have designed. The script imports the socket, machine and urequests libraries, defines the internal port to which the external port input defined in the router is diverted, includes the key defined in IFTTT©, configures the status LED, the message() function which displays both messages in the console and on the W e b , t h e control() function, which includes the actions to be performed with each of the events in the previous table and the actions that we have defined. 445

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Finally, the ifttt() function is defined to send the Webhooks to control Home Automation devices, the main loop of the server where the received messages are checked and the corresponding controls for IFTTT© sending errors, such as server creation, etc. ###########################

# E062_IFTTT_SERVER.PY: Activate Web server & IFTTT© # INPUTS: [IP]:[int_port]/[origin] [IFTTT© key] # OUTPUTS: LED simulation with [origin] and algorithm # IMPORTANT: In IFTTT© use NO-IP© as: # http://[name].hopto.org:[ext_port]/[action] # On the router, derive the port [ext_port] to # [int_port] and the [IP] of the ESP32© ############################ ''' EXAMPLES OF WEBHOOK (ESP32© RECEIVE A WEBHOOK) NAME ORIGIN DEVICE EVENT ACTION score_on/off board eWelink© on/off LED color_on/off lamp Wiz© on/off LED print_on/off printer eWelink© on/off LED tado_away/home tado Tado© away/home Several ''' import socket # Web server management import machine # GPIO control import urequests # HTTP client # Server port configuration port = '[int_port]' # For example the xx80 key_ifttt = '[my IFTTT© key]' # Webhook IFTTT© key # LED configuration to display actions red = machine.Pin(27, machine.Pin.OUT) # Red LED green = machine.Pin(26, machine.Pin.OUT) # Green LED red.value(0) # LED off green.value(0) # Send messages to console and Web def message(men): try: print(men) # Text that appears on the Web response = "HTTP/1.1 200 OK\n\nLED Estate: {}".format(men) conn.send(response) except: 446

Electronics & MicroPython© with ESP32©: 80 complete projects

print('Error sending message') # IFTTT© action with the Home Automation algorithm def control(accion): if 'score_on' in accion: # Snooker© score On message('Scoreboard on') red.value(1) green.value(0) ifttt('colors_on') # Colored lamp on if 'score_off' in accion: # Snooker© score Off message('Scoreboard off') red.value(0) green.value(1) ifttt('colors_off') # Colored lamp off if 'color_on' in accion: # Colored lamp on message('Colored lamp on') red.value(1) green.value(0) ifttt('colors_on') # Colored lamp on if 'color_off' in accion: # Colored lamp off message('Colored lamp off') red.value(0) green.value(1) ifttt('colors_off') # Colored lamp off if 'print_on' in accion: # Printer on message('Printer on') red.value(1) green.value(0) ifttt('colors_on') # Colored lamp on if 'print_off' in accion: # Printer off message('Printer off') red.value(0) green.value(1) ifttt('colors_off') # Colored lamp off if 'tado_away' in accion: # Tado© away from home message('Away from home') red.value(1) green.value(0) ifttt('colors_off') # Colored lamp off ifttt('printer_off') # Printer off message('Printer off') if 'tado_home' in accion: # Tado inside home message('Inside home') red.value(0) green.value(1) 447

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

ifttt('colors_on') ifttt('printer_on') message('Printer on')

# Colored lamp on # Printer on

# Call to the IFTTT© Webhook def ifttt(webhook): try: response = urequests.post('https://maker. ifttt.com/trigger/'+webhook+'/with/key/'+key_ifttt) if response.status_code == 200: print(response.text) print('Webhook activated: '+webhook) else: print('Server error: '+response. status_code) except: print('Webhook error: '+webhook) # Create the server socket try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', port)) s.listen(5) # To connect up to 5 devices print("Web server on http://[IP]:{}".format(port)) except: print('Error creating server') # Script main loop try: while True: # Web command reading loop conn, addr = s.accept() print("Connection from {}".format(addr)) request = conn.recv(1024) request = str(request) control(request) except: print('Error receiving Webhook') conn.close()

⊝⊝⊝

448

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E294: Rotary decoder with Webhook. Develop a MicroPython© script for ESP32© that uses a rotary decoder with a callback function that is triggered when the decoder rotates in a specific direction by a specific amount. When that particular type of spin is detected, the script should send an event to IFTTT© via a Webhook in which a light turns on for a while and then turns off. Specify the external device, the IFTTT© Webhook and the script. •E295: ADC and internal temperature reading. Create a script that reads analog values through the ESP32© ADC converter generated by a joystick. On the other hand, read the internal temperature of the ESP32©. When the ADC reading and ESP32© temperature reach a specific threshold, the script must send an event to IFTTT© using a Webhook to trigger a switch. •E296: Using thermistor with Webhook. Develop a script that uses a thermistor to measure room temperature. Convert thermistor readings into values using an ADC and, if the temperature exceeds a certain limit for a certain preset time, triggers an IFTTT© Webhook that turns off an infrared device. •E297: Temperature with DHT11© and Webhook. Write a MicroPython© script that integrates the DHT11© sensor to measure humidity and temperature. If the humidity or temperature reaches certain levels, entered with a rotary decoder, the script must send an event to IFTTT© that sends an SMS to a mobile phone. 449

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

•E298: Light control through Webhooks. Develop a script that configures the ESP32© as a Web server. When the ESP32© detects an open/close door sensor Webhook, it activates or deactivates a relay that controls a light. •E299: Blinds automation with Webhooks. Create a script in the ESP32© that, upon receiving an IFTTT© event, controls a blinds motor using a relay connected to the ESP32© or another Webhook that performs this function. The script must interpret the event and determine, based on the state and time of day, whether the blinds should open, close, or stop. •E300: Thermostat adjustment using Webhooks. Write a script that receives IFTTT© events via Webhooks to adjust the temperature of a simulated thermostat on the ESP32©. We can use a DAC with an LED to simulate temperature control accordingly. •E301: Sound playback with Webhooks. Develop a script that, upon receiving an event from IFTTT©, plays a specific sound file previously stored in the ESP32©. •E302: Geolocation and Home Automation devices. Create a script that uses the geolocation received through an IFTTT© Webhook to activate or deactivate specific Home Automation devices based on location, time of day, and the state of temperature and touch sensors. Include turning on lights when we approach home or turning off devices when we leave. Add corresponding error controls with Webhooks and Home Automation devices.

⊝⊝⊝

450

Electronics & MicroPython© with ESP32©: 80 complete projects

*Exercise 63: NO-IP© Remote Management In this exercise we will use one of the previous exercises to access a specific script on our ESP32© but, instead of accessing it directly from the home local WiFi, we will do it from the Internet to be able to access the ESP32© from outside the home remotely. To access remotely we use dynamic DNS services that allow us to maintain the public IP associated with our router with a domain provided by a certain provider. In order to access our ESP32© from outside the home, we need to know the public IP of our router, but this information can change every time the router is disconnected from the power line, every time it is updated, every time it is restarted, etc. The most convenient thing would be to have a domain (if it's free, much better) and for it to permanently point to the public IP of the router or for the public IP of our router to be a fixed IP (this usually has a cost). There are several solutions on the market: DynDNS©, DuckDNS©, etc. and in this exercise the NOIP© application is used, which is free (we only need to confirm the domain name monthly) and easy to use. To configure NO-IP© we will register on their website at www.noip.com, which will assign us a free domain in the format [name].hopto.org, where [name] can be, e.g our NO-IP© user. 451

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

On the other hand, we need to always keep our router's public [IP] updated to NO-IP©, we can do this manually or better yet configure it within the router. We will see later in an example, how it is done. Finally we will have to indicate in our network that Web requests, coming from abroad and entering through our domain and therefore through our router, reach the ESP32©. To perform the diversion or “routing” from the router to the ESP32© we will do the following: •

Open a xx000 port on the main router.



Access our [IP], for example 192.168.1.[IP].



Enter the access password.



Access the advanced configuration menu similar to: [Advanced Setup] [NAT] [Virtual Servers].



Add a new line with the following information and example ports xx000 and xx80: Server Name (Custom Service): Example External Port Start: Example External Port End: Protocol:

ESP32 xx000 xx000 TCP/UDP

Example Internal Port Start: xx80 Example Internal Port End: xx80 Server IP Address: 192.168.1.[IP] Where [IP] is the IP of the ESP32©. With this configuration, access from outside the Wifi to the Web server that runs on the ESP32© is: [name].hopto.org:xx000, w h e r e [name] is the domain provided by www.noip.com and xx000 the port opened. Now if in a Web browser we write the address: [name].hopto.org:xx000/[command] a n d the specific [command] contemplated in the MicroPython© script that is being executed will be executed. 452

Electronics & MicroPython© with ESP32©: 80 complete projects

For example, if we use the script example of use of Web, HTML and LED and [name].hopto.org:xx000/red_on the red LED will light up, also for red_off, green_on, green_off, etc. To expand this exercise, a very interesting and fun option is to use a voice assistant, for example a Google Home© to execute the previous options (turn on/off LED, relays, request data, etc.) without having to type anything. Currently, at the time of writing, IFTTT© is available for Google Home©, but it is not available for the Alexa© or Apple© voice assistants. To implement this option we need a “bridge” that links the Google Home© with the ESP32© and the “bridge” described here is IFTTT©, that is: “If This Then That”. To use IFTTT© we will: •

Open the application (also available in APP) and identify ourselves.



Use the [create] option which is very intuitive.



In the [If This] section we can look for [google assistant], select it and give it a name, for example “turns on green”.



I n t h e [Then That] section we search for [webhook], select [make a web request] and add: URL http://[name].hopto.org:[port]/green_on Method: Rest: Where:

GET blank

[name] is the domain that the NO-IP© service has assigned us and [port] is the port that we have managed on our previously described router e.g. xx000.

453

Gregorio Chenlo Romero (gregochenlo.blogspot.com)



Pre ss [create action] [continue] [finish] the [connected] button will appear.

and

We will have to wait a couple of minutes for IFTTT© to integrate the actions and we can now try on the Google Home© speaker or the Google© assistant on the mobile, saying “ok Google, activate green” and the green LED will light up connected to ESP32©. As we can see, it is very useful and practical, but we can make it even more comfortable by eliminating the word “activate” from the voice command in Google©. To do this, we can enter the Google© Home© APP, go to [automatic] and create a routine with the same name but without the word “activate”, for example, “turn on green”. We can add as a trigger whit: [when we talk to Google Assistant] [turn on green] [add trigger] [add action] [Try adding your own commands] [activate turn green] [done] [save]. Now if we say: “ok Google, turn on green” the green LED will light up. To complete it, we can add more activation phrases such as [turn on green LED], etc., in this way and with various combinations of phrases, the desired action will always be carried out comfortably. Finally, and since the routine is defined in the Home© APP, we can execute it, via voice, from any device that contains Google Assistant©, for example, Home Mini©, Google Nest©, Lenovo© alarm clock, Sony© headphones, Xiaomi© TV, etc. With this functionality we will have a very useful, comfortable and also fun Home Automation tool.

⊝⊝⊝

454

Electronics & MicroPython© with ESP32©: 80 complete projects

Suggested exercises: •E303: Execution of scripts with NO-IP©. Use NO-IP© to run other scripts from the Internet, that is, from outside the local WiFi network, for example to display the internal temperature of the ESP32© and the DHT11© together with the % humidity. •E304: LED Similar change, from LED using the lighting of a

brightness from NO-IP©. to the previous exercise but allows to outside the home, the brightness of an DAC converter. The LED will simulate the room.

•E305: HTML and NO-IP© code. Change the HTML body of previous exercises to define enough buttons and options so that the previous options can be executed directly on the Web, by pressing buttons, without having to write the corresponding Web addresses for each of the commands. •E306: Voice commands. Implement voice commands for the previous exercises and check their correct operation. Add the corresponding routines in the Home© APP to make voice commands as comfortable as possible. •E307: Access control with username and password. Add remote access control to the ESP32©, via user and NO-IP©. Tip: Use the web access format with the following parameters: [name].hopto.org:[port]/[script.py]? user=[user]&password=[pass]

⊝⊝⊝

455

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

*Exercise 64: ADXL345© Accelerometer In this exercise we will see how another electronic device is connected using the I2C bus communication, specifically we will work with the ADXL345© accelerometer, which is a 3-axis motion sensor. The connections of the ADXL345© module that we are going to use are the following:

ADXL345©

ESP32©

Observations

+5V

Not used

VCC

+3.3V

GND

GND

SDA

GPIO21

I2C data

SCL

GPIO22

I2C clock

CS

Not used

Chip select

SDO

Not used

Serial data output

INT1

Not used

IRQ 1

INT2

Not used

IRQ 2

Do not use with ESP32© Power Ground

We must take into account the following: •

456

VCC, GND: +3.3V power and ground pins that must be as stable as possible to guarantee the accuracy of the sensor.

Electronics & MicroPython© with ESP32©: 80 complete projects



SDA, SCL: Pins of the main I2C bus that will allow us to transmit data between the sensor and the ESP32© and vice versa and in a simple and fast way.



CS: Chip Select to select several hardware sensors from the ESP32©, in this exercise the selection is made by the I2C bus itself.



SDO: Serial Data Output that allows sensor data without using the I2C bus.



INT1, INT2: IRQ interrupt outputs that can allow the ESP32© to know that there is some new data using an interrupt without having to continuously read the I2C bus by polling.

reading

Let us remember that I2C (Inter-Integrated Circuit) communication allows the connection of electronic devices using two main lines: SDA (Serial Data) and SCL (Serial Clock) and we can highlight: Hardware Connection: SDA (Serial Data): It is the bidirectional data line through which data is transmitted between the devices, in the ESP32© located in the GPIO21. SCL (Serial Clock): It is the clock line that synchronizes the data transfer, in the ESP32© located in GPIO22. •

I2C Bus Configuration: On the ESP32©, we can configure the I2C bus using the machine l i b r a r y a n d t h e i n s t a n c e SoftI2C(scl=Pin(22),sda=Pin(21)) to specify the GPIO GPIO21 and GPIO22. •

The usual transmission speed of the I2C bus is 100kb/s, which is what this instance assigns if we do not specify otherwise. On those occasions (long cables, specific devices, many devices connected to the bus, etc.) we can lower this frequency by indicating it as: SoftI2C(scl=Pin(22),sda=Pin(21),freq=50000). 457

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

Device Addresses: Each device on the I2C bus has a unique 7-bit address (can vary between 8 and 127) assigned by the device manufacturer. In this case it is 0x53 and we can scan it. •

Start and Stop of Communication: I2C communication begins with a start condition where SDA changes from high to low while SCL is high and ends with a stop condition where SDA changes from low to high while SCL is high. These operations are handled by the MicroPython© SoftI2C instance. •

Data transfer: Data is transferred in 1byte=8bit packets and each byte is followed by an ACK/NACK bit that indicates whether or not the receiver accepts the received byte. •

The script summarizes the connections between the ADXL345© and the ESP32©, remember that all signals connected directly to the ESP32© must be a maximum of +3.3V. We import the machine and time libraries, we define where the I2C bus is connected, in our case SDA in GPIO21 and SCL in GPIO22. Although we know that the manufacturer of the ADXL345© has assigned address 0x53 for the I2C bus, we c a n c h e c k i t w i t h t h e scan_i2c() MicroPython© function, which tells us that it has been found, therefore we assign this address, we activate the sensor in measurement mode with parameters 0x2D and b'\x08 (energy control register and activation value). We make an infinite sensor reading loop where we read the reading register 0x32 with 6 bytes (2 bytes per axis) and process the data obtained in the acce_data[] list for each axis, shifting the first byte 8 bits to the left and adding to it (function OR) the 8btis of the second byte and repeating this action for the x, y, z axes. Finally we present the acceleration values on each axis and wait a while. 458

Electronics & MicroPython© with ESP32©: 80 complete projects

If we connect the LA1010© logic analyzer to the I2C bus we can see the data in the SDA signal and the clock in SCL. We can see how I2C communication starts when SDA is lowered with SCL high and how byte 0x32 is sent to activate the reading of the next 6 bytes (2 for each axis). The analyzer also displays a PWM signal that serves as a reference.

############################ # E064_ACCE_ADXL345.PY: ADXL345© accelerometer # INPUTS: I2C (0x53) & GPIO21 (SDA) & GPIO22 (SCL) # OUTPUTS: Acceleration values in 3 axes ############################ ''' ADXL345© CONNECTIONS -----------------------------------------ADXL345© Function ESP32© -----------------------------------------5V +5V Do not use VCC, GND +3.3V and ground 3V, GND SDA, SCL I2C bus GPIO21, GPIO22 CS Chip Select Not used SDO Serial Data Output Not used 459

Gregorio Chenlo Romero (gregochenlo.blogspot.com)

INT1 Interruption 1 INT2 Interruption 2 ''' from machine import SoftI2C, Pin import time

Not used Not used # I2C and GPIO # Timing control

i2c = SoftI2C(scl=Pin(22), sda=Pin(21)) # GPIO & I2C # Scan the address of the ADXL345© on the I2C bus def scan_i2c(): print('Scanning I2C bus...') devices = i2c.scan() if devices: # Device found for device in devices: print('I2C device found on: ',hex(device)) else: print('No I2C devices found') # I2C address scanning scan_i2c() # ADXL345 I2C address (0x53 by default) dir_adxl345 = 0x53 # Change as scan_i2c() # Configure the ADXL345 (activate measurement mode) i2c.writeto_mem(dir_adxl345, 0x2D, b'\x08') # Reading loop print('ADXL345© ACCELEROMETER CONTROL') print('Move the sensor...') try: while True: # ADXL345 (read with 2bytes/axis) acce_data = i2c.readfrom_mem(dir_adxl345, 0x32, 6) # Processes data in ADXL345 format # Byte [x] shifts left 8bits and adds [x-1] x = (acce_data[1]