MicroPython Programming with ESP32 and ESP8266

Learn how to MicroPython Programming with ESP32 and ESP8266, a re-implementation of Python programming language for microcontrollers.

Apart from a few minor differences, programming in MicroPython is very similar to programming in Python since it shares all of Python's language capabilities. MicroPython does not by default include the whole standard library since embedded systems and microcontrollers have far more limited capabilities than our PCs.

MicroPython programming is identical to Python programming if you already know how to do it. You only need to keep in mind that MicroPython is only used for restricted devices. As a result, you may expect to see a lot of traffic on your website.

This article explains the Python programming language syntax basics that also apply to MicroPython, like:

  • Mathematical operators
  • Relational operators
  • Data types
  • print() function
  • Conditional statements
  • While and for loops
  • User defined functions
  • Classes and objects
  • Modules

Prerequisites

We're going to use the uPyCraft IDE in this tutorial, but you may use any other program. Follow these next tutorials to install and get started with the uPyCraft IDE:

Mathematical Operators

Micropython is capable of doing mathematical operations. The following table shows the mathematical operators that are supported:

OperatorMathematical Operation
+Addition
Subtraction
*Multiplication
/Division
//Division, discarding the decimal point
%Remainder after division

In the Shell, try several operations to see how they work. For example:

>>> 2+2*9-3
17
>>> 28594/2312
12.36765
>>> 214522236/7.5
2.860297e+07
>>> 23//2
11
>>> 25%3
1

If you import the math module, you may perform more mathematical operations like square root, trigonometric functions, logarithms, exponentiation, etc.

Relational Operators

By using relational operators, comparisons may be performed. These show the relation between the two values and compare the values on each side.

OperatorDescription
==Equal to
!=Not equal to
>Greater than
<Less than
>=Greater than or equal to
<=Less than or equal to

Try several comparisons and test the result:

>>> 2 == 3
False
>>> 4 == 4
True
>>> 3 > 2
True
>>> 489808234 != 2223
True
>>> 4.5 >= 4.5
True

Assigning Values to Variables

You don't need to declare the type of each variable in Python. You know that you need to declare the type of a variable when adding a new variable if you're used to programming your boards using the Arduino IDE. In Python, there is a thing.

For values like text or numbers, variables are simply storage placeholders. The equal sign (=), with the variable name on the left and the value on the right, is used to assign a value to a variable.

For example, you might simply type the following to create a variable to hold the GPIO number where an LED is connected:

led_pin = 23

In the Arduino IDE, you would have something like:

const int led_pin = 23;

As you can see, Python is much simpler than programming in C (in Arduino IDE).

Note: The variable names you give must be case-sensitive and cannot include spaces; thus, led_pin differs from LED_PIN or Led_Pin.

Data Types

Variables don't simply store whole numbers; they may also store other types of values. This is where data types come into play. A data type classification tells what operations may be done with a value and how it should be stored.

The following table shows the data types we’ll use most often in our projects.

Data typeDescription
int (Int)Integer (whole number)
float (Float)Number with a decimal point
str (String)Set of characters between quotation marks
bool (Boolean)True or False

Let’s create variables with different data types:

>>> a = 6
>>> b = 95.32
>>> c = 'Hello World!'
>>> d = True
  • The first value assigned to a is an integer, which is a whole number.
  • The b variable contains a float value, which is a number with a decimal.
  • The third value, ‘Hello World!’, is a string, which is a series of characters. A string must be put inside single (‘Hello World!’) or double quotation (“Hello World!”) marks.
  • Finally, d is a Boolean, which is a type that can only take either True or False.

The type() function may be used to check the data type of a variable. This function accepts as an argument the variable whose data type you wish to check.

type(variable)

For example, after declaring the variables in the previous example (abc, and d), you can check their data type. For example, if you type:

>>> type(a)

It returns:

<class 'int'>

This tells us that a is an int (integer). Experiment with the other variables, and you should get:

>>> type(b)
<class 'float'>
>>> type(c)
<class 'str'>
>>> type(d)
<class 'bool'>

print() Function

Between the brackets, the print() function prints the message into the Shell. Debugging the code and keeping track of what's going on is very useful in our projects. For example:

>>> print('LED is on')
LED is on

Comments

Python comments start with the hash character (#) and go all the way to the end of the line. A comment is useful to add “notes” to your program or to tell everyone who reads the script what the program does. Your program doesn't get any more functionality as a result of this. For example:

# This is just a comment

There are occasions when you should avoid adding comments to save space on the ESP memory since we are working under constrained conditions in MicroPython.

Conditional Statements

You'll probably need to perform various actions based on whether a given condition is True or False to write useful programs. Conditional statements are what we're talking about. The following describes their structure:

if <expr1>:
  <statement1>
elif <expr2>:
  <statement2>
elif <expr3>:
  <statement3>
(...)
else:
  <statementn>

<expr> is a Boolean expression, and it can be either True or False. If it is True, the <statement> right after it is executed. The <statement> should be indented so that Python knows what statement belongs to each expression.

The elif statement stands for else if and runs only if the first if condition is not True.

The else statement only runs if none of the other expressions are True.

A program may have an unlimited number of elif statements. It's not required to include another clause, but if there is one, it must come at the end.

Curly brackets are used in the Arduino IDE to define code blocks. We use indentation with MicroPython. After each expression, you also need to include a colon (:). The expression does not need to be enclosed inside parentheses, unlike the Arduino IDE.

Important: Four spaces are the standard indentation in Python. To fit more code into the memory of the microcontroller, the indentation in MicroPython should only be 2 spaces.

While and For loops

As long as a condition is satisfied, loops let you execute a piece of code multiple times. While and for loops are two different types of loops. For instance, using a while loop, you can print all the numbers between 1 and 10:

number = 1
while number <= 10:
  print(number)
  number = number + 1

As long as the number variable's value is less than or equal to (<=) 10, the while loop's code, which is shown by the indentation, is executed. Every loop prints the current number, followed by an addition of 1.

You can also print numbers from 1 to 10 using a for loop, like this:

number = 1
for number in range(1, 11):
  print(number)

As long as the value of the long variable falls between the range of 1 and 11, the for loop will execute. The range() function automatically assigns the next value to the next variable until it is one lower than the final value you specify.

When you wish to repeat a block of code a certain number of times, you should use a for loop. When you want to repeatedly run code until a certain condition is no longer true, use a while loop. Then, if you're lucky enough to have a job, you may be able to get away with it.

The for and while Boolean expressions should have a colon right after them, much like the conditional statements, and the expressions that will be executed should be indented.

User-defined Functions

You use the word def, followed by the side you wish to give the function, and a set of brackets to define a new function. Add a colon after the parentheses, then tell the function what to do. In MicroPython, the statements must be indented by two spaces. For example:

def my_function(<arg1>, <arg2>, ...):
  <statement>
  (...)
  return

For example, a function that converts the temperature in Celsius to Fahrenheit could be the following:

def celsius_to_fahrenheit(temp_celsius): 
  temp_fahrenheit = temp_celsius * (9/5) + 32 
  return temp_fahrenheit

The celsius_to_fahrenheit() function accepts as an argument a temperature in Celsius (temp_celsius). Then, it does the calculation to convert the temperature. Finally, it returns the temperature in Fahrenheit (temp_fahrenheit).

Note: Functions don’t necessarily need to return something. They could just perform some work without needing to return anything.

Classes and Objects

Python is a language for object-oriented programming (OOP). Classes and objects are two crucial OOP ideas that you should comprehend.

A class is an object's blueprint. It specifies a set of characteristics (data and function) for an object. Methods are the names given to the functions found inside a class. The class keyword is used to define classes, followed by the class name. For example:

class MyClass:
  (...)

Note: By convention, classes’ names in Python should be CapWords. However, you can give it whatever name you want.

A class's instances are objects. Simply put, it is a single entity made up of data and methods. All the functions of the object's class are accessible through it. Confused? Take a look at a simple example.

We may think of the term “person” as a class if we'd like to define several persons in a Python program using the same attributes. Using attributes like name, age, nationality, etc., we may wish to define a person.

MicroPython Programming with ESP32 and ESP8266: objects class

Therefore, a class named “Person” may be created. The attributes of our class will be as follows: name, age, and country. As many attributes as you want may be added. We'll also create a method (function) that prints a summary of the person depending on its attributes:

class Person:
  name = ""
  age = 0
  country = ""
  def description(self):
    print("%s is %d years old and he is from %s." %(self.name, self.age, self.country))

You can see that we define a new class by using the keyword class, followed by the name we wish to give the class.

We define a number of variables that may store values within the Person class. By default, the age is 0, and the name and country are empty strings. The function (method) that prints all the values of the variables into the Shell is then also defined.

The self-parameter should be an argument for all functions inside a class, along with any other arguments that may be required.

The self parameter refers to the actual object. It is used to get access to variables belonging to the class. To access the name variable inside the class, for example, we should use self.name.

We can produce as many Person objects as we desire by using the class we just built. A name, an age, and a nation will be included in the Person object. Using the description() method, we can also print its description.

For example, to create a new Person object called person1:

>>> person1 = Person()

Set the object’s properties

To set the nameage, and country of the person1 object. You can do it as follows:

>>> person1.name = "Rui"
>>> person1.age = 25
>>> person1.country = "Portugal"

Calling methods

Later in your code, you can use the created description() method on any Person object. To call the description() method on the person1 object:

>>> person1.description()

This should print the following:

Rui is 25 years old and he is from Portugal.

You should now understand that you are able to create as many objects as you want using the same class and that you can use the available methods with all of that class's methods.

MicroPython Programming with ESP32 and ESP8266: creating objects

The constructor method

You may use the constructor method inside your class instead of having to define a class and then set the object's properties, which can be time-consuming.

As soon as a class object is created, data is started using the constructor method. Also known as the __init__ method, the constructor method is a method. The Person() class looks as follows when using the __init__ method:

class Person():
  def __init__(self, name, age, country):
    self.name = name
    self.age = age
    self.country = country
  def description(self):
    print("%s is %d years old and he is from %s." %(self.name, self.age, self.country))

Then, to instantiate a Person object with the same attributes we’ve defined earlier, we just need to do the following:

>>> person1 = Person("Rui", 25, "Portugal")

If you call the description() on the person1 object, you’ll get the same result:

>>> person1.description()
Rui is 25 years old and he is from Portugal.

Modules

You may use a set of classes and functions from a module in your code. A module is a file. It's possible to call it a library if you want to, but it's not a must. You just need to import that class into your code to have access to the classes and functions inside that code.

Use pre-made modules from the standard Python library or create your own. When it comes to MicroPython, it only comes with a small portion of the standard Python library, but it does come with a set of modules to control GPIOs, make network connections, and much more.

Importing modules/libraries is as simple as using:

import module_name

For example, to import the machine library that contains classes to control GPIOs, type the following:

import machine

You won't need all the classes in one module for the majority of programs. Just a single class may be what you wish to import. To import only the Pin class from the machine module, for example.

from machine import Pin
from machine import pin Copy

Conclusion

The basics of Python that also apply to MicroPython have just been touched on in this tutorial. You'll find that MicroPython has a far more straightforward and user-friendly syntax if you're accustomed to programming electronics using the Arduino IDE. Let's just summarise a few of the key differences between your Arduino sketches and MicroPython programs:

  • You don’t use a semicolon at the end of a statement.
  • After Boolean expressions in conditional statements and loops, you use a colon:.
  • To define code blocks, use indentation instead of curly brackets {}.
  • When creating a variable, you don’t need to define which data type it is; you don’t need to declare a variable.
  • Indentation in MicroPython is 2 spaces.

If you like MicroPython, you may also like:

We hope you find this tutorial useful. Thanks for reading.

Oh hi there It’s nice to meet you.

Sign up to receive awesome content in your inbox, every month.

We don’t spam! Read our privacy policy for more info.

Leave a Reply

Your email address will not be published. Required fields are marked *

Developing IoT Projects with ESP32

Automate your home or business with inexpensive Wi-Fi devices

ESP8266 Home Automation Projects

Leverage the power of this tiny WiFi chip to build exciting smart home projects