MicroPython is a software implementation of the Python 3 programming language for microcontrollers. Almost all major microcontroller platforms are supported by MicroPython firmware.
MicroPython facilitates embedded systems development in two ways. On the one hand, it allows users to program microcontrollers and microcomputers in a common programming language (such as Python, which is currently the most popular programming language for developing networked embedded applications on microcomputers). MicroPython brings the same syntax and programming features to microcontroller platforms.
Secondly, Python is a high-level programming language with a clean and weakly typed syntax, especially compared to embedded C. This allows users to access several high-level programming features with microcontrollers, making programming of networked embedded applications possible.
Understanding MicroPython
Since MicroPython is a subset of the Python 3 programming language, it shares the same syntax and programming style. However, MicroPython is intended for use with microcontrollers and low-level hardware platforms, so it has language-related limitations.
Its libraries include the rewritten Python 3 standard libraries, as well as others written from scratch to manage hardware-specific functions and resources. As a result, even an experienced Python developer may encounter syntax errors and programming bugs if they follow standard Python when scripting MicroPython codes.
To get the most out of this article, be sure to load your MicroPython firmware onto a compatible microcontroller board such as ESP, Arduino, Raspberry Pi Pico, or Pyboard. Also, make sure your MicroPython programming environment includes uPyCraft or Thonny IDE.
Next, we'll look at programming fundamentals to help MicroPython and Python programmers recognize the key differences between the two.
Importing modules
The first statements in a MicroPython script are import modules. Each MicroPython program uses one or more modules. Machine and/or time modules are used in all embedded applications running in MicroPython.
Already available modules/libraries are ideal for saving time and focusing on new developments. Modules or libraries are a collection of functions and classes written for specific tasks/applications and are excellent for organizing similar and related blocks of code. Developers can also write their own modules to add or support new functions and features.
In MicroPython scripts, modules are imported using this syntax:
import module_name
Because MicroPython codes are typically loaded on microcontrollers that have limited RAM and flash memory, you can import specific classes from a module using this syntax:
from module_name import class_name
In fact, several classes from a module can be imported in a single statement using:
from module_name import class_name1, class_name2
Here are some examples of importing modules in MicroPython:
import machine
Machine Import Pin
Pin machine import, PWM
machine import, Pin, PWM, ADC, ADCBlock
Data types
Just as the name implies, data types are the data types supported in a programming language. Data types specify the type of value and what operations can be performed on that type.
There are five data types supported in MicroPython:
1. Integers (int): stores positive and negative integers, including zero
2. Float (float): stores positive and negative decimal numbers, including zero
3. String (str): stores a set of text characters enclosed in quotation marks
4. Boolean (bool): stores True or False — an expression that results in a non-zero value is considered True and an expression that results in a value equal to zero is considered False.
5. Object (obj): an instantiation of a class, which provides access to all properties and methods of a specified class
Much like Python, MicroPython is a weakly typed language. This means that variables must not be explicitly declared with specific data types. Instead, variables can be instantiated anywhere in the code and the data type is assumed based on the value assigned to them.
However, the type of a variable can be confirmed by calling the type(variable) method, which is useful if data validation is required.
Variables
Variables are the placeholders for data values. The value stored in a variable can change during a program.
In MicroPython, the data type for variables does not need to be defined and is instantiated by assigning a value to an identifier.
Examples:
newPWMfreq = 10
defPWMfreq = 1000
msg = “Data recorded on SD card”
Variables can be instantiated anywhere in the code. Its data type is automatically assumed or changed based on the value assigned to it.
Variables for instantiating class objects are defined by assignment to the constructor function. For example, this statement instantiates a variable as a pin object:
led = Pin (5, Pin.OUT)
Identifiers used as variable names must begin with a letter or underscore and can contain numbers, letters, and underscore. Although special characters are not allowed in variable names. By convention, functions and classes should have camel-shaped identifiers, and variables should have all lowercase identifiers.
Examples of valid variable names:
led
led2
adc1_2
Examples of invalid variable names:
1led
took&1
Comments
Comments are an excellent way to document scripts. MicroPython allows shell-style comments, which are single-line comments starting with the hash character (#). Everything from the hash character to the end of the line is considered a comment and is not part of the executed script.
In MicroPython scripts, comments should only be used minimally or if they are unavoidable. This is because a large number of comments in the code can significantly increase the size of the executing script and compromise the target port's flash memory. (Note: Script files are loaded into the target microcontroller's flash memory.) They are also not converted to an executable as they are in other programming languages, such as embedded C.
Examples of MicroPython comments:
led = Pin (5, Pin.OUT) #LED connected to GPIO5
#function to read sensor data via UART
Mathematical operators
MicroPython allows arithmetic operations. Supported math operators include: addition (+), subtraction (-), multiplication
division (/), remainder after division (%) and division discarding decimal point (//).
Additional mathematical operations and constants can be accessed by importing the math module. The module provides two constants: math.and math.pi.
Functions available in the MicroPython math module include: math.acos(x), math.acosh(x), math.asin(x), math.asinh(x), math.atan(x), math.atan2(y , x), math.atanh(x), math.ceil(x), math.copysign(x, y), math.cos(x), math.cosh(x), math.degrees(x), math. erf (x), math.erfc(x), math.exp(x), math.expm1(x), math.fabs(x), math.floor(x), math.fmod(x, y), math . freexp(x), math.gamma(x), math.isfinite(x), math.isinf(x), math.isnan(x), math.ldexp(x, exp), math.lgamma(x), math .log(x), math.log10(x), math.log2(x), math.modf(x), math.pow(x, y), math.radians(x), math.sin(x), math.sinh(x), math.sqrt(x), math.tan(x), math.tanh(x) and math.trunc(x).
Examples of mathematical operators:
5*8+9
>>>49
589/256
>>>2.3007815
2022%4
>>>2
Relational operators
Relational operators are used to compare values. These operators are useful for writing conditional statement expressions.
Relational operators supported in MicroPython include: equal to (==), not equal to (!=), greater than (>), less than (<), greater than or equal to (>=), and less than or equal to (<= ).
Expressions that use relational operators use only two operands, which are placed on each side of the relational operator. The result of an expression of a relational operator is always True or False.
Examples of relational operators:
5>3
>>> Truth
2/3 = 1.5
>>> Truth
5.3 >= 5.3
>>> Truth
Conditional statements
Conditional statements are used to evaluate conditions based on comparing values. Two values are compared in an expression using relational operators. The result of the expression is True or False. If the result of the relational expression is True, the body of the condition is executed — otherwise, it is ignored during program execution.
In MicroPython, comparison can be between integer values and strings. Methods called on an object can also return True or False. The conditional body includes one or more program instructions.
Unlike embedded C, the body of the conditional is not enclosed in square brackets. Instead, your goal is to group together a single block of code. Only the use of a colon is necessary after the conditional expression.
There are three conditional statements supported in MicroPython: 1. if statement:
tests a single expression and executes or skips a block of code, depending on the result.
A valid MicroPython example when the “if” statement is conditional:
one = 1
b = 2
if (a == b):
print(“a and b are equal”) 2. else statement:
tests a single expression and executes or skips a block of code, depending on the result. If the expression is False, a block of code will be defined after the “else” statement is executed.
A valid MicroPython example when the “else” statement is conditional:
one = 1
b = 2
if (a == b):
print(“a and b are equal”)
other:
print(“a and b are not equal”) 3. elif statement:
tests multiple conditions and, based on a match, executes one of the code blocks. After an expression is matched, a block of code for the given expression is executed and the program exits the condition.
A valid MicroPython example when the “elif” statement is conditional.
one = 3
if (a == 0):
print(“a is equal to 0”)
Elif (a == 1):
print(“a is equal to 1”)
Elif (a == 2):
print(“a is equal to 2”)
Elif (a == 3):
print(“a is equal to 3”)
other:
print(“a receives no value”)
In MicroPython, an indent requires only two spaces (an indent in Python3.x uses four). This is done to minimize the size of the execution script as it must be loaded on memory-constrained microcontrollers.
Classes and objects
Just as Python is an object-oriented programming language, so is MicroPython, which is a reimplementation of Python 3. In object-oriented programming, real-life entities are first modeled as objects. Defining a model for certain objects is called a class.
The attributes of these entities are specified with the help of the variables associated with a particular class. These variables are called properties or attributes. The computational operations associated with the entities are expressed as the definitions of functions associated with the given class. These functions are called methods.
In MicroPython, the definition of a class begins with the keyword “class”, followed by the class name and a pair of parentheses. The class name is followed by a colon (:) to begin the class definition.
The prototype of a class in MicroPython:
class class_name:
class_definition
The definition of a class includes the instantiation of associated properties/attributes, a constructor, and the definition of class-specific methods. Properties or attributes are instantiated as variables with the body of a given class.
Example:
DHT11 class:
pin = 0
temperature = 0
hum = 0
In the code above, pin, temp and hum are the properties/attributes of the DHT11 class. If properties/attributes are referenced in the class definition, the “self” keyword will be used. Outside the class definition, attributes are accessed by the object name, followed by a period (.) and the attribute name.
A valid example of calling an attribute within a class definition:
DHT11 class:
pin = 0
temperature = 0
hum = 0
def getTemp:
….
self.temp = temp
print(self.temp)
A valid example of accessing the attributes of a class outside its definition:
DHT11 class:
pin = 0
temperature = 0
hum = 0
dht = DHT11
currentTemp = dht.temp
The definition of a class can include one or more methods. Methods are used to perform computational operations on class attributes and/or global variables. Methods are defined as functions within a class body.
Example of defining a method for a given class:
DHT11 class:
pin = 0
temperature = 0
hum = 0
def getTemp:
return self.temp
If a method needs to be accessed within a class definition, the “self” keyword is used. If it needs to be accessed outside the class definition, it must be called by the class name, followed by a period (.) and the method name.
Example of a method call within a class definition:
DHT11 class:
pin = 0
temperature = 0
hum = 0
def getTemp:
return self.temp
def printTemp:
temperature = self.getTemp
print(“Temperature:“)
print (temperature)
Example of calling a method outside a class definition:
DHT11 class:
pin = 0
temperature = 0
hum = 0
def getTemp:
return self.temp
dht = DHT11
temperature = dht.getTemp
The values of mandatory attributes of a class can be assigned as soon as an object of a given class is instantiated. This first requires defining a constructor method. The constructor method explicitly sets the default values for attributes or assigns the values of essential attributes by passing arguments.
The constructor method is defined using the __init__ function. If the value of attributes is user-defined, the constructor definition uses one or more parameters.
Example of a constructor that explicitly sets attribute values:
class login:
username = user
password = password
def __init__ :
self.user = “root”
self.password = “raspberry”
logcredentials = login
Example constructor that allows the user to specify the value of required class attributes:
DHT11 class:
pin = 0
temperature = 0
hum = 0
def __init__(pin):
pin = self.pin
dhtpin = Pin(5, Pin.IN)
dht11 = DHT11(dhtpin)
An object of a given class is instantiated by calling the constructor method. Outside the class definition, the constructor method has the same name as the class name.
A valid example of defining a class, instantiating an object of the class and using its attributes and methods:
DHT11 class:
pin = 0
temperature = 0
hum = 0
def __init__(pin):
pin = self.pin
def getTemp:
….
def getHumdity :
….
dhtpin = Pin(5, Pin.IN)
dht11 = DHT11(dhtpin)
dht11.getTemp
dht11.getHumidity
if dht11.temp > 25:
…
Conclusion
In this article, we cover the basics of MicroPython programming, a subset of Python 3 – meaning that MicroPython shares much of the same syntax and object-oriented programming as Python 3. However, there are slight differences and Python developers may experience errors of syntax and bugs if they apply their knowledge of Python only to the MicroPython domain.
The fundamentals of Pythonic syntax programming features are applicable in MicroPython scripts, which are covered in this article. These language basics can serve as the basis for your MicroPython scripts.