Nachrichten versenden mit ESP32 und ESP8266 in MicroPython - Teil 4 - Whatsapp - AZ-Delivery

This post is also available as PDF document.

Next to Ifttt, Thingspeak and Telegram WhatsApp also offers the option of sending messages using a bot. The modules used are not very demanding regarding the memory requirement. And so our controller ESP32 and ESP8266 are both back. The text message that we send to Callmebot must be URL-Encoded. This means that special characters such as "Äöüß" have to be replaced by hexadecimal codes. That makes my module urlen Thanks to urequest.Py we only need one line for the transfer of the data to the server for the transmission. In this post, you can find out how to set up a WhatsApp account and bot

Micropython on the ESP32 and ESP8266


ESP32 and ESP8266 Send values ​​via WhatsApp

Forget to switch off the basement light? Yes, that happens from time to time. Well, if our ESP registered this and after a certain time you send us a message via WhatsApp. The circuit effort is extremely low. In the lean stage, a controller, an LDR (Light dependent resistor = photo resistance) and a simple resistance of 10kΩ, or the module Ky-018, on which both are already assembled. If you want, you can take a display with it so that system messages can be displayed. The circuit will very probably not be connected to the PC in use.



D1 Mini Nodemcu with ESP8266-12F WLAN module or

D1 Mini V3 Nodemcu with ESP8266-12F or

Nodemcu Lua Amica Module V2 ESP8266 ESP-12F WiFi or

Nodemcu Lua Lolin V3 Module ESP8266 ESP-12F WIFI or

ESP32 Dev Kit C unpleasant or

ESP32 Dev Kit C V4 unplacerated or

ESP32 NODEMCU Module WiFi Development Board with CP2102 or

Nodemcu-ESP-32S kit or

ESP32 Lolin Lolin32 WiFi Bluetooth Dev Kit


0.91 inch OLED I2C Display 128 x 32 pixels


Ky-018 Photo LDR resistance or

Photo resistance Photo Resistor plus

Resistance 10 kΩ


MB-102 Breadboard Pug with 830 contacts


Ky-004 button module


Jumper Wire cable 3 x 40 pcs. 20 cm M2M / F2M / F2F each possibly too

65stk. Jumper wire cable plug -in bridges for Breadboard

So that slots for the cables are still free next to the controller, I have put two Breadboards together with a power rail in between.

Figure 1: circuit ESP8266 D1 Mini with discrete resistance

Figure 1: circuit ESP8266 D1 Mini with discrete resistance

The LDR reduces its resistance with increasing brightness. It is switched into row with a fixed resistance of 10kΩ. The two together form a voltage divider. Center contact S There are tensions from a little over 0V to close to 3.3V. So that there is also a higher voltage of S in the event of a lot of light, the LDR must be 3.3V and the 10kΩ resistance to GND. If you use the loose LDR, you can easily do it.

Figure 2: voltage divider made of individual parts

Figure 2: voltage divider made of individual parts

In the KY-018 module, however, the LDR is against mass if you connect it as the lettering pretends. So that the part behaves exactly as we wish, you have to put GND on the middle pen and +3.3V on the right. S connect to the analogue input of the controller, GPIO36 at the ESP32 and A0 at the ESP8266.

Figure 3: circuit of the module KY-018

Figure 3: circuit of the module KY-018

Figure 4: circuit with ESP32 and LDR module

Figure 4: circuit with ESP32 and LDR module

Figure 5: circuit with ESP8266 and individual resistance

Figure 5: circuit with ESP8266 and individual resistance

The software

For flashing and the programming of the ESP32:

Thonny or


Used firmware for the ESP32:

V1.19.1 (2022-06-18).

Used firmware for the ESP8266:

V1.19.1 (2022-06-18).

The micropython programs for the project:

SSD1306.PY Hardware driver for the OLED display API for the OLED display Driver module for the HTTP operation of the ESP8266 URL-Encoder module Softwareimer module Demo program for sending e-mail

Micropython - Language - Modules and Programs

To install Thonny you will find one here Detailed instructions (English version). There is also a description of how that Micropython firmware (As of 18.06.2022) on the ESP chip burned becomes.

Micropython is an interpreter language. The main difference to the Arduino IDE, where you always flash entire programs, is that you only have to flash the Micropython firmware once on the ESP32 so that the controller understands micropython instructions. You can use Thonny, µpycraft or ESPTOOL.PY. For Thonny I have the process here described.

As soon as the firmware has flashed, you can easily talk to your controller in a dialogue, test individual commands and see the answer immediately without having to compile and transmit an entire program beforehand. That is exactly what bothers me on the Arduino IDE. You simply save an enormous time if you can check simple tests of the syntax and hardware to trying out and refining functions and entire program parts via the command line before knitting a program from it. For this purpose, I always like to create small test programs. As a kind of macro, they summarize recurring commands. Whole applications then develop from such program fragments.


If the program is to start autonomously by switching on the controller, copy the program text into a newly created blank tile. Save this file under in WorkSpace and upload it to the ESP chip. The program starts automatically the next time the reset or switching on.

Test programs

Programs from the current editor window in the Thonny-IDE are started manually via the F5 button. This can be done faster than the mouse click on the start button, or via the menu run. Only the modules used in the program must be in the flash of the ESP32.

In between, Arduino id again?

Should you later use the controller together with the Arduino IDE, just flash the program in the usual way. However, the ESP32/ESP8266 then forgot that it has ever spoken Micropython. Conversely, any espressif chip that contains a compiled program from the Arduino IDE or AT-Firmware or Lua or ... can be easily provided with the micropython firmware. The process is always like here described.

How to come to a WhatsApp account

  1. WhatsApp from the Google Playstore (App Store from iPhone) download
  2. Install the app
  3. Start whatsapp
  4. Enter the cell phone number. The usual 0 falls away, use +49.
    So about this pattern: +49 512 123456789
  5. Wait for the SMS with the WhatsApp confirmation code - enter code - finish.
  6. Allow whatsapp to access the contact list
  7. The app has now imported all the contacts that also use WhatsApp

WhatsApp for the PC

For the PC there is also a Windows app at Unpacking after the start of the downloaded EXE file runs smoothly. However, the program brings an error message after the start and stops.

Alternatively you can have one App also at Chip, or in the Microsoft Store. However, she always works with her cell phone, the devices have to be coupled. After the start of the immediately running file, the following window is shown:

Figure 6: WhatsApp Portable for the PC

Figure 6: WhatsApp Portable for the PC

Open WhatsApp on your cell phone. Go to the menu and tap linked devices. Now scan the QR code with your cell phone. Shortly afterwards you get a two -part window by selecting the chat on the left. On the right you will see the news.

How to create a bot

  1. Add Add the following number to the contacts on the cell phone:
    +34 644 51 95 23. Enter any name, it does not do anything.
  2. Send the following text to the new contact via WhatsApp:
    I allow callmebot to send me messages
  3. A short time later you get a message from WhatsApp with your api key.

Figure 7: API-Key for the new offer

Figure 7: API-Key for the new offer

  1. Tap on the URL line.
  2. After a few seconds you get a test message from WhatsApp.

 Figure 8: Test message from the bot

Figure 8: Test message from the bot

The Micropython program for WhatsApp-Bot

The import business is somewhat larger. PIN, SOFTI2C and ADC come from the module machine. time supplies Sleep. Software-timer for microse customers, milliseconds and seconds that do not block the program are in time-out ready. urlen code offers the function Urlen code(), which, together with the lists Q and Z, translates special characters into Hexadecimal code.

 From machine import Pin code, Softi2c, ADC
 From time import sleep
 From time-out import *
 From urlen code import *
 import urequest AS requests
 From OLED import OLED
 import network
 import sys
 import GC

Http requests are with urequest very simplified. The class OLED Is the API for the display, network Makes the connection to the WLAN router. sys We use to query the controller type and for a secure program exit. GC stands for Garbage Collection and clears no longer required data waste.

 trigger=500 # counts
 warning=60 # Seconds

The ADC level trigger, which separates light from dark, must be set individually for each case, as well as warning, the value for repeating news.

 myssid = 'Empire_of_ants'; mypass = "Nightingale"

For myssid and mypass Please use the credentials for your router. The same applies to API-Key and phone number.

The next block recognizes the controller type and accordingly instantates an I2C object and the ADC.

 IF sys.platform == "ESP8266":
     I2C=Softi2c(scl=Pin code(5),sda=Pin code(4))
 elif sys.platform == "ESP32":
     I2C=Softi2c(scl=Pin code(22),sda=Pin code(21))
     ADC=ADC(Pin code(36))
     raise Runtime("Unknown Port")

We hand over the I2C bus instance to the constructor of the display object, set the brightness and output the title line.

 D=OLED(I2C,Heightw=64) # 128x64 pixel display
 D.writer("Cellar light",2,0)

We put the button on GPIO14 and activate the pullup resistance.

 button=Pin code(14,Pin code.IN,Pin code.Pull_up)

The dictionary connect status Translates the numbers codes that we network.status() delivers, in plain text. The ESP32 delivers numbers other than the ESP8266.

 connect status = {
     1000: "Stat_idle",
     1001: "Stat_Connecting",
     1010: "Stat_got_ip",
     202:  "Stat_wrong_Password",
     201:  "No ap found",
     5:    "Unknown",
     0: "Stat_idle",
     1: "Stat_Connecting",
     5: "Stat_got_ip",
     2:  "Stat_wrong_Password",
     3:  "No ap found",
     4:  "Stat_Connect_Fail",

In order for the station interface to be accessed from the WLAN router, the MAC address must be known to the router if MAC filtering is activated there. Incidentally, it is not a good idea to switch off the filtering because any WLAN nomads can then log in more easily to the router.

This time I packed the registration sequence to the router in a function that returns the station object. As long as there is no connection, a point in the terminal and the display will be output every second.

 def Connect2router():
     # ************
     nic=network.WIRELESS INTERNET ACCESS(network.Ap_if)
     nic = network.WIRELESS INTERNET ACCESS(network.Sta_if)  # creates WiFi object                    # Nic turn on
     Mac = nic.config('Mac')# Call base Mac address and  
     mymac=hexmac(Mac)      # convert into the succession
     print("Mac station: \ t"+mymac+"\ n") # spend
     IF need nic.Isconnected():
       nic.connect(myssid, mypass)
       print("Status:", nic.Isconnected())
       D.writer("WLAN Connecting",0,1)
       while nic.status() != network.Stat_got_ip:
     print("\ nstatus:",connect status[nic.status()])
     Staconf = nic.ifconfig()
     print("Sta-IP: \ t \ t",Staconf[0],"\ nsta-netmask: \ t",\
           Staconf[1], "\ nsta-gateway: \ t",Staconf[2] ,sep='')
     return nic

Because the ESP8266 builds up a radio connection to the router with which it has already had a connection when switching on, no point appears. The following test confirms this. Connect such an ESP8266 to the PC and start Thonny. Enter the following instructions in the terminal.

 >>> import network
 >>> nic = network.WIRELESS INTERNET ACCESS(network.Sta_if)
 >>> nic.Isconnected()

This is also the reason why the ESP8266 sometimes booted constantly. He tries to contact the router. If that doesn't work, he makes a restart. Sometimes it helps to switch off web replacement (the spotted terminal).

 # After flashing the firmware on the ESP8266:
 >>> import webrepl_setup
     > D for disable
 # Then RST; Restart!

The ESP32 does not show this strange behavior. Therefore, around three to five points appear here.

To reduce the noise of the ADC values, the function determines measure() the mean of n Measurements. The return value is 1 if the measured value greater than the limit value in trigger is otherwise 0. We are not interested in the quasi-brightness value, but only whether the light is on (1) or (0).

 def measure(n):
     for _ in range(n):
     return 1 IF Val > trigger Else 0

The main loop becomes clearer if you have jobs like measure() or event traders in functions. Sending the message to WhatsApp is therefore coded as a function.

 def sender(text):
          phon+"& text ="+Urlen code(text)+"& Apikey ="+key
 # Print (URL)
     IF respect.status_code == 200:
         print("Transfer OK")
         print("Transfer error")

Everything about information is in the variable url Packed, protocol, server, phone number, the urlcoded text and and the API key. The result can be output for control. Then we send the URL with the Get method on the trip. The attribute status_code of the response object respect Tell us whether the transfer was successful or not. In any case, we close the socket and clear the memory.


The connection is established. During the development phase we break off the program at this point. We now have a functioning network connection, and all the objects, variables and functions are declared. So we can test the individual components manually.

 >>> measure(20)

Now cover the LDR

 >>> measure(20)
 >>> sender("Morning hour is all trucks at the beginning")
 transfer OK

A few seconds later, the cell phone and the Windows app report.

Figure 9: First message from ESP32

Figure 9: First message from ESP32

If everything worked out, we comment sys.exit() out of.

The alarm clock for the next scan is set to 20 milliseconds. Then we get the light value, the wake -up time for to warn we put in infinity.

 to warn=Time-out(0)
 IF old==1:
     to warn=Time-out(warning)

If the light is already on, we'll remember the time and set up the warning timer warning. old is the condition of the past measurement.

Then it goes into the main loop. If the timer has expired for the next scanning of the LDR, we get the current state. Depending on the old and new condition, three situations can arise.

The light was over and is now on.

We put the timer to warn on warning And notice the time. No further action.

The light was and is still on.

Is the timer to warn() expired, then it is time to fire a message. We put the timer to warn again on warning.

The light was on and is now over.

We take the time again and calculate the switching duration from it. We give all -clear with a new message.

 while 1:
     IF NextScan():
         IF old==0 and new==1:
             to warn=Time-out(warning)
         elif old==1 and new==1:
             IF to warn():
                 sender("Light has been on.".\
                 to warn=Time-out(warning)
         elif old==1 and new==0:
             IF duration > warning:
                 sender("Light is out of {} s.".\

In any case, the new light value will be transferred to the old. Because NextScan() We have expired, we reorganize the timer. The print command can be deleted or commented on in production operation

There is still the mandatory key query.

The program will be tested restarted. Now messages have to be sent if the light longer than warning Seconds is on or/and if the light is made out.

DisplaysEsp-32Esp-8266Projekte für anfängerSensoren

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery