diff --git a/content/micropython/00.first-steps/00.intro-micropython/assets/micropython-arduino.png b/content/micropython/00.first-steps/00.intro-micropython/assets/micropython-arduino.png new file mode 100644 index 0000000000..54cc1e3b3b Binary files /dev/null and b/content/micropython/00.first-steps/00.intro-micropython/assets/micropython-arduino.png differ diff --git a/content/micropython/00.first-steps/00.intro-micropython/assets/run-script.gif b/content/micropython/00.first-steps/00.intro-micropython/assets/run-script.gif new file mode 100644 index 0000000000..57e942f891 Binary files /dev/null and b/content/micropython/00.first-steps/00.intro-micropython/assets/run-script.gif differ diff --git a/content/micropython/00.first-steps/00.intro-micropython/intro-micropython.md b/content/micropython/00.first-steps/00.intro-micropython/intro-micropython.md new file mode 100644 index 0000000000..4329e46b24 --- /dev/null +++ b/content/micropython/00.first-steps/00.intro-micropython/intro-micropython.md @@ -0,0 +1,61 @@ +--- +title: 'Introduction to MicroPython' +description: 'Learn about the fundamentals of Micropython on Arduino boards.' +author: 'Pedro Lima' +tags: [MicroPython, Introduction] +micropython_type: test +--- + +MicroPython is a lightweight implementation of Python 3 designed to run on microcontrollers and embedded systems. Think of it as a mini-version of Python, tailored for hardware with limited resources like memory and processing power. Despite its smaller size, MicroPython retains the simplicity and flexibility of Python, making it an excellent option for programming hardware. + +## MicroPython on Arduino Boards + +![MicroPython with Arduino](assets/micropython-arduino.png) + +When using MicroPython on Arduino boards, the software is first installed on your Arduino. This allows the board to interpret and run Python code. Once MicroPython is installed on your board (don't worry, we'll cover this [here](/micropython/first-steps/install-guide)), you can start writing and executing Python scripts instantly. + +Unlike traditional development approaches, where you compile code and then flash it to the board, with MicroPython you write Python scripts and run them instantly on your Arduino. This makes the development process much faster and more interactive. + +## Running Programs in MicroPython + +Once MicroPython is installed, you can start programming by writing scripts and uploading them to the board. These scripts are interpreted in real-time, meaning you can make quick changes and see immediate results, streamlining the development process. + +![Running a script.](assets/run-script.gif) + +MicroPython also includes a simple file system where your scripts are stored. For example, when you write a script, it is saved directly on the board and can be executed immediately without compiling. You can also save other scripts that can be activated from the main script! + +### How it Works + +The MicroPython installation includes several key components: + +1. **File System**: MicroPython has a small file system built into the microcontroller. You can store Python scripts and configuration files on the board itself. Common files include: + - `main.py`: This script runs automatically when the board boots up. It's where you can put the main logic of your program. + - `boot.py`: This script runs before `main.py` and is often used for setting up configurations like WiFi connections or hardware initialization. + + These files are fully editable, allowing you to control how your board starts and operates. + +2. **Base Modules**: MicroPython comes with built-in modules for working with hardware like pins, sensors, and communication protocols (I2C, SPI, etc.). This includes essential modules like `machine`, `network`, and `time`. + +## How to Program for MicroPython + +Programming in MicroPython involves writing Python scripts in a text editor and then running them on your board. For this, we can use the [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython). + +When writing MicroPython code, it's essential to think in terms of **modularity**. A good practice is to break down your code into smaller, reusable modules rather than writing everything in one large file. This approach makes it easier to manage and maintain code, especially for larger projects. + +### Structuring Your Code + +1. **Main Logic**: This goes into the `main.py` file. You can think of it as your "sketch" in Arduino terms. +2. **Helper Modules**: Break down your code into smaller modules for specific tasks, such as controlling a sensor or managing a display. These modules can be imported into `main.py` as needed. +3. **Interrupts and Background Tasks**: If you're dealing with hardware, you may also need to work with interrupts or periodic tasks, which can be handled in dedicated modules. + +## MicroPython vs. C++ for Electronics Projects + +MicroPython offers a different approach to programming compared to the traditional C++ used in Arduino development. Here are a few key comparisons: + +- **Ease of Use**: Python’s syntax is generally more accessible for beginners. It is less verbose and easier to read, which can speed up the learning process. +- **Real-Time Interactivity**: With MicroPython, you can write and test code interactively, without needing to compile. This makes it faster to experiment and troubleshoot hardware setups. +- **Resource Efficiency**: C++ is more efficient in terms of memory and speed, making it a better option for projects that need to squeeze every bit of performance out of the hardware. MicroPython, on the other hand, prioritizes ease of development over raw performance, but it is still capable of handling many common hardware tasks. + +## Summary + +In summary, MicroPython provides a powerful and flexible way to develop electronic projects, especially for those familiar with Python. Its ability to run on microcontrollers like Arduino boards makes it an attractive option for both beginners and experienced developers who want a fast and efficient workflow. diff --git a/content/micropython/00.first-steps/01.install-guide/assets/installation-success.png b/content/micropython/00.first-steps/01.install-guide/assets/installation-success.png new file mode 100644 index 0000000000..391d7a23ff Binary files /dev/null and b/content/micropython/00.first-steps/01.install-guide/assets/installation-success.png differ diff --git a/content/micropython/00.first-steps/01.install-guide/assets/repl-print.png b/content/micropython/00.first-steps/01.install-guide/assets/repl-print.png new file mode 100644 index 0000000000..aac4677254 Binary files /dev/null and b/content/micropython/00.first-steps/01.install-guide/assets/repl-print.png differ diff --git a/content/micropython/00.first-steps/01.install-guide/assets/select-board-ide.png b/content/micropython/00.first-steps/01.install-guide/assets/select-board-ide.png new file mode 100644 index 0000000000..d144bafe37 Binary files /dev/null and b/content/micropython/00.first-steps/01.install-guide/assets/select-board-ide.png differ diff --git a/content/micropython/00.first-steps/01.install-guide/assets/select-board.png b/content/micropython/00.first-steps/01.install-guide/assets/select-board.png new file mode 100644 index 0000000000..6d1d2ec20f Binary files /dev/null and b/content/micropython/00.first-steps/01.install-guide/assets/select-board.png differ diff --git a/content/micropython/00.first-steps/01.install-guide/assets/usb-comp.png b/content/micropython/00.first-steps/01.install-guide/assets/usb-comp.png new file mode 100644 index 0000000000..e3c90f42cd Binary files /dev/null and b/content/micropython/00.first-steps/01.install-guide/assets/usb-comp.png differ diff --git a/content/micropython/00.first-steps/01.install-guide/assets/write-code-run.png b/content/micropython/00.first-steps/01.install-guide/assets/write-code-run.png new file mode 100644 index 0000000000..277bc44409 Binary files /dev/null and b/content/micropython/00.first-steps/01.install-guide/assets/write-code-run.png differ diff --git a/content/micropython/00.first-steps/01.install-guide/installing-micropython.md b/content/micropython/00.first-steps/01.install-guide/installing-micropython.md new file mode 100644 index 0000000000..8848312c00 --- /dev/null +++ b/content/micropython/00.first-steps/01.install-guide/installing-micropython.md @@ -0,0 +1,114 @@ +--- +featured: micropython-101 +title: 'Installing MicroPython' +description: 'Learn how to install MicroPython on your Arduino board.' +author: 'Pedro Lima' +tags: [MicroPython, Installation] +micropython_type: test +--- + +# Installing MicroPython + +In this article, we will go through the necessary tools needed to install and run MicroPython on an Arduino board. By the end of this guide, we will be ready to write and run our first MicroPython script. Let's get started! + +## Requirements + +Before we start, let's check the requirements: + +### MicroPython Compatible Arduino Boards + +MicroPython is officially supported on several Arduino boards. Here’s a list of the compatible boards: + +- [Portenta C33](https://store.arduino.cc/products/portenta-c33) +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/arduino-giga-r1-wifi) +- [Portenta H7](https://store.arduino.cc/products/portenta-h7) +- [Portenta H7 Lite](https://store.arduino.cc/products/portenta-h7-lite) +- [Portenta H7 Lite Connected](https://store.arduino.cc/products/portenta-h7-lite-connected) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) +- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) +- [Arduino Nano 33 BLE](https://store.arduino.cc/products/arduino-nano-33-ble) +- [Arduino Nano 33 BLE Rev2](https://store.arduino.cc/products/nano-33-ble-rev2) +- [Arduino Nano 33 BLE Sense Rev2](https://store.arduino.cc/products/arduino-nano-33-ble-sense-rev2) +- [Arduino Nano ESP32](https://store.arduino.cc/products/arduino-nano-esp32) + + +### Software Requirements + +- [MicroPython Firmware Installer](https://labs.arduino.cc/en/labs/micropython-installer) - the firmware installer is needed to install MicroPython on our Arduino board. +- [Arduino Lab for Micropython](https://labs.arduino.cc/en/labs/micropython) - Arduino Lab for MicroPython is an editor where we can create and run MicroPython scripts on our Arduino board. + +***Note that the editor is also available online, at [Arduino Cloud - Arduino Labs for MicroPython](https://lab-micropython.arduino.cc/)*** + +## Install MicroPython + +1. First, download the [Micropython Firmware Installer](https://labs.arduino.cc/en/labs/micropython-installer) and launch it. +2. Connect your board to your computer, it should be recognized by the installer. + ![Arduino Nano ESP32 detected!](./assets/select-board.png) +3. Press **INSTALL MICROPYTHON**. A loading animation will appear. + + Once the firmware is installed a "Installation successful" message will appear. At this point you can safely close the installer as your board is now ready for tinkering! + ![Firmware Successfully Uploaded!](./assets/installation-success.png) + +## Editor Setup + +After installing MicroPython on your board, we will need an editor to write code. We now have the option to choose the **offline** or **online** option. + +### Offline Setup + +First, download the latest version of [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) for your operative system. See instructions for MacOS / Windows below: + +#### MacOS + +Unzip the downloaded file, and run the application. + +#### Windows + +Unzip the downloaded file, and run the executable file (`.exe`). + +### Online Setup + +Alternatively, we can use the IDE without the need of installing anything. Simply visit the link below: +- [Arduino Lab for MicroPython (online)](https://lab-micropython.arduino.cc/). + +## Connecting Board and IDE + +At this point in the tutorial, we have +- Installed MicroPython on our board +- Downloaded and installed the editor (or opted for the online version). + +We will now try out running a script on the board, to make sure things are working properly. + +1. Plug the Arduino board into the computer using a USB cable. + ![Connect board to computer.](assets/usb-comp.png) +2. Press the connection button on the top left corner of the window. The connected Arduino board should appear (by its port name), and we can click it: + ![Connect to the board in the editor.](assets/select-board-ide.png) + +We have now set up all necessary steps for running a script! + +## Running a Test Script + +With the installation and setup complete, let's try out running a very simple script: **Hello World!** + +1. In the text area field of the editor, write `print("Hello World!")`, and then click on the play symbol (RUN). + ![Write hello world.](assets/write-code-run.png) +2. After running it, you should see `Hello World!` in the black box. This is the board sending the **"Hello World!"** back to you, because the script is run on the board, not on the computer. This means everything is successful, and you are ready to start writing MicroPython scripts! + ![Hello world from the board.](assets/repl-print.png) + +## Troubleshooting + +If you run into any issues during installation, here are some common problems and solutions: + +- **Board Not Detected** - if you cannot locate your board, ensure that your board is properly connected and the correct USB drivers are installed. Try using a different USB cable, or double tap the reset button on the board. If a light starts fading, it means it is in default mode, and is ready to be installed! + +- **Unable to Install Firmware** - double-check that the MicroPython Firmware Installer was able to install the firmware and that your board is compatible (it will not show up on the installer if it is not). Also, verify that no other software is using the same serial port. + +## Summary + +By following these steps, you should be able to successfully install MicroPython on your Arduino board and run your first script. + +### Next Steps + +This tutorial is **Part Two** of the **"First Steps"** series. We recommend you following the next tutorial that will allow you to control the Arduino board's LED. +- [First Steps - My First Script](/micropython/first-steps/first-script) + + diff --git a/content/micropython/00.first-steps/02.first-script/assets/blink.gif b/content/micropython/00.first-steps/02.first-script/assets/blink.gif new file mode 100644 index 0000000000..bbf186abc7 Binary files /dev/null and b/content/micropython/00.first-steps/02.first-script/assets/blink.gif differ diff --git a/content/micropython/00.first-steps/02.first-script/assets/open-files.png b/content/micropython/00.first-steps/02.first-script/assets/open-files.png new file mode 100644 index 0000000000..ebf777e46c Binary files /dev/null and b/content/micropython/00.first-steps/02.first-script/assets/open-files.png differ diff --git a/content/micropython/00.first-steps/02.first-script/assets/run-script.png b/content/micropython/00.first-steps/02.first-script/assets/run-script.png new file mode 100644 index 0000000000..b45b9ca0c6 Binary files /dev/null and b/content/micropython/00.first-steps/02.first-script/assets/run-script.png differ diff --git a/content/micropython/00.first-steps/02.first-script/assets/select-board-ide.png b/content/micropython/00.first-steps/02.first-script/assets/select-board-ide.png new file mode 100644 index 0000000000..d144bafe37 Binary files /dev/null and b/content/micropython/00.first-steps/02.first-script/assets/select-board-ide.png differ diff --git a/content/micropython/00.first-steps/02.first-script/assets/usb-comp.png b/content/micropython/00.first-steps/02.first-script/assets/usb-comp.png new file mode 100644 index 0000000000..e3c90f42cd Binary files /dev/null and b/content/micropython/00.first-steps/02.first-script/assets/usb-comp.png differ diff --git a/content/micropython/00.first-steps/02.first-script/first-script.md b/content/micropython/00.first-steps/02.first-script/first-script.md new file mode 100644 index 0000000000..07436709c6 --- /dev/null +++ b/content/micropython/00.first-steps/02.first-script/first-script.md @@ -0,0 +1,180 @@ +--- +title: 'My First Script' +description: 'Learn how to write a basic MicroPython script to blink an LED.' +author: 'Pedro Lima' +tags: [MicroPython, Blink] +micropython_type: test +--- + +In this tutorial, we will create our very first MicroPython script that will run on an Arduino board. Starting of simple, we will make an LED blink, a classic beginner project that will get us familiar with the MicroPython programming environment. + +## Requirements + +Before we start, let's check the requirements: + +### MicroPython Compatible Arduino Boards + +MicroPython is officially supported on several Arduino boards. Here’s a list of the compatible boards: + +- [Portenta C33](https://store.arduino.cc/products/portenta-c33) +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/arduino-giga-r1-wifi) +- [Portenta H7](https://store.arduino.cc/products/portenta-h7) +- [Portenta H7 Lite](https://store.arduino.cc/products/portenta-h7-lite) +- [Portenta H7 Lite Connected](https://store.arduino.cc/products/portenta-h7-lite-connected) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) +- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) +- [Arduino Nano 33 BLE](https://store.arduino.cc/products/arduino-nano-33-ble) +- [Arduino Nano 33 BLE Rev2](https://store.arduino.cc/products/nano-33-ble-rev2) +- [Arduino Nano 33 BLE Sense Rev2](https://store.arduino.cc/products/arduino-nano-33-ble-sense-rev2) +- [Arduino Nano ESP32](https://store.arduino.cc/products/arduino-nano-esp32) + + +### Software Requirements + +- [Arduino Lab for Micropython](https://labs.arduino.cc/en/labs/micropython) - Arduino Lab for MicroPython is an editor where we can create and run MicroPython scripts on our Arduino board. + +***Note that the editor is also available online, at [Arduino Cloud - Arduino Labs for MicroPython](https://lab-micropython.arduino.cc/)*** + +## Board and Editor Setup + +1. Open the [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) application. +2. Plug the Arduino board into the computer using a USB cable. + ![Connect board to computer.](assets/usb-comp.png) +3. Press the connection button on the top left corner of the window. The connected Arduino board should appear (by its port name), and we can click it: + ![Connect to the board in the editor.](assets/select-board-ide.png) + +***Need help installing MicroPython on your board? Visit the [MicroPython installation guide](/micropython/first-steps/install-guide).*** + +## First Script (LED Blink) + +Once your board is connected, we can start writing code! Below you will find a basic example, that will flash the built in LED on your board every second. + +1. First, open the `main.py` file on your board. We write in this file, because once saved, the code will run even if you reset the board. + ![Open main.py file.](assets/open-files.png) + +2. Copy and paste the following code into your editor: + ```python + import machine + import time + + # The pin used for built-in LED varies + # GIGA: 0 (green), Nano ESP32: 0 (green), Nano RP2040 Connect: 25 + # Nano BLE Sense: 13 + led = machine.Pin(25, machine.Pin.OUT) + + while True: + led.value(1) + time.sleep(1) + led.value(0) + time.sleep(1) + ``` + + ***Note: The built-in LED pin varies from board to board. For example, on the Arduino Nano RP2040 Connect, the built-in LED is on pin `25`.*** + +3. Click the **Run** button in your editor to transfer the script to your board. + ![Run the script.](assets/run-script.png) + +Once the script is running, the LED on the board should start blinking at one-second intervals. This means our MicroPython script has loaded successfully. + +![LED blinking on your board.](assets/blink.gif) + +### Code Breakdown + +Let's take a look at the code, line by line, to understand what is happening: + +- **Import Modules**: + + ```python + import machine + import time + ``` + + We import the `machine` and `time` modules to access hardware functions and time delays. + +- **Initialize the LED Pin**: + + ```python + led = machine.Pin(25, machine.Pin.OUT) + ``` + + We create a `Pin` object named `led`, set to pin number `25`, and configure it as an output. + +- **Infinite Loop**: + + ```python + while True: + led.value(1) + time.sleep(1) + led.value(0) + time.sleep(1) + ``` + + Inside the loop, we: + + - Turn the LED on by setting its value to `1`. + - Wait for 1 second. + - Turn the LED off by setting its value to `0`. + - Wait for another second. + - Repeat the cycle. + +## Understanding Programming Concepts + +Let's break down the key programming concepts used in this script: + +### `machine` Module + +The machine module is a built-in MicroPython library that provides direct access to your board's hardware components. It allows you to control and interact with the microcontroller's features, such as: + +- **Pins:** Configure and control digital and analog pins. +- **Timers:** Set up timers for scheduling tasks. +- **Communication Interfaces:** Use protocols like I2C, SPI, and UART. +- **Hardware-Specific Functions:** Access features unique to your microcontroller. + +In our script, we use the `machine.Pin` class to interact with a specific pin on the board. By creating a `Pin` object, we can control the voltage level of that pin, which in turn controls the LED. + +### `time` Module + +The time module provides functions for managing time-related tasks. It allows you to add delays, measure time intervals, and schedule events. Key functions include: + +- `time.sleep(seconds)` Pauses the execution of your script for the specified number of seconds. It accepts floating-point numbers for sub-second delays. + +### `while True` Loop + +A `while True` loop creates an infinite loop, allowing the code inside it to run repeatedly. This is essential for tasks that need to run continuously, like blinking an LED. + +## Modification: Make the LED Blink Faster + +Let's modify the script to make the LED blink faster. We'll change the delay from 1 second to 0.2 seconds. + +### Modified Code + +```python +import machine +import time + +led = machine.Pin(25, machine.Pin.OUT) + +while True: + led.value(1) + time.sleep(0.5) # 0.5 seconds + led.value(0) + time.sleep(0.5) # 0.5 seconds +``` + +### Steps + +1. Change the `time.sleep(1)` lines to `time.sleep(0.5)`. +2. Upload the modified script to your board. +3. Observe that the LED now blinks faster, turning on and off every 0.5 seconds. + +## Summary + +Great work! We have now written and modified our first MicroPython script on an Arduino board. This exercise introduced: + +- Importing modules (`machine`, `time`) +- Initializing hardware components (LED) +- Using loops (`while`) +- Controlling time delays (`time.sleep()`) + +These concepts are key for a vast majoraty of operations we can perform while writing MicroPython programs. + diff --git a/content/micropython/00.first-steps/first-steps.md b/content/micropython/00.first-steps/first-steps.md new file mode 100644 index 0000000000..ef0430aa15 --- /dev/null +++ b/content/micropython/00.first-steps/first-steps.md @@ -0,0 +1,3 @@ +--- +title: First Steps +--- \ No newline at end of file diff --git a/content/micropython/01.basics/00.digital-io/assets/LED.png b/content/micropython/01.basics/00.digital-io/assets/LED.png new file mode 100644 index 0000000000..dff0de7cc0 Binary files /dev/null and b/content/micropython/01.basics/00.digital-io/assets/LED.png differ diff --git a/content/micropython/01.basics/00.digital-io/assets/pull-down.png b/content/micropython/01.basics/00.digital-io/assets/pull-down.png new file mode 100644 index 0000000000..5e2e6c4fca Binary files /dev/null and b/content/micropython/01.basics/00.digital-io/assets/pull-down.png differ diff --git a/content/micropython/01.basics/00.digital-io/assets/pull-up.png b/content/micropython/01.basics/00.digital-io/assets/pull-up.png new file mode 100644 index 0000000000..18869c200d Binary files /dev/null and b/content/micropython/01.basics/00.digital-io/assets/pull-up.png differ diff --git a/content/micropython/01.basics/00.digital-io/assets/select-board-ide.png b/content/micropython/01.basics/00.digital-io/assets/select-board-ide.png new file mode 100644 index 0000000000..d144bafe37 Binary files /dev/null and b/content/micropython/01.basics/00.digital-io/assets/select-board-ide.png differ diff --git a/content/micropython/01.basics/00.digital-io/assets/usb-comp.png b/content/micropython/01.basics/00.digital-io/assets/usb-comp.png new file mode 100644 index 0000000000..e3c90f42cd Binary files /dev/null and b/content/micropython/01.basics/00.digital-io/assets/usb-comp.png differ diff --git a/content/micropython/01.basics/00.digital-io/digital-io.md b/content/micropython/01.basics/00.digital-io/digital-io.md new file mode 100644 index 0000000000..b7a241aa06 --- /dev/null +++ b/content/micropython/01.basics/00.digital-io/digital-io.md @@ -0,0 +1,213 @@ +--- +title: 'Digital I/O' +description: 'A guide to digital inputs and outputs using MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, Digital I/O] +--- + +Digital pins are fundamental for interacting with the physical world using your Arduino board. With them, you can: + +- Control outputs, such as turning an LED on and off. +- Read inputs, like detecting the state of a button. + +Digital signals have two distinct values: + +- **HIGH (1)**: Represents a voltage level close to the board's operating voltage (e.g., 3.3V or 5V). +- **LOW (0)**: Represents a voltage level close to 0V (ground). + +Although they can only represent two states, digital signals are highly useful. Being binary in nature, they directly interface with microcontrollers and processors, making them ideal for tasks requiring fast, on/off communication, such as reading sensors or controlling simple outputs. Their simplicity also gives them a natural resilience to electrical noise, as noise only disrupts digital signals when it is strong enough to cross the threshold between HIGH and LOW states. This makes them reliable for clear, consistent communication in various environments. + +In this chapter, we'll explore how to use digital pins in MicroPython. + +## Requirements + +Before we start, let's check the requirements: + +### MicroPython Compatible Arduino Boards + +MicroPython is officially supported on several Arduino boards. Here’s a list of the compatible boards: + +- [Portenta C33](https://store.arduino.cc/products/portenta-c33) +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/arduino-giga-r1-wifi) +- [Portenta H7](https://store.arduino.cc/products/portenta-h7) +- [Portenta H7 Lite](https://store.arduino.cc/products/portenta-h7-lite) +- [Portenta H7 Lite Connected](https://store.arduino.cc/products/portenta-h7-lite-connected) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) +- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) +- [Arduino Nano 33 BLE](https://store.arduino.cc/products/arduino-nano-33-ble) +- [Arduino Nano 33 BLE Rev2](https://store.arduino.cc/products/nano-33-ble-rev2) +- [Arduino Nano 33 BLE Sense Rev2](https://store.arduino.cc/products/arduino-nano-33-ble-sense-rev2) +- [Arduino Nano ESP32](https://store.arduino.cc/products/arduino-nano-esp32) + +### Hardware Components + +In this guide, we will be using some additional electronic components: +- LEDs (optional if using the onboard LED) +- Current-limiting resistor (e.g. 220Ω) if using an external LED +- Jumper wires +- Pushbutton +- Breadboard + +### Software Requirements + +- [Arduino Lab for Micropython](https://labs.arduino.cc/en/labs/micropython) - Arduino Lab for MicroPython is an editor where we can create and run MicroPython scripts on our Arduino board. + +***Note that the editor is also available online, at [Arduino Cloud - Arduino Labs for MicroPython](https://lab-micropython.arduino.cc/)*** + +## Board and Editor Setup + +1. Open the [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) application. +2. Plug the Arduino board into the computer using a USB cable. + ![Connect board to computer.](assets/usb-comp.png) +3. Press the connection button on the top left corner of the window. The connected Arduino board should appear (by its port name), and we can click it: + ![Connect to the board in the editor.](assets/select-board-ide.png) + +***Need help installing MicroPython on your board? Visit the [MicroPython installation guide](/micropython/first-steps/install-guide).*** + +## Digital Outputs + +To control digital outputs in MicroPython, we use the `Pin` class from the `machine` module. Setting a pin as an output allows you to control devices like LEDs, relays, or other actuators. + +Let's create the classic "Blink" example, where we turn an LED on and off at regular intervals. + +### Circuit Diagram + +Connect an LED to the Arduino board, following the circuit diagram below: + +- Connect the anode (+) of the LED to a digital output pin. +- Connect the cathode (-) of the LED through a resistor to `GND`. + +![LED circuit.](assets/LED.png) + +***You can also use the built-in LED on your board, if you do not have an external LED.*** + +After completing the circuit diagram, copy the following code into your editor, and run the script. + +```python +from machine import Pin +import time + +# Initialize the LED pin +# Uncomment the line that matches your board +led = Pin(25, Pin.OUT) # For Arduino Nano RP2040 Connect +# led = Pin(13, Pin.OUT) # For Arduino Nano 33 BLE / Sense (built-in LED) +# led = Pin(2, Pin.OUT) # For Arduino Portenta H7 + +while True: + led.value(1) # Turn LED on + time.sleep(1) # Wait for 1 second + led.value(0) # Turn LED off + time.sleep(1) # Wait for 1 second +``` + +Let's take a look at what's included in this code example: + +- **Import Modules**: We import `Pin` from `machine` and `time` for delays. +- **Initialize LED Pin**: with the `Pin` object, we set the pin number and direction (`Pin.OUT`). +- **Main Loop**: + - `led.value(1)` - Sets the pin to HIGH, turning the LED on. + - `time.sleep(1)` - Pauses the program for 1 second. + - `led.value(0)` - Sets the pin to LOW, turning the LED off. + - `while True:` - The loop repeats indefinitely, causing the LED to blink. + + + +## Digital Inputs + +Reading digital inputs allows your program to respond to external events, like button presses or sensor signals. In MicroPython, we use the `Pin` class to set up pins as inputs, and we can specify pull modes to stabilize the input readings. + +In this section, we will explain the different pull modes, and then try them out, by connecting a **pushbutton** to the Arduino. + +### Understanding Pull Modes + +When a digital input pin is not connected to a definite HIGH or LOW voltage, it is said to be "floating," which can result in unreliable readings due to electrical noise. To prevent this, we use internal pull-up or pull-down resistors, activated by specifying the pull mode in the `Pin` constructor. + +- **Pull-Up Mode (`Pin.PULL_UP`)**: Connects the input pin internally to a HIGH voltage level, ensuring the pin reads HIGH when not connected to anything else. +- **Pull-Down Mode (`Pin.PULL_DOWN`)**: Connects the input pin internally to GND, ensuring the pin reads LOW when not connected to anything else. + +These internal resistors are built into the microcontroller and can be enabled in your code, eliminating the need for external resistors. + +### Example: Pull-Up Mode + +In pull-up mode, the input pin is internally connected to a HIGH voltage level. When the input device (like a button) is activated and connects the pin to GND, the pin reads LOW (`0`). + +- Connect one side of the button to **GND**. +- Connect the other side to a digital input pin. + +![Pull-up mode circuit.](assets/pull-up.png) + +After completing the circuit diagram, copy the following code into your editor, and run the script. + +```python +from machine import Pin +import time + +# Initialize the button pin with internal pull-up resistor +button = Pin(14, Pin.IN, Pin.PULL_UP) # Replace 14 with your input pin number + +while True: + button_state = button.value() + if button_state == 0: + print("Button Pressed") + else: + print("Button Released") + time.sleep(0.1) +``` + +Let's take a look at what's included in this code example: + +- **Initialize Button Pin**: + - We set up the pin as an input with a pull-up mode (`Pin.PULL_UP`), enabling the internal pull-up resistor. + - This means the pin reads HIGH (`1`) when the button is not pressed. +- **Reading the Pin**: + - When the button is **not pressed**, the pin is pulled HIGH internally (`button.value()` returns `1`). + - When the button is **pressed**, it connects the pin to GND, making `button.value()` return `0`. +- **Main Loop**: + - Reads the button state and prints a message accordingly. + - A short delay helps debounce the button. + +### Example: Pull-Down Mode + +In pull-down mode, the input pin is internally connected to GND. When the input device is activated and connects the pin to a HIGH voltage level (e.g., 3.3V), the pin reads HIGH (`1`). + +- Connect one side of the button to **3.3V** (or **5V**, depending on your board's logic level). +- Connect the other side to a digital input pin. + +![Pull-down mode circuit.](assets/pull-down.png) + +After completing the circuit diagram, copy the following code into your editor, and run the script. + +```python +from machine import Pin +import time + +# Initialize the button pin with internal pull-down resistor +button = Pin(14, Pin.IN, Pin.PULL_DOWN) # Replace 14 with your input pin number + +while True: + button_state = button.value() + if button_state == 1: + print("Button Pressed") + else: + print("Button Released") + time.sleep(0.1) +``` + +Let's take a look at what's included in this code example: + +- **Initialize Button Pin**: + - We set up the pin as an input with a pull-down mode (`Pin.PULL_DOWN`), enabling the internal pull-down resistor. + - This means the pin reads LOW (`0`) when the button is not pressed. +- **Reading the Pin**: + - When the button is **not pressed**, the pin is pulled LOW internally (`button.value()` returns `0`). + - When the button is **pressed**, it connects the pin to HIGH voltage, making `button.value()` return `1`. +- **Main Loop**: + - Reads the button state and prints a message accordingly. + - A short delay helps debounce the button. + +## Summary + +In this guide, we have looked at different ways of interacting with digital pins on an Arduino, using MicroPython: +- How to use digital outputs (turning on/off an LED) +- How the different pull modes work (`PULL_DOWN`, `PULL_UP`) +- How to read a button press using either pull modes. \ No newline at end of file diff --git a/content/micropython/01.basics/01.analog-io/analog-io.md b/content/micropython/01.basics/01.analog-io/analog-io.md new file mode 100644 index 0000000000..f15090565d --- /dev/null +++ b/content/micropython/01.basics/01.analog-io/analog-io.md @@ -0,0 +1,187 @@ +--- +title: 'Analog I/O' +description: 'A guide to analog inputs (ADC) and outputs (PWM) using MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, Analog I/O] +--- + +Analog inputs and outputs (I/O) are essential for handling a range of values rather than simple on/off states, allowing for more nuanced control over devices and inputs in your projects. In this chapter, we’ll cover how to work with analog I/O using MicroPython, focusing on how to: + +- Read analog values, such as a light sensor or potentiometer. +- Generate analog outputs, like controlling LED brightness or the speed of a motor. + +Analog signals differ from digital signals in that they represent a continuous range of values. This flexibility enables more refined interactions with the physical world, making analog I/O indispensable for many types of sensors and actuators. + +## Requirements + +Before we start, let's check the requirements: + +### MicroPython Compatible Arduino Boards + +MicroPython is officially supported on several Arduino boards. Here’s a list of the compatible boards: + +- [Portenta C33](https://store.arduino.cc/products/portenta-c33) +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/arduino-giga-r1-wifi) +- [Portenta H7](https://store.arduino.cc/products/portenta-h7) +- [Portenta H7 Lite](https://store.arduino.cc/products/portenta-h7-lite) +- [Portenta H7 Lite Connected](https://store.arduino.cc/products/portenta-h7-lite-connected) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) +- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) +- [Arduino Nano 33 BLE](https://store.arduino.cc/products/arduino-nano-33-ble) +- [Arduino Nano 33 BLE Rev2](https://store.arduino.cc/products/nano-33-ble-rev2) +- [Arduino Nano 33 BLE Sense Rev2](https://store.arduino.cc/products/arduino-nano-33-ble-sense-rev2) +- [Arduino Nano ESP32](https://store.arduino.cc/products/arduino-nano-esp32) + +### Hardware Components + +In this guide, we will be using some additional electronic components: +- LEDs +- Current-limiting resistor (e.g. 220Ω) if using an external LED +- Jumper wires +- Breadboard + +### Software Requirements + +- [Arduino Lab for Micropython](https://labs.arduino.cc/en/labs/micropython) - Arduino Lab for MicroPython is an editor where we can create and run MicroPython scripts on our Arduino board. + +***Note that the editor is also available online, at [Arduino Cloud - Arduino Labs for MicroPython](https://lab-micropython.arduino.cc/)*** + +## Board and Editor Setup + +1. Open the [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) application. +2. Plug the Arduino board into the computer using a USB cable. + ![Connect board to computer.](assets/usb-comp.png) +3. Press the connection button on the top left corner of the window. The connected Arduino board should appear (by its port name), and we can click it: + ![Connect to the board in the editor.](assets/select-board-ide.png) + +***Need help installing MicroPython on your board? Visit the [MicroPython installation guide](/micropython/first-steps/install-guide).*** + +## Analog Inputs + +Analog input signals allow you to interact with the world more fluidly by capturing gradual changes rather than absolute states. Analog sensors output a range of voltages to reflect changes in physical conditions. By converting these values into digital numbers, your Arduino board can interpret real-world signals, and convert them into known properties, such as light intensity or temperature. + +### Analog-to-Digital Converter (ADC) + +To read analog values, we use an Analog-to-Digital Converter (ADC). This takes an input voltage, and converts it to a digital value, that can then be used by the Arduino. Analog inputs measure voltage levels that range continuously between two values, often 0V (LOW) and the board's operating voltage, like 3.3V or 5V. + +Using MicroPython, we use a specific method to access the ADC: `read_u16()`. The "16" indicates a 16-bit resolution, which means we can capture a range between 0-65535\*. + +***\*What does a 16-bit resolution mean? Find out at the [end of this article](#analog-resolution).*** + +### Code Example: Reading a Light Sensor + +We will now try an example, where we will read the light intensity of a photoresistor. + +For this example, we will need the following external components: + +- Breadboard +- Photo resistor +- Jumper wires +- 10k Ω resistor + +Connect the photoresistor to the Arduino board, following the circuit diagram below: + +![Photoresistor circuit.](assets/photoresistor.png) + +After completing the circuit diagram, copy the following code into your editor, and run the script. + +```python +from machine import ADC +import time + +# Initialize ADC for the analog pin +light_sensor = ADC(0) # Replace '0' with the correct ADC channel for your board + +while True: + light_level = light_sensor.read_u16() # Reads a 16-bit value (0-65535) + print("Light level:", light_level) + time.sleep(1) +``` + +Let's take a look at what's included in this code example: + +- **ADC Initialization**: We initialize the `ADC` class, passing the analog channel as an argument. +- **Reading Values**: `read_u16()` reads a 16-bit integer (0-65535), where `0` represents 0V and `65535` represents the board's maximum operating voltage. +- **Loop**: The sensor reading is printed every second, showing how the value changes based on light intensity. + +## Analog Outputs + +Unlike analog input, analog output on microcontrollers doesn’t provide a truly continuous range of voltages. Instead, we use **Pulse Width Modulation** (PWM) to simulate varying voltage levels. PWM rapidly switches a digital output between HIGH and LOW at a specified duty cycle, creating the illusion of analog output by controlling the amount of time the signal stays HIGH. + +### Pulse Width Modulation (PWM) + +True analog signals involve a continuous voltage range, but since microcontrollers primarily handle digital signals (on or off), PWM bridges the gap by rapidly switching the signal between HIGH and LOW. By adjusting the time the signal remains in the HIGH state (known as the "duty cycle"), PWM simulates varying voltage levels. + +PWM is especially useful in applications where true analog output is not possible but smooth transitions are necessary. Common scenarios include: + +- **LED Dimming**: PWM allows for adjusting brightness levels by controlling how long the LED is ON versus OFF within a given time frame. +- **Motor Control**: By modifying the duty cycle, PWM can control the speed of motors for robotics or other mechanical devices, as the motor responds to the average power supplied over time. +- **Audio Signals**: Some sound applications also use PWM to generate varying sound frequencies or control speaker volume. + +The main advantage of PWM is that it allows you to control analog-like behavior using digital pins, adding versatility to your projects while keeping power consumption efficient. + +![How PWM works.](assets/pwm.gif) + +### Code Example: Dimming an LED with PWM + +We will now try an example, where we will dim an LED using PWM. + +For this example, we will need the following external components: + +- Breadboard +- LED +- Current-limiting resistor (e.g., 220Ω) +- Jumper wires + +Connect the LED to the Arduino board, following the circuit diagram below: + +![LED circuit.](assets/LED.png) + +After completing the circuit diagram, copy the following code into your editor, and run the script. + +```python +from machine import Pin, PWM +import time + +# Initialize PWM for the LED pin +led_pwm = PWM(Pin(5)) # Replace '5' with the correct pin for your board +led_pwm.freq(1000) # Set frequency to 1 kHz + +# Gradually change the LED brightness +while True: + for duty in range(0, 65536, 1024): # 0 to 65535 for 16-bit PWM + led_pwm.duty_u16(duty) + time.sleep(0.01) + for duty in range(65535, -1, -1024): + led_pwm.duty_u16(duty) + time.sleep(0.01) +``` + +Let's take a look at what's included in this code example: + +- **PWM Initialization**: We create a `PWM` object and set the frequency to 1 kHz, which works well for LEDs. +- **Duty Cycle**: `duty_u16()` takes a value between 0 and 65535. The higher the value, the longer the signal stays HIGH, making the LED brighter. +- **Loop**: The brightness gradually increases and decreases by adjusting the duty cycle in small steps, causing the LED to fade in and out. + +## Analog Resolution + +The resolution of an ADC can simply be explained as how detailed it is. When using MicroPython, the default is **16-bits**, while using the Arduino programming language it is **10-bits**. So what is the difference? + +When we read something in 16-bit resolution, we receive a range of 0-65355. Let's say the voltage range is 0-3.3V, as is standard in most modern boards. If we were to read 3.3V, it means "max" or "65355". If we read half of that voltage (1.65V), it would be 65355/2 = 32677. + +Now let's say we have an analog sensor reading temperature. If the temperature is at its very max for that component, and it outputs 3.3V, we will read 65355. If it is not outputting any voltage (which is unlikely), we would read 0. + +If we are using a different resolution, such as **10-bits**, the range would instead be **0-1023**. The voltage remains the same, but the value we read is different. + +Why does it work this way? See, bits are used to represent information. A single bit can hold only two values: 0 or 1, while 2 bits can be between 0-3, 3 bits between 0-8 and so on. See below: +- 1-bit = 0-1 +- 2-bits = 0-3 +- 4-bits = 0-8 +- 8-bits = 0-255 +- 10-bits = 0-1023 +- 16-bits = 0-65355 +- 32-bits = 0-4,294,967,295 + +## Summary + +In this guide we have learned about analog inputs, outputs & resolution. We have also gone through a number of fundamental examples to understand how it works in practice. \ No newline at end of file diff --git a/content/micropython/01.basics/01.analog-io/assets/LED.png b/content/micropython/01.basics/01.analog-io/assets/LED.png new file mode 100644 index 0000000000..dff0de7cc0 Binary files /dev/null and b/content/micropython/01.basics/01.analog-io/assets/LED.png differ diff --git a/content/micropython/01.basics/01.analog-io/assets/photoresistor.png b/content/micropython/01.basics/01.analog-io/assets/photoresistor.png new file mode 100644 index 0000000000..c481fdaee6 Binary files /dev/null and b/content/micropython/01.basics/01.analog-io/assets/photoresistor.png differ diff --git a/content/micropython/01.basics/01.analog-io/assets/pwm.gif b/content/micropython/01.basics/01.analog-io/assets/pwm.gif new file mode 100644 index 0000000000..2414e50761 Binary files /dev/null and b/content/micropython/01.basics/01.analog-io/assets/pwm.gif differ diff --git a/content/micropython/01.basics/01.analog-io/assets/select-board-ide.png b/content/micropython/01.basics/01.analog-io/assets/select-board-ide.png new file mode 100644 index 0000000000..d144bafe37 Binary files /dev/null and b/content/micropython/01.basics/01.analog-io/assets/select-board-ide.png differ diff --git a/content/micropython/01.basics/01.analog-io/assets/usb-comp.png b/content/micropython/01.basics/01.analog-io/assets/usb-comp.png new file mode 100644 index 0000000000..e3c90f42cd Binary files /dev/null and b/content/micropython/01.basics/01.analog-io/assets/usb-comp.png differ diff --git a/content/micropython/01.basics/01.overview/overview.md b/content/micropython/01.basics/01.overview/overview.md deleted file mode 100644 index be1db2d232..0000000000 --- a/content/micropython/01.basics/01.overview/overview.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Overview -description: An introduction to Arduino and MicroPython -author: Francesca Sanfilippo -micropython_type: basics ---- - -MicroPython is an implementation of the Python programming language, and includes some of the standard Python libraries. It is designed to run on microcontrollers with constrained environments. - -In this sequence of guides, you will among other things, learn how to: -- Install MicroPython on your Arduino board, -- Install an editor with support for MicroPython, -- How to make basic scripts that can for example blink an LED, read an analog pin and print things to the terminal (REPL). - -You do not need any prior knowledge in either programming with Arduino or MicroPython, but it is recommended to know the basics of Python. - -What you need to do it is have a Compatible Board and a Code Editor. You can choose between two alternatives: -- **Arduino Lab for MicroPython:** an experimental editor from Arduino, designed for simpler projects. -- **OpenMV:** an editor for more complex projects, such as computer vision. - -## Python vs C/C++. - -If you are experienced with Arduino programming in C and C++ a lot of the presented topics will look familiar to you. -There's a big difference between how we program an Arduino board with the Arduino IDE, using the Arduino programming language (based on C++), and how we program it using MicroPython. -- The “Arduino way” requires compiling the sketch before uploading it to your board. The previous code running is replaced by the new one. -- The “MicroPython way” does not require compiling, as you will have MicroPython installed on the actual board. Code is instead run through an interpreter, line by line. - -## Python vs MicroPython - -MicroPython was created to work under constrained conditions, like a small environment. The main difference between Python and MicroPython is that MicroPython does not have the full standard Python language, it is only a subset of it. \ No newline at end of file diff --git a/content/micropython/01.basics/01.overview/py-hero-banner.png b/content/micropython/01.basics/01.overview/py-hero-banner.png deleted file mode 100644 index 35dc29dfde..0000000000 Binary files a/content/micropython/01.basics/01.overview/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/ble-sense.png b/content/micropython/01.basics/02.board-installation/assets/ble-sense.png deleted file mode 100644 index 52908dbc5e..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/ble-sense.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/ble.png b/content/micropython/01.basics/02.board-installation/assets/ble.png deleted file mode 100644 index e63994064d..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/ble.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/board-selected.png b/content/micropython/01.basics/02.board-installation/assets/board-selected.png deleted file mode 100644 index 96ca301d46..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/board-selected.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/boardmanager-portenta.png b/content/micropython/01.basics/02.board-installation/assets/boardmanager-portenta.png deleted file mode 100644 index 8611774cc0..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/boardmanager-portenta.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/boardmanager.png b/content/micropython/01.basics/02.board-installation/assets/boardmanager.png deleted file mode 100644 index c6045bb130..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/boardmanager.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/examplesketch.png b/content/micropython/01.basics/02.board-installation/assets/examplesketch.png deleted file mode 100644 index 4de4d978ac..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/examplesketch.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/flashed.png b/content/micropython/01.basics/02.board-installation/assets/flashed.png deleted file mode 100644 index 5e81087c88..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/flashed.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/giga-r1-wifi.png b/content/micropython/01.basics/02.board-installation/assets/giga-r1-wifi.png deleted file mode 100644 index 45c29be8a9..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/giga-r1-wifi.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/nano-rp2040.png b/content/micropython/01.basics/02.board-installation/assets/nano-rp2040.png deleted file mode 100644 index d38a07ea22..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/nano-rp2040.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/portenta-c33-1.png b/content/micropython/01.basics/02.board-installation/assets/portenta-c33-1.png deleted file mode 100644 index 87ce87533d..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/portenta-c33-1.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/portenta-c33-2.png b/content/micropython/01.basics/02.board-installation/assets/portenta-c33-2.png deleted file mode 100644 index c6e2846adf..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/portenta-c33-2.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/portenta-c33-3.png b/content/micropython/01.basics/02.board-installation/assets/portenta-c33-3.png deleted file mode 100644 index fe48fda770..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/portenta-c33-3.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/assets/portenta.png b/content/micropython/01.basics/02.board-installation/assets/portenta.png deleted file mode 100644 index b696c79a88..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/assets/portenta.png and /dev/null differ diff --git a/content/micropython/01.basics/02.board-installation/board-installation.md b/content/micropython/01.basics/02.board-installation/board-installation.md deleted file mode 100644 index 56e80d6c52..0000000000 --- a/content/micropython/01.basics/02.board-installation/board-installation.md +++ /dev/null @@ -1,305 +0,0 @@ ---- -title: Board Installation -description: A list of Arduino boards compatible with MicroPython and how to install them. -author: Francesca Sanfilippo, Karl Söderby & Jacob Hylén -micropython_type: basics -featured: micropython -hero_image: "./hero-banner.png" -hero_position: 1 ---- - -So what do you need to start your first project with MicroPython and Arduino? First, you will need a compatible board. In this page, you will find the compatible boards, with instructions on how to install them. - -In order to understand which board is more suitable to your project, you can visit the documentation of each board. - -## Supported Boards - -The following boards support MicroPython: -- [Nano BLE](https://store.arduino.cc/products/arduino-nano-33-ble) / [Nano BLE Sense](https://store.arduino.cc/products/arduino-nano-33-ble-sense) / [Nano BLE Sense Rev2](https://store.arduino.cc/products/nano-33-ble-sense-rev2) -- [Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) -- [Nano ESP32](https://store.arduino.cc/products/nano-esp32) -- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) -- [GIGA R1 WiFi](https://store.arduino.cc/products/giga-r1-wifi) -- [Portenta H7](https://store.arduino.cc/collections/portenta-family/products/portenta-h7) -- [Portenta C33](https://store.arduino.cc/collections/portenta-family/products/portenta-c33) - - -## Arduino MicroPython Installer - -We have developed a tool for installing the MicroPython firmware to your Arduino boards with a simple click. This tool lets you plug in the board, select it from a menu, and automatically flash the latest firmware, or a custom one of your choice to the board. - -Download [Arduino MicroPython Installer here](https://labs.arduino.cc/en/labs/micropython-installer). - -Arduino MicroPython Installer is part of [Arduino Labs](https://labs.arduino.cc), and is therefore considered experimental software. - -To get started, open the app and plug in your board to the computer. You should now see it pop up ready to be selected in the list. If it doesn't, try putting it in bootloader mode by double tapping the reset button. - -![Arduino Nano ESP32 detected!](./assets/board-selected.png) - -Now, uploading the MicroPython firmware is as easy as pressing **"install MicroPython"** and waiting for a couple of seconds while the installer tool takes care of everything else. - -![Firmware Successfully Uploaded!](./assets/flashed.png) - - -If you don't want to use the Arduino MicroPython Installer tool, these are the per-board steps for manual installation: - -## Nano ESP32 - -Software required: -- MicroPython Firmware -- [esptool.py](https://github.com/espressif/esptool) installed -- [Python](https://www.python.org) installed on your computer -​ -First prepare the board for a new firmware upload by shorting the B1 pin to GND and pressing the reset button. - -Then run the following esptool command to erase the flash, replace `{port-name}` with the name of the port your board is connected to: - -​ -``` -esptool.py --chip esp32s3 --port {port-name} erase_flash -``` -​ -Then run this command to upload the new firmware, replace `{firmware.bin}` with the name of your firmware binary file, and `{port-name}` with the name of the port your board is connected to: - - -​ -``` -esptool.py --chip esp32s3 --port {port-name} write_flash -z 0 {firmware.bin} - -``` -​ -Now your board should be prepared to be programmed with MicroPython! - -## Nano 33 BLE & Nano 33 BLE Sense - -- [Nano 33 BLE documentation](/hardware/nano-33-ble). -- [Nano 33 BLE Rev2 documentation.](/hardware/nano-33-ble-rev2) -- [Nano 33 BLE Sense documentation.](/hardware/nano-33-ble-sense) -- [Nano 33 BLE Sense Rev2 documentation.](/hardware/nano-33-ble-sense-rev2) - -![Nano 33 BLE.](assets/ble.png) - -The process for flashing the firmware on the Nano 33 BLE requires to first update the bootloader and SoftDevice. Once this is done you can flash the MicroPython firmware to your board. - -This process requires a version of the [Arduino IDE](https://www.arduino.cc/en/main/software) installed, which is explained in the next step. - -**Step 1: Installing the Core** - -Start by making sure that you have the respective core installed. Open the **Arduino IDE** (not Arduino Lab for MicroPython) and navigate to the boards manager. Search for your board (Nano 33 BLE), and make sure you have the latest version of the core installed. More detailed information about this step can be found [here](/software/ide-v2/tutorials/ide-v2-board-manager). - -![Board manager](assets/boardmanager.png) - -This is not only needed to upload the next sketch, but you're also going to dive into the core files themselves to find a specific tool in an upcoming step. - -**Step 2: Update Bootloader** - -In the Nano 33 BLE core is an example sketch that you will use to update the bootloader and SoftDevice of your board. Go back to the Arduino IDE and navigate to `File > Examples > Nano33BLE_System > Nano33_updateBLandSoftDevice` and open the sketch. - -![Example sketch](assets/examplesketch.png) - -Upload the sketch to your board. Beware! the bootloader is not updated just yet! Once the sketch is uploaded, you can interface with your board through the serial monitor to actually update the bootloader. - -In the Serial monitor, you are asked to confirm that you want to update the bootloader. In the message text box in the top of the serial monitor, write a **"y"** and press enter to send it to your board. - -You can now watch as the bootloader update process progresses, **do not disconnect or reset your board during this process** or you could brick your board. - -Once this bar completes, you will be prompted with another choice. This time it asks if you want to update the SoftDevice on your board. Repeat the process of sending a **"y"** to the board, and watch the progress of this too. - -When this bar fills and the SoftDevice update completes, the board will restart, and you've successfully made it through the procedure. - -***Note: An important thing to do at this point which is easily forgotten is to close the serial monitor, we will need to use the serial port for other things very soon and if you leave the monitor open it will be busy and won't be able to receive any new interactions.*** - -**Step 3: Download Firmware** - -Now you will need to find the specific firmware that you need to flash to your board. You can find the available firmware on the [MicroPython](/micropython) Documentation site. - -Download the `.bin` file that corresponds to the board you have. - -Now you will need to dive into the core files you downloaded in the first step to find a command line tool that is included called BOSSAC. This process will be different for you depending on if you're on a Windows or MacOS computer. - - -**Step 4a: Flash Firmware (Windows)** - ->Instructions for MacOS are available just below this section. - -The file you will is named `bossac.exe` and can be found in the following directory: - -``` -C:\Users\[your-username]\AppData\Local\Arduino15\staging\packages\bossac-1.9.1-arduino2-windows.tar.gz\bossac-1.9.1-arduino2-windows.tar\bin\` -``` - -One you've found the file, extract it from the `.tar` archive and copy it somewhere else, your desktop for example. - -Open a command terminal and start typing in `start`, now drag and drop the bossac.exe file you've found into the terminal, and press enter. - -If successful, another command terminal window should open in which you are able to execute the command that will flash your board with the MicroPython firmware. - -Execute the following command, but replace the port with the name of the port where your board is connected, and the firmware file with the directory where you have placed the firmware you downloaded previously: - -``` -bossac -e -w --offset=0x16000 --port=[port] -i -d -U -R [firmware] -``` - -Don't disconnect or power off your board during this part of the process, watch the progress of flashing the firmware to your board. Once complete, you're all set and you're ready to start programming the board in MicroPython. - -Go to the Arduino Lab MicroPython IDE and press connect in the top left, choose the port, and you are now ready to program your Nano 33 BLE. - -**Step 4b: Flash Firmware (MacOS)** - -The file you will need to access is called `bossac` and can be found in the following directory: - -``` -Users/[your-user]/Library/Arduino15/packages/arduino/tools/bossac/1.9.1-arduino2 -``` - -***Note: The `"Library"` directory is hidden, press `Shift + Command + . ` to reveal hidden directories.*** - -Open a terminal window and drag and drop the `bossac` file into the terminal window. - -Now, you should be able to execute the command that will flash your board with the MicroPython firmware. - -Execute the following command, but replace the port with the name of the port where your board is connected, and the firmware file with the directory where you have placed the firmware you downloaded previously: - -``` -bossac -e -w --offset=0x16000 --port=[port] -i -d -U -R [firmware] -``` - -Again, don't disconnect or power off your board during this part of the process, watch the progress of flashing the firmware to your board. Once complete, you're all set and you're ready to start programming the board in MicroPython. - -Go to the Arduino Lab MicroPython IDE and press connect in the top left, choose the port, and you are now ready to program your Nano 33 BLE! - -## Nano RP2040 Connect - -- [Arduino Nano RP2040 Documentation](https://docs.arduino.cc/hardware/nano-rp2040-connect) - -![Nano RP2040 Connect.](assets/nano-rp2040.png) - -To program your Nano RP2040 Connect board with MicroPython, follow the instructions below. The installation for Nano RP2040 Connect requires no additional software tools for installation. - -Follow the steps below to install MicroPython on the Nano RP2040 Connect board. - -1. Download the `.uf2` firmware file from the [MicroPython](/micropython) page. -2. Connect the `REC` pin to `GND` (they are placed next to each other) and press the reset button. This exposes the board's file system to your computer. -3. Drag and drop the firmware file onto the boards flash storage which shows up as an external storage device on your computer -4. Go to the Arduino Lab MicroPython IDE and press connect in the top left, choose the port. - -Congratulations, you are now ready to program your Nano RP2040 Connect with MicroPython. - -## GIGA R1 WiFi - -- [Arduino GIGA R1 WiFi documentation](/hardware/giga-r1-wifi) - -![GIGA R1 WiFi.](assets/giga-r1-wifi.png) - -The installation instructions for the **GIGA R1 WiFi** is identical to the **Portenta H7** instructions found just below. - -You will however need a different firmware, which you can download from the link below: - -- [Download GIGA R1 WiFi MicroPython firmware (dfu)](/resources/firmware/GIGAR1_MP_FW.dfu) - -***The GIGA R1 WiFi and Portenta H7 boards are based on the same microcontroller, [STM32H747XI](static/resources/datasheets/stm32h747xi.pdf) and therefore share the same installation instructions.*** - -## Portenta H7 - -- [Arduino Portenta H7 Documentation](https://docs.arduino.cc/hardware/portenta-h7) - -![Portenta H7.](assets/portenta.png) - -To install MicroPython on the Portenta H7 you will first need to install the corresponding core which also installs the required command line tool, called `dfu-util`. - -This tool can be used to directly flash a binary to your board, in this case, a MicroPython build. - -***The instructions below uses the `dfu-util` that is bundled with the Arduino IDE. You can also obtain the `dfu-util` directly, through the [dfu-util home page](https://dfu-util.sourceforge.net/) or via package management systems such as [Homebrew](https://formulae.brew.sh/formula/dfu-util) (MacOS / Linux).*** - -**Step 1: Install Arduino IDE** - -First, download and install the [Arduino IDE](https://arduino.cc/en/software) for your operating system. - -Open the Arduino IDE (not Arduino Lab for MicroPython) and navigate to the boards manager. Search for "Portenta H7", and make sure you have the latest version of the core installed. - -![Installing the Portenta core](assets/boardmanager-portenta.png) - -**Step 2: Download Firmware** - -Now you will need to find the specific firmware that you need to flash to your board. You can find the available firmware on the [MicroPython with Arduino](https://docs.arduino.cc/micropython/) home page. The firmware is available as a `.dfu` file for the Portenta H7. - -In the next step you will be diving into the core files you downloaded in the first step to find a command line tool called **dfu-util**. This process is differs depending on if you're on a Windows or MacOS computer. MacOS instructions are available further below. - -**Step 3a: Install Firmware (Windows)** - -To flash your board, you will need a file named `dfu-util.exe`. This is found in your following directory: - -``` -C:\Users\\AppData\Local\Arduino15\staging\packages\dfu-util-0.10.0-arduino1-windows.tar.bz2\dfu-util-0.10.0-arduino1-windows.tar\windows\ -``` - -One you've found the file, extract it from the .tar archive and copy it somewhere else, your desktop for example. - -Open a command terminal and start typing in `start`, now drag and drop the dfu-util.exe file you've found into the terminal, and press enter. - -If successful, another command terminal window should open in which you are able to execute the command that will flash your board with the MicroPython firmware. - -Double tap the reset button on your board to put it in DFU mode, and execute the following command, but replace the path of the firmware file with the directory where you have placed the firmware you downloaded previously: - -``` -dfu-util -a 0 -d 0x2341:0x035b -D .dfu -``` - -Again, don't disconnect or power off your board during this part of the process, watch the progress of flashing the firmware to your board. - -You should now see **two** progress bars appear in one after the other. The first one is showing the progress of erasing the firmware that was previously on the board, and the second one is showing the progress of flashing the new firmware. - -Once complete, you're all set and you're ready to start programming the board in MicroPython. - -Go to the Arduino Lab MicroPython IDE and press connect in the top left, choose the port, and code away! - -**Step 3b: Install Firmware (MacOS)** - -The file you will need to access is named `dfu-util` and can be found in the following directory: - -``` -Users/[your-username]/Library/Arduino15/packages/arduino/tools/dfu-util/0.10.0-arduino1/dfu-util -``` - -***Note: The `"Library"` directory is hidden, press `Shift + Command + . ` to reveal hidden directories.*** - -Open a terminal window and drag and drop the dfu-util file into the terminal window. - -Now, you should be able to execute the command that will flash your board with the MicroPython firmware. - -Double tap the reset button on your board to put it in DFU mode, and execute the following command, but replace the path of the firmware file with the directory where you have placed the firmware you downloaded previously: - -``` -dfu-util -a 0 -d 0x2341:0x035b -D .dfu -``` - -Do not disconnect your board during this part of the process, watch the progress of flashing the firmware to your board. - -Once complete, you're all set and you're ready to start programming the board in MicroPython. - -Go to the Arduino Lab MicroPython IDE and press connect in the top left corner, choose the port and you are ready to load scripts to your board. - -## Portenta C33 - -To install the MicroPython firmware to the Portenta C33 board, you can use the **Arduino MicroPython Installer**. This tool lets you plug in the board, select it from a menu, and automatically flash the latest firmware or a custom one of your choice to the board. You can download the [Arduino MicroPython Installer here](https://labs.arduino.cc/en/labs/micropython-installer). - -***The Arduino MicroPython Installer is part of [Arduino Labs](https://labs.arduino.cc) and is considered experimental software.*** - -Before installing the MicroPython firmware, **ensure you have installed the latest Portenta Renesas board package**. To install the board package for the Portenta C33 board, navigate to **Tools > Board > Boards Manager** or click the Boards Manager icon in the left tab of the IDE. In the Boards Manager tab, search for `renesas` and install the latest `Arduino Renesas Portenta Boards` version. - - -![Installing the Arduino Renesas Portenta Board Package in the Arduino IDE](./assets/portenta-c33-1.png) - - -With the latest board package installed, open the Arduino MicroPython Installer and plug your board into your computer; your board should appear ready to be selected, as shown in the image below. If your board does not appear in the installer, try putting it in bootloader mode by double-tapping your board's reset button. - - - -![Portenta C33 board detected on the Arduino MicroPython Installer](./assets/portenta-c33-2.png) - -To install the MicroPython firmware, press the **INSTALL MICROPYTHON** button and wait a few seconds while the installer tool takes care of everything else. When finished, you should see a message in the image below. - -![Firmware successfully uploaded to the Portenta C33 board](./assets/portenta-c33-3.png) - - -Now you are ready to use MicroPython with your Portenta C33 board. \ No newline at end of file diff --git a/content/micropython/01.basics/02.board-installation/hero-banner.svg b/content/micropython/01.basics/02.board-installation/hero-banner.svg deleted file mode 100644 index 4d1f364db5..0000000000 --- a/content/micropython/01.basics/02.board-installation/hero-banner.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/content/micropython/01.basics/02.board-installation/py-hero-banner.png b/content/micropython/01.basics/02.board-installation/py-hero-banner.png deleted file mode 100644 index 2a33e91b55..0000000000 Binary files a/content/micropython/01.basics/02.board-installation/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/02.loops/assets/select-board-ide.png b/content/micropython/01.basics/02.loops/assets/select-board-ide.png new file mode 100644 index 0000000000..d144bafe37 Binary files /dev/null and b/content/micropython/01.basics/02.loops/assets/select-board-ide.png differ diff --git a/content/micropython/01.basics/02.loops/assets/usb-comp.png b/content/micropython/01.basics/02.loops/assets/usb-comp.png new file mode 100644 index 0000000000..e3c90f42cd Binary files /dev/null and b/content/micropython/01.basics/02.loops/assets/usb-comp.png differ diff --git a/content/micropython/01.basics/02.loops/loops.md b/content/micropython/01.basics/02.loops/loops.md new file mode 100644 index 0000000000..173f24910d --- /dev/null +++ b/content/micropython/01.basics/02.loops/loops.md @@ -0,0 +1,200 @@ +--- +title: 'Loops' +description: 'Learn how to use different loops with MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, Loops] +--- + +Loops are fundamental constructs in all programming languages, that allow you to execute a block of code multiple times. In MicroPython, loops help you perform repetitive tasks efficiently and are an awesome tool to keep in your coder's toolbox. + +In this guide, we will explore the different loop structures available. + +## Requirements + +Before we start, let's check the requirements: + +### MicroPython Compatible Arduino Boards + +MicroPython is officially supported on several Arduino boards. Here’s a list of the compatible boards: + +- [Portenta C33](https://store.arduino.cc/products/portenta-c33) +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/arduino-giga-r1-wifi) +- [Portenta H7](https://store.arduino.cc/products/portenta-h7) +- [Portenta H7 Lite](https://store.arduino.cc/products/portenta-h7-lite) +- [Portenta H7 Lite Connected](https://store.arduino.cc/products/portenta-h7-lite-connected) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) +- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) +- [Arduino Nano 33 BLE](https://store.arduino.cc/products/arduino-nano-33-ble) +- [Arduino Nano 33 BLE Rev2](https://store.arduino.cc/products/nano-33-ble-rev2) +- [Arduino Nano 33 BLE Sense Rev2](https://store.arduino.cc/products/arduino-nano-33-ble-sense-rev2) +- [Arduino Nano ESP32](https://store.arduino.cc/products/arduino-nano-esp32) + +### Software Requirements + +- [Arduino Lab for Micropython](https://labs.arduino.cc/en/labs/micropython) - Arduino Lab for MicroPython is an editor where we can create and run MicroPython scripts on our Arduino board. + +***Note that the editor is also available online, at [Arduino Cloud - Arduino Labs for MicroPython](https://lab-micropython.arduino.cc/)*** + +## Board and Editor Setup + +1. Open the [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) application. +2. Plug the Arduino board into the computer using a USB cable. + ![Connect board to computer.](assets/usb-comp.png) +3. Press the connection button on the top left corner of the window. The connected Arduino board should appear (by its port name), and we can click it: + ![Connect to the board in the editor.](assets/select-board-ide.png) + +***Need help installing MicroPython on your board? Visit the [MicroPython installation guide](/micropython/first-steps/install-guide).*** + +## Loop Structures in MicroPython + +MicroPython supports two primary loop structures, each with a specific purpose: + +- **`for` loops**: for loops iterate over a predefined sequence, such as a list, tuple, or string. The loop automatically retrieves each item in the sequence, one at a time, and performs actions until every item has been handled. + +- **`while` loops**: while loops continue executing as long as a specified condition is true. Unlike `for` loops, which depend on a sequence, `while` loops rely on a conditional expression that determines when the loop should stop. + +To better understand these loops, let’s imagine them as tasks at the supermarket: + +- **for loops** - imagine walking down a supermarket aisle with a shopping list that specifies exactly how many items to pick up, one by one, in order. Once you’ve gathered all the items on your list, your task is complete. This is like a `for` loop iterating over a sequence, handling each specified item one at a time. + +- **while loops** - imagine going to the supermarket to buy a certain product that’s on sale, as long as it stays in stock. You keep coming back, day after day, until the sale ends or the stock runs out. In a `while` loop, you keep “coming back” as long as a condition (like the sale continuing) remains true. + + +## For Loops + +The `for` loop is used for iterating over a sequence. It automatically retrieves each item in the sequence one after another. + +```python +for variable in sequence: + # Code block to execute +``` + +- **`for`**: Keyword that starts the loop. +- **`variable`**: Takes the value of each item in the sequence during iteration this is where you will get the value for each iteration of a collection. +- **`in`**: Keyword used to specify the sequence to iterate over. +- **`sequence`**: The collection (like a list, tuple, or string) over which the loop iterates. +- **Code block**: The indented block of code that runs on each iteration. + +### Example Code + +Let's try out making a for loop. In this example, we set `i` which stands for *iteration*, in a range of 5. + +```python +for i in range(5): + print(i) +``` + +Running this script will result in printing `i` for five times. Each time the loop is run, `i` is increased, so in the REPL, we should see: + +``` +0 +1 +2 +3 +4 +``` + +This is because we start counting from 0. So the first time the loop runs, we print `0`, the second time it runs `1` and so on. + +## While Loops + +A `while` loop continues to execute as long as a specified condition is true. + +```python +while condition: + # Code block to execute +``` + +- **`while`**: Keyword that starts the loop. +- **`condition`**: A boolean expression evaluated before each iteration; if `True`, the loop continues. +- **Code block**: The indented block of code that runs on each iteration. + +### Example Code + +Let's try making a while loop! In the example below, we have a counter, which we print to the REPL. This is to track how many times the loop has run. We pause between each print using the `time.sleep(1)` function, so that it is easier to read in the REPL. + +```python +import time +counter = 0 + +while True: + counter += 1 + print('Number of iterations: ' + str(counter)) + time.sleep(1) +``` + +In this example, we used: + +- `while True:` - this keeps a while loop running forever. +- `print('Number of iterations: ' + str(counter))`, to print out the current iteration. +- because we cannot mix numeric values with strings when using the `print()` function, we need to use `str(counter)` when printing to the REPL. + +The result will be an infinite loop, that will print the current iteration: + +```python +Number of iterations: 10 +Number of iterations: 11 +Number of iterations: 12 +..... +Number of iterations: 99999 # this loop has been running for a long time.. +``` + +## Control Statements + +While inside a loop, we can control how it should behave using control statements: **continue** and **break** + +### Continue + +The `continue` statement can be used to skip past an iteration. For example, if we for some reason want to skip every fifth iteration, we could use the following code: + +```python +for i in range(10) + if i == 5: + continue + print(i) +``` + +Running this script will result in: + +```python +0 +1 +2 +3 +4 +6 # we skip the 5th iteration +7 +8 +9 +10 +``` + +### Break + +The `break` statement can be used to break out of a loop before it finishes all iterations. This can be useful to for example cancel a process if something unexpected happens. + +```python +for i in range(10) + if i == 5: + break + print(i) +``` + +Running this script will result in: + +```python +0 +1 +2 +3 +4 +``` + +## Conclusion + +Loops are essential for automating repetitive tasks in MicroPython. Understanding how to use different loop structures allows you to write more efficient and effective code. + +In these examples, we've demonstrated how to create loops that can: +- Run *for* a specific amount of iterations (for loops) +- Loops that can run *while* a condition is met (while loops) + diff --git a/content/micropython/01.basics/03.code-editors/assets/mpylabs-ss.png b/content/micropython/01.basics/03.code-editors/assets/mpylabs-ss.png deleted file mode 100644 index b56c8a1a7e..0000000000 Binary files a/content/micropython/01.basics/03.code-editors/assets/mpylabs-ss.png and /dev/null differ diff --git a/content/micropython/01.basics/03.code-editors/assets/openmv-ss.png b/content/micropython/01.basics/03.code-editors/assets/openmv-ss.png deleted file mode 100644 index ede5900ed6..0000000000 Binary files a/content/micropython/01.basics/03.code-editors/assets/openmv-ss.png and /dev/null differ diff --git a/content/micropython/01.basics/03.code-editors/code-editors.md b/content/micropython/01.basics/03.code-editors/code-editors.md deleted file mode 100644 index 35d440d769..0000000000 --- a/content/micropython/01.basics/03.code-editors/code-editors.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Code Editors -description: Explore the available code editors for programming your Arduino board with MicroPython -author: Francesca Sanfilippo & Karl Söderby -micropython_type: basics -featured: micropython -hero_image: "./hero-banner.png" ---- - -To write and load scripts to your board, you will also need a Code Editor. In this page, you will find two alternatives: -- **Arduino Lab for MicroPython:** an experimental editor from Arduino, designed for simpler projects. -- **OpenMV:** an editor for more complex projects, such as computer vision. - -## Arduino Lab for MicroPython - -Arduino Lab for MicroPython is a software that supports programming Arduino boards with MicroPython. Through the customized editor, we can install MicroPython, and upload scripts directly to the board. The editor is able to manage the files and you can see what is uploaded on the board and vice versa. - -![Arduino Lab for MicroPython](assets/mpylabs-ss.png) - -- [Download Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython). - -## OpenMV Editor - -OpenMV is a platform that supports programming Arduino boards with MicroPython. Through the OpenMV editor, we can install MicroPython and upload scripts directly to the board. There's also a number of examples available directly in the editor. - -![OpenMV editor.](assets/openmv-ss.png) - -- [Download OpenMV](https://openmv.io/pages/download). - -***You can also check out the full list of examples in the [OpenMV's GitHub repository](https://github.com/openmv/openmv/tree/master/scripts/examples/50-Arduino-Boards).*** \ No newline at end of file diff --git a/content/micropython/01.basics/03.code-editors/py-hero-banner.png b/content/micropython/01.basics/03.code-editors/py-hero-banner.png deleted file mode 100644 index 00021c97cc..0000000000 Binary files a/content/micropython/01.basics/03.code-editors/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/03.data-logger/assets/data-csv.png b/content/micropython/01.basics/03.data-logger/assets/data-csv.png new file mode 100644 index 0000000000..4b6e0dd241 Binary files /dev/null and b/content/micropython/01.basics/03.data-logger/assets/data-csv.png differ diff --git a/content/micropython/01.basics/03.data-logger/assets/select-board-ide.png b/content/micropython/01.basics/03.data-logger/assets/select-board-ide.png new file mode 100644 index 0000000000..d144bafe37 Binary files /dev/null and b/content/micropython/01.basics/03.data-logger/assets/select-board-ide.png differ diff --git a/content/micropython/01.basics/03.data-logger/assets/usb-comp.png b/content/micropython/01.basics/03.data-logger/assets/usb-comp.png new file mode 100644 index 0000000000..e3c90f42cd Binary files /dev/null and b/content/micropython/01.basics/03.data-logger/assets/usb-comp.png differ diff --git a/content/micropython/01.basics/03.data-logger/data-logger.md b/content/micropython/01.basics/03.data-logger/data-logger.md new file mode 100644 index 0000000000..2a9dae2391 --- /dev/null +++ b/content/micropython/01.basics/03.data-logger/data-logger.md @@ -0,0 +1,105 @@ +--- +title: 'Data Logger' +description: 'Learn how to store data on a .csv file using MicroPython' +author: 'Karl Söderby' +tags: [MicroPython, Data Storage, CSV] +--- + +Data logging using MicroPython is a great feature, as we can use the board's file system to create files and store data in them. + +In this tutorial, we will create a `.csv` file, make some readings from an analog pin, and store the data in the file. The file can then be accessed via the Arduino Lab for MicroPython editor. + +***To learn more about the MicroPython file system, visit [this article](/micropython/environment/file-system).*** + +## Requirements + +Before we start, let's check the requirements: + +### MicroPython Compatible Arduino Boards + +MicroPython is officially supported on several Arduino boards. Here’s a list of the compatible boards: + +- [Portenta C33](https://store.arduino.cc/products/portenta-c33) +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/arduino-giga-r1-wifi) +- [Portenta H7](https://store.arduino.cc/products/portenta-h7) +- [Portenta H7 Lite](https://store.arduino.cc/products/portenta-h7-lite) +- [Portenta H7 Lite Connected](https://store.arduino.cc/products/portenta-h7-lite-connected) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect) +- [Nicla Vision](https://store.arduino.cc/products/nicla-vision) +- [Arduino Nano 33 BLE](https://store.arduino.cc/products/arduino-nano-33-ble) +- [Arduino Nano 33 BLE Rev2](https://store.arduino.cc/products/nano-33-ble-rev2) +- [Arduino Nano 33 BLE Sense Rev2](https://store.arduino.cc/products/arduino-nano-33-ble-sense-rev2) +- [Arduino Nano ESP32](https://store.arduino.cc/products/arduino-nano-esp32) + +### Software Requirements + +- [Arduino Lab for Micropython](https://labs.arduino.cc/en/labs/micropython) - Arduino Lab for MicroPython is an editor where we can create and run MicroPython scripts on our Arduino board. + +***Note that the editor is also available online, at [Arduino Cloud - Arduino Labs for MicroPython](https://lab-micropython.arduino.cc/)*** + +## Board and Editor Setup + +1. Open the [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) application. +2. Plug the Arduino board into the computer using a USB cable. + ![Connect board to computer.](assets/usb-comp.png) +3. Press the connection button on the top left corner of the window. The connected Arduino board should appear (by its port name), and we can click it: + ![Connect to the board in the editor.](assets/select-board-ide.png) + +***Need help installing MicroPython on your board? Visit the [MicroPython installation guide](/micropython/first-steps/install-guide).*** + +## Data Logger Example + +Copy and paste the script below, and run it: + +```python +import machine +from machine import Pin +import time + +adc_pin = machine.Pin("A1") +adc = machine.ADC(adc_pin) +led = Pin("D13", Pin.OUT) +readings = 0 + +# create a file named "data.csv" +file=open("data.csv","w") +file.write("data"+"\n") + +while True: + + led.value(1) + reading = adc.read_u16() + print("ADC: ",reading) + + time.sleep_ms(100) + + # convert and write the reading from the analog pin + file.write(str(reading)+"\n") + + led.value(0) + time.sleep_ms(100) + readings += 1 + + # if 25 readings are done, finish the program + if readings >= 25: + file.close() + break +``` + +### How it Works + +The data logger example works as follows: + +- First, we create a `.csv` file, and open it using `file.open()`. +- Then, we read the value of an analog pin, and log it, using the `file.write()` function. +- We repeat 25 times and then finish script by closing the file with `file.close()`. +- Each time a reading is recorded, the built-in LED flashes. + +At the end of the script, a file will appear in your file system called `data.csv`. This is now accessible in the editor, where you can open it, and move it over to your computer. + +### Access the File + +To access the data, click the "Files" button, and navigate to the `data.csv` file. Open it, and you will see the data inside it. You can now move it to the computer by using the arrows, or simply copy the whole content of the file. + +![Accessing data.csv](assets/data-csv.png) + diff --git a/content/micropython/01.basics/04.essentials/essentials.md b/content/micropython/01.basics/04.essentials/essentials.md new file mode 100644 index 0000000000..52ffc24920 --- /dev/null +++ b/content/micropython/01.basics/04.essentials/essentials.md @@ -0,0 +1,290 @@ +--- +title: 'Essentials' +description: 'A guide to digital inputs and outputs using MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, Basics, Essentials] +--- + +To make the most of all the tools available in your "Python" belt (thankfully, pythons are non-venomous!), understanding MicroPython's fundamental concepts is essential. This guide focuses on the language basics, covering variable types, lists, tuples, functions, and exception handling to help you build efficient and powerful programs. + +## Variables and Data Types + +Variables in MicroPython don’t need explicit type declarations. The type is inferred based on the assigned value. + +### Example: + +```python +# Different data types +integer_var = 42 # Integer +float_var = 3.14 # Float +string_var = "Hello!" # String +boolean_var = True # Boolean + +# Print variable types +print(type(integer_var)) # Output: +print(type(float_var)) # Output: +print(type(string_var)) # Output: +print(type(boolean_var)) # Output: +``` + +## Lists + +Lists are a versatile way to store collections of items in MicroPython. They can hold any combination of data types and are mutable, meaning you can modify them after creation. + +### Creating Lists + +To create a list, we need to define a variable, followed by square brackets `[]`. The content of the list is separated by a comma (`,`). + +```python +my_list = [1, 2, 3, "Four", True] +print(my_list) # Output: [1, 2, 3, 'Four', True] +``` + +### Accessing Elements + +Lists are zero-indexed, meaning the first element is at index `0`. + +```python +print(my_list[0]) # Output: 1 +print(my_list[3]) # Output: Four +``` + +### Modifying Lists + +We can modify an element inside a list by assigning it a new value. + +```python +my_list[1] = 20 +print(my_list) # Output: [1, 20, 3, 'Four', True] +``` + +### Common List Methods + +```python +my_list.append("New Item") # Add an item +print(my_list) # Output: [1, 20, 3, 'Four', True, 'New Item'] + +my_list.pop(2) # Remove item at index 2 +print(my_list) # Output: [1, 20, 'Four', True, 'New Item'] +``` + + + +## Tuples + +Tuples are similar to lists but **immutable**, meaning their values cannot be changed after they are created. They are useful for representing fixed collections of items. + +### Creating Tuples + +```python +my_tuple = (1, 2, 3, "Four", True) +print(my_tuple) # Output: (1, 2, 3, 'Four', True) +``` + +### Accessing Elements: + +Like lists, tuples are zero-indexed. + +```python +print(my_tuple[0]) # Output: 1 +print(my_tuple[3]) # Output: Four +``` + +### Why Use Tuples? + +- **Efficiency**: Tuples consume less memory than lists. +- **Safety**: Their immutability prevents accidental changes to the data. + +### Common Tuple Methods: + +Tuples are limited compared to lists but have a few useful methods: + +```python +my_tuple = (1, 2, 3, 2, 4) + +print(my_tuple.count(2)) # Output: 2 (number of times 2 appears) +print(my_tuple.index(3)) # Output: 2 (index of the first occurrence of 3) +``` + +## Functions + +Functions allow you to encapsulate reusable blocks of code, making your programs more modular and readable. + +To define a function, we use `def` followed by the name of the function and parameters. In this case, let's define a function named `greet()`, which has the parameter `name`. + +```python +def greet(name): + print(f"Hello, {name}!") +``` + +Then, we can call the function, and insert a name. + +```python +greet("Karl") # Output: Hello, Karl! +greet("Alex") # Output: Hello, Alex! +``` + +The result will be: + +```cmd +Hello Karl! +Hello Alex! +``` + +### Returning Values + +A function can also accept numbers, and compute them for you. In this case, we want to find out the **square number** of a number (a number multiplied by itself). + +Inside the function we use `number * number` to get the value, and `return` to return the value to where it is called. + +```python +def square(number): + return number * number + +result = square(4) +print(result) # Output: 16 +``` + +### Default Arguments + +If you have function with parameters, you can set a **default** value, so that if we call the function without a parameter, we get a default value returned. + +In this case, we set the default to be `"World"`. + +```python +def greet(name="World"): + print(f"Hello, {name}!") + +greet() # Output: Hello, World! +greet("Karl") # Output: Hello, Karl! +``` + +## Objects + +Objects are a cornerstone of Python, and MicroPython fully supports object-oriented programming (OOP). An object is an instance of a **class**, and it can have **properties (attributes)** and **behaviors (methods)**. Let’s break these concepts down: + +- **Class**: A blueprint or template for creating objects. It defines the structure (attributes) and behavior (methods) that the objects will have. Think of a class as the recipe for making objects. +- **Attributes**: Variables that store data specific to an object. These are the properties or characteristics of the object, like a dog’s name or breed. +- **Methods**: Functions defined inside a class that operate on the object’s attributes or perform specific actions. These represent the behavior of the object, like a dog barking. + +Here’s how these concepts come together: + +### Defining a Class + +Use the `class` keyword to define a class. Inside the class, we can define attributes and methods. + +```python +class Dog: + # Constructor method to initialize attributes + def __init__(self, name, breed): + self.name = name # Attribute: name + self.breed = breed # Attribute: breed + + # Method: A behavior of the dog + def bark(self): + print(f"{self.name} says: Woof!") +``` + +### Creating an Object + +An object is an instance of the class. It represents a specific entity created from the class blueprint. + +```python +# Create an object of the Dog class +my_dog = Dog("Denver", "Golden Retriever") + +# Access attributes +print(my_dog.name) # Output: Denver +print(my_dog.breed) # Output: Golden Retriever + +# Call a method +my_dog.bark() # Output: Buddy says: Woof! +``` + +In this example: +1. The `Dog` class is the blueprint. +2. `name` and `breed` are attributes (properties of the dog). +3. `bark()` is a method (a behavior of the dog). + + +## Exception Handling + +In MicroPython, exceptions are a powerful way to deal with errors gracefully, ensuring your program doesn’t crash unexpectedly. By catching and handling exceptions, you can recover or retry alternative solutions. + +Exceptions use logic we are already familiar with, just in a slightly different format, and contribute to making more foolproof code. + +### Basic Structure + +Exceptions follow a simple structure using `try`, `except`, and optionally `finally` blocks: + +```python +try: + # Code that might raise an exception + risky_operation() +except ExceptionType: + # Code to handle the exception +finally: + # Code that runs no matter what (optional) +``` + +### Common Exceptions + +- **`ZeroDivisionError`**: Raised when dividing by zero. +- **`ValueError`**: Raised when a function receives an invalid argument. +- **`TypeError`**: Raised when an operation is applied to an unsupported type. + +#### Example: Handling a ZeroDivisionError + +In this case, we will set up the script to "fail", by providing it with an impossible task: dividing something by `0`. + +```python +try: + result = 10 / 0 +except ZeroDivisionError: + print("Cannot divide by zero!") # Output: Cannot divide by zero! +``` + +### Example: Using `else` and `finally` + +We can make the decision tree a bit more complex, by using the `else` and `finally` operators. + +In this case, we first try a division. If successful, we skip the `except` and jump to the `else`, which will print out the value, and `finally` we print out a statement `"Completed!"`. + +```python +try: + result = 10 / 2 +except ZeroDivisionError: + print("Cannot divide by zero!") +else: + print(f"Result: {result}") # Output: Result: 5.0 +finally: + print("Completed!") # Always executes +``` + +### Raising Custom Exceptions + +We can also implement custom exceptions: + +```python +def check_positive(number): + if number < 0: + raise ValueError("Number must be positive!") + +try: + check_positive(-5) +except ValueError as e: + print(e) # Output: Number must be positive! +``` + + + +## Summary + +MicroPython provides a solid foundation for programming microcontrollers with ease. In this guide, we covered: + +- Variables and data types +- Lists and tuples +- Defining and calling functions +- Exception handling for graceful error recovery + +With these fundamentals, you’re ready to build powerful and efficient applications. Dive into our additional tutorials for more advanced topics! diff --git a/content/micropython/01.basics/04.micropython-basics/assets/labs-connect.png b/content/micropython/01.basics/04.micropython-basics/assets/labs-connect.png deleted file mode 100644 index 53d4b1d934..0000000000 Binary files a/content/micropython/01.basics/04.micropython-basics/assets/labs-connect.png and /dev/null differ diff --git a/content/micropython/01.basics/04.micropython-basics/micropython-basics.md b/content/micropython/01.basics/04.micropython-basics/micropython-basics.md deleted file mode 100644 index af91c68cf9..0000000000 --- a/content/micropython/01.basics/04.micropython-basics/micropython-basics.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: MicroPython Basics -description: An introduction to MicroPython -author: Francesca Sanfilippo & Karl Söderby -micropython_type: basics ---- - -As you read in the Overview, MicroPython is an implementation of Python. In this page, you will find some basic and intermediate MicroPython scripts that can be used by any Arduino board. This includes some very common concepts such as variables, loops, delays, how to print and more. - -***There are some differences between MicroPython and Python, which mostly concern standard library and types, but also some language-level features.*** - -After you download [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython), click the file for your system, extract and run the application. The interface is similar to Arduino IDE. - -First of all, we need to connect our board to the computer via USB. - -After connecting the board, click on the connect button, and select the port. - -![Connect and select the port.](assets/labs-connect.png) - -Now that you have connected your board, let’s create a file that will contain the script that will run on your board. Click on New button to create your file. The editor automatically creates the main file in the board. - -If you are not working with the editor, the file should be named main.py and should be saved to your board manually. The board will recognize this as the main program. - -## First MicroPython Script - -Our first example is a basic script that will print `Hello world!` every second in the terminal. Paste the below script in the editor, and press the **"Play"** button. - -```python -print('Hello world!') -``` - -## Program Constructs - -There are three basic programming constructs which are Sequential, Looping and Branching. -- Sequential: a sequence of instructions. -- Looping: the program is executed according to the condition being used. There are two functions: while loop and for loop. -- Branching: it is a programming construct where a section of code is run only if a condition is met. - -In this section we’ll see some of program constructs. - -## Variables, While Loop and Sleep - -In this second example we introduce the module time using import in order to pause the execution for a specific time. The module help us control the board with MicroPython. - -```python -import time -content = "Hello world!" - -while True: - print(content) - time.sleep(1) -``` - -By definition a variable is a string of characters and numbers associated with a piece of information. We define the variable content `Hello World!`. - -Then with the `while` loop we execute the statements as long as the condition is true. In the code we use the `sleep` function to pause the execution of the script for a second before it continues to print. This is imported from the `time` module. - -## Functions - -A function is a block of code, a sequence of instructions composed by several statements, which runs only when it is called. -You can pass the information as parameters into a function. A function can have input arguments, and can also have output parameters. - -We can define our own functions, the most common way can be specified using the def keyword, inside the parentheses you can find the arguments if there are. Take a look to the example below: - -```python -def my_function(): - print("Hello world!") -``` - -Then you can call your function using the function name followed by parentheses: - -```python -my_function() -``` - -The function need two components: the header, starting with keyword def, followed by parentheses with inside the arguments and ending by colon (:) and the indented body is composed by descriptive string, function statements, return statements. - -This script prints "Hello world!" every second. In addition, the function counter_function() increases the number every second and will be printed next to. - -```python -import time - -content = "Hello world!" -count = 0 - -def counter_function(): - global count - count = count + 1 - -while True: - counter_function() - print(content, count) - time.sleep(1) -``` - -## Conditionals and Loops - -MicroPython supports logical conditions from mathematics, that can be used in several ways, the most common is an "if conditional" and “for loop”. The if statements is written by if keyword and it needs the indentation, otherwise you will get an error. - -### If/Else Statement - -A if/else statement is used to handle conditions in your program. These statements guide the program while making decisions based on the conditions encountered by the program. - -You can try the code below: - -```python -a = 42 -b = 23 -if a > b : - print("a is greater than b") -else : - print("a is not greater than b") -``` - -The result in this case is always going to be: `a is greater than b`, because `42` is larger than `23`. - -### For Loop - -Simple use of a for loop and functions. This script counts to 10, and then back to 0. - -```python -import time - -count = 0 - -def function_increase(): - global count - count = count +1 - print(count) - -def function_decrease(): - global count - count = count -1 - print(count) - -while True: - for x in range(10): - function_increase() - time.sleep(1) - - for x in range(10): - function_decrease() - time.sleep(1) -``` - -## Arrays - -An array is one of the most known and used construct in programming. In MicroPython an array by definition is a collection of elements (values or variables), selected by one or more indices computed at run-time, you refer to an array element by referring to the index number. - -```python -myFruit = ['orange', 'persimon', 'apple', 'kiwi', 'lemon'] - -def printFruitNames(): - for fruit in myFruit: - print(fruit) - -printFruitNames() -``` \ No newline at end of file diff --git a/content/micropython/01.basics/04.micropython-basics/py-hero-banner.png b/content/micropython/01.basics/04.micropython-basics/py-hero-banner.png deleted file mode 100644 index 0aaf7ba007..0000000000 Binary files a/content/micropython/01.basics/04.micropython-basics/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/05.digital-analog-pins/digital-analog-pins.md b/content/micropython/01.basics/05.digital-analog-pins/digital-analog-pins.md deleted file mode 100644 index 5ba0ba6616..0000000000 --- a/content/micropython/01.basics/05.digital-analog-pins/digital-analog-pins.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: Digital and Analog Pins -description: Learn how to use digital and analog Pins with Micropython -author: Francesca Sanfilippo & Karl Söderby -micropython_type: basics ---- - -In this chapter we will learn about managing digital and analog pins. - -All the compatible boards have a series of pins, most of these pins work as a general-purpose input/output (GPIO) pin. There are Digital Pins and Analog Pins depending on the signal. We will learn how to use the inputs and outputs. - -There are essentially two types of pins, analog and digital pins. Digital pins can be set to either HIGH (usually 5V or 3.3V) or LOW (0V). You can use that to e.g. read a button state or toggle an LED. - -***Important: unfortunately, the MicroPython implementation does not match the regular pinout of your board. This means, that if you want to use for example, digital pin (5), it might be digital pin (27) on one board, or digital pin (14) on another. Please visit the [Board API article](/micropython/basics/board-examples) to see what the pin map for your board is.*** - -## Digital Pins - -Digital signals have two distinct values: HIGH (1) or LOW (0). You use digital signals in situations where the input or output will have one of those two values. For example, you can use a digital signal to turn an LED on or off. - -### Digital Write - -In this section we will introduce the `machine` module to control the state of a pin. In this example, we will name the pin `myLED`. - -In MicroPython we can declare a `Pin` with two arguments: Pin number, such as `25`, which defines the number of the pin that you would like to control, and `Pin.OUT`, to declare a pin as output. - -Finally, to turn the pin to a high or low state, we set the `value` to either `1` or `0`. - -```python -from machine import Pin #import pin function - -myLED = Pin(25, Pin.OUT) #declare pin 25 as an output - -myLED.value(1) #set pin to a high state (1) / ON -myLED.value(0) #set pin to a low state (0) / OFF -``` - -To create the classic "blink" example, we can also import the `time` module, and create a `while` loop. - -The following example blinks the onboard LED every second. - -```python -from machine import Pin -import time - -myLED = Pin(25, Pin.OUT) #Nano RP2040 Connect -#myLED = Pin(10, Pin.OUT) #Nano 33 BLE / Nano 33 BLE Sense -#myLED = Pin(2, Pin.OUT) #Portenta H7 - - -while True: - myLED.value(0) - time.sleep(1) - myLED.value(1) - time.sleep(1) -``` - -### Digital Read (Pull Up) - -In this example we read a digital value from a digital pin, using the `PULL_UP` mode. Here, we declare the pin an input through the `Pin.IN` command. - -Then, we use `p2.value()` to read the state, which returns either 0 (low) or 1 (high). - -```python -from machine import Pin -import utime - -p2 = Pin(25, Pin.IN, Pin.PULL_UP) - -while True: - print(p2.value()) - utime.sleep(1) -``` - -### Digital Read (Pull Down) - -In this example we read a digital value from a digital pin, using the `PULL_DOWN` mode. Here, we declare the pin an input through the `Pin.IN` command. - -Then, we use `p2.value()` to read the state, which returns either 0 (low) or 1 (high). - -```python -from machine import Pin -import utime - -p2 = Pin(25, Pin.IN, Pin.PULL_DOWN) - -while True: - print(p2.value()) - utime.sleep(1) -``` - -## Analog Pins - -An example of the analog pin is the ADC class, which supplies an interface to analog-to-digital converters, and figures a single endpoint that can sample a continuous voltage and convert it to a discretized value. - -There are four methods to use inside the ADC class: `ADC.init`, `ADC.block()`, `ADC.read_16()` and `ADC.read_uv()`. - -### Analog Read - -To read an analog pin, we can use the `ADC.read_u16` command. This reads the specified analog pin and returns an integer in the range 0 - 65535. For this, we need to import `ADC` and `Pin` from the `machine` module. - -```python -import machine -import time - -# Make sure to follow the GPIO map for the board you are using. -# Pin 29 in this case is the "A3" pin on the Nano 33 BLE / BLE Sense -adc_pin = machine.Pin(29) -adc = machine.ADC(adc_pin) - -while True: - reading = adc.read_u16() - print("ADC: ",reading) - time.sleep_ms(500) -``` - -***If you are using an [Arduino Nano RP2040 Connect](https://store.arduino.cc/products/arduino-nano-rp2040-connect), you can also do the following: `adc = ADC("A4")`. For more information check out the example [here](http://docs.arduino.cc/micropython/basics/board-examples/#analog-read).*** - -## PWM (Pulse Width Modulation) - -[PWM](/learn/microcontrollers/analog-output) is used to produce analog results with digital means, by switching ON/OFF a signal rapidly. - -As a result, you can simulate a specific voltage written to a pin. In the example below, we write `30000` in a range between 0 - 65535 (16 bits), which if you connect an LED to the pin, will be on at about "half" capacity. - -For this, we need to import `PWM` and `Pin` from the `machine` module. - -### Coding with PWM - -```python -from machine import Pin, PWM, ADC - -pwm = PWM(Pin(15)) -duty = 30000 #between 0-65000 - -pwm.freq(1000) - -while True: - pwm.duty_u16(duty) -``` -In this example: - -- `Pin(15)` is attached to PWM -- `duty` is set at 3000 -- `freq` is set at 1 Hz - -### PWM on the GIGA R1 - -On STM32 boards like the [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/giga-r1-wifi), PWM is handled differently. You need to use the `Timer` class along with the `Pin` class from the `pyb` module. - -Here's the correct code that works on these boards: - -```python -from pyb import Pin, Timer - -p = Pin('A13') # Replace 'A13' with your desired PWM-capable pin -tim = Timer(2, freq=1000) -ch = tim.channel(1, Timer.PWM, pin=p) -ch.pulse_width_percent(25) -``` - -In this example: - -- `p` is a `Pin` object initialized on pin `'A13'`. This pin is set up for PWM output. -- `tim` is a `Timer` object initialized with timer number 2 and a frequency of 1000 Hz. -- `ch` is a PWM channel created on timer 2, channel 1, and is associated with pin `p`. -- `ch.pulse_width_percent(25)` sets the duty cycle of the PWM signal to 25%. -- `'A13'` is marked as **DAC1** on the GIGA R1 WiFi - - - -- Pin names and timer configurations, may vary between different STM32 boards. For more information, check out the [GIGA R1 MicroPython Guide](https://docs.arduino.cc/tutorials/giga-r1-wifi/giga-micropython/). - diff --git a/content/micropython/01.basics/05.digital-analog-pins/py-hero-banner.png b/content/micropython/01.basics/05.digital-analog-pins/py-hero-banner.png deleted file mode 100644 index f0680b9243..0000000000 Binary files a/content/micropython/01.basics/05.digital-analog-pins/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/06.board-examples/assets/ble-sense.png b/content/micropython/01.basics/06.board-examples/assets/ble-sense.png deleted file mode 100644 index 52908dbc5e..0000000000 Binary files a/content/micropython/01.basics/06.board-examples/assets/ble-sense.png and /dev/null differ diff --git a/content/micropython/01.basics/06.board-examples/assets/ble.png b/content/micropython/01.basics/06.board-examples/assets/ble.png deleted file mode 100644 index e63994064d..0000000000 Binary files a/content/micropython/01.basics/06.board-examples/assets/ble.png and /dev/null differ diff --git a/content/micropython/01.basics/06.board-examples/assets/nano-rp2040.png b/content/micropython/01.basics/06.board-examples/assets/nano-rp2040.png deleted file mode 100644 index d38a07ea22..0000000000 Binary files a/content/micropython/01.basics/06.board-examples/assets/nano-rp2040.png and /dev/null differ diff --git a/content/micropython/01.basics/06.board-examples/assets/portenta.png b/content/micropython/01.basics/06.board-examples/assets/portenta.png deleted file mode 100644 index b696c79a88..0000000000 Binary files a/content/micropython/01.basics/06.board-examples/assets/portenta.png and /dev/null differ diff --git a/content/micropython/01.basics/06.board-examples/assets/portenta33_MKR_pinout.png b/content/micropython/01.basics/06.board-examples/assets/portenta33_MKR_pinout.png deleted file mode 100644 index 6767c082b1..0000000000 Binary files a/content/micropython/01.basics/06.board-examples/assets/portenta33_MKR_pinout.png and /dev/null differ diff --git a/content/micropython/01.basics/06.board-examples/board-examples.md b/content/micropython/01.basics/06.board-examples/board-examples.md deleted file mode 100644 index 16535998d2..0000000000 --- a/content/micropython/01.basics/06.board-examples/board-examples.md +++ /dev/null @@ -1,1895 +0,0 @@ ---- -title: Examples by Board -description: Find examples that work only with specific boards, such as reading built-in sensors. -author: Karl Söderby -micropython_type: basics -featured: micropython -hero_image: "./hero-banner.png" ---- - -In this article, you will find examples that works only with specific boards. Each board also has a GPIO map that explains how each pin can be addressed. - -## Nano RP2040 Connect - -![Nano RP2040 Connect.](assets/nano-rp2040.png) - -### GPIO Map - -The pinout for the **Nano RP2040 Connect** and the **RP2040 microcontroller** varies greatly. For example, if we are to use `D2` according to the Arduino pinout, we would actually need to use **pin 25**. - -```python -# Defining "D2" on the Arduino Nano RP2040 Connect -p0 = Pin(25, Pin.OUT) -``` - -Before you start using the board's pins, it might be a good idea to check out the table below to understand the relationship between Arduino's pinout and the RP2040's pinout. - -| Arduino | RP2040 | Usage | -| ------- | ------ | ------------- | -| TX | GPIO0 | UART/TX | -| RX | GPIO1 | UART/RX | -| D2 | GPIO25 | GPIO | -| D3 | GPIO15 | GPIO | -| D4 | GPIO16 | GPIO | -| D5 | GPIO17 | GPIO | -| D6 | GPIO18 | GPIO | -| D7 | GPIO19 | GPIO | -| D8 | GPIO20 | GPIO | -| D9 | GPIO21 | GPIO | -| D10 | GPIO5 | GPIO | -| D11 | GPIO7 | SPI/COPI | -| D12 | GPIO4 | SPI/CIPO | -| D13 | GPIO6 | SPI/SCK | -| D14/A0 | GPIO26 | ADC/RP2040 | -| D15/A1 | GPIO27 | ADC/RP2040 | -| D16/A2 | GPIO28 | ADC/RP2040 | -| D17/A3 | GPIO29 | ADC/RP2040 | -| D18/A4 | GPIO12 | I2C | -| D19/A5 | GPIO13 | I2C | -| D20/A6 | GPIO36 | ADC/NINA-W102 | -| D21/A7 | GPIO35 | ADC/NINA-W102 | - -### Analog Read - -***Note: This is currently only available on the nightly build. Follow [this link](https://docs.arduino.cc/micropython/#firmware) to download it.*** - -To read an analog pin, we can use the `ADC.read_u16` command. This reads the specified analog pin and returns an integer in the range 0 - 65535. For this, we need to import `ADC` from the `machine` module. - -```python -from machine import ADC - -while True: - adc = ADC("A4") - adc.read_u16() -``` - -### Sensors - -#### IMU (LSM6DSOX) - -Prints the accelerometer and gyroscope values in the Serial Monitor. - -```python -import time -from lsm6dsox import LSM6DSOX -from machine import Pin, I2C - -# Initialize the LSM6DSOX sensor with I2C interface -lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12))) - -while True: - # Read accelerometer values - accel_values = lsm.accel() - print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*accel_values)) - - # Read gyroscope values - gyro_values = lsm.gyro() - print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*gyro_values)) - - print("") - time.sleep_ms(100) -``` - -### Microphone (MP34DT05) - -Below example can be used with OpenMV's frame buffer window (top right corner). - -```python -import image, audio, time -from ulab import numpy as np -from ulab import scipy as sp - -CHANNELS = 1 -FREQUENCY = 32000 -N_SAMPLES = 32 if FREQUENCY == 16000 else 64 -SCALE = 2 -SIZE = (N_SAMPLES * SCALE) // CHANNELS - -raw_buf = None -fb = image.Image(SIZE+(50*SCALE), SIZE, image.RGB565, copy_to_fb=True) -audio.init(channels=CHANNELS, frequency=FREQUENCY, gain_db=16) - -def audio_callback(buf): - # NOTE: do Not call any function that allocates memory. - global raw_buf - if (raw_buf == None): - raw_buf = buf - -# Start audio streaming -audio.start_streaming(audio_callback) - -def draw_fft(img, fft_buf): - fft_buf = (fft_buf / max(fft_buf)) * SIZE - fft_buf = np.log10(fft_buf + 1) * 20 - color = (0xFF, 0x0F, 0x00) - for i in range(0, len(fft_buf)): - img.draw_line(i*SCALE, SIZE, i*SCALE, SIZE-int(fft_buf[i]) * SCALE, color, SCALE) - -def draw_audio_bar(img, level, offset): - blk_size = (SIZE//10) - color = (0xFF, 0x00, 0xF0) - blk_space = (blk_size//4) - for i in range(0, int(round(level/10))): - fb.draw_rectangle(SIZE+offset, SIZE - ((i+1)*blk_size) + blk_space, 20 * SCALE, blk_size - blk_space, color, 1, True) - -while (True): - if (raw_buf != None): - pcm_buf = np.frombuffer(raw_buf, dtype=np.int16) - raw_buf = None - - if CHANNELS == 1: - fft_buf = sp.signal.spectrogram(pcm_buf) - l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) - else: - fft_buf = sp.signal.spectrogram(pcm_buf[0::2]) - l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) - r_lvl = int((np.mean(abs(pcm_buf[0::2])) / 32768)*100) - - fb.clear() - draw_fft(fb, fft_buf) - draw_audio_bar(fb, l_lvl, 0) - draw_audio_bar(fb, l_lvl, 25*SCALE) - if CHANNELS == 2: - draw_audio_bar(fb, r_lvl, 25 * SCALE) - fb.flush() - -# Stop streaming -audio.stop_streaming() -``` - -### Communication - -#### I2C - -Scans for devices connected to the I2C buses: - -```python -import time -from machine import Pin, I2C - -i2c_list = [None, None] -i2c_list[0] = I2C(0, scl=Pin(13), sda=Pin(12), freq=100_000) -i2c_list[1] = I2C(1, scl=Pin(7), sda=Pin(6), freq=100_000) - -for bus in range(0, 2): - print("\nScanning bus %d..."%(bus)) - for addr in i2c_list[bus].scan(): - print("Found device at address %d:0x%x" %(bus, addr)) -``` - -#### UART - -To read data and write data through TX and RX pins, you can use `uart.write()` and `uart.read()`. - -```python -from machine import UART, Pin -import time - -uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) - -while True: - uart.write('hello') # writes 5 bytes - val = uart.read(5) # reads up to 5 bytes - print(val) # prints data - time.sleep(1) -``` - -### Wireless - -Below are examples on wireless connectivity, using the NINA-W102 module onboard the Nano RP2040 Connect. - -***In order to use these examples, you may have to upgrade your firmware. You can find instructions on how to in [Upgrading Nano RP2040 Connect NINA firmware](/tutorials/nano-rp2040-connect/rp2040-upgrading-nina-firmware).*** - -#### Wi-Fi AP Mode - -Turn your board into an access point: - -```python -# Wi-Fi AP Mode Example -# -# This example shows how to use Wi-Fi in Access Point mode. -import network, socket, sys, time, gc - -SSID ='My_Nano_RP2040_Connect' # Network SSID -KEY ='1234567890' # Network key (must be 10 chars) -HOST = '' # Use first available interface -PORT = 8080 # Arbitrary non-privileged port - -# Init wlan module and connect to network -wlan = network.WLAN(network.AP_IF) -wlan.active(True) -wlan.config(essid=SSID, key=KEY, security=wlan.WEP, channel=2) -print("AP mode started. SSID: {} IP: {}".format(SSID, wlan.ifconfig()[0])) - -def recvall(sock, n): - # Helper function to recv n bytes or return None if EOF is hit - data = bytearray() - while len(data) < n: - packet = sock.recv(n - len(data)) - if not packet: - raise OSError("Timeout") - data.extend(packet) - return data - -def start_streaming(server): - print ('Waiting for connections..') - client, addr = server.accept() - - # set client socket timeout to 5s - client.settimeout(5.0) - print ('Connected to ' + addr[0] + ':' + str(addr[1])) - - # FPS clock - clock = time.clock() - while (True): - try: - # Read data from client - data = recvall(client, 1024) - # Send it back - client.send(data) - except OSError as e: - print("start_streaming(): socket error: ", e) - client.close() - break - -while (True): - try: - server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # Bind and listen - server.bind([HOST, PORT]) - server.listen(1) - - # Set server socket to blocking - server.setblocking(True) - while (True): - start_streaming(server) - except OSError as e: - server.close() - print("Server socket error: ", e) -``` - -#### Wi-Fi® Scan - -To scan available networks: - -```python -# Scan Example - -# This example shows how to scan for Wi-Fi networks. - -import time, network - -wlan = network.WLAN(network.STA_IF) -wlan.active(True) - -print("Scanning...") -while (True): - scan_result = wlan.scan() - for ap in scan_result: - print("Channel:%d RSSI:%d Auth:%d BSSID:%s SSID:%s"%(ap)) - print() - time.sleep_ms(1000) -``` - -#### HTTP Request - -Making an HTTP request (in this case to google): - -***Remember to enter your network name and password inside the SSID and KEY variables.*** - -```python -import network, socket - -# AP info -SSID='' # Network SSID -KEY='' # Network key - -PORT = 80 -HOST = "www.google.com" - -# Init wlan module and connect to network -print("Trying to connect. Note this may take a while...") - -wlan = network.WLAN(network.STA_IF) -wlan.active(True) -wlan.connect(SSID, KEY) - -# We should have a valid IP now via DHCP -print("Wi-Fi Connected ", wlan.ifconfig()) - -# Get addr info via DNS -addr = socket.getaddrinfo(HOST, PORT)[0][4] -print(addr) - -# Create a new socket and connect to addr -client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -client.connect(addr) - -# Set timeout -client.settimeout(3.0) - -# Send HTTP request and recv response -client.send("GET / HTTP/1.1\r\nHost: %s\r\n\r\n"%(HOST)) -print(client.recv(1024)) - -# Close socket -client.close() -``` - -#### NTP (Network Time Protocol) - -***Remember to enter your network name and password inside the SSID and KEY variables.*** - -Obtain accurate time and date from the Internet: - -```python -# NTP Example -# -# This example shows how to get the current time using NTP - -import network, usocket, ustruct, utime - -# AP info -SSID='' # Network SSID -KEY='' # Network key - -TIMESTAMP = 2208988800 - -# Init wlan module and connect to network -print("Trying to connect... (may take a while)...") - -wlan = network.WLAN() -wlan.active(True) -wlan.connect(SSID, key=KEY, security=wlan.WPA_PSK) - -# We should have a valid IP now via DHCP -print(wlan.ifconfig()) - -# Create new socket -client = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM) -client.bind(("", 8080)) -#client.settimeout(3.0) - -# Get addr info via DNS -addr = usocket.getaddrinfo("pool.ntp.org", 123)[0][4] - -# Send query -client.sendto('\x1b' + 47 * '\0', addr) -data, address = client.recvfrom(1024) - -# Print time -t = ustruct.unpack(">IIIIIIIIIIII", data)[10] - TIMESTAMP -print ("Year:%d Month:%d Day:%d Time: %d:%d:%d" % (utime.localtime(t)[0:6])) -``` - -In the terminal, we should see it in this format: - -``` -Year:2021 Month:8 Day:10 Time: 7:56:30 -``` - -#### Bluetooth® Low Energy - -This example allows us to connect to our board via our phone, and control the built-in LED. We recommend using the **nRF Connect** applications. - -- [nRF desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop) -- [nRF mobile](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile) - -***After loading the script below, your board should be listed as "Nano RP2040 Connect" in the list of available devices. You need to pair in order to control the built-in LED.*** - -```python -import bluetooth -import random -import struct -import time -from ble_advertising import advertising_payload -from machine import Pin -from micropython import const - -LED_PIN = 6 - -_IRQ_CENTRAL_CONNECT = const(1) -_IRQ_CENTRAL_DISCONNECT = const(2) -_IRQ_GATTS_WRITE = const(3) - -_FLAG_READ = const(0x0002) -_FLAG_WRITE = const(0x0008) -_FLAG_NOTIFY = const(0x0010) -_FLAG_INDICATE = const(0x0020) - -_SERVICE_UUID = bluetooth.UUID(0x1523) -_LED_CHAR_UUID = (bluetooth.UUID(0x1525), _FLAG_WRITE) -_LED_SERVICE = (_SERVICE_UUID, (_LED_CHAR_UUID,),) - -class BLETemperature: - def __init__(self, ble, name="NANO RP2040"): - self._ble = ble - self._ble.active(True) - self._ble.irq(self._irq) - ((self._handle,),) = self._ble.gatts_register_services((_LED_SERVICE,)) - self._connections = set() - self._payload = advertising_payload(name=name, services=[_SERVICE_UUID]) - self._advertise() - - def _irq(self, event, data): - # Track connections so we can send notifications. - if event == _IRQ_CENTRAL_CONNECT: - conn_handle, _, _ = data - self._connections.add(conn_handle) - elif event == _IRQ_CENTRAL_DISCONNECT: - conn_handle, _, _ = data - self._connections.remove(conn_handle) - # Start advertising again to allow a new connection. - self._advertise() - elif event == _IRQ_GATTS_WRITE: - Pin(LED_PIN, Pin.OUT).value(int(self._ble.gatts_read(data[-1])[0])) - - def _advertise(self, interval_us=500000): - self._ble.gap_advertise(interval_us, adv_data=self._payload) - -if __name__ == "__main__": - ble = bluetooth.BLE() - temp = BLETemperature(ble) - - while True: - time.sleep_ms(1000) -``` - -## Nano 33 BLE - -![Nano 33 BLE.](assets/ble.png) - -### GPIO Map - -The pinout for the **Nano 33 BLE** and the **NRF52840 microcontroller** varies greatly. For example, if we are to use `D2` according to the Arduino pinout, we would actually need to use **pin 43**. - -```python -# Defining "D2" on the Nano 33 BLE -p0 = Pin(43, Pin.OUT) -``` - -In the MicroPython port of the Nano 33 BLE board, the pinout is the same as the Nordic NRF52840 (the microcontroller). You will find a GPIO Map below that explains how to address the different pins. - -| Arduino | nRF52840 | -| ------- | -------- | -| TX | 35 | -| RX | 42 | -| D2 | 43 | -| D3 | 44 | -| D4 | 47 | -| D5 | 45 | -| D6 | 46 | -| D7 | 23 | -| D8 | 21 | -| D9 | 27 | -| D10 | 34 | -| D11 | 33 | -| D12 | 40 | -| D13 | 13 | -| D14/A0 | 4 | -| D15/A1 | 5 | -| D16/A2 | 30 | -| D17/A3 | 29 | -| D18/A4 | 31 | -| D19/A5 | 2 | -| D20/A6 | 28 | -| D21/A7 | 3 | - -### Analog Read - -***The following example is currently only possible with the nightly build*** - -### LED Control - -There are 3 different LEDs that can be accessed on the Nano 33 BLE: **RGB, the built-in LED** and the **power LED**. - -They can be accessed by importing the `LED` module, where the RGB and built-in LED can be accessed. - -```python -from board import LED - -led_red = LED(1) # red LED -led_green = LED(2) # green LED -led_blue = LED(3) # blue LED -led_builtin = LED(4) # classic built-in LED (also accessible through pin 13) -``` - -To access the **power LED** we need to import the `Pin` module. - -```python -from machine import Pin - -led_pwr = Pin(41, Pin.OUT) -``` - -#### RGB - -Blink all RGB lights every 0.25 seconds. - -```python -from board import LED -import time - -led_red = LED(1) -led_green = LED(2) -led_blue = LED(3) - -while (True): - - # Turn on LEDs - led_red.on() - led_green.on() - led_blue.on() - - # Wait 0.25 seconds - time.sleep_ms(250) - - # Turn off LEDs - led_red.off() - led_green.off() - led_blue.off() - - # Wait 0.25 seconds - time.sleep_ms(250) -``` - -#### Built-in LED - -The classic blink example! Blink the built-in LED every 0.25 seconds. - -```python -from board import LED -import time - -led_builtin = LED(4) - -while (True): - - # Turn on LED - led_builtin.on() - - # Wait 0.25 seconds - time.sleep_ms(250) - - # Turn off LED - led_builtin.off() - - # Wait 0.25 seconds - time.sleep_ms(250) - -``` - -### Sensors - -#### IMU (LSM9DS1, BMI270 + BMM150) - -Access the `accelerometer`, `magnetometer`, and `gyroscope` data from the IMU module. - -```python -import time -import imu -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -imu = imu.IMU(bus) - -while (True): - print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.accel())) - print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.gyro())) - print('Magnetometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.magnet())) - print("") - time.sleep_ms(100) -``` - -### Wireless - -#### Bluetooth® Low Energy - -This example allows us to connect to our board via our phone, and control the built-in LED. We recommend using the **nRF Connect** applications. - -- [nRF desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop) -- [nRF mobile](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile) - -***After loading the script below, your board should be listed as "Nano 33 BLE" in the list of available devices. You need to pair in order to control the built-in LED.*** - -```python -# Use nRF Connect from App store, connect to the Nano and write 1/0 to control the LED. - -import time -from board import LED -from ubluepy import Service, Characteristic, UUID, Peripheral, constants - -def event_handler(id, handle, data): - global periph - global service - if id == constants.EVT_GAP_CONNECTED: - pass - elif id == constants.EVT_GAP_DISCONNECTED: - # restart advertisement - periph.advertise(device_name="Nano 33 BLE", services=[service]) - elif id == constants.EVT_GATTS_WRITE: - LED(1).on() if int(data[0]) else LED(1).off() - -# start off with LED(1) off -LED(1).off() - -notif_enabled = False -uuid_service = UUID("0x1523") -uuid_led = UUID("0x1525") - -service = Service(uuid_service) -char_led = Characteristic(uuid_led, props=Characteristic.PROP_WRITE) -service.addCharacteristic(char_led) - -periph = Peripheral() -periph.addService(service) -periph.setConnectionHandler(event_handler) -periph.advertise(device_name="Nano 33 BLE", services=[service]) - -while (True): - time.sleep_ms(500) -``` - -## Nano 33 BLE Sense - -![Nano 33 BLE Sense.](assets/ble-sense.png) - -### Pin Map - -The pinout for the **Nano 33 BLE Sense** and the **NRF52840 microcontroller** varies greatly. For example, if we are to use `D2` according to the Arduino pinout, we would actually need to use **pin 43**. - -```python -# Defining "D2" on the Nano 33 BLE Sense -p0 = Pin(43, Pin.OUT) -``` - -In the MicroPython port of the Nano 33 BLE Sense board, the pinout is the same as the Nordic NRF52840 (the microcontroller). You will find a pin map below this section that explains how to address the different pins. - -| Arduino | nRF52840 | -| ------- | -------- | -| TX | 35 | -| RX | 42 | -| D2 | 43 | -| D3 | 44 | -| D4 | 47 | -| D5 | 45 | -| D6 | 46 | -| D7 | 23 | -| D8 | 21 | -| D9 | 27 | -| D10 | 34 | -| D11 | 33 | -| D12 | 40 | -| D13 | 13 | -| D14/A0 | 4 | -| D15/A1 | 5 | -| D16/A2 | 30 | -| D17/A3 | 29 | -| D18/A4 | 31 | -| D19/A5 | 2 | -| D20/A6 | 28 | -| D21/A7 | 3 | - - -### LED Control - -There are 3 different LEDs that can be accessed on the Nano 33 BLE Sense: **RGB, the built-in LED** and the **power LED**. - -They can be accessed by importing the `LED` module, where the RGB and built-in LED can be accessed. - -```python -from board import LED - -led_red = LED(1) # red LED -led_green = LED(2) # green LED -led_blue = LED(3) # blue LED -led_builtin = LED(4) # classic built-in LED (also accessible through pin 13) -``` - -To access the **power LED** we need to import the `Pin` module. - -```python -from machine import Pin - -led_pwr = Pin(41, Pin.OUT) -``` - -#### RGB - -Blink all RGB lights every 0.25 seconds. - -```python -from board import LED -import time - -led_red = LED(1) -led_green = LED(2) -led_blue = LED(3) - -while (True): - - # Turn on LEDs - led_red.on() - led_green.on() - led_blue.on() - - # Wait 0.25 seconds - time.sleep_ms(250) - - # Turn off LEDs - led_red.off() - led_green.off() - led_blue.off() - - # Wait 0.25 seconds - time.sleep_ms(250) -``` - -#### Built-in LED - -The classic blink example! Blink the built-in LED every 0.25 seconds. - -```python -from board import LED -import time - -led_builtin = LED(4) - -while (True): - - # Turn on LED - led_builtin.on() - - # Wait 0.25 seconds - time.sleep_ms(250) - - # Turn off LED - led_builtin.off() - - # Wait 0.25 seconds - time.sleep_ms(250) - -``` - -### Sensors - -There are several sensors onboard the Nano 33 BLE Sense. The scripts below can be used to access the data from each of them. - -#### IMU (LSM9DS1, BMI270 + BMM150) - -Access the `accelerometer`, `magnetometer`, and `gyroscope` data from the IMU module. - -```python -import time -import imu -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -imu = imu.IMU(bus) - -while (True): - print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.accel())) - print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.gyro())) - print('Magnetometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.magnet())) - print("") - time.sleep_ms(100) -``` - - -#### Temperature & Humidity (HTS221) - -Access the `temperature` & `humidity` values from the HTS221 sensor (Nano 33 BLE Sense). - -```python -import time -import hts221 -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -hts = hts221.HTS221(bus) - -while (True): - rH = hts.humidity() - temp = hts.temperature() - print ("rH: %.2f%% T: %.2fC" %(rH, temp)) - time.sleep_ms(100) -``` - -#### Temperature & Humidity (HS3003) - -Access the `temperature` & `humidity` values from the HTS221 sensor (Nano 33 BLE Sense Rev2). - -```python -import time -from hs3003 import HS3003 -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -hts = HS3003(bus) - -while True: - rH = hts.humidity() - temp = hts.temperature() - print ("rH: %.2f%% T: %.2fC" %(rH, temp)) - time.sleep_ms(100) -``` - -#### Pressure (LPS22) - -Access the `pressure` values from the LPS22 sensor. - -```python -import time -import lps22h -from machine import Pin, I2C - -bus = I2C(1, scl=Pin(15), sda=Pin(14)) -lps = lps22h.LPS22H(bus) - -while (True): - pressure = lps.pressure() - temperature = lps.temperature() - print("Pressure: %.2f hPa Temperature: %.2f C"%(pressure, temperature)) - time.sleep_ms(100) -``` - -#### Ambient Light (APDS9960) - -Access the `Ambient Light` values from the APDS9960 sensor. - -```python -from time import sleep_ms -from machine import Pin, I2C -from apds9960.const import * -from apds9960 import uAPDS9960 as APDS9960 - -bus = I2C(1, sda=Pin(13), scl=Pin(14)) -apds = APDS9960(bus) - -print("Light Sensor Test") -print("=================") -apds.enableLightSensor() - -while True: - sleep_ms(250) - val = apds.readAmbientLight() - print("AmbientLight={}".format(val)) -``` - -#### Proximity (APDS9960) - -Access the `Proximity values` from the APDS9960 sensor. - -```python -from time import sleep_ms -from machine import Pin, I2C - -from apds9960.const import * -from apds9960 import uAPDS9960 as APDS9960 - -bus = I2C(1, sda=Pin(13), scl=Pin(14)) -apds = APDS9960(bus) - -apds.setProximityIntLowThreshold(50) - -print("Proximity Sensor Test") -print("=====================") -apds.enableProximitySensor() - -while True: - sleep_ms(250) - val = apds.readProximity() - print("proximity={}".format(val)) -``` - -#### Microphone (MP34DT05) - -Below example can be used with OpenMV's frame buffer window (top right corner). - -```python -import image, audio, time -from ulab import numpy as np -from ulab import scipy as sp - -CHANNELS = 1 -SIZE = 256//(2*CHANNELS) - -raw_buf = None -fb = image.Image(SIZE+50, SIZE, image.RGB565, copy_to_fb=True) -audio.init(channels=CHANNELS, frequency=16000, gain_db=80, highpass=0.9883) - -def audio_callback(buf): - # NOTE: do Not call any function that allocates memory. - global raw_buf - if (raw_buf == None): - raw_buf = buf - -# Start audio streaming -audio.start_streaming(audio_callback) - -def draw_fft(img, fft_buf): - fft_buf = (fft_buf / max(fft_buf)) * SIZE - fft_buf = np.log10(fft_buf + 1) * 20 - color = (0xFF, 0x0F, 0x00) - for i in range(0, SIZE): - img.draw_line(i, SIZE, i, SIZE-int(fft_buf[i]), color, 1) - -def draw_audio_bar(img, level, offset): - blk_size = SIZE//10 - color = (0xFF, 0x00, 0xF0) - blk_space = (blk_size//4) - for i in range(0, int(round(level/10))): - fb.draw_rectangle(SIZE+offset, SIZE - ((i+1)*blk_size) + blk_space, 20, blk_size - blk_space, color, 1, True) - -while (True): - if (raw_buf != None): - pcm_buf = np.frombuffer(raw_buf, dtype=np.int16) - raw_buf = None - - if CHANNELS == 1: - fft_buf = sp.signal.spectrogram(pcm_buf) - l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) - else: - fft_buf = sp.signal.spectrogram(pcm_buf[0::2]) - l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) - r_lvl = int((np.mean(abs(pcm_buf[0::2])) / 32768)*100) - - fb.clear() - draw_fft(fb, fft_buf) - draw_audio_bar(fb, l_lvl, 0) - if CHANNELS == 2: - draw_audio_bar(fb, r_lvl, 25) - fb.flush() - -# Stop streaming -audio.stop_streaming() -``` - -### Wireless - -#### Bluetooth® Low Energy - -This example allows us to connect to our board via our phone, and control the built-in LED. We recommend using the **nRF Connect** applications. - -- [nRF desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop) -- [nRF mobile](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-mobile) - -***After loading the script below, your board should be listed as "Nano 33 BLE Sense" in the list of available devices. You need to pair in order to control the built-in LED.*** - -```python -# Use nRF Connect from App store, connect to the Nano and write 1/0 to control the LED. - -import time -from board import LED -from ubluepy import Service, Characteristic, UUID, Peripheral, constants - -def event_handler(id, handle, data): - global periph - global service - if id == constants.EVT_GAP_CONNECTED: - pass - elif id == constants.EVT_GAP_DISCONNECTED: - # restart advertisement - periph.advertise(device_name="Nano 33 BLE Sense", services=[service]) - elif id == constants.EVT_GATTS_WRITE: - LED(1).on() if int(data[0]) else LED(1).off() - -# start off with LED(1) off -LED(1).off() - -notif_enabled = False -uuid_service = UUID("0x1523") -uuid_led = UUID("0x1525") - -service = Service(uuid_service) -char_led = Characteristic(uuid_led, props=Characteristic.PROP_WRITE) -service.addCharacteristic(char_led) - -periph = Peripheral() -periph.addService(service) -periph.setConnectionHandler(event_handler) -periph.advertise(device_name="Nano 33 BLE Sense", services=[service]) - -while (True): - time.sleep_ms(500) -``` - -## Portenta H7 - -![Portenta H7.](assets/portenta.png) - -***Note that the [Portenta H7 Lite](/hardware/portenta-h7-lite) and [Portenta H7 Lite Connected](/hardware/portenta-h7-lite-connected) boards are compatible with most examples listed here, as they are variations of the Portenta H7.*** - -### GPIO Map - -Most of the pins are referred to via their port name or their function. Please refer to the list below to see which function corresponds to which port on the Portenta H7. - -| Arduino | STM32H747 | -| ---------------- | --------- | -| PA0 | PA0 | -| PA1 | PA1 | -| PA2 | PA2 | -| PA3 | PA3 | -| PA4 | PA4 | -| PA5 | PA5 | -| PA6 | PA6 | -| PA7 | PA7 | -| PA8 | PA8 | -| PA9 | PA9 | -| PA10 | PA10 | -| PA11 | PA11 | -| PA12 | PA12 | -| PA13 | PA13 | -| PA14 | PA14 | -| PA15 | PA15 | -| PB0 | PB0 | -| PB1 | PB1 | -| PB2 | PB2 | -| PB3 | PB3 | -| PB4 | PB4 | -| PB5 | PB5 | -| PB6 | PB6 | -| PB7 | PB7 | -| PB8 | PB8 | -| PB9 | PB9 | -| PB10 | PB10 | -| PB11 | PB11 | -| PB12 | PB12 | -| PB13 | PB13 | -| PB14 | PB14 | -| PB15 | PB15 | -| PC0 | PC0 | -| PC1 | PC1 | -| PC2 | PC2 | -| PC3 | PC3 | -| PC4 | PC4 | -| PC5 | PC5 | -| PC6 | PC6 | -| PC7 | PC7 | -| PC8 | PC8 | -| PC9 | PC9 | -| PC10 | PC10 | -| PC11 | PC11 | -| PC12 | PC12 | -| PC13 | PC13 | -| PC14 | PC14 | -| PC15 | PC15 | -| PD0 | PD0 | -| PD1 | PD1 | -| PD2 | PD2 | -| PD3 | PD3 | -| PD4 | PD4 | -| PD5 | PD5 | -| PD6 | PD6 | -| PD7 | PD7 | -| PD8 | PD8 | -| PD9 | PD9 | -| PD10 | PD10 | -| PD11 | PD11 | -| PD12 | PD12 | -| PD13 | PD13 | -| PD14 | PD14 | -| PD15 | PD15 | -| PE0 | PE0 | -| PE1 | PE1 | -| PE2 | PE2 | -| PE3 | PE3 | -| PE4 | PE4 | -| PE5 | PE5 | -| PE6 | PE6 | -| PE7 | PE7 | -| PE8 | PE8 | -| PE9 | PE9 | -| PE10 | PE10 | -| PE11 | PE11 | -| PE12 | PE12 | -| PE13 | PE13 | -| PE14 | PE14 | -| PE15 | PE15 | -| PF0 | PF0 | -| PF1 | PF1 | -| PF2 | PF2 | -| PF3 | PF3 | -| PF4 | PF4 | -| PF5 | PF5 | -| PF6 | PF6 | -| PF7 | PF7 | -| PF8 | PF8 | -| PF9 | PF9 | -| PF10 | PF10 | -| PF11 | PF11 | -| PF12 | PF12 | -| PF13 | PF13 | -| PF14 | PF14 | -| PF15 | PF15 | -| PG0 | PG0 | -| PG1 | PG1 | -| PG2 | PG2 | -| PG3 | PG3 | -| PG4 | PG4 | -| PG5 | PG5 | -| PG6 | PG6 | -| PG7 | PG7 | -| PG8 | PG8 | -| PG9 | PG9 | -| PG10 | PG10 | -| PG11 | PG11 | -| PG12 | PG12 | -| PG13 | PG13 | -| PG14 | PG14 | -| PG15 | PG15 | -| PH0 | PH0 | -| PH1 | PH1 | -| PH2 | PH2 | -| PH3 | PH3 | -| PH4 | PH4 | -| PH5 | PH5 | -| PH6 | PH6 | -| PH7 | PH7 | -| PH8 | PH8 | -| PH9 | PH9 | -| PH10 | PH10 | -| PH11 | PH11 | -| PH12 | PH12 | -| PH13 | PH13 | -| PH14 | PH14 | -| PH15 | PH15 | -| PI0 | PI0 | -| PI1 | PI1 | -| PI2 | PI2 | -| PI3 | PI3 | -| PI4 | PI4 | -| PI5 | PI5 | -| PI6 | PI6 | -| PI7 | PI7 | -| PI8 | PI8 | -| PI9 | PI9 | -| PI10 | PI10 | -| PI11 | PI11 | -| PI12 | PI12 | -| PI13 | PI13 | -| PI14 | PI14 | -| PI15 | PI15 | -| PJ0 | PJ0 | -| PJ1 | PJ1 | -| PJ2 | PJ2 | -| PJ3 | PJ3 | -| PJ4 | PJ4 | -| PJ5 | PJ5 | -| PJ6 | PJ6 | -| PJ7 | PJ7 | -| PJ8 | PJ8 | -| PJ9 | PJ9 | -| PJ10 | PJ10 | -| PJ11 | PJ11 | -| PJ12 | PJ12 | -| PJ13 | PJ13 | -| PJ14 | PJ14 | -| PJ15 | PJ15 | -| PK0 | PK0 | -| PK1 | PK1 | -| PK2 | PK2 | -| PK3 | PK3 | -| PK4 | PK4 | -| PK5 | PK5 | -| PK6 | PK6 | -| PK7 | PK7 | -| UART1_TX | PA9 | -| UART1_RX | PA10 | -| UART4_TX | PA0 | -| UART4_RX | PI9 | -| UART6_TX | PG14 | -| UART6_RX | PG9 | -| UART8_TX | PJ8 | -| UART8_RX | PJ9 | -| ETH_RMII_REF_CLK | PA1 | -| ETH_MDIO | PA2 | -| ETH_RMII_CRS_DV | PA7 | -| ETH_MDC | PC1 | -| ETH_RMII_RXD0 | PC4 | -| ETH_RMII_RXD1 | PC5 | -| ETH_RMII_TX_EN | PG11 | -| ETH_RMII_TXD0 | PG13 | -| ETH_RMII_TXD1 | PG12 | -| USB_HS_CLK | PA5 | -| USB_HS_STP | PC0 | -| USB_HS_NXT | PH4 | -| USB_HS_DIR | PI11 | -| USB_HS_D0 | PA3 | -| USB_HS_D1 | PB0 | -| USB_HS_D2 | PB1 | -| USB_HS_D3 | PB10 | -| USB_HS_D4 | PB11 | -| USB_HS_D5 | PB12 | -| USB_HS_D6 | PB13 | -| USB_HS_D7 | PB5 | -| USB_HS_RST | PJ4 | -| USB_DM | PA11 | -| USB_DP | PA12 | -| BOOT0 | BOOT0 | -| DAC1 | PA4 | -| DAC2 | PA5 | -| LEDR | PK5 | -| LEDG | PK6 | -| LEDB | PK7 | -| I2C1_SDA | PB7 | -| I2C1_SCL | PB6 | -| I2C3_SDA | PH8 | -| I2C3_SCL | PH7 | -| -WL_REG_ON | PJ1 | -| -WL_HOST_WAKE | PJ5 | -| -WL_SDIO_0 | PC8 | -| -WL_SDIO_1 | PC9 | -| -WL_SDIO_2 | PC10 | -| -WL_SDIO_3 | PC11 | -| -WL_SDIO_CMD | PD2 | -| -WL_SDIO_CLK | PC12 | -| -BT_RXD | PF6 | -| -BT_TXD | PA15 | -| -BT_CTS | PF9 | -| -BT_RTS | PF8 | -| -BT_REG_ON | PJ12 | -| -BT_HOST_WAKE | PJ13 | -| -BT_DEV_WAKE | PJ14 | -| -QSPI2_CS | PG6 | -| -QSPI2_CLK | PF10 | -| -QSPI2_D0 | PD11 | -| -QSPI2_D1 | PD12 | -| -QSPI2_D2 | PF7 | -| -QSPI2_D3 | PD13 | - - -### I/O Pins - -To access the I/O pins, you can use the `Pin` module from the `pyb` library. - -```python -from pyb import Pin -``` - -To reference a pin on the Portenta, you can use the `Pin()` constructor. The first argument you have to provide is the pin you want to use. The second parameter, `mode`, can be set as: `Pin.IN`, `Pin.OUT_PP`, `Pin.OUT_OD`, `Pin.AF_PP`, `Pin.AF_OD` or `Pin.ANALOG`. An explanation of the pin modes can be found [here](https://docs.openmv.io/library/pyb.Pin.html#methods). The third parameter, `pull`, represents the pull mode. It can be set to: `Pin.PULL_NONE`, `Pin.PULL_UP` or `Pin.PULL_DOWN`. E.g.: - -```python -pin0 = Pin('P0', mode, pull) -``` - -To get the logic level of a pin, call `.value()`. It will return a 0 or a 1. This corresponds to `LOW` and `HIGH` in Arduino terminology. - -```python -pin0.value() -``` - -### PWM - -To use PWM, you import the `pyb`, `time`, `Pin`, `Timer` modules. - -```python -import pyb -import time -from pyb import Pin, Timer -``` - -First you need to choose the pin you want to use PWM with. - -```python -pin1 = Pin("PC6", Pin.OUT_PP, Pin.PULL_NONE) -``` - -Create a timer for the PWM, where you set the ID and the frequency. - -```python -timer1 = Timer(3, freq=1000) -``` - -Then you need to start a PWM channel with the timer object. - -```python -channel1 = timer1.channel(1, Timer.PWM, pin=pin1, pulse_width=0) -``` - -Get or set the pulse width value on a channel. To get, pass no arguments. To set, give a value as an argument. - -```python -channel1.pulse_width(Width) -``` - -### RGB LED - -The Portenta H7 has built-in RGB that can be used as feedback for applications. Using the `pyb` library, you can easily define the different LED colors on the Portenta. - -For this you will use the `pyb` library. - -```python -import pyb -``` - -Now you can easily define the different colors of the built in LED. - -```python -redLED = pyb.LED(1) -greenLED = pyb.LED(2) -blueLED = pyb.LED(3) -``` - -And then control them in our script. - -```python -redLED.on() -redLED.off() - -greenLED.on() -greenLED.off() - -blueLED.on() -blueLED.off() -``` - -You could also set a custom intensity for our LED lights. This ranges between the values 0 (off) and 255 (full on). Below you can see an example of how to set the intensity on our different LED lights. - -```python -redLED.intensity(128) -greenLED.intensity(64) -blueLED.intensity(50) -``` - -If no argument is given in the `.intensity()` function, it will return the LED intensity. - -### Communication - -Like other Arduino® products, the Portenta H7 features dedicated pins for different protocols. - -#### SPI - -The pins used for SPI on the Portenta H7 are the following: - - -| Pin | Function | -| :---: | :------: | -| PI0 | CS | -| PC3 | COPI | -| PI1 | CK | -| PC2 | CIPO | - -You can refer to the [pinout](#gpio-map-2) above to find them on the board. - -First, you have to import the relevant module from `pyb`. - -```python -from pyb import SPI -``` - -When you initialize SPI, the only thing you need to state is the bus, which will always be `2` on the Portenta H7; this is the only available bus. The rest of the arguments are optional. But if it is needed, you can state the mode of the SPI device as either `SPI.MASTER` or `SPI.SLAVE`, you can also manually set the `baudrate` of the device. `Polarity` can be set to 0 or 1, and is the logic level the idle clock line sits at (HIGH or LOW). `Phase` can be 0 or 1 to sample data on the first (0) or second (1) clock edge. - -```python -spi = SPI(2, SPI.MASTER, baudrate=100000, polarity=0, phase=0) -``` - -Now, if you want to send data over SPI, you simply call `.send()` inside the arguments you want to send. `data` is the data to send, which could be an integer (dataInt) or a buffer object (dataBuffer). It is optional to set the `timeout`, it indicates the timeout in milliseconds to wait for the send. - -```python -dataInt = 21 -dataBuffer = bytearray(4) -spi.send(data, timeout=5000) -``` - -Similarly, if you want to receive data over SPI, you call `.recv()`. `data` indicates the number of bytes to receive, this can be an integer (dataInt) or a buffer (dataBuffer), which will be filled with received bytes. It is optional to set the `timeout`, which is the time in milliseconds to wait for the receive. - -```python -dataInt = 0 -dataBuffer = bytearray(4) -SPI.recv(data, timeout=5000) -``` - -#### I2C - -The pins used for I2C (Inter-Integrated Circuit) on the Portenta H7 are the following: - -| Pin | Function | -| :---: | :------: | -| PH8 | SDA | -| PH7 | SCL | - -You can refer to the [pinout](##gpio-map-2) above to find them on the board. - -To use the I2C, you import the relevant module. - -```python -from pyb import I2C -``` - -You can now create the I2C object. To create an I2C object you need to state the bus, this indicates what pins you will use for I2C. Giving bus a value of `3` starts I2C on the SCL and SDA pins on the Portenta H7. There are 4 I2C buses on the Portenta H7. - -```python -i2c = I2C(3) -``` - -Now that the object is created, you can initialize it. You need to decide if your device is going to be a controller (I2C.MASTER) or a reader (I2C.SLAVE). If it is a reader device, you also need to set the `address`. You can then set a baudrate if you need to. - -```python -i2c.init(I2C.MASTER, addr=address, baudrate=100000) -``` - -To receive data on the bus, you call the `.recv()` function. In the functions arguments `data` is the number of bytes to receive, it can be an integer (dataInt) or a buffer (dataBuffer), which will be filled with received bytes. `addr` is the address to receive from, this is only required in controller mode. `timeout` indicates how many milliseconds to wait for the receive. The code below shows how to receive and print your data in the OpenMV serial terminal. - -```python -dataInt = 0 -dataBuffer = bytearray(4) -receivedData = i2c.recv(data, addr=0, timeout=5000) -Print(receivedData) -``` - -To send data on the bus, you can call the `.send()` function. In the functions arguments `data` is the data to send, an integer (dataInt) or a buffer object (dataBuffer). `addr` is the address to send to, this is only required in controller mode. `timeout` indicates how many milliseconds to wait for the send. - -```python -dataInt = 412 -dataBuffer = bytearray(4) -i2c.send(data, addr=0, timeout=5000) -``` - -If you need to make sure that devices are connected to the I2C bus, you can use the `.scan()` function. It will scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. It only works when in controller mode. - -```python -i2c.scan() -``` - -#### UART - -The pins used for UART on the Portenta H7 are the following: - -| Pin | Function | -| :---: | :------: | -| PA10 | RX | -| PA9 | TX | - -You can refer to the [pinout](#gpio-map-2) above to find them on the board. - -To use the UART, you need to import the relevant module. - -```python -from pyb import UART -``` - -To create the UART object, you need to indicate the UART bus, the Portenta has 3 UART buses, but there is only on UART bus available to use with OpenMV through the boards pins. - -```python -uart = UART(1) -``` - -With the object created, you can initialize it with `init`. When initilazing, you can set the `baudrate`. `bits` is the number of bits per character (7, 8 or 9). `parity` can be set to `None`, `0` (even) or `1` (odd). `stop` is the number of stop bits, 1 or 2. `flow` sets the flow control type, can be 0, UART.RTS, UART.CTS or UART.RTS | UART.CTS. More information on this can be found [here](https://docs.openmv.io/library/pyb.UART.html#flow-control). `timeout` is the time in milliseconds to wait for writing/reading the first character. `timeout_char` is the timeout in milliseconds to wait between characters while writing or reading. `read_buf_len` is the character length of the read buffer (0 to disable). - -```python -uart.init(baudrate, bits=8, parity=None, stop=1, timeout=0, flow=0, timeout_char=0, read_buf_len=64) -``` - -To read from UART, you can call `.read()`. If `bytes` is specified then read at most that many bytes. If `bytes` is not given then the method reads as much data as possible. It returns after the timeout has elapsed. The example code below will read bytes received through uart into an array and then print it in the serial terminal. - -```python -array = bytearray(5) -uart.read(array) -print(array) -``` - -If you intend to write over UART, you can call `.write()`. The function writes `buffer` of bytes to the bus. If characters are 7 or 8 bits wide then each byte is one character. If characters are 9 bits wide then two bytes are used for each character and `buffer` must contain an even number of bytes. - -```python -uart.write(buffer) -``` - -#### Wi-Fi® - -To use Wi-Fi® you first need to import the relevant library. - -```python -import network -``` - -Then you need to define the Wi-Fi® networks SSID and put that in a variable. You must do the same for the networks password. - -```python -SSID='' -PASSWORD='' -``` - -Next, you can create a WLAN network interface object. In the argument you can enter `network.STA_IF`, which indicates that your device will be a client and connect to a Wi-Fi® access point. - -```python -wlan = network.WLAN(network.STA_IF) -``` - -To activate the network interface, you can simply call `.activate` with the argument `True`. - -```python -wlan.active(True) -``` - -Now you can decide which network to connect to. Here it is where the `SSID` and `PASSWORD` variables come in handy. - -```python -wlan.connect(SSID, PASSWORD, timeout=30000) -``` - -If you need to troubleshoot, the connection `.status()` can be used. This function will return a value that describes the connection status. It will also let you know what went wrong with the connection in case it failed. - -```python -wlan.status() -``` - -### Audio - -If you want to use audio with the Portenta H7, you first need to include the `audio` module. Another helpful module is `micro_speech`, this runs Google's TensorFlow Lite for Microcontrollers Micro Speech framework for voice recognition. - -```python -import audio, micro_speech -``` - -Next you need to initialize the audio object. In the initialization you can decide how many `channels` to use, it is possible to use either 1 or 2 channels. Frequency decides the sample frequency. Using a higher sample frequency results in a higher noise flow, meaning less effective bits per sample. By default audio samples are 8-bits with 7-bits of effective dynamic range. `gain_db` sets the microphone gain to use. `highpass` is the high pass filter cut off given the target sample frequency. - -```python -audio.init(channels=2, frequency=16000, gain_db=24, highpass=0.9883) -``` - -If you need to deinitialize the audio object, you can simply call `deint()`. - -```python -audio.deint() -``` - -To use micro_speech, you first need to create a micro_speech object. You can create this object in the variable `speech`. - -```python -speech = micro_speech.MicroSpeech() -``` - -Next you can start streaming audio into the `micro_speech` object, to do this you can call `audio.start_streaming()`. Here you can pass the `micro_speech` object as the argument, this will fill the object with audio samples. The MicroSpeech module will compute the FFT of the audio samples and keep a sliding window internally of the FFT the last 100ms or so of audio samples received as features for voice recognition. - -```python -audio.start_streaming(speech.audio_callback) -``` - -If you need to stop the audio streaming, you can call `.stop_streaming()`. - -```python -audio.stop_streaming() -``` - -## Portenta C33 - -### Pinout Mapping - -The Portenta C33 has two ways its pins are physically available: through its MKR-styled connectors and its High-Density connectors. Most pins are referred to via their port name or function. In the image below, the Portenta C33 MKR-styled connectors pinout is shown. - -![Portenta C33 MKR-styled connectors pinout](assets/portenta33_MKR_pinout.png) - -The MKR-styled connectors pinout is mapped in MicroPython as follows: - -| **Arduino Pin Mapping** | **MicroPython Pin Mapping** | -|:-----------------------:|:---------------------------:| -| `P006`/`A0` | `P006` | -| `P005`/`A1` | `P005` | -| `P004`/`A2` | `P004` | -| `P002`/`A3` | `P002` | -| `P001`/`A4` | `P001` | -| `P015`/`A5` | `P015` | -| `P014`/`A6` | `P014` | -| `P105`/`D0` | `P105` | -| `P106`/`D1` | `P106` | -| `P111`/`D2` | `P111` | -| `P303`/`D3` | `P303` | -| `P401`/`D4` | `P401` | -| `P210`/`D5` | `P210` | -| `P602` | `P602` | -| `P110` | `P110` | -| `P408` | `P408` | -| `P407` | `P407` | -| `P315` | `P315` | -| `P204` | `P204` | -| `P900` | `P900` | -| `P402` | `P402` | -| `P601` | `P601` | - -The complete MicroPython pinout is available [here](https://github.com/micropython/micropython/blob/master/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/pins.csv). - -### Input/Output Pins - -The `Pin` class in the `machine` module is essential for controlling Input/Output (I/O) pins of the Portenta C33 board. These pins are crucial for a wide range of applications, including reading sensor data, controlling actuators, and interfacing with other hardware components. - -#### Pin Initialization - -To begin using an I/O pin of the Portenta C33 board with MicroPython, you need to initialize it using the `Pin` class from the `machine` module. This involves specifying the pin identifier and its mode (input, output, etc.). - -```python -from machine import Pin - -# Initializing pin P107 as an output -p107 = Pin('P107', Pin.OUT) -``` - -#### Configuring Pin Modes - -You can configure a pin as an input or output. For input pins, it's often useful to activate an internal pull-up or pull-down resistor. This helps to stabilize the input signal, especially in cases where the pin is reading a mechanical switch or a button. - -```python -# Configuring pin P105 as an input with its pull-up resistor enabled -p105 = Pin('P105', Pin.IN, Pin.PULL_UP) -``` - -#### Reading from and Writing to Pins - -To read a digital value from a pin, use the `.value()` method without any arguments. This is particularly useful for input pins. Conversely, to write a digital value, use the `.value()` method with an argument. Passing `1` sets the pin to `HIGH`, while `0` sets it to `LOW`. This is applicable to output pins. - -```python -# Reading from P105 -pin_value = p105.value() - -# Writing to P107 -p107.value(1) # Set p2 to high -``` - -#### Advanced Pin Configuration - -The Pin class allows dynamic reconfiguration of pins and setting up interrupt callbacks. This feature is essential for creating responsive and interactive applications. - -```python -# Reconfiguring P105 as an input with a pull-down resistor -p105.init(Pin.IN, Pin.PULL_DOWN) - -# Setting up an interrupt on P105 -p105.irq(lambda p: print("- IRQ triggered!", p)) -``` - -#### Practical Example - -In this example, we will configure one pin as an input to read the state of a button and another pin as an output to control an LED. The LED will turn on when the button is pressed and off when it's released. - -```python -from machine import Pin -import time - -# Configure pin P107 as an output (for the LED) -led = Pin('P107', Pin.OUT_PP) - -# Configure pin P105 as input with pull-up resistor enabled (for the button) -button = Pin('P105', Pin.IN, Pin.PULL_UP) - -while True: - # Read the state of the button - button_state = button.value() - if button_state == 0: - # Turn on LED if button is pressed (button_state is LOW) - led.value(1) - else: - # Turn off LED if button is not pressed (button_state is HIGH) - led.value(0) - - # Short delay to debounce the button - time.sleep(0.1) -``` - -This practical example demonstrates controlling an LED based on a button's state. The LED, connected to pin `P107` (configured as an output), is turned on or off depending on the button's input read from pin `P105` (set as an input with a pull-up resistor). The main loop continually checks the button's state; pressing the button fixes the LED on while releasing it turns the LED off. A brief delay is included for debouncing, ensuring stable operation without false triggers from the button. - -### Analog to Digital Converter - -The `ADC` class in MicroPython provides an interface for the Analog-to-Digital (ADC) converter of the Portenta C33 board, enabling the measurement of continuous voltages and their conversion into discrete digital values. This functionality is crucial for applications that, for example, require reading from analog sensors. The `ADC` class represents a single endpoint for sampling voltage from an analog pin and converting it to a digital value. - -The available ADC pins of the Portenta C33 board in MicroPython are the following: - -| **Available ADC Pins** | -|:----------------------:| -| `P006` | -| `P005` | -| `P004` | -| `P002` | -| `P001` | -| `P015` | -| `P014` | -| `P000` | - -#### Initializing the ADC - -First, to use an ADC of the Portenta C33 board, create an ADC object associated with a specific pin. This pin will be used to read analog values. - -```python -from machine import ADC - -# Create an ADC object on a specific pin -adc = ADC(pin) -``` - -#### Reading Analog Values - -You can read analog values as raw values using the `read_u16()` method. This method returns a raw integer from 0-65535, representing the analog reading. - -```python -# Reading a raw analog value -val = adc.read_u16() -``` - -#### Practical Example - -This example demonstrates the use of the `ADC` class to read values from a potentiometer on the Portenta C33 board. First, connect your potentiometer to the Portenta C33 board. One outer pin goes to `GND`, the other to `3V3`, and the middle pin to an analog-capable I/O pin, such as `P006`. This setup creates a variable voltage divider, with the voltage at the center pin changing as you adjust the potentiometer. - -```python -from machine import ADC, Pin -import time - -# Initialize the ADC on the potentiometer-connected pin -pot_pin = Pin('P006') -pot_adc = ADC(pot_pin) - -while True: - # Read the raw analog value - raw_value = pot_adc.read_u16() - print("- Potentiometer raw value:", raw_value) - - # Delay for readability - time.sleep(0.1) -``` -The example starts by importing the necessary modules and setting up the ADC on a pin connected to a potentiometer (`P006`). The ADC object (`pot_adc`) is used to interface with the potentiometer. Inside the loop, the analog value from the potentiometer is continuously read using the `read_u16()` method that provides a raw integer value scaled between `0` and `65535`, reflecting the potentiometer's position. The analog value value is printed to the console, and a short delay is included in the loop to ensure the output is readable. - -### Pulse Width Modulation - -Pulse Width Modulation (PWM) is a method to emulate an analog output using a digital pin. It does this by rapidly toggling the pin between low and high states. Two primary aspects define PWM behavior: - -- **Frequency**: This is the speed at which the pin toggles between low and high states. A higher frequency means the pin toggles faster. -- **Duty cycle**: This refers to the ratio of the high state duration to the total cycle duration. A 100% duty cycle means the pin remains high all the time, while a 0% duty cycle means it stays low. - -The available PWM pins of the Portenta C33 board in MicroPython are the following: - -| **Available PWM Pins** | -|:----------------------:| -| `P105` | -| `P106` | -| `P111` | -| `P303` | -| `P401` | -| `P601` | - -#### Setting Up PWM - -To use PWM, start by initializing a pin and then creating a PWM object associated with that pin. - -```python -import machine - -# Initialize a pin for PWM (e.g., pin P105) -p105 = machine.Pin('P105') -pwm1 = machine.PWM(p105) -``` - -#### Configuring PWM Parameters - -The frequency and duty cycle of the PWM signal are set based on the specific needs of your application: - -```python -# Set the frequency to 500 Hz -pwm1.freq(500) - -# Adjusting the duty cycle to 50 for 50% duty -pwm1.duty(50) -``` - -#### Checking PWM Configuration - -You can check the current configuration of the PWM object by printing it: - -```python -# Will show the current frequency and duty cycle -print(pwm1) -``` - -Retrieve the frequency and duty cycle values: - -```python -current_freq = pwm1.freq() -current_duty = pwm1.duty() -``` - -#### Deinitializing PWM - -When PWM is no longer needed, the pin can be deinitialized: - -```python -pwm1.deinit() -``` - -#### Practical Example - -In this example, we will use PWM to control the brightness of an LED connected to pin `P105` of the Portenta C33 board. - -```python -import machine -import time - -# Configure the LED pin and PWM -led_pin = machine.Pin('P105') -led_pwm = machine.PWM(led_pin) -led_pwm.freq(500) - -# Loop to vary brightness -while True: - # Increase brightness - for duty in range(100): - led_pwm.duty(duty) - time.sleep(0.001) - - # Decrease brightness - for duty in range(100, -1, -1): - led_pwm.duty(duty) - time.sleep(0.001) -``` - -### Real-Time Clock - -The `RTC` class in MicroPython provides a way to manage and utilize the Real-Time Clock (RTC) of the Portenta C33 board. This feature is essential for applications that require accurate timekeeping, even when the main processor is not active. The RTC maintains accurate time and date, functioning independently from the main system. It continues to keep track of the time even when the board is powered off, as long as it's connected to a power source like a battery. - -#### Initializing the RTC - -To use the RTC, first create an RTC object. This object is then used to set or read the current date and time. - - -```python -import machine - -# Create an RTC object -rtc = machine.RTC() -``` - -#### Setting and Getting Date and Time - -The RTC allows you to set and retrieve the current date and time. The date and time are represented as an 8-tuple format. - -```python -# Setting the RTC date and time -rtc.datetime((2024, 1, 4, 4, 20, 0, 0, 0)) - -# Getting the current date and time -current_datetime = rtc.datetime() -print("- Current date and time:", current_datetime) -``` - -The 8-tuple for the date and time follows the format `(year, month, day, weekday, hours, minutes, seconds, subseconds)`. - -#### Practical Example - -A practical use case for the RTC is to add timestamps to sensor data readings. By setting the current time on the RTC, you can then append an accurate timestamp each time a sensor value is logged. - -```python -import machine - -# Initialize the RTC and set the current datetime -rtc.datetime((2024, 1, 4, 4, 20, 0, 0, 0)) - -# Function to read a sensor value (placeholder) -def read_sensor(): - # Replace with actual sensor reading logic - return 42 - -# Read sensor value and get the current time -sensor_value = read_sensor() -timestamp = rtc.datetime() - -# Output the sensor value with its timestamp -print("- Sensor value at ", timestamp, ":", sensor_value) -``` - -In this example, every sensor reading is accompanied by a timestamp, which can be crucial for data analysis or logging purposes. The RTC's ability to maintain time independently of the main system's power status makes it reliable for time-sensitive applications. diff --git a/content/micropython/01.basics/06.board-examples/py-hero-banner.png b/content/micropython/01.basics/06.board-examples/py-hero-banner.png deleted file mode 100644 index d597d5b64e..0000000000 Binary files a/content/micropython/01.basics/06.board-examples/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/07.installing-modules/assets/delete-file.png b/content/micropython/01.basics/07.installing-modules/assets/delete-file.png deleted file mode 100644 index e80cc59480..0000000000 Binary files a/content/micropython/01.basics/07.installing-modules/assets/delete-file.png and /dev/null differ diff --git a/content/micropython/01.basics/07.installing-modules/assets/install-cert.png b/content/micropython/01.basics/07.installing-modules/assets/install-cert.png deleted file mode 100644 index 42169ed361..0000000000 Binary files a/content/micropython/01.basics/07.installing-modules/assets/install-cert.png and /dev/null differ diff --git a/content/micropython/01.basics/07.installing-modules/installing-modules.md b/content/micropython/01.basics/07.installing-modules/installing-modules.md deleted file mode 100644 index 3fc3715447..0000000000 --- a/content/micropython/01.basics/07.installing-modules/installing-modules.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Installing Modules -description: Learn how to install and remove external modules on your Arduino board. -author: Karl Söderby -micropython_type: basics -hero_image: "./hero-banner.png" ---- - -Your MicroPython installation comes with a set of modules built-in to the firmware. If you are using any external components such as sensors, displays or neopixels, you will need to install these manually. - -There are currently two methods available when installing a module on your board running MicroPython: -- Using the `mip` module on your **board**, (download and install via Wi-Fi® connection), -- using `mpremote` on your **computer** (download and install through a USB connection), - -In this article, we will cover these two methods, as well as how to remove them from your board. - -***Please note: installing packages that contain 2-byte characters (such as emojis, Chinese symbols), is currently not supported in the [Arduino Lab for MicroPython editor](https://labs.arduino.cc/en/labs/micropython). You will however receive a "successful installation" response, which is a bug being investigated.*** - -## Hardware & Software Needed - -- [A MicroPython compatible board](/micropython/basics/board-installation#supported-boards), - -- [Arduino Lab for MicroPython editor](https://labs.arduino.cc/en/labs/micropython), -- [mpremote](https://pypi.org/project/mpremote/) (optional). - -## Option 1: MIP - -***Please note that the `mip` module requires a stable Internet connection via Wi-Fi. Installation may fail if connection is unstable.*** - -[mip](https://docs.micropython.org/en/latest/reference/packages.html#installing-packages-with-mip) is a module that allows you to install external packages/libraries/modules remotely. This module is built in to your MicroPython firmware. - -To use the `mip` module, you will however need to connect to Internet via a Wi-Fi network first. To do so, open the **Arduino Lab for MicroPython editor**, and run the following code: - -***Note: Replace "YOUR_NETWORK_NAME" and "" YOUR_NETWORK_PASSWORD" with the SSID and password for your Wi-Fi® network.*** - - -```python -import network - -WIFI_NETWORK='YOUR_NETWORK_NAME' -WIFI_PASSWORD='YOUR_NETWORK_PASSWORD' - -wlan = network.WLAN(network.STA_IF) -wlan.active(True) -wlan.connect(WIFI_NETWORK, WIFI_PASSWORD) - -print() -print("Connected to ",WIFI_NETWORK) -``` - -Once you are connected, you can use the `mip` module to install external modules. - -You can install by specifying the **organisation** and **repository**: - -```python -import mip -mip.install(github:org/repo) -``` - -Or you can specify the url to the file you want to install: - -``` -mip.install("https://raw.githubusercontent.com/tinypico/tinypico-micropython/master/lis3dh%20library/lis3dh.py") - -``` - -Files are added to a folder named `lib` on your board. - -***There are a number of ways you can use the `install()` method, read more about this in the [MIP documentation](https://docs.micropython.org/en/latest/reference/packages.html#installing-packages-with-mip).*** - -### Complete Example - -In this example, we first connect to Wi-Fi®, and then proceed to install the `[arduino-iot-cloud-py](https://github.com/arduino/arduino-iot-cloud-py) module. - -```python -import network -import mip - -# enter wi-fi creds -WIFI_NETWORK='YOUR_NETWORK_NAME' -WIFI_PASSWORD='YOUR_NETWORK_PASSWORD' - -# connect to wi-fi -wlan = network.WLAN(network.STA_IF) -wlan.active(True) -wlan.connect(WIFI_NETWORK, WIFI_PASSWORD) - -print() -print("Connected to ",WIFI_NETWORK) - -# install the arduino-iot-cloud module -mip.install("github:arduino/arduino-iot-cloud-py") -``` - -***Running this example twice will result in a `202` error, as you have already connected to Wi-Fi. Once you have connected once to Wi-Fi, you only need to use the `mip.install()` method.*** - -### Failed Installation - -Installation via `mip` may fail due to an unstable Internet connection. If you have installed a module but you are receiving errors, make sure your Internet connection is good (your board is within reach of your router), and run the installation again. - -This is typically not an issue with smaller installations (like single files), but when installing larger packages it is increased. - -You can install the same module again, it will only overwrite the existing version. - -## Option 2: Mpremote - -To install a MicroPython module on your board, you can use the Python based tool `mpremote`. This requires Python to be installed. On macOS and Linux Python usually comes pre-installed. If it's not installed on your system you may download it from [here](https://www.python.org/downloads/). Then, to install `mpremote` you can use pip: - -```bash -$ pip install mpremote -``` - -Run `mpremote connect list` to retrieve the serial number of your device. The output will look similar to this: - -``` -/dev/cu.usbmodem3871345733302 335B34603532 2341:055b Arduino Portenta Virtual Comm Port in HS Mode -``` - -Pass this serial number (the second value) to the install command: - -```bash -$ mpremote connect id:335B34603532 mip install github:arduino/arduino-iot-cloud-py -``` - -This will install the library and all required dependencies on the board. - -### Error: Certificate Verify Fail (MacOS) - -On some computers, you may receive error: - -``` -[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: -unable to get local issuer certificate (_ssl.c:1002) -``` - -This indicates a problem with the Python version installed, and that it is unable to locate the SSL certificate. To work around this, navigate to your Python installation (typically **Applications > Python 3.X**), and run the `Install Certificates.command` script. - -![Install Certificate.](assets/install-cert.png) - -## Delete Files - -To delete a file from your board, open the **Arduino Lab for MicroPython** editor, connect to your board, and click the **"File"** button. This will open your local files as well as your board's files. - -If you want to remove a file, simply mark it and click on the trashcan icon in the top right of the file window, as the image below shows: - -![Removing files.](assets/delete-file.png) \ No newline at end of file diff --git a/content/micropython/01.basics/07.installing-modules/py-hero-banner.png b/content/micropython/01.basics/07.installing-modules/py-hero-banner.png deleted file mode 100644 index d9a2f1d9dc..0000000000 Binary files a/content/micropython/01.basics/07.installing-modules/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/08.reference/py-hero-banner.png b/content/micropython/01.basics/08.reference/py-hero-banner.png deleted file mode 100644 index f0680b9243..0000000000 Binary files a/content/micropython/01.basics/08.reference/py-hero-banner.png and /dev/null differ diff --git a/content/micropython/01.basics/basics.md b/content/micropython/01.basics/basics.md index abf7073e1a..c2556bad89 100644 --- a/content/micropython/01.basics/basics.md +++ b/content/micropython/01.basics/basics.md @@ -1,4 +1,3 @@ --- title: Basics -description: Basics Description --- \ No newline at end of file diff --git a/content/micropython/02.environment/00.online-editor/assets/connect-board.png b/content/micropython/02.environment/00.online-editor/assets/connect-board.png new file mode 100644 index 0000000000..c4e8c8f407 Binary files /dev/null and b/content/micropython/02.environment/00.online-editor/assets/connect-board.png differ diff --git a/content/micropython/02.environment/00.online-editor/assets/online-editor-access.png b/content/micropython/02.environment/00.online-editor/assets/online-editor-access.png new file mode 100644 index 0000000000..b2544f9186 Binary files /dev/null and b/content/micropython/02.environment/00.online-editor/assets/online-editor-access.png differ diff --git a/content/micropython/02.environment/00.online-editor/online-editor.md b/content/micropython/02.environment/00.online-editor/online-editor.md new file mode 100644 index 0000000000..010faf9cc4 --- /dev/null +++ b/content/micropython/02.environment/00.online-editor/online-editor.md @@ -0,0 +1,42 @@ +--- +title: 'Arduino Lab for MicroPython (online)' +description: 'The Arduino Lab for MicroPython is an online code editor for writing and loading MicroPython scripts.' +author: 'Karl Söderby' +--- + +The [Arduino Lab for MicroPython](https://lab-micropython.arduino.cc/) is an online code editor that allows you to load MicroPython scripts to your Arduino board. This editor is part of the [Arduino Cloud](https://app.arduino.cc/), and is free to use for everyone. + +In this tutorial, we will take a look at how we can access it, and test it out by writing a simple script. + +***Note that this tutorial does not go in depth on how the Arduino Lab for MicroPython works. For more details, you can visit the [guide to the Arduino Lab for MicroPython](/micropython/environment/code-editor).*** + +## Requirements + +- **Google Chrome, Opera, Edge** - these are the currently supported browsers. +- [Arduino Cloud account registered](https://login.arduino.cc/login) +- [A MicroPython compatible board](/micropython/first-steps/install-guide/#micropython-compatible-arduino-boards) + +## Setting Up + +***To follow these steps, you will need to have MicroPython installed on your board. Haven't done this yet? Don't worry, check out the [Installing MicroPython](/micropython/first-steps/install-guide) guide.*** + +Setting up the online environment is quick and easy. Follow the steps below to achieve it: + +1. Go to [Arduino Cloud](https://app.arduino.cc/) and log in / create an account. +2. Navigate to [lab-micropython.arduino.cc](https://lab-micropython.arduino.cc/). This is accessible through the cloud interface, under **Resources > Online Lab for MicroPython**. + ![Navigate to the editor.](assets/online-editor-access.png) +3. Click on the **"Connect"** button, and select our board from the list. + ![Select your board](assets/connect-board.png) +4. With the board connected, in the text area, copy and paste the following: + ```python + print("Hello World!") + ``` + +We should now see `Hello World!` printed in the REPL. + +## Troubleshooting + +- If the "RUN" button is faded out, it means the board is not connected. Click the "Connect" button to get a list of available boards connected. +- Make sure MicroPython is installed on your board. +- If you have recently installed MicroPython on your board, try resetting the board by pressing the reset button (once), or disconnect & reconnect the USB cable. + diff --git a/content/micropython/02.environment/01.code-editor/assets/IDEFileManager.png b/content/micropython/02.environment/01.code-editor/assets/IDEFileManager.png new file mode 100644 index 0000000000..eb59e8eb11 Binary files /dev/null and b/content/micropython/02.environment/01.code-editor/assets/IDEFileManager.png differ diff --git a/content/micropython/02.environment/01.code-editor/assets/IDEOverview.png b/content/micropython/02.environment/01.code-editor/assets/IDEOverview.png new file mode 100644 index 0000000000..d79c0ba09c Binary files /dev/null and b/content/micropython/02.environment/01.code-editor/assets/IDEOverview.png differ diff --git a/content/micropython/02.environment/01.code-editor/assets/consoleTerminal.png b/content/micropython/02.environment/01.code-editor/assets/consoleTerminal.png new file mode 100644 index 0000000000..945cd59a13 Binary files /dev/null and b/content/micropython/02.environment/01.code-editor/assets/consoleTerminal.png differ diff --git a/content/micropython/02.environment/01.code-editor/assets/indentation.png b/content/micropython/02.environment/01.code-editor/assets/indentation.png new file mode 100644 index 0000000000..a2daa54ecb Binary files /dev/null and b/content/micropython/02.environment/01.code-editor/assets/indentation.png differ diff --git a/content/micropython/02.environment/01.code-editor/code-editor.md b/content/micropython/02.environment/01.code-editor/code-editor.md new file mode 100644 index 0000000000..5cfe6053ea --- /dev/null +++ b/content/micropython/02.environment/01.code-editor/code-editor.md @@ -0,0 +1,147 @@ +--- +title: 'Code Editor' +description: 'Learn the basics for loops on MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, Arduino Lab for MicroPython] +--- + +Arduino Lab for MicroPython includes a user-friendly code editor that helps us write, format, and run MicroPython code with ease. In this article, we’ll explore how the code editor works, key formatting rules for MicroPython, and some useful tips to keep our code clean and error-free. + +## Requirements + +- [Arduino Lab for MicroPython](https://labs.arduino.cc/en/labs/micropython) +- **MicroPython compatible board** (not required for using the editor, but for running any code). + +***Note that the Arduino Lab for MicroPython is now also available online, as part of the Arduino Cloud platform. You will find it here: [Arduino Cloud - Arduino Lab for MicroPython](/micropython/environment/code-editor).*** + +## Arduino Labs for MicroPython + +The code editor in Arduino Labs is designed to streamline our coding experience, providing tools to: + +- Write and format MicroPython code. +- View and manage indentation easily. +- Run our code and view results directly in the REPL. + +As we get familiar with the editor, remember that MicroPython has a few syntax rules that differ from other languages we might know. + +### Overview + +The Arduino Lab for MicroPython editor provides several essential tools to make coding intuitive and efficient: + +1. **Connect/Disconnect Board**: Use this button to connect or disconnect your MicroPython-compatible board. This allows the code editor to communicate with your board for running and testing code. +2. **Run/Stop Script**: Click this button to run or stop your script. The output will be displayed in the REPL, providing immediate feedback or error messages. +3. **File Management**: This option lets you manage files on your MicroPython board. You can upload, download, and organize your scripts. +4. **Edit Script**: The main area of the editor where you write and modify your MicroPython code. It provides features like syntax highlighting to enhance readability. +5. **Expand Terminal**: Use this button to expand or collapse the terminal section, which displays the REPL output, helping you debug and interact with your code in real time. + +![Overview of the code editor.](assets/IDEOverview.png) + +### Files + +Managing files in the Arduino Lab for MicroPython is straightforward and allows for efficient organization and transfer between your board and computer: + +1. **Board Storage**: This section displays the files stored on your MicroPython-compatible board. You can view and manage scripts or data saved directly on the board. +2. **Computer Storage**: This section shows the files on your computer, allowing you to select and manage files for uploading or downloading. +3. **Download/Upload Files**: Use this option to transfer files between your computer and your board. You can upload new scripts or download data logs from your board. +4. **Create File/Folder**: This option lets you create new files or folders directly on the board or in your project directory, making it easy to organize your code and assets. + +![Managing files in Arduino Lab for MicroPython](assets/IDEFileManager.png) + +***For a detailed tutorial on using the file system, please refer to the [File System Tutorial](/micropython/environment/file-system).*** + +### REPL + +The REPL can be found by expanding the terminal. Here you can interact with the terminal. The buttons allow for basic features like copy and pasting as the shortcuts like `CTRL+C will` not work on this window. + +![The REPL.](assets/consoleTerminal.png) +***For a detailed tutorial on using the REPL, please refer to the [REPL Tutorial](/micropython/environment/repl).*** + +## Code Editor + +### Indentation + +In MicroPython, indentation (using spaces or tabs) is essential for defining the structure of our code. Unlike many other languages, MicroPython relies on indentation instead of symbols like `{ }` to define code blocks. + +- **Indent with Consistency**: Typically, each block of code (such as inside a function, loop, or conditional) is indented by four spaces. Make sure all lines in the same block are indented with the same number of spaces. +- **Nested Blocks**: For nested code, simply increase the indentation by another four spaces or one tab. + +**Example of Proper Indentation:** + +```python +def greet(name): + if name: + print(f"Hello, {name}!") + else: + print("Hello, world!") +``` + +In this example, each level of code indentation clearly defines which lines belong to which block. The `print` statements align under the `if` and `else` statements, showing they’re part of those blocks. + +#### Avoiding Common Indentation Mistakes + +- **Mixing Tabs and Spaces**: Use either spaces or tabs consistently. Mixing them can lead to indentation errors. Tabs are generally preferred as these are easier to keep consistency. +- **Missing Indentation**: Every line within a block (like the lines inside the `if` statement) must be indented correctly. If not, we’ll encounter syntax errors. + +### Comments: Inline and Multiline + +Comments are essential for making our code understandable and documenting complex logic. In MicroPython: + +- **Inline Comments**: Use `#` to add a comment on a single line. Anything following the `#` symbol will be ignored by the interpreter. + + ```python + print("Hello, world!") # This prints a greeting + ``` + +- **Multiline Comments**: While MicroPython doesn’t have a dedicated multiline comment syntax, we can use multiple inline comments to achieve the same effect, or use a multiline string with triple quotes (`""" ... """`) as a workaround. + + ```python + # This is a comment + # that spans multiple lines. + + """ + Alternatively, we can use + triple quotes to comment on + multiple lines. + """ + ``` + +Using comments effectively helps both us and others understand the code’s purpose and logic. + +### MicroPython Syntax: No Semicolons Needed! + +In MicroPython, each statement ends automatically at the end of a line, so there’s no need to use semicolons (`;`) as in languages like C++ or Java. This simplifies code and makes it cleaner and easier to read. + +```python +# In C++: +# int a = 5; +# int b = 10; + +# In MicroPython: +a = 5 +b = 10 +``` + +If we’d like to place two commands on the same line, however, we can use a semicolon: + +```python +a = 5; b = 10 +``` + +But this is generally discouraged, as it can make the code harder to read. + +## Running and Compiling Code + +In MicroPython, code isn’t “compiled” like in traditional Arduino sketches. Instead, it’s **interpreted** line by line, making MicroPython highly interactive and flexible for rapid testing and development. + +- **Writing Code**: We write our code in the editor as usual. +- **Running Code**: When we run our code, Arduino Labs for MicroPython sends it to the REPL, which reads and executes each line in real-time. +- **Seeing Results**: The output (or any errors) appears immediately, allowing us to test code quickly and see immediate feedback. + +## Best Practices for Using the Editor + +Here are a few quick tips to make the most of our time in the code editor: + +- **Use Descriptive Names**: Name variables and functions clearly to make the code readable. +- **Keep It Modular**: Split complex code into functions for easier maintenance. +- **Comment as We Go**: Leave helpful comments explaining why we wrote certain sections of code. +- **Indent Carefully**: Pay attention to indentation for clean, error-free code. \ No newline at end of file diff --git a/content/micropython/02.environment/02.file-system/IDEFileManager.png b/content/micropython/02.environment/02.file-system/IDEFileManager.png new file mode 100644 index 0000000000..0dbeae0a5f Binary files /dev/null and b/content/micropython/02.environment/02.file-system/IDEFileManager.png differ diff --git a/content/micropython/02.environment/02.file-system/assets/IDEFileManager.png b/content/micropython/02.environment/02.file-system/assets/IDEFileManager.png new file mode 100644 index 0000000000..0dbeae0a5f Binary files /dev/null and b/content/micropython/02.environment/02.file-system/assets/IDEFileManager.png differ diff --git a/content/micropython/02.environment/02.file-system/assets/ImportScript.png b/content/micropython/02.environment/02.file-system/assets/ImportScript.png new file mode 100644 index 0000000000..b7768f8c2f Binary files /dev/null and b/content/micropython/02.environment/02.file-system/assets/ImportScript.png differ diff --git a/content/micropython/02.environment/02.file-system/assets/RunningScript.png b/content/micropython/02.environment/02.file-system/assets/RunningScript.png new file mode 100644 index 0000000000..1faf82e128 Binary files /dev/null and b/content/micropython/02.environment/02.file-system/assets/RunningScript.png differ diff --git a/content/micropython/02.environment/02.file-system/file-system.md b/content/micropython/02.environment/02.file-system/file-system.md new file mode 100644 index 0000000000..f5975ff91b --- /dev/null +++ b/content/micropython/02.environment/02.file-system/file-system.md @@ -0,0 +1,142 @@ +--- +title: 'File System' +description: 'Learn how to use the File System in MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, File System] +--- + +When working with MicroPython, we’re not limited to a single program file like in traditional Arduino sketches (using C++). Instead, MicroPython provides a file system, enabling us to store and manage multiple files on our microcontroller. This opens up powerful capabilities for organizing code, managing assets, and creating modular projects. + +In this article, we'll explore how the MicroPython file system works, how to organize files effectively, and the typical structure of MicroPython projects. + + +## The MicroPython File System: Key Differences + +In traditional Arduino programming, we upload a single compiled file directly to the microcontroller, where it runs immediately. In MicroPython we work within a file system that can store multiple files. This file system allows us to: + +- **Upload and Download Files**: We can save individual scripts, libraries, and assets directly on the device. +- **Organize Project Files**: Create folders, save multiple scripts, and organize files for a modular approach. +- **Edit Files Directly on the Device**: Modify files without needing to overwrite everything, making adjustments faster and more flexible. +- **Run Different Scripts**: while we have `boot.py` (runs at start) and `main.py` (runs after start), we can also create more scripts that we can run, either from the editor, or from the board itself. + +## Accessing the MicroPython File System + +To interact with the MicroPython file system, we’ll use Arduino Labs for MicroPython, which provides tools to manage and view files directly on our device. Here’s how to get started: + +1. **Connect to Your Device**: Open Arduino Labs for MicroPython and establish a connection to our microcontroller. +2. **Upload and Download Files**: Use the file manager to upload files from our computer to the microcontroller or download files back to our computer. +3. **Organize Files**: We can create folders and store multiple files, making it easy to organize our project. + +![IDE's File Manager](./assets/IDEFileManager.png) + +## Basic MicroPython File Structure + +A typical MicroPython project includes a `main.py` file, `boot.py` file, libraries, and any supporting files our project needs. Here’s a standard layout: + +``` +/ (Root Directory) +├── boot.py +├── main.py +``` + +### Key Files + +- **`boot.py`**: Runs once at startup, before `main.py`, and is typically used for system configurations that need to be set when the device first powers on. +- **`main.py`**: This is the primary script, similar to the `setup()` and `loop()` structure in Arduino. It runs automatically after `boot.py` finishes. + +## Example: Importing Code from Scripts + +With the MicroPython file system, we can create our own scripts and import them in the `main.py` script. This can be helpful in avoiding long scripts, as we instead can store the code in other files. This approach also makes it more modular. + +To run code from a separate script in our `main.py` file, we can follow the instructions below: + +1. Create a file named `my_new_script.py`, and add the following function: + + ```python + def test(): + print("This runs from my_new_script.py") + ``` + +2. In `main.py`, we run some initial code and then switches to executing a function from `my_new_script.py`. Here's an example: + + ```python + import my_new_script + print("This runs from main.py") + + my_new_script.test() + ``` + +3. Check the REPL, we should see: + + ```bash + This runs from main.py # executed from main.py + This runs from my_new_script #executed from my_new_script + ``` + +Essentially, this is how [modules](/micropython/environment/modules) work. You import a module, and use a function from that module. + +![Import code from a script.](assets/ImportScript.png) + +## Example: Directly Executing a Script + +We can also directly execute another script stored on the device. For this example, let's create a script and name it `run_directly.py`. + +1. In the script, store this code: + + ```python + print("I was run from main.py") + ``` + +2. Then in `main.py`, we will use the `open()`, `exec()` and `read()` functions. + + ```python + with open("run_directly.py") as f: + exec(f.read()) + ``` + +- `open()` - opens a file +- `exec()` - executes a file +- `read()` - reads a file + +As a result, we should read `"I was run from main.py"` in the REPL. How this differs from the previous example, is that the `run_directly.py` script was just run from top to bottom, as opposed to importing a specific segment of code. + +![Executing a script directly.](assets/RunningScript.png) + + +## Organizing Code with Modules and Libraries + +When you start importing custom modules or libraries, MicroPython will automatically create a `/lib` folder to store them. This helps keep external libraries or reusable functions separate from your main code. You can use this structure to further organize your project, making it easy to manage larger codebases. + +For example: + +``` +/ (Root Directory) +├── boot.py +├── main.py +├── /lib +│ ├── my_custom_library.py +``` + +### Using Libraries in `main.py` + +After placing reusable code in `/lib`, you can import it directly in `main.py`: + +```python +from lib.my_custom_library import some_function + +some_function() +``` + +This structure allows for cleaner, more modular code that’s easy to scale as your project grows. + +## Conclusion + +MicroPython’s file system brings flexibility and structure to embedded programming, enabling a more organized and modular approach. By understanding the typical file structure and how to manage files, we’ll be able to create more complex and maintainable projects. + +**Tips for Organizing Our MicroPython Projects** + +- **Modularize Code with Additional Scripts**: Store reusable or specific tasks in separate files, making `main.py` clean and focused on high-level logic. +- **Leverage the `/lib` Folder**: Use the automatically created `/lib` folder to keep libraries organized and separate from your main application code. +- **Edit and Manage Files Easily**: Arduino Labs for MicroPython’s file management tools make it easy to upload, download, and modify files on the device. + +With a well-organized file system, we can streamline our development process and unlock new possibilities with MicroPython! \ No newline at end of file diff --git a/content/micropython/02.environment/03.modules/assets/MPInstaller.png b/content/micropython/02.environment/03.modules/assets/MPInstaller.png new file mode 100644 index 0000000000..892655a3c9 Binary files /dev/null and b/content/micropython/02.environment/03.modules/assets/MPInstaller.png differ diff --git a/content/micropython/02.environment/03.modules/assets/microPythonLabsFiles.png b/content/micropython/02.environment/03.modules/assets/microPythonLabsFiles.png new file mode 100644 index 0000000000..da29c64214 Binary files /dev/null and b/content/micropython/02.environment/03.modules/assets/microPythonLabsFiles.png differ diff --git a/content/micropython/02.environment/03.modules/modules.md b/content/micropython/02.environment/03.modules/modules.md new file mode 100644 index 0000000000..cb51ba3d7c --- /dev/null +++ b/content/micropython/02.environment/03.modules/modules.md @@ -0,0 +1,116 @@ +--- +title: 'Modules' +description: 'Understanding modules in MicroPython and how to use them.' +author: 'Pedro Lima' +tags: [MicroPython, Modules] +--- + + +In this guide, we’ll cover how modules work in MicroPython, explore a few built-in modules, and demonstrate how to install an external package like Modulino to extend our MicroPython project’s functionality. + +## What Are Modules? + +Modules are collections of functions, classes, and variables organized into separate files, which we can import and use in our main program. Modules allow us to: + +- **Reuse Code**: We can import useful functionality instead of writing everything from scratch. +- **Organize Code**: Breaking code into modules makes projects more readable and maintainable. +- **Access Special Functionality**: Some tasks require advanced functions (e.g., time delays or hardware communication) that are available only through modules. + +## Built-in Modules + +MicroPython comes with a set of built-in modules that provide essential functions for programming tasks. For instance: + +- **`time`**: This module allows us to add time delays, get timestamps, and measure durations in code. +- **`os`**: Provides functions to manage the file system, such as creating files or listing directories. +- **`machine`**: A module designed for hardware interaction, allowing us to control pins, I2C, and more. + +We can access built-in modules directly without any installation. Here’s a quick example using the `time` module to add a delay: + +```python +import time + +print("Starting countdown...") +time.sleep(3) # Pauses the program for 3 seconds +print("Countdown complete!") +``` + +In this example, `time.sleep()` introduces a delay. Built-in modules like `time` are pre-installed with MicroPython, so we don’t need to install anything extra to use them. + +## External Modules + +Some modules aren’t included with the default MicroPython installation and need to be installed separately. External modules, often provided by the community or specific hardware packages, extend MicroPython’s functionality. For example, the [Modulino library](https://github.com/arduino/arduino-modulino-mpy) is an external module that provides tools for working with Arduino Modulinos. + +To demonstrate how to use external modules, we’ll go through the steps to install the Modulino package on an Arduino board. + +### Step 1: Install MicroPython on Your Board + +Before we can install external modules, we need to have MicroPython running on our board. Use the [MicroPython Installer](https://labs.arduino.cc/en/labs/micropython-installer) to install it: + +- Open the installer. +- Connect the board to your computer. +- Press the "Refresh" button if the board does not appear. +- Click "**Install MicroPython**" and wait for the installation to complete. + +***For more details, visit the [MicroPython installation guide](/micropython/first-steps/install-guide)*** + +### Step 2: Install the Modulino Package + +To install the Modulino package, we’ll use `mpremote`, a tool that allows us to install MicroPython packages directly onto our board from the command line. + +1. Make sure Python is installed on your computer +2. Open a terminal on your machine. +3. Run the following command to install `mpremote`. + + ```bash + pip install mpremote + ``` + +4. With `mpremote` installed, run the following script to find our board's serial port. + + ```bash + mpremote connect list + ``` + + This command should return something akin to: + + ```bash + /dev/cu.usbmodem101 ecda3b60a4dccb3f 2341:056b Arduino Nano ESP32 + ``` + + - Copy the port, e.g., `/dev/cu.usbmodem101`. + +5. Use the following command to install the Modulino package (or any other package we want to install), replacing `` with our board’s port retrieved in the previous step. + + ```bash + mpremote connect mip install github:arduino/arduino-modulino-mpy + ``` + +6. After the installation, open Arduino Labs for MicroPython, and connect your board. In the board's files, we should see a `/lib` folder with the Modulino library inside, indicating a successful installation. + + ![MicroPython Lab Files](./assets/microPythonLabsFiles.png) + +## Organizing and Using Modules + +With the Modulino package installed, we’ll see a `/lib` folder in Arduino Labs, where MicroPython automatically stores external modules. This directory structure is commonly used for organizing additional libraries, making it easy to import and use custom functions in our main program. + +### Using an External Module + +To use a function from the Modulino library, simply import it in `main.py`: + +```python +from modulino import distance_sensor # Example function + +# Example usage +distance = distance_sensor.read_distance() +print("Distance:", distance) +``` + +This setup keeps `main.py` clean and makes it easy to incorporate external functionality without crowding the main script. + +## Conclusion + +MicroPython modules—whether built-in or external—allow us to keep our code organized, reduce duplication, and add powerful functionality to our projects. Some modules, like `time`, are included by default, while others, like the Modulino library, require installation. + +- **Built-in Modules**: Modules like `time` and `machine` are part of MicroPython and need no installation. +- **External Modules**: Packages like Modulino must be installed separately, typically into the `/lib` folder. +- **Using Modules**: Once installed, we can import modules into our main program to extend functionality and keep our code modular. \ No newline at end of file diff --git a/content/micropython/02.environment/04.runtime/assets/AsyncvsSync.png b/content/micropython/02.environment/04.runtime/assets/AsyncvsSync.png new file mode 100644 index 0000000000..d3b32eacbd Binary files /dev/null and b/content/micropython/02.environment/04.runtime/assets/AsyncvsSync.png differ diff --git a/content/micropython/02.environment/04.runtime/runtime.md b/content/micropython/02.environment/04.runtime/runtime.md new file mode 100644 index 0000000000..8f777f7759 --- /dev/null +++ b/content/micropython/02.environment/04.runtime/runtime.md @@ -0,0 +1,66 @@ +--- +title: 'Runtime' +description: 'Learn about the MicroPython runtime environment and how it handles code execution on microcontrollers.' +author: 'Pedro Lima' +tags: [MicroPython, Modules] +--- + +MicroPython is a lean and efficient implementation of Python designed to run on microcontrollers and embedded systems. One of the key concepts to understand when working with MicroPython is its **runtime environment**—how it handles code execution, manages resources, and interacts with hardware. + +We’ll demystify the MicroPython runtime, explore how it differs from other environments like standard Python, and discuss best practices for working within its constraints. + +## What is a Runtime Environment? + +A **runtime environment** is the infrastructure that allows code to execute on a given platform. It provides the necessary resources, such as memory management, libraries, and system interfaces, for the code to run properly. + +For MicroPython, the runtime is a lightweight version of the Python runtime, optimized to work with the limited resources of microcontrollers. This means it has to manage memory efficiently, provide quick access to hardware components, and interpret Python code in real-time. + +### MicroPython's Runtime + +MicroPython's runtime environment consists of several key components: + +1. **Interpreter**: MicroPython interprets Python code line by line. This is different from compiled languages (like C or C++ on traditional Arduino) that need to be fully compiled before running. MicroPython’s interpreter is built to be efficient, ensuring quick code execution even on constrained hardware. + +2. **Memory Management**: Since microcontrollers have limited RAM, the MicroPython runtime includes a garbage collector to manage memory automatically. The [garbage collector](https://docs.micropython.org/en/latest/library/gc.html) frees up unused memory to prevent the system from running out of resources. + +3. **Built-in Libraries and Modules**: MicroPython comes with a set of built-in libraries that provide access to hardware interfaces like pins, I2C, SPI, and UART. These libraries are tightly integrated into the runtime to allow seamless interaction with the hardware. + +4. **File System**: The runtime includes a file system, typically mounted on the microcontroller’s flash storage. This allows MicroPython to load and execute scripts, save configuration files, or store data persistently. + +### MicroPython Runtime Features + +1. **REPL (Read-Eval-Print Loop)**: One of the standout features of MicroPython's runtime is the REPL. The REPL is an interactive shell where we can type and execute Python code line by line, get immediate feedback, and test ideas quickly. It’s especially useful for debugging and learning how the hardware responds to different commands. + +2. **Boot and Main Scripts**: When the microcontroller starts up, the MicroPython runtime automatically looks for two scripts: + + - **`boot.py`**: This script is executed first and is typically used for system configuration, such as setting up Wi-Fi or initializing hardware settings. + - **`main.py`**: After `boot.py` runs, `main.py` is executed. This is where we typically put our main application logic. + +3. **Concurrency with `uasyncio`**: MicroPython provides support for asynchronous programming using the `uasyncio` module. This allows us to handle multiple tasks concurrently, such as reading a sensor while controlling an LED, without blocking the main program. + +### MicroPython vs Python + +While MicroPython aims to be as compatible as possible with standard Python, there are some important differences due to the limited resources available on microcontrollers: + +- **Memory Constraints**: Standard Python runs on desktops or servers with abundant RAM, but MicroPython runs on devices with as little as 16KB to 512KB of RAM. The runtime is optimized to be efficient, but we must be mindful of memory usage. +- **Limited Libraries**: Many of Python’s standard libraries are unavailable in MicroPython because they are too large or not relevant for embedded systems. However, MicroPython provides specialized libraries for hardware interaction. +- **Performance**: MicroPython is generally slower than compiled languages, but it’s fast enough for most embedded applications thanks to its lightweight runtime and efficient interpreter. + +## Code Execution Works in MicroPython + +When we upload a MicroPython script to our microcontroller, the runtime handles code execution as follows: + +1. **Interpreter Reads Code**: The interpreter reads each line of Python code and executes it immediately. If there are syntax errors, they are reported right away. +2. **Memory Allocation**: Variables, objects, and data structures are allocated in the microcontroller’s RAM. The garbage collector runs periodically to free up memory that’s no longer needed. +3. **Hardware Interaction**: The runtime communicates with the microcontroller’s hardware through built-in libraries. For example, we can control GPIO pins, read sensor data, or send data over I2C using simple Python commands. +4. **Error Handling**: MicroPython includes mechanisms for error handling and debugging. If the script encounters an error, the runtime will stop execution and display an error message in the REPL or console. + +## Best Practices +1. **Manage Memory Wisely**: Be mindful of memory usage, especially when working with large data structures or performing frequent allocations. Use the garbage collector [(`gc`)](https://docs.micropython.org/en/latest/library/gc.html) if you need to manually free up memory. +2. **Use REPL for Testing**: Take advantage of the REPL to experiment and debug code interactively. This can save time and help you understand how your code interacts with the hardware. +3. **Optimize Code for Speed and Efficiency**: Use efficient data structures and algorithms to keep your code fast and responsive. Avoid blocking operations when possible, and consider using `uasyncio` for concurrency. +4. **Organize Code with Modules**: Break your code into reusable modules to keep `main.py` clean and organized. This can make your project easier to maintain and extend. + +## Conclusion + +The MicroPython runtime is a powerful yet lightweight environment that brings the flexibility of Python to embedded systems. By understanding how the runtime handles code execution, memory management, and hardware interaction, we can write efficient and effective MicroPython programs. \ No newline at end of file diff --git a/content/micropython/02.environment/05.repl/assets/replcover.png b/content/micropython/02.environment/05.repl/assets/replcover.png new file mode 100644 index 0000000000..f96cf581e6 Binary files /dev/null and b/content/micropython/02.environment/05.repl/assets/replcover.png differ diff --git a/content/micropython/02.environment/05.repl/assets/replgif.gif b/content/micropython/02.environment/05.repl/assets/replgif.gif new file mode 100644 index 0000000000..72c152dd21 Binary files /dev/null and b/content/micropython/02.environment/05.repl/assets/replgif.gif differ diff --git a/content/micropython/02.environment/05.repl/repl.md b/content/micropython/02.environment/05.repl/repl.md new file mode 100644 index 0000000000..a92081357c --- /dev/null +++ b/content/micropython/02.environment/05.repl/repl.md @@ -0,0 +1,88 @@ +--- +title: 'REPL' +description: 'Learn how to use the REPL (Read-Eval-Print Loop) in MicroPython.' +author: 'Pedro Lima' +tags: [MicroPython, REPL] +--- + +**REPL**, short for **Read-Eval-Print Loop**, is an interactive environment that makes programming in MicroPython fast and flexible. REPL allows you to enter code line-by-line and see the results immediately. Although sometimes overlooked it is a great way for testing and debugging on the fly. + +In this guide, we’ll go through how the REPL functions, why it’s useful, and how you can use it to enhance your MicroPython experience. + +## What is REPL? + +![REPL.](assets/replcover.png) + +The REPL process involves four basic steps: + +- **R - ead**: Reads and accepts your code input line-by-line. +- **E - val**: Evaluates the entered code. +- **P - rint**: Displays the result of the code execution. +- **L - oop**: Repeats the process, allowing you to enter new code immediately. + +Think of REPL as a conversation between you and your MicroPython environment, where each line you type gets an instant response, making it ideal for exploring ideas and troubleshooting. + +## How REPL Works in MicroPython + +In MicroPython, REPL can be accessed via Arduino Labs for MicroPython terminal, enabling you to run code in real-time directly on your device. Here’s a step-by-step guide on using it: + +1. **Connect to REPL**: Open Arduino Labs for MicroPython and establish a connection to your microcontroller. Once connected, you’ll see a prompt (`>>>`), indicating the REPL is ready. +2. **Enter Code**: Type any valid MicroPython code directly after the prompt. When you press Enter, REPL will execute your code. +3. **See Results Instantly**: Any output, return values, or errors are displayed right away. If your code contains expressions, REPL will evaluate and print them for you. +4. **Iterate**: The loop resets, and you can immediately enter more code, building on previous commands or testing new lines independently. + +## Example: Store and Print Your Name + +Let's create a REPL session, where you will enter your name, and then print it. + +Connect your board, and click on the **RUN** button with an empty script, then enter the following things in the REPL, line by line. + +``` +>>> name = "Pedro" +>>> name +``` + +When writing `name` in the REPL, (after `name = "Pedro"`), we should get: + +``` +'Pedro' +``` + +![How the REPL works.](assets/replgif.gif) + +## Example: Perform a Calculation in the REPL + +Now let's create a REPL session that performs a calculation, by adding two numbers together: + +```python +>>> a = 5 +>>> b = 3 +>>> a + b +8 +``` + +In this REPL session, we: + +- Defined variables by setting `a` to `5` and `b` to `3`. +- Performed a calculation by entering `a + b`, which immediately returns `8`, showing the result without having to write a full script. + +## Common Uses of REPL + +REPL is particularly useful for: + +- **Testing code snippets**: Quickly check how individual pieces of code behave. +- **Debugging**: Test small parts of a larger project interactively. +- **Learning**: Practice MicroPython commands and get instant feedback, ideal for beginners. + +## Summary + +REPL in MicroPython is an useful tool that enables instant testing and feedback, making coding more interactive and efficient. Whether you're learning, debugging, or exploring ideas, REPL provides a flexible and powerful coding experience. + +**Experiment with REPL** + +- **Explore Built-in Functions**: Use functions like `len()`, `sum()`, or `type()` and see the results immediately, allowing you to get a quick feel for MicroPython’s standard library. +- **Test Sensor and Pin Outputs**: Quickly check real-time data from sensors or pin states by writing simple lines to read values directly, helping you troubleshoot hardware setups. +- **Debug Variable Values**: Enter and modify variables on the spot to test changes in data or simulate inputs, allowing you to observe how your program behaves step-by-step. +- **Practice Logical Expressions**: Experiment with logical statements and conditionals to understand how `if` statements, comparisons, and loops work in MicroPython. + +By mastering REPL, you’ll be well-equipped to make the most of MicroPython’s interactive capabilities and streamline your development process. \ No newline at end of file diff --git a/content/micropython/02.environment/environment.md b/content/micropython/02.environment/environment.md new file mode 100644 index 0000000000..ad258423d7 --- /dev/null +++ b/content/micropython/02.environment/environment.md @@ -0,0 +1,3 @@ +--- +title: Environment +--- \ No newline at end of file diff --git a/content/micropython/01.basics/08.reference/reference.md b/content/micropython/03.language/01.reference/reference.md similarity index 99% rename from content/micropython/01.basics/08.reference/reference.md rename to content/micropython/03.language/01.reference/reference.md index 3c6e92eed1..c52b3dc8b5 100644 --- a/content/micropython/01.basics/08.reference/reference.md +++ b/content/micropython/03.language/01.reference/reference.md @@ -1336,7 +1336,7 @@ print("Hello World!") `while True:` -A loop is not required in a MicroPython script, but is required in order to run a script continuously on the board. To have a loop in a program, we need to use a [while loop](). +A loop is not required in a MicroPython script, but is required in order to run a script continuously on the board. To have a loop in a program, we need to use a [while loop](/micropython/basics/loops/#while-loops). **Example:** diff --git a/content/micropython/03.language/language.md b/content/micropython/03.language/language.md new file mode 100644 index 0000000000..9abfe019da --- /dev/null +++ b/content/micropython/03.language/language.md @@ -0,0 +1,3 @@ +--- +title: Language +--- \ No newline at end of file diff --git a/content/micropython/04.board-examples/board-examples.md b/content/micropython/04.board-examples/board-examples.md new file mode 100644 index 0000000000..4d35cd122f --- /dev/null +++ b/content/micropython/04.board-examples/board-examples.md @@ -0,0 +1,3 @@ +--- +title: Board Examples +--- \ No newline at end of file diff --git a/content/micropython/04.board-examples/giga-r1-wifi/assets/ABX00063-pinout.png b/content/micropython/04.board-examples/giga-r1-wifi/assets/ABX00063-pinout.png new file mode 100644 index 0000000000..5fc3571cd4 Binary files /dev/null and b/content/micropython/04.board-examples/giga-r1-wifi/assets/ABX00063-pinout.png differ diff --git a/content/micropython/04.board-examples/giga-r1-wifi/assets/giga-r1.png b/content/micropython/04.board-examples/giga-r1-wifi/assets/giga-r1.png new file mode 100644 index 0000000000..4b0ac70349 Binary files /dev/null and b/content/micropython/04.board-examples/giga-r1-wifi/assets/giga-r1.png differ diff --git a/content/micropython/04.board-examples/giga-r1-wifi/giga-r1-wifi.md b/content/micropython/04.board-examples/giga-r1-wifi/giga-r1-wifi.md new file mode 100644 index 0000000000..30022eca55 --- /dev/null +++ b/content/micropython/04.board-examples/giga-r1-wifi/giga-r1-wifi.md @@ -0,0 +1,187 @@ +--- +title: GIGA R1 WiFi +description: Learn how to use specific features on the GIGA R1 WiFi using MicroPython +author: Pedro Sousa Lima +--- + +![GIGA R1 WiFi](./assets/giga-r1.png) + +In this guide, you will find information specific to the [GIGA R1 WiFi board](https://store.arduino.cc/products/giga-r1-wifi), such as supported serial protocols, built-in peripherals, and how to access the wireless features. + +For installation instructions, please visit the link below: +- [Installing MicroPython](https://labs.arduino.cc/en/labs/micropython-installer) + +## Pinout + +The pinout for the GIGA R1 WiFi can be found in the image below. + +![GIGA R1 WiFi Pinout](./assets/ABX00063-pinout.png) + +***For more details on this product, visit the [hardware product page](/hardware/giga-r1-wifi/).*** + +## Board-Specific Features + +The GIGA R1 WiFi has several board-specific features that we can access through MicroPython: + +- **Dual-core STM32H7**: Leverage the power of two cores (Cortex-M7 and Cortex-M4) and RPC for advanced multitasking applications. +- **RGB LED**: A built-in RGB LED that can be controlled by setting `r`, `g`, and `b` values. +- **Wireless Connectivity**: Supports both **Wi-Fi®** and **Bluetooth®** using the integrated Murata 1DX module. +- **High-speed Connectivity**: Includes a USB-C® connector, high-speed UART, and CAN bus support. + +## Dual-Core Programming + +The GIGA R1 WiFi supports dual-core programming, where the Cortex-M7 and Cortex-M4 cores can execute separate tasks simultaneously. Below is an example of how to run MicroPython on one core while offloading specific tasks to the other: + +**Example:** Running MicroPython on Cortex-M7 and using the M4 for auxiliary tasks. + +```python +from machine import freq +import _thread + +# Function to run on Cortex-M4 core +def auxiliary_task(): + while True: + print("Running auxiliary task on M4") + time.sleep(1) + +# Run main task on M7 core +def main_task(): + print("Main task on M7 core") + _thread.start_new_thread("Aux", auxiliary_task, ()) + +main_task() +``` + +**Note**: Dual-core programming is an advanced topic and requires proper synchronization to avoid resource conflicts. + +## RGB LED + +The GIGA R1 WiFi has a built-in RGB LED that can be easily controlled to turn on each color individually. The following example shows how to cycle through red, green, and blue, waiting a second between each, and then turning off all colors before looping back. + +```python +from machine import Pin +import time + +# Initialize pins for the RGB LED +red = Pin("LED_RED", Pin.OUT) # LED_RED GPIO +green = Pin("LED_GREEN", Pin.OUT) # LED_GREEN GPIO +blue = Pin("LED_BLUE", Pin.OUT) # LED_BLUE GPIO + +# Function to turn off all colors +def turn_off_all(): + red.value(0) + green.value(0) + blue.value(0) + +# Cycle through colors +while True: + red.value(1) # Turn on Red + time.sleep(1) # Wait for 1 second + red.value(0) # Turn off Red + + green.value(1) # Turn on Green + time.sleep(1) # Wait for 1 second + green.value(0) # Turn off Green + + blue.value(1) # Turn on Blue + time.sleep(1) # Wait for 1 second + blue.value(0) # Turn off Blue + + turn_off_all() # Ensure all colors are off +``` + + +## PWM on the GIGA R1 WiFi + +On STM32 boards like the Arduino GIGA R1 WiFi, PWM is handled differently than on typical MicroPython boards. Instead of directly using the `PWM` class, you need to use the `Timer` class in combination with the `Pin` class from the `pyb` module. + +Below is an example of how to set up PWM on the GIGA R1 WiFi: + +```python +from pyb import Pin, Timer + +# Set up the PWM pin +p = Pin('A13') # Replace 'A13' with your desired PWM-capable pin + +# Initialize a timer for PWM +tim = Timer(2, freq=1000) # Timer 2 with a frequency of 1 kHz + +# Create a PWM channel on the timer +ch = tim.channel(1, Timer.PWM, pin=p) + +# Set the duty cycle +ch.pulse_width_percent(25) # 25% duty cycle +``` + +- **Pin Setup**: + `p = Pin('A13')` initializes the pin `A13` for PWM output. Replace `'A13'` with another PWM-capable pin if needed. Note that on the GIGA R1 WiFi, `A13` is marked as **DAC1** on the pinout. + +- **Timer Initialization**: + `tim = Timer(2, freq=1000)` initializes **Timer 2** with a frequency of 1000 Hz. + +- **Channel Setup**: + `ch = tim.channel(1, Timer.PWM, pin=p)` creates a PWM channel on Timer 2, Channel 1, and associates it with pin `p`. + +- **Set Duty Cycle**: + `ch.pulse_width_percent(25)` sets the duty cycle of the PWM signal to 25%. You can adjust this value between `0` and `100` to control the signal's ON time. + + +## RPC + +The **msgpackrpc** library provides the same functionality as the Arduino RPC library for MicroPython, allowing seamless communication between the two cores (M7 and M4) on the GIGA R1 WiFi. This library enables binding of local functions or objects, starting the M4 core, and invoking remote calls from Python scripts. + +### Key Features: +- **Dual-Core Support**: Execute tasks on the M4 core while the main MicroPython code runs on the M7 core. +- **Ease of Use**: The library is built-in and enabled by default in compatible Arduino boards, starting with MicroPython release v1.23. +- **No External Dependencies**: The library is included in the MicroPython firmware and does not require additional installations. + + +### Restrictions: + +While powerful, the **msgpackrpc** library has some limitations: +1. Arduino sketches can only run on the **M4 core**. +2. **SDRAM-based firmware** is not supported. +3. **Flash-based firmware** must use a 1.5MB M7 + 0.5MB M4 flash partitioning scheme. + + +### Example + +Here’s how to bind a function on the M7 core and call it from the M4 core: + +**On the M7 Core:** + +```python +from rpc import RPCServer + +# Define a function to bind +def hello_world(): + return "Hello from M7!" + +# Start the RPC server +rpc_server = RPCServer() +rpc_server.bind_function("hello_world", hello_world) + +# Keep the server running +rpc_server.run() +``` + +**On the M4 Core:** + +```python +from rpc import RPCClient + +# Connect to the M7 core +rpc_client = RPCClient() + +# Call the bound function on the M7 core +result = rpc_client.call_function("hello_world") +print(result) # Outputs: Hello from M7! +``` + +For a detailed explanation of the RPC library, including advanced use cases and configuration, visit the [RPC Library with MicroPython guide](https://docs.arduino.cc/tutorials/giga-r1-wifi/giga-dual-core/#using-the-rpc-library-with-micropython). + +## Summary + +The GIGA R1 WiFi is a robust microcontroller packed with advanced features for embedded programming with MicroPython. From dual-core programming to high-speed connectivity and wireless communication, this guide provides the essentials to get started with this powerful board. + +For more advanced projects and examples, visit the [Arduino Docs - MicroPython](https://docs.arduino.cc/micropython/). diff --git a/content/micropython/04.board-examples/nano-ble-sense/assets/ABX00031-pinout.png b/content/micropython/04.board-examples/nano-ble-sense/assets/ABX00031-pinout.png new file mode 100644 index 0000000000..1e4a42f20e Binary files /dev/null and b/content/micropython/04.board-examples/nano-ble-sense/assets/ABX00031-pinout.png differ diff --git a/content/micropython/04.board-examples/nano-ble-sense/assets/ble-sense.png b/content/micropython/04.board-examples/nano-ble-sense/assets/ble-sense.png new file mode 100644 index 0000000000..6771ea143a Binary files /dev/null and b/content/micropython/04.board-examples/nano-ble-sense/assets/ble-sense.png differ diff --git a/content/micropython/04.board-examples/nano-ble-sense/nano-ble-sense.md b/content/micropython/04.board-examples/nano-ble-sense/nano-ble-sense.md new file mode 100644 index 0000000000..89a97ed334 --- /dev/null +++ b/content/micropython/04.board-examples/nano-ble-sense/nano-ble-sense.md @@ -0,0 +1,333 @@ +--- +title: Nano BLE Sense +description: Learn how to use specific features on the Nano BLE Sense using MicroPython +author: Karl Söderby +--- + +![Nano BLE Sense](assets/ble-sense.png) + +In this guide, you will find information specific to the [Nano BLE Sense board](https://store.arduino.cc/products/nano-33-ble-sense-rev2), such as supported serial protocols and built-in sensors that can be accessed. + +For installation instructions, please visit the link below. +- [Installing MicroPython](/micropython/first-steps/install-guide) + +## Pinout + +The pinout for the Nano BLE Sense can be found in the image below. + +![Nano BLE Sense Pinout](assets/ABX00031-pinout.png) + +***For more details on this product, visit the [hardware product page](/hardware/nano-33-ble-sense-rev2/).*** + +## Board Specific Features + +The Nano BLE Sense has a number of board-specific features that can be accessed through MicroPython: + +- **Built-in LED** - a small single pixel LED on the board. +- **RGB LED** - a simple RGB pixel that can be controlled by setting `r`, `g` and `b` values. +- **Microphone (MP34DT05)** - a microphone for recording audio samples. +- **Gesture Sensor (APDS9960)** - measure ambient light and proximity. +- **Pressure Sensor (LPS22)** - measure air pressure for weather applications. +- **Temperature and Humidity - HTS221 (Rev1), HS3003 (Rev2)** - record temperature and relative humidity. +- **IMU - LSM9DS1 (Rev1), BMI270 + BMM150 (Rev2)** - read gyroscope and accelerometer data. + +## RGB LED + +To use the RGB pixel, we can control it by using the `1`, `2` and `3` pins. Below is an example that will blink the main colors in sequence: + +```python +from board import LED +import time + +led_red = LED(1) +led_green = LED(2) +led_blue = LED(3) + +while (True): + + # Turn on LEDs + led_red.on() + led_green.on() + led_blue.on() + + # Wait 0.25 seconds + time.sleep_ms(250) + + # Turn off LEDs + led_red.off() + led_green.off() + led_blue.off() + + # Wait 0.25 seconds + time.sleep_ms(250) +``` + +## Built-in LED + +The classic blink example! Blink the built-in LED every 0.25 seconds. + +```python +from board import LED +import time + +led_builtin = LED(4) + +while (True): + + # Turn on LED + led_builtin.on() + + # Wait 0.25 seconds + time.sleep_ms(250) + + # Turn off LED + led_builtin.off() + + # Wait 0.25 seconds + time.sleep_ms(250) + +``` + +## IMU (LSM9DS1, BMI270 + BMM150) + +Access the `accelerometer`, `magnetometer`, and `gyroscope` data from the IMU module. + +```python +import time +import imu +from machine import Pin, I2C + +bus = I2C(1, scl=Pin(15), sda=Pin(14)) +imu = imu.IMU(bus) + +while (True): + print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.accel())) + print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.gyro())) + print('Magnetometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.magnet())) + print("") + time.sleep_ms(100) +``` + +## Temperature & Humidity (HTS221) + +Access the `temperature` & `humidity` values from the HTS221 sensor (Nano 33 BLE Sense). + +```python +import time +import hts221 +from machine import Pin, I2C + +bus = I2C(1, scl=Pin(15), sda=Pin(14)) +hts = hts221.HTS221(bus) + +while (True): + rH = hts.humidity() + temp = hts.temperature() + print ("rH: %.2f%% T: %.2fC" %(rH, temp)) + time.sleep_ms(100) +``` + +## Temperature & Humidity (HS3003) + +Access the `temperature` & `humidity` values from the HTS221 sensor (Nano 33 BLE Sense Rev2). + +```python +import time +from hs3003 import HS3003 +from machine import Pin, I2C + +bus = I2C(1, scl=Pin(15), sda=Pin(14)) +hts = HS3003(bus) + +while True: + rH = hts.humidity() + temp = hts.temperature() + print ("rH: %.2f%% T: %.2fC" %(rH, temp)) + time.sleep_ms(100) +``` + +## Pressure (LPS22) + +Access the `pressure` values from the LPS22 sensor. + +```python +import time +import lps22h +from machine import Pin, I2C + +bus = I2C(1, scl=Pin(15), sda=Pin(14)) +lps = lps22h.LPS22H(bus) + +while (True): + pressure = lps.pressure() + temperature = lps.temperature() + print("Pressure: %.2f hPa Temperature: %.2f C"%(pressure, temperature)) + time.sleep_ms(100) +``` + +## Ambient Light (APDS9960) + +Access the `Ambient Light` values from the APDS9960 sensor. + +```python +from time import sleep_ms +from machine import Pin, I2C +from apds9960.const import * +from apds9960 import uAPDS9960 as APDS9960 + +bus = I2C(1, sda=Pin(13), scl=Pin(14)) +apds = APDS9960(bus) + +print("Light Sensor Test") +print("=================") +apds.enableLightSensor() + +while True: + sleep_ms(250) + val = apds.readAmbientLight() + print("AmbientLight={}".format(val)) +``` + +## Proximity (APDS9960) + +Access the `Proximity values` from the APDS9960 sensor. + +```python +from time import sleep_ms +from machine import Pin, I2C + +from apds9960.const import * +from apds9960 import uAPDS9960 as APDS9960 + +bus = I2C(1, sda=Pin(13), scl=Pin(14)) +apds = APDS9960(bus) + +apds.setProximityIntLowThreshold(50) + +print("Proximity Sensor Test") +print("=====================") +apds.enableProximitySensor() + +while True: + sleep_ms(250) + val = apds.readProximity() + print("proximity={}".format(val)) +``` + +## Microphone (MP34DT05) + +Below example can be used with OpenMV's frame buffer window (top right corner). + +```python +import image, audio, time +from ulab import numpy as np +from ulab import scipy as sp + +CHANNELS = 1 +SIZE = 256//(2*CHANNELS) + +raw_buf = None +fb = image.Image(SIZE+50, SIZE, image.RGB565, copy_to_fb=True) +audio.init(channels=CHANNELS, frequency=16000, gain_db=80, highpass=0.9883) + +def audio_callback(buf): + # NOTE: do Not call any function that allocates memory. + global raw_buf + if (raw_buf == None): + raw_buf = buf + +# Start audio streaming +audio.start_streaming(audio_callback) + +def draw_fft(img, fft_buf): + fft_buf = (fft_buf / max(fft_buf)) * SIZE + fft_buf = np.log10(fft_buf + 1) * 20 + color = (0xFF, 0x0F, 0x00) + for i in range(0, SIZE): + img.draw_line(i, SIZE, i, SIZE-int(fft_buf[i]), color, 1) + +def draw_audio_bar(img, level, offset): + blk_size = SIZE//10 + color = (0xFF, 0x00, 0xF0) + blk_space = (blk_size//4) + for i in range(0, int(round(level/10))): + fb.draw_rectangle(SIZE+offset, SIZE - ((i+1)*blk_size) + blk_space, 20, blk_size - blk_space, color, 1, True) + +while (True): + if (raw_buf != None): + pcm_buf = np.frombuffer(raw_buf, dtype=np.int16) + raw_buf = None + + if CHANNELS == 1: + fft_buf = sp.signal.spectrogram(pcm_buf) + l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) + else: + fft_buf = sp.signal.spectrogram(pcm_buf[0::2]) + l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) + r_lvl = int((np.mean(abs(pcm_buf[0::2])) / 32768)*100) + + fb.clear() + draw_fft(fb, fft_buf) + draw_audio_bar(fb, l_lvl, 0) + if CHANNELS == 2: + draw_audio_bar(fb, r_lvl, 25) + fb.flush() + +# Stop streaming +audio.stop_streaming() +``` + +## Communication + +The Nano BLE Sense supports **I2C**, **UART** and **SPI**. Below you will find examples on how to use them. + +### I2C + +The I2C bus on the Nano BLE Sense is available through the **A4/A5** pins. Below is an example for how to use it: + +```python +from machine import Pin, I2C + +# Initialize I2C with SCL on A5 and SDA on A4 +i2c = I2C(0, scl=Pin(5), sda=Pin(4)) +devices = i2c.scan() + +print("I2C devices found:", devices) +``` + +***Read more about I2C in [this article](/micropython/communication/i2c).*** + +### UART + +The Nano BLE Sense supports **UART** through the **D0/D1** pins. Below is an example for how to use it: + +```python +from machine import UART + +# Initialize UART on pins 16 (TX) and 17 (RX) +uart = UART(1, baudrate=9600, tx=16, rx=17) + +# Send and receive data +uart.write("Hello from Nano BLE Sense!") +data = uart.read() +print("Received:", data) +``` + +### SPI + +The Nano BLE Sense supports **SPI** through the following pins: +- **(CIPO)** - D12 +- **(COPI)** - D11 +- **(SCK)** - D13 +- **(CS)** - Any GPIO (except for A6/A7) + +Below is an example for how to use it: + +```python +from machine import Pin, SPI + +# Initialize SPI with SCK on pin 18, MOSI on pin 23, and MISO on pin 19 +spi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) + +print("SPI initialized") +``` \ No newline at end of file diff --git a/content/micropython/04.board-examples/nano-esp32/assets/ABX00083-pinout.png b/content/micropython/04.board-examples/nano-esp32/assets/ABX00083-pinout.png new file mode 100644 index 0000000000..255dfaa818 Binary files /dev/null and b/content/micropython/04.board-examples/nano-esp32/assets/ABX00083-pinout.png differ diff --git a/content/micropython/04.board-examples/nano-esp32/assets/esp32.png b/content/micropython/04.board-examples/nano-esp32/assets/esp32.png new file mode 100644 index 0000000000..eafe5ff42a Binary files /dev/null and b/content/micropython/04.board-examples/nano-esp32/assets/esp32.png differ diff --git a/content/micropython/04.board-examples/nano-esp32/nano-esp32.md b/content/micropython/04.board-examples/nano-esp32/nano-esp32.md new file mode 100644 index 0000000000..35186c000c --- /dev/null +++ b/content/micropython/04.board-examples/nano-esp32/nano-esp32.md @@ -0,0 +1,126 @@ +--- +title: Nano ESP32 +description: Learn how to use specific features on the Nano ESP32 using MicroPython +author: Pedro Lima +--- + +![Nano ESP32](./assets/esp32.png) + +In this guide, you will find information specific to the [Nano ESP32 board](https://store.arduino.cc/products/nano-esp32), such as supported serial protocols, built-in sensors, and how to access the wireless features. + +For installation instructions, please visit the link below: +- [Installing MicroPython](https://labs.arduino.cc/en/labs/micropython-installer) + +## Pinout + +The pinout for the Nano ESP32 can be found in the image below. + +![Nano ESP32 Pinout](./assets/ABX00083-pinout.png) + +***For more details on this product, visit the [hardware product page](/hardware/nano-esp32/).*** + +## Board-Specific Features + +The Nano ESP32 has several board-specific features that we can access through MicroPython: + +- **RGB LED**: A built-in RGB LED that can be controlled by setting `r`, `g`, and `b` values. +- **Touch Pins**: Capacitive touch sensors available on multiple pins. +- **ESP-NOW**: A wireless communication protocol developed by Espressif that enables low-power, peer-to-peer communication without the need for a Wi-Fi router. ESP-NOW is particularly useful for creating mesh networks or communicating with other ESP32 devices with low latency and minimal setup. + +### ESP-NOW + +ESP-NOW is a powerful feature of the ESP32 that allows devices to communicate directly with each other using a simple, lightweight protocol. This is useful for applications where quick data transfer is needed between devices, such as in sensor networks or remote control systems. + +**Example:** +Here's a basic outline of how you can set up ESP-NOW communication between two ESP32 boards using MicroPython: + +```python +import espnow +import network + +# Initialize the Wi-Fi interface in station mode +wifi = network.WLAN(network.STA_IF) +wifi.active(True) + +# Initialize ESP-NOW +esp_now = espnow.ESPNow() +esp_now.init() + +# Add a peer device (MAC address needed) +peer_mac = b'\x24\x0A\xC4\x12\x34\x56' # Replace with the MAC address of the peer +esp_now.add_peer(peer_mac) + +# Send a message +esp_now.send(peer_mac, b'Hello, ESP-NOW!') + +# Receive messages +def on_recv_msg(mac, msg): + print("Received message from:", mac, "Message:", msg) + +esp_now.on_recv(on_recv_msg) +``` + +> **Note**: ESP-NOW requires you to know the MAC address of the peer device in advance and does not require a Wi-Fi router or internet connection. + + +## Communication Protocols + +The Nano ESP32 supports **I2C**, **UART**, and **SPI** for communication with external devices. Here are examples of how to use them in MicroPython. + +### I2C + +The I2C bus on the Nano ESP32 is available on pins **A4 (SDA)** and **A5 (SCL)**. Here is how to set it up: + +```python +from machine import Pin, I2C + +# Initialize I2C with SCL on A5 and SDA on A4 +i2c = I2C(0, scl=Pin(5), sda=Pin(4)) +devices = i2c.scan() + +print("I2C devices found:", devices) +``` + +***Read more about I2C in [this article](/micropython/communication/i2c).*** + +### UART + +The Nano ESP32 can communicate using UART, available on specific pins. Here’s how to set it up: + +```python +from machine import UART + +# Initialize UART on pins 16 (TX) and 17 (RX) +uart = UART(1, baudrate=9600, tx=16, rx=17) + +# Send and receive data +uart.write("Hello from Nano ESP32!") +data = uart.read() +print("Received:", data) +``` + +### SPI + +SPI communication is also supported on the Nano ESP32, which is useful for high-speed data transfer with peripherals: + +```python +from machine import Pin, SPI + +# Initialize SPI with SCK on pin 18, MOSI on pin 23, and MISO on pin 19 +spi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) + +print("SPI initialized") +``` + +## Additional Features + +The Nano ESP32 includes other features that can be explored: + +- **Analog Pins**: Use `ADC` to read analog values from sensors. +- **PWM**: Use `PWM` for pulse-width modulation to control motors or LEDs. + +## Summary + +The Nano ESP32 is a powerful microcontroller that supports a variety of features for embedded programming with MicroPython. From controlling the built-in RGB LED to using capacitive touch sensors and establishing wireless connections, this guide covers the essentials to get started. + +For more advanced projects and examples, visit the [Arduino Docs - MicroPython](https://docs.arduino.cc/micropython/). \ No newline at end of file diff --git a/content/micropython/04.board-examples/nano-rp2040-connect/assets/ABX00053-pinout.png b/content/micropython/04.board-examples/nano-rp2040-connect/assets/ABX00053-pinout.png new file mode 100644 index 0000000000..e9f998cb1e Binary files /dev/null and b/content/micropython/04.board-examples/nano-rp2040-connect/assets/ABX00053-pinout.png differ diff --git a/content/micropython/04.board-examples/nano-rp2040-connect/assets/rp-2040.png b/content/micropython/04.board-examples/nano-rp2040-connect/assets/rp-2040.png new file mode 100644 index 0000000000..e20ea6dde1 Binary files /dev/null and b/content/micropython/04.board-examples/nano-rp2040-connect/assets/rp-2040.png differ diff --git a/content/micropython/04.board-examples/nano-rp2040-connect/nano-rp2040-connect.md b/content/micropython/04.board-examples/nano-rp2040-connect/nano-rp2040-connect.md new file mode 100644 index 0000000000..0889954314 --- /dev/null +++ b/content/micropython/04.board-examples/nano-rp2040-connect/nano-rp2040-connect.md @@ -0,0 +1,206 @@ +--- +title: Nano RP2040 Connect +description: Learn how to use specific features on the Nano RP2040 Connect using MicroPython +author: Karl Söderby +--- + +![Nano RP2040 Connect](assets/rp-2040.png) + +In this guide, you will find information specific to the [Nano RP2040 Connect board](https://store.arduino.cc/products/arduino-nano-rp2040-connect), such as supported serial protocols and built-in sensors that can be accessed. + +For installation instructions, please visit the link below. +- [Installing MicroPython](/micropython/first-steps/install-guide) + +## Pinout + +The pinout for the Nano RP2040 Connect can be found in the image below. + +![Nano RP2040 Connect Pinout](assets/ABX00053-pinout.png) + +***For more details on this product, visit the [hardware product page](/hardware/nano-rp2040-connect/).*** + +## Board Specific Features + +The Nano RP2040 Connect has a number of board-specific features that can be accessed through MicroPython: + +- **RGB LED** - a simple RGB pixel that can be controlled by setting `r`, `g` and `b` values. +- **Microphone (MP34DT05)** - a microphone for recording audio samples. +- **IMU (LSM6DSOX)** - for sampling gyroscope and accelerometer data. + +### RGB LED + +To use the RGB pixel, we can control it by using the `1`, `2` and `3` pins. Below is an example that will blink the main colors in sequence: + +```python +from board import LED +import time + +led_red = LED(1) +led_green = LED(2) +led_blue = LED(3) + +while (True): + + # Turn on LEDs + led_red.on() + led_green.on() + led_blue.on() + + # Wait 0.25 seconds + time.sleep_ms(250) + + # Turn off LEDs + led_red.off() + led_green.off() + led_blue.off() + + # Wait 0.25 seconds + time.sleep_ms(250) +``` + +### Microphone (MP34DT05) + +The Nano RP2040 Connect has a built-in microphone, that can be used through the OpenMV editor. To use it, you will need to install [OpenMV](https://openmv.io/pages/download) and run the following script. + +```python +import image, audio, time +from ulab import numpy as np +from ulab import scipy as sp + +CHANNELS = 1 +FREQUENCY = 32000 +N_SAMPLES = 32 if FREQUENCY == 16000 else 64 +SCALE = 2 +SIZE = (N_SAMPLES * SCALE) // CHANNELS + +raw_buf = None +fb = image.Image(SIZE+(50*SCALE), SIZE, image.RGB565, copy_to_fb=True) +audio.init(channels=CHANNELS, frequency=FREQUENCY, gain_db=16) + +def audio_callback(buf): + # NOTE: do Not call any function that allocates memory. + global raw_buf + if (raw_buf == None): + raw_buf = buf + +# Start audio streaming +audio.start_streaming(audio_callback) + +def draw_fft(img, fft_buf): + fft_buf = (fft_buf / max(fft_buf)) * SIZE + fft_buf = np.log10(fft_buf + 1) * 20 + color = (0xFF, 0x0F, 0x00) + for i in range(0, len(fft_buf)): + img.draw_line(i*SCALE, SIZE, i*SCALE, SIZE-int(fft_buf[i]) * SCALE, color, SCALE) + +def draw_audio_bar(img, level, offset): + blk_size = (SIZE//10) + color = (0xFF, 0x00, 0xF0) + blk_space = (blk_size//4) + for i in range(0, int(round(level/10))): + fb.draw_rectangle(SIZE+offset, SIZE - ((i+1)*blk_size) + blk_space, 20 * SCALE, blk_size - blk_space, color, 1, True) + +while (True): + if (raw_buf != None): + pcm_buf = np.frombuffer(raw_buf, dtype=np.int16) + raw_buf = None + + if CHANNELS == 1: + fft_buf = sp.signal.spectrogram(pcm_buf) + l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) + else: + fft_buf = sp.signal.spectrogram(pcm_buf[0::2]) + l_lvl = int((np.mean(abs(pcm_buf[1::2])) / 32768)*100) + r_lvl = int((np.mean(abs(pcm_buf[0::2])) / 32768)*100) + + fb.clear() + draw_fft(fb, fft_buf) + draw_audio_bar(fb, l_lvl, 0) + draw_audio_bar(fb, l_lvl, 25*SCALE) + if CHANNELS == 2: + draw_audio_bar(fb, r_lvl, 25 * SCALE) + fb.flush() + +# Stop streaming +audio.stop_streaming() +``` + +## IMU (LSM6DSOX) + +The Nano RP2040 Connect has a built-in inertial measure unit (IMU). With the following script, you can retrieve the accelerometer and gyroscope data and print it in the REPL. + +```python +import time +from lsm6dsox import LSM6DSOX +from machine import Pin, I2C + +# Initialize the LSM6DSOX sensor with I2C interface +lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12))) + +while True: + # Read accelerometer values + accel_values = lsm.accel() + print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*accel_values)) + + # Read gyroscope values + gyro_values = lsm.gyro() + print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*gyro_values)) + + print("") + time.sleep_ms(100) +``` + +## Communication + +The Nano RP2040 Connect supports **I2C**, **UART** and **SPI**. Below you will find examples on how to use them. + +### I2C + +The I2C bus on the Nano RP2040 Connect is available through the **A4/A5** pins. Below is an example for how to use it: + +```python +from machine import Pin, I2C + +# Initialize I2C with SCL on A5 and SDA on A4 +i2c = I2C(0, scl=Pin(5), sda=Pin(4)) +devices = i2c.scan() + +print("I2C devices found:", devices) +``` + +***Read more about I2C in [this article](/micropython/communication/i2c).*** + +### UART + +The Nano RP2040 Connect supports **UART** through the **D0/D1** pins. Below is an example for how to use it: + +```python +from machine import UART + +# Initialize UART on pins 16 (TX) and 17 (RX) +uart = UART(1, baudrate=9600, tx=16, rx=17) + +# Send and receive data +uart.write("Hello from Nano ESP32!") +data = uart.read() +print("Received:", data) +``` + +### SPI + +The Nano RP2040 Connect supports **SPI** through the following pins: +- **(CIPO)** - D12 +- **(COPI)** - D11 +- **(SCK)** - D13 +- **(CS)** - Any GPIO (except for A6/A7) + +Below is an example for how to use it: + +```python +from machine import Pin, SPI + +# Initialize SPI with SCK on pin 18, MOSI on pin 23, and MISO on pin 19 +spi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) + +print("SPI initialized") +``` \ No newline at end of file diff --git a/content/micropython/04.board-examples/portenta-c33/portenta-c33.md b/content/micropython/04.board-examples/portenta-c33/portenta-c33.md new file mode 100644 index 0000000000..4c9a21e329 --- /dev/null +++ b/content/micropython/04.board-examples/portenta-c33/portenta-c33.md @@ -0,0 +1,327 @@ +--- +title: 'Portenta C33' +description: 'Learn how to use specific features on the Portenta C33 using MicroPython' +author: 'Karl Söderby' +--- + +In this guide, you will information related only to the [Arduino® Portenta C33](https://store.arduino.cc/products/portenta-c33) and MicroPython. + +## Pinout Mapping + +The Portenta C33 has two ways its pins are physically available: through its MKR-styled connectors and its High-Density connectors. Most pins are referred to via their port name or function. In the image below, the Portenta C33 MKR-styled connectors pinout is shown. + +![Portenta C33 MKR-styled connectors pinout](assets/portenta33_MKR_pinout.png) + +The MKR-styled connectors pinout is mapped in MicroPython as follows: + +| **Arduino Pin Mapping** | **MicroPython Pin Mapping** | +|:-----------------------:|:---------------------------:| +| `P006`/`A0` | `P006` | +| `P005`/`A1` | `P005` | +| `P004`/`A2` | `P004` | +| `P002`/`A3` | `P002` | +| `P001`/`A4` | `P001` | +| `P015`/`A5` | `P015` | +| `P014`/`A6` | `P014` | +| `P105`/`D0` | `P105` | +| `P106`/`D1` | `P106` | +| `P111`/`D2` | `P111` | +| `P303`/`D3` | `P303` | +| `P401`/`D4` | `P401` | +| `P210`/`D5` | `P210` | +| `P602` | `P602` | +| `P110` | `P110` | +| `P408` | `P408` | +| `P407` | `P407` | +| `P315` | `P315` | +| `P204` | `P204` | +| `P900` | `P900` | +| `P402` | `P402` | +| `P601` | `P601` | + +The complete MicroPython pinout is available [here](https://github.com/micropython/micropython/blob/master/ports/renesas-ra/boards/ARDUINO_PORTENTA_C33/pins.csv). + +## Input/Output Pins + +The `Pin` class in the `machine` module is essential for controlling Input/Output (I/O) pins of the Portenta C33 board. These pins are crucial for a wide range of applications, including reading sensor data, controlling actuators, and interfacing with other hardware components. + +### Pin Initialization + +To begin using an I/O pin of the Portenta C33 board with MicroPython, you need to initialize it using the `Pin` class from the `machine` module. This involves specifying the pin identifier and its mode (input, output, etc.). + +```python +from machine import Pin + +# Initializing pin P107 as an output +p107 = Pin('P107', Pin.OUT) +``` + +### Configuring Pin Modes + +You can configure a pin as an input or output. For input pins, it's often useful to activate an internal pull-up or pull-down resistor. This helps to stabilize the input signal, especially in cases where the pin is reading a mechanical switch or a button. + +```python +# Configuring pin P105 as an input with its pull-up resistor enabled +p105 = Pin('P105', Pin.IN, Pin.PULL_UP) +``` + +### Reading from and Writing to Pins + +To read a digital value from a pin, use the `.value()` method without any arguments. This is particularly useful for input pins. Conversely, to write a digital value, use the `.value()` method with an argument. Passing `1` sets the pin to `HIGH`, while `0` sets it to `LOW`. This is applicable to output pins. + +```python +# Reading from P105 +pin_value = p105.value() + +# Writing to P107 +p107.value(1) # Set p2 to high +``` + +### Advanced Pin Configuration + +The Pin class allows dynamic reconfiguration of pins and setting up interrupt callbacks. This feature is essential for creating responsive and interactive applications. + +```python +# Reconfiguring P105 as an input with a pull-down resistor +p105.init(Pin.IN, Pin.PULL_DOWN) + +# Setting up an interrupt on P105 +p105.irq(lambda p: print("- IRQ triggered!", p)) +``` + +### Practical Example + +In this example, we will configure one pin as an input to read the state of a button and another pin as an output to control an LED. The LED will turn on when the button is pressed and off when it's released. + +```python +from machine import Pin +import time + +# Configure pin P107 as an output (for the LED) +led = Pin('P107', Pin.OUT_PP) + +# Configure pin P105 as input with pull-up resistor enabled (for the button) +button = Pin('P105', Pin.IN, Pin.PULL_UP) + +while True: + # Read the state of the button + button_state = button.value() + if button_state == 0: + # Turn on LED if button is pressed (button_state is LOW) + led.value(1) + else: + # Turn off LED if button is not pressed (button_state is HIGH) + led.value(0) + + # Short delay to debounce the button + time.sleep(0.1) +``` + +This practical example demonstrates controlling an LED based on a button's state. The LED, connected to pin `P107` (configured as an output), is turned on or off depending on the button's input read from pin `P105` (set as an input with a pull-up resistor). The main loop continually checks the button's state; pressing the button fixes the LED on while releasing it turns the LED off. A brief delay is included for debouncing, ensuring stable operation without false triggers from the button. + +## Analog to Digital Converter + +The `ADC` class in MicroPython provides an interface for the Analog-to-Digital (ADC) converter of the Portenta C33 board, enabling the measurement of continuous voltages and their conversion into discrete digital values. This functionality is crucial for applications that, for example, require reading from analog sensors. The `ADC` class represents a single endpoint for sampling voltage from an analog pin and converting it to a digital value. + +The available ADC pins of the Portenta C33 board in MicroPython are the following: + +| **Available ADC Pins** | +|:----------------------:| +| `P006` | +| `P005` | +| `P004` | +| `P002` | +| `P001` | +| `P015` | +| `P014` | +| `P000` | + +### Initializing the ADC + +First, to use an ADC of the Portenta C33 board, create an ADC object associated with a specific pin. This pin will be used to read analog values. + +```python +from machine import ADC + +# Create an ADC object on a specific pin +adc = ADC(pin) +``` + +### Reading Analog Values + +You can read analog values as raw values using the `read_u16()` method. This method returns a raw integer from 0-65535, representing the analog reading. + +```python +# Reading a raw analog value +val = adc.read_u16() +``` + +### Practical Example + +This example demonstrates the use of the `ADC` class to read values from a potentiometer on the Portenta C33 board. First, connect your potentiometer to the Portenta C33 board. One outer pin goes to `GND`, the other to `3V3`, and the middle pin to an analog-capable I/O pin, such as `P006`. This setup creates a variable voltage divider, with the voltage at the center pin changing as you adjust the potentiometer. + +```python +from machine import ADC, Pin +import time + +# Initialize the ADC on the potentiometer-connected pin +pot_pin = Pin('P006') +pot_adc = ADC(pot_pin) + +while True: + # Read the raw analog value + raw_value = pot_adc.read_u16() + print("- Potentiometer raw value:", raw_value) + + # Delay for readability + time.sleep(0.1) +``` +The example starts by importing the necessary modules and setting up the ADC on a pin connected to a potentiometer (`P006`). The ADC object (`pot_adc`) is used to interface with the potentiometer. Inside the loop, the analog value from the potentiometer is continuously read using the `read_u16()` method that provides a raw integer value scaled between `0` and `65535`, reflecting the potentiometer's position. The analog value value is printed to the console, and a short delay is included in the loop to ensure the output is readable. + +## Pulse Width Modulation + +Pulse Width Modulation (PWM) is a method to emulate an analog output using a digital pin. It does this by rapidly toggling the pin between low and high states. Two primary aspects define PWM behavior: + +- **Frequency**: This is the speed at which the pin toggles between low and high states. A higher frequency means the pin toggles faster. +- **Duty cycle**: This refers to the ratio of the high state duration to the total cycle duration. A 100% duty cycle means the pin remains high all the time, while a 0% duty cycle means it stays low. + +The available PWM pins of the Portenta C33 board in MicroPython are the following: + +| **Available PWM Pins** | +|:----------------------:| +| `P105` | +| `P106` | +| `P111` | +| `P303` | +| `P401` | +| `P601` | + +### Setting Up PWM + +To use PWM, start by initializing a pin and then creating a PWM object associated with that pin. + +```python +import machine + +# Initialize a pin for PWM (e.g., pin P105) +p105 = machine.Pin('P105') +pwm1 = machine.PWM(p105) +``` + +### Configuring PWM Parameters + +The frequency and duty cycle of the PWM signal are set based on the specific needs of your application: + +```python +# Set the frequency to 500 Hz +pwm1.freq(500) + +# Adjusting the duty cycle to 50 for 50% duty +pwm1.duty(50) +``` + +### Checking PWM Configuration + +You can check the current configuration of the PWM object by printing it: + +```python +# Will show the current frequency and duty cycle +print(pwm1) +``` + +Retrieve the frequency and duty cycle values: + +```python +current_freq = pwm1.freq() +current_duty = pwm1.duty() +``` + +### Deinitializing PWM + +When PWM is no longer needed, the pin can be deinitialized: + +```python +pwm1.deinit() +``` + +### Practical Example + +In this example, we will use PWM to control the brightness of an LED connected to pin `P105` of the Portenta C33 board. + +```python +import machine +import time + +# Configure the LED pin and PWM +led_pin = machine.Pin('P105') +led_pwm = machine.PWM(led_pin) +led_pwm.freq(500) + +# Loop to vary brightness +while True: + # Increase brightness + for duty in range(100): + led_pwm.duty(duty) + time.sleep(0.001) + + # Decrease brightness + for duty in range(100, -1, -1): + led_pwm.duty(duty) + time.sleep(0.001) +``` + +## Real-Time Clock + +The `RTC` class in MicroPython provides a way to manage and utilize the Real-Time Clock (RTC) of the Portenta C33 board. This feature is essential for applications that require accurate timekeeping, even when the main processor is not active. The RTC maintains accurate time and date, functioning independently from the main system. It continues to keep track of the time even when the board is powered off, as long as it's connected to a power source like a battery. + +### Initializing the RTC + +To use the RTC, first create an RTC object. This object is then used to set or read the current date and time. + + +```python +import machine + +# Create an RTC object +rtc = machine.RTC() +``` + +### Setting and Getting Date and Time + +The RTC allows you to set and retrieve the current date and time. The date and time are represented as an 8-tuple format. + +```python +# Setting the RTC date and time +rtc.datetime((2024, 1, 4, 4, 20, 0, 0, 0)) + +# Getting the current date and time +current_datetime = rtc.datetime() +print("- Current date and time:", current_datetime) +``` + +The 8-tuple for the date and time follows the format `(year, month, day, weekday, hours, minutes, seconds, subseconds)`. + +### Practical Example + +A practical use case for the RTC is to add timestamps to sensor data readings. By setting the current time on the RTC, you can then append an accurate timestamp each time a sensor value is logged. + +```python +import machine + +# Initialize the RTC and set the current datetime +rtc.datetime((2024, 1, 4, 4, 20, 0, 0, 0)) + +# Function to read a sensor value (placeholder) +def read_sensor(): + # Replace with actual sensor reading logic + return 42 + +# Read sensor value and get the current time +sensor_value = read_sensor() +timestamp = rtc.datetime() + +# Output the sensor value with its timestamp +print("- Sensor value at ", timestamp, ":", sensor_value) +``` + +In this example, every sensor reading is accompanied by a timestamp, which can be crucial for data analysis or logging purposes. The RTC's ability to maintain time independently of the main system's power status makes it reliable for time-sensitive applications. diff --git a/content/micropython/04.board-examples/portenta-h7/portenta-h7.md b/content/micropython/04.board-examples/portenta-h7/portenta-h7.md new file mode 100644 index 0000000000..e04343fa3b --- /dev/null +++ b/content/micropython/04.board-examples/portenta-h7/portenta-h7.md @@ -0,0 +1,563 @@ +--- +title: 'Portenta H7' +description: 'Learn how to use specific features on the Portenta H7 using MicroPython' +author: 'Karl Söderby' +--- + +![Portenta H7.](assets/portenta.png) + +In this guide, you will information related only to the [Arduino® Portenta H7](https://store.arduino.cc/en-se/products/portenta-h7) and MicroPython. + +***Note that the [Portenta H7 Lite](/hardware/portenta-h7-lite) and [Portenta H7 Lite Connected](/hardware/portenta-h7-lite-connected) boards are compatible with most examples listed here, as they are variations of the Portenta H7.*** + +### GPIO Map + +Most of the pins are referred to via their port name or their function. Please refer to the list below to see which function corresponds to which port on the Portenta H7. + +| Arduino | STM32H747 | +| ---------------- | --------- | +| PA0 | PA0 | +| PA1 | PA1 | +| PA2 | PA2 | +| PA3 | PA3 | +| PA4 | PA4 | +| PA5 | PA5 | +| PA6 | PA6 | +| PA7 | PA7 | +| PA8 | PA8 | +| PA9 | PA9 | +| PA10 | PA10 | +| PA11 | PA11 | +| PA12 | PA12 | +| PA13 | PA13 | +| PA14 | PA14 | +| PA15 | PA15 | +| PB0 | PB0 | +| PB1 | PB1 | +| PB2 | PB2 | +| PB3 | PB3 | +| PB4 | PB4 | +| PB5 | PB5 | +| PB6 | PB6 | +| PB7 | PB7 | +| PB8 | PB8 | +| PB9 | PB9 | +| PB10 | PB10 | +| PB11 | PB11 | +| PB12 | PB12 | +| PB13 | PB13 | +| PB14 | PB14 | +| PB15 | PB15 | +| PC0 | PC0 | +| PC1 | PC1 | +| PC2 | PC2 | +| PC3 | PC3 | +| PC4 | PC4 | +| PC5 | PC5 | +| PC6 | PC6 | +| PC7 | PC7 | +| PC8 | PC8 | +| PC9 | PC9 | +| PC10 | PC10 | +| PC11 | PC11 | +| PC12 | PC12 | +| PC13 | PC13 | +| PC14 | PC14 | +| PC15 | PC15 | +| PD0 | PD0 | +| PD1 | PD1 | +| PD2 | PD2 | +| PD3 | PD3 | +| PD4 | PD4 | +| PD5 | PD5 | +| PD6 | PD6 | +| PD7 | PD7 | +| PD8 | PD8 | +| PD9 | PD9 | +| PD10 | PD10 | +| PD11 | PD11 | +| PD12 | PD12 | +| PD13 | PD13 | +| PD14 | PD14 | +| PD15 | PD15 | +| PE0 | PE0 | +| PE1 | PE1 | +| PE2 | PE2 | +| PE3 | PE3 | +| PE4 | PE4 | +| PE5 | PE5 | +| PE6 | PE6 | +| PE7 | PE7 | +| PE8 | PE8 | +| PE9 | PE9 | +| PE10 | PE10 | +| PE11 | PE11 | +| PE12 | PE12 | +| PE13 | PE13 | +| PE14 | PE14 | +| PE15 | PE15 | +| PF0 | PF0 | +| PF1 | PF1 | +| PF2 | PF2 | +| PF3 | PF3 | +| PF4 | PF4 | +| PF5 | PF5 | +| PF6 | PF6 | +| PF7 | PF7 | +| PF8 | PF8 | +| PF9 | PF9 | +| PF10 | PF10 | +| PF11 | PF11 | +| PF12 | PF12 | +| PF13 | PF13 | +| PF14 | PF14 | +| PF15 | PF15 | +| PG0 | PG0 | +| PG1 | PG1 | +| PG2 | PG2 | +| PG3 | PG3 | +| PG4 | PG4 | +| PG5 | PG5 | +| PG6 | PG6 | +| PG7 | PG7 | +| PG8 | PG8 | +| PG9 | PG9 | +| PG10 | PG10 | +| PG11 | PG11 | +| PG12 | PG12 | +| PG13 | PG13 | +| PG14 | PG14 | +| PG15 | PG15 | +| PH0 | PH0 | +| PH1 | PH1 | +| PH2 | PH2 | +| PH3 | PH3 | +| PH4 | PH4 | +| PH5 | PH5 | +| PH6 | PH6 | +| PH7 | PH7 | +| PH8 | PH8 | +| PH9 | PH9 | +| PH10 | PH10 | +| PH11 | PH11 | +| PH12 | PH12 | +| PH13 | PH13 | +| PH14 | PH14 | +| PH15 | PH15 | +| PI0 | PI0 | +| PI1 | PI1 | +| PI2 | PI2 | +| PI3 | PI3 | +| PI4 | PI4 | +| PI5 | PI5 | +| PI6 | PI6 | +| PI7 | PI7 | +| PI8 | PI8 | +| PI9 | PI9 | +| PI10 | PI10 | +| PI11 | PI11 | +| PI12 | PI12 | +| PI13 | PI13 | +| PI14 | PI14 | +| PI15 | PI15 | +| PJ0 | PJ0 | +| PJ1 | PJ1 | +| PJ2 | PJ2 | +| PJ3 | PJ3 | +| PJ4 | PJ4 | +| PJ5 | PJ5 | +| PJ6 | PJ6 | +| PJ7 | PJ7 | +| PJ8 | PJ8 | +| PJ9 | PJ9 | +| PJ10 | PJ10 | +| PJ11 | PJ11 | +| PJ12 | PJ12 | +| PJ13 | PJ13 | +| PJ14 | PJ14 | +| PJ15 | PJ15 | +| PK0 | PK0 | +| PK1 | PK1 | +| PK2 | PK2 | +| PK3 | PK3 | +| PK4 | PK4 | +| PK5 | PK5 | +| PK6 | PK6 | +| PK7 | PK7 | +| UART1_TX | PA9 | +| UART1_RX | PA10 | +| UART4_TX | PA0 | +| UART4_RX | PI9 | +| UART6_TX | PG14 | +| UART6_RX | PG9 | +| UART8_TX | PJ8 | +| UART8_RX | PJ9 | +| ETH_RMII_REF_CLK | PA1 | +| ETH_MDIO | PA2 | +| ETH_RMII_CRS_DV | PA7 | +| ETH_MDC | PC1 | +| ETH_RMII_RXD0 | PC4 | +| ETH_RMII_RXD1 | PC5 | +| ETH_RMII_TX_EN | PG11 | +| ETH_RMII_TXD0 | PG13 | +| ETH_RMII_TXD1 | PG12 | +| USB_HS_CLK | PA5 | +| USB_HS_STP | PC0 | +| USB_HS_NXT | PH4 | +| USB_HS_DIR | PI11 | +| USB_HS_D0 | PA3 | +| USB_HS_D1 | PB0 | +| USB_HS_D2 | PB1 | +| USB_HS_D3 | PB10 | +| USB_HS_D4 | PB11 | +| USB_HS_D5 | PB12 | +| USB_HS_D6 | PB13 | +| USB_HS_D7 | PB5 | +| USB_HS_RST | PJ4 | +| USB_DM | PA11 | +| USB_DP | PA12 | +| BOOT0 | BOOT0 | +| DAC1 | PA4 | +| DAC2 | PA5 | +| LEDR | PK5 | +| LEDG | PK6 | +| LEDB | PK7 | +| I2C1_SDA | PB7 | +| I2C1_SCL | PB6 | +| I2C3_SDA | PH8 | +| I2C3_SCL | PH7 | +| -WL_REG_ON | PJ1 | +| -WL_HOST_WAKE | PJ5 | +| -WL_SDIO_0 | PC8 | +| -WL_SDIO_1 | PC9 | +| -WL_SDIO_2 | PC10 | +| -WL_SDIO_3 | PC11 | +| -WL_SDIO_CMD | PD2 | +| -WL_SDIO_CLK | PC12 | +| -BT_RXD | PF6 | +| -BT_TXD | PA15 | +| -BT_CTS | PF9 | +| -BT_RTS | PF8 | +| -BT_REG_ON | PJ12 | +| -BT_HOST_WAKE | PJ13 | +| -BT_DEV_WAKE | PJ14 | +| -QSPI2_CS | PG6 | +| -QSPI2_CLK | PF10 | +| -QSPI2_D0 | PD11 | +| -QSPI2_D1 | PD12 | +| -QSPI2_D2 | PF7 | +| -QSPI2_D3 | PD13 | + + +### I/O Pins + +To access the I/O pins, you can use the `Pin` module from the `pyb` library. + +```python +from pyb import Pin +``` + +To reference a pin on the Portenta, you can use the `Pin()` constructor. The first argument you have to provide is the pin you want to use. The second parameter, `mode`, can be set as: `Pin.IN`, `Pin.OUT_PP`, `Pin.OUT_OD`, `Pin.AF_PP`, `Pin.AF_OD` or `Pin.ANALOG`. An explanation of the pin modes can be found [here](https://docs.openmv.io/library/pyb.Pin.html#methods). The third parameter, `pull`, represents the pull mode. It can be set to: `Pin.PULL_NONE`, `Pin.PULL_UP` or `Pin.PULL_DOWN`. E.g.: + +```python +pin0 = Pin('P0', mode, pull) +``` + +To get the logic level of a pin, call `.value()`. It will return a 0 or a 1. This corresponds to `LOW` and `HIGH` in Arduino terminology. + +```python +pin0.value() +``` + +### PWM + +To use PWM, you import the `pyb`, `time`, `Pin`, `Timer` modules. + +```python +import pyb +import time +from pyb import Pin, Timer +``` + +First you need to choose the pin you want to use PWM with. + +```python +pin1 = Pin("PC6", Pin.OUT_PP, Pin.PULL_NONE) +``` + +Create a timer for the PWM, where you set the ID and the frequency. + +```python +timer1 = Timer(3, freq=1000) +``` + +Then you need to start a PWM channel with the timer object. + +```python +channel1 = timer1.channel(1, Timer.PWM, pin=pin1, pulse_width=0) +``` + +Get or set the pulse width value on a channel. To get, pass no arguments. To set, give a value as an argument. + +```python +channel1.pulse_width(Width) +``` + +### RGB LED + +The Portenta H7 has built-in RGB that can be used as feedback for applications. Using the `pyb` library, you can easily define the different LED colors on the Portenta. + +For this you will use the `pyb` library. + +```python +import pyb +``` + +Now you can easily define the different colors of the built in LED. + +```python +redLED = pyb.LED(1) +greenLED = pyb.LED(2) +blueLED = pyb.LED(3) +``` + +And then control them in our script. + +```python +redLED.on() +redLED.off() + +greenLED.on() +greenLED.off() + +blueLED.on() +blueLED.off() +``` + +You could also set a custom intensity for our LED lights. This ranges between the values 0 (off) and 255 (full on). Below you can see an example of how to set the intensity on our different LED lights. + +```python +redLED.intensity(128) +greenLED.intensity(64) +blueLED.intensity(50) +``` + +If no argument is given in the `.intensity()` function, it will return the LED intensity. + +### Communication + +Like other Arduino® products, the Portenta H7 features dedicated pins for different protocols. + +#### SPI + +The pins used for SPI on the Portenta H7 are the following: + + +| Pin | Function | +| :---: | :------: | +| PI0 | CS | +| PC3 | COPI | +| PI1 | CK | +| PC2 | CIPO | + +You can refer to the [pinout](#gpio-map-2) above to find them on the board. + +First, you have to import the relevant module from `pyb`. + +```python +from pyb import SPI +``` + +When you initialize SPI, the only thing you need to state is the bus, which will always be `2` on the Portenta H7; this is the only available bus. The rest of the arguments are optional. But if it is needed, you can state the mode of the SPI device as either `SPI.MASTER` or `SPI.SLAVE`, you can also manually set the `baudrate` of the device. `Polarity` can be set to 0 or 1, and is the logic level the idle clock line sits at (HIGH or LOW). `Phase` can be 0 or 1 to sample data on the first (0) or second (1) clock edge. + +```python +spi = SPI(2, SPI.MASTER, baudrate=100000, polarity=0, phase=0) +``` + +Now, if you want to send data over SPI, you simply call `.send()` inside the arguments you want to send. `data` is the data to send, which could be an integer (dataInt) or a buffer object (dataBuffer). It is optional to set the `timeout`, it indicates the timeout in milliseconds to wait for the send. + +```python +dataInt = 21 +dataBuffer = bytearray(4) +spi.send(data, timeout=5000) +``` + +Similarly, if you want to receive data over SPI, you call `.recv()`. `data` indicates the number of bytes to receive, this can be an integer (dataInt) or a buffer (dataBuffer), which will be filled with received bytes. It is optional to set the `timeout`, which is the time in milliseconds to wait for the receive. + +```python +dataInt = 0 +dataBuffer = bytearray(4) +SPI.recv(data, timeout=5000) +``` + +#### I2C + +The pins used for I2C (Inter-Integrated Circuit) on the Portenta H7 are the following: + +| Pin | Function | +| :---: | :------: | +| PH8 | SDA | +| PH7 | SCL | + +You can refer to the [pinout](##gpio-map-2) above to find them on the board. + +To use the I2C, you import the relevant module. + +```python +from pyb import I2C +``` + +You can now create the I2C object. To create an I2C object you need to state the bus, this indicates what pins you will use for I2C. Giving bus a value of `3` starts I2C on the SCL and SDA pins on the Portenta H7. There are 4 I2C buses on the Portenta H7. + +```python +i2c = I2C(3) +``` + +Now that the object is created, you can initialize it. You need to decide if your device is going to be a controller (I2C.MASTER) or a reader (I2C.SLAVE). If it is a reader device, you also need to set the `address`. You can then set a baudrate if you need to. + +```python +i2c.init(I2C.MASTER, addr=address, baudrate=100000) +``` + +To receive data on the bus, you call the `.recv()` function. In the functions arguments `data` is the number of bytes to receive, it can be an integer (dataInt) or a buffer (dataBuffer), which will be filled with received bytes. `addr` is the address to receive from, this is only required in controller mode. `timeout` indicates how many milliseconds to wait for the receive. The code below shows how to receive and print your data in the OpenMV serial terminal. + +```python +dataInt = 0 +dataBuffer = bytearray(4) +receivedData = i2c.recv(data, addr=0, timeout=5000) +Print(receivedData) +``` + +To send data on the bus, you can call the `.send()` function. In the functions arguments `data` is the data to send, an integer (dataInt) or a buffer object (dataBuffer). `addr` is the address to send to, this is only required in controller mode. `timeout` indicates how many milliseconds to wait for the send. + +```python +dataInt = 412 +dataBuffer = bytearray(4) +i2c.send(data, addr=0, timeout=5000) +``` + +If you need to make sure that devices are connected to the I2C bus, you can use the `.scan()` function. It will scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. It only works when in controller mode. + +```python +i2c.scan() +``` + +#### UART + +The pins used for UART on the Portenta H7 are the following: + +| Pin | Function | +| :---: | :------: | +| PA10 | RX | +| PA9 | TX | + +You can refer to the [pinout](#gpio-map-2) above to find them on the board. + +To use the UART, you need to import the relevant module. + +```python +from pyb import UART +``` + +To create the UART object, you need to indicate the UART bus, the Portenta has 3 UART buses, but there is only on UART bus available to use with OpenMV through the boards pins. + +```python +uart = UART(1) +``` + +With the object created, you can initialize it with `init`. When initilazing, you can set the `baudrate`. `bits` is the number of bits per character (7, 8 or 9). `parity` can be set to `None`, `0` (even) or `1` (odd). `stop` is the number of stop bits, 1 or 2. `flow` sets the flow control type, can be 0, UART.RTS, UART.CTS or UART.RTS | UART.CTS. More information on this can be found [here](https://docs.openmv.io/library/pyb.UART.html#flow-control). `timeout` is the time in milliseconds to wait for writing/reading the first character. `timeout_char` is the timeout in milliseconds to wait between characters while writing or reading. `read_buf_len` is the character length of the read buffer (0 to disable). + +```python +uart.init(baudrate, bits=8, parity=None, stop=1, timeout=0, flow=0, timeout_char=0, read_buf_len=64) +``` + +To read from UART, you can call `.read()`. If `bytes` is specified then read at most that many bytes. If `bytes` is not given then the method reads as much data as possible. It returns after the timeout has elapsed. The example code below will read bytes received through uart into an array and then print it in the serial terminal. + +```python +array = bytearray(5) +uart.read(array) +print(array) +``` + +If you intend to write over UART, you can call `.write()`. The function writes `buffer` of bytes to the bus. If characters are 7 or 8 bits wide then each byte is one character. If characters are 9 bits wide then two bytes are used for each character and `buffer` must contain an even number of bytes. + +```python +uart.write(buffer) +``` + +#### Wi-Fi® + +To use Wi-Fi® you first need to import the relevant library. + +```python +import network +``` + +Then you need to define the Wi-Fi® networks SSID and put that in a variable. You must do the same for the networks password. + +```python +SSID='' +PASSWORD='' +``` + +Next, you can create a WLAN network interface object. In the argument you can enter `network.STA_IF`, which indicates that your device will be a client and connect to a Wi-Fi® access point. + +```python +wlan = network.WLAN(network.STA_IF) +``` + +To activate the network interface, you can simply call `.activate` with the argument `True`. + +```python +wlan.active(True) +``` + +Now you can decide which network to connect to. Here it is where the `SSID` and `PASSWORD` variables come in handy. + +```python +wlan.connect(SSID, PASSWORD, timeout=30000) +``` + +If you need to troubleshoot, the connection `.status()` can be used. This function will return a value that describes the connection status. It will also let you know what went wrong with the connection in case it failed. + +```python +wlan.status() +``` + +### Audio + +If you want to use audio with the Portenta H7, you first need to include the `audio` module. Another helpful module is `micro_speech`, this runs Google's TensorFlow Lite for Microcontrollers Micro Speech framework for voice recognition. + +```python +import audio, micro_speech +``` + +Next you need to initialize the audio object. In the initialization you can decide how many `channels` to use, it is possible to use either 1 or 2 channels. Frequency decides the sample frequency. Using a higher sample frequency results in a higher noise flow, meaning less effective bits per sample. By default audio samples are 8-bits with 7-bits of effective dynamic range. `gain_db` sets the microphone gain to use. `highpass` is the high pass filter cut off given the target sample frequency. + +```python +audio.init(channels=2, frequency=16000, gain_db=24, highpass=0.9883) +``` + +If you need to deinitialize the audio object, you can simply call `deint()`. + +```python +audio.deint() +``` + +To use micro_speech, you first need to create a micro_speech object. You can create this object in the variable `speech`. + +```python +speech = micro_speech.MicroSpeech() +``` + +Next you can start streaming audio into the `micro_speech` object, to do this you can call `audio.start_streaming()`. Here you can pass the `micro_speech` object as the argument, this will fill the object with audio samples. The MicroSpeech module will compute the FFT of the audio samples and keep a sliding window internally of the FFT the last 100ms or so of audio samples received as features for voice recognition. + +```python +audio.start_streaming(speech.audio_callback) +``` + +If you need to stop the audio streaming, you can call `.stop_streaming()`. + +```python +audio.stop_streaming() +``` diff --git a/content/micropython/05.modulinos/01.installation/assets/MicroPythonPackageInstallationDone.png b/content/micropython/05.modulinos/01.installation/assets/MicroPythonPackageInstallationDone.png new file mode 100644 index 0000000000..ae8645faae Binary files /dev/null and b/content/micropython/05.modulinos/01.installation/assets/MicroPythonPackageInstallationDone.png differ diff --git a/content/micropython/05.modulinos/01.installation/assets/microPythonInstaller.png b/content/micropython/05.modulinos/01.installation/assets/microPythonInstaller.png new file mode 100644 index 0000000000..35bc310d6c Binary files /dev/null and b/content/micropython/05.modulinos/01.installation/assets/microPythonInstaller.png differ diff --git a/content/micropython/05.modulinos/01.installation/assets/microPythonLabs.png b/content/micropython/05.modulinos/01.installation/assets/microPythonLabs.png new file mode 100644 index 0000000000..05234fc82d Binary files /dev/null and b/content/micropython/05.modulinos/01.installation/assets/microPythonLabs.png differ diff --git a/content/micropython/05.modulinos/01.installation/assets/microPythonLabsFiles.png b/content/micropython/05.modulinos/01.installation/assets/microPythonLabsFiles.png new file mode 100644 index 0000000000..da29c64214 Binary files /dev/null and b/content/micropython/05.modulinos/01.installation/assets/microPythonLabsFiles.png differ diff --git a/content/micropython/05.modulinos/01.installation/assets/microPythonLabsSelectPort.png b/content/micropython/05.modulinos/01.installation/assets/microPythonLabsSelectPort.png new file mode 100644 index 0000000000..0837793cce Binary files /dev/null and b/content/micropython/05.modulinos/01.installation/assets/microPythonLabsSelectPort.png differ diff --git a/content/micropython/05.modulinos/01.installation/assets/package-installed.png b/content/micropython/05.modulinos/01.installation/assets/package-installed.png new file mode 100644 index 0000000000..a24a08957c Binary files /dev/null and b/content/micropython/05.modulinos/01.installation/assets/package-installed.png differ diff --git a/content/micropython/05.modulinos/01.installation/installation.md b/content/micropython/05.modulinos/01.installation/installation.md new file mode 100644 index 0000000000..5b652ec985 --- /dev/null +++ b/content/micropython/05.modulinos/01.installation/installation.md @@ -0,0 +1,113 @@ +--- +title: 'Modulino Installation' +description: 'Get started with using the Modulinos' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Package Installation] +--- + +In this tutorial, we will go through the installation process required for programming the Arduino Modulinos with MicroPython. + +## Goals + +The goals of this tutorial are: + +- Learn how to install a MicroPython package on an Arduino board (the Modulino package). + +## Hardware & Software Needed + +We will need a MicroPython compatible board that works with the Modulinos: +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) +- [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [MicroPython Installer](https://labs.arduino.cc/en/labs/micropython-installer) +- [Modulino MicroPython package](https://github.com/arduino/arduino-modulino-mpy) + +## Install MicroPython + +To follow this tutorial, we will need to install MicroPython on our Arduino board. The easiest way is to install it using the [MicroPython Installer](https://labs.arduino.cc/en/labs/micropython-installer). + +- Open the installer. +- Connect the board to the computer. +- If it does not appear press the refresh button. +- Press "Install MicroPython". +- Wait for the installation to finish. + +![MicroPython Installer](./assets/microPythonInstaller.png) + +***More details on installing MicroPython on our board are available in the [MicroPython installation guide](/micropython/first-steps/install-guide).*** + +## Install Modulino Package + +To program Modulinos using MicroPython we must first install the Modulino package. It's where all the code, necessary to interact with the Modulinos is being stored. + +### Terminal Installation + +To install a module, we can use `mpremote`. Currently, we will need a version of Python installed on our computer. + +1. Open a terminal, and write the following line: + ```bash + pip install mpremote + ``` + This will install `mpremote`, which makes it possible to install packages on our board via our computer. +2. With `mpremote` installed, we need to run the following command to identify our board's serial port: + ```bash + mpremote connect list + ``` + + Which will give us something like this: + + ```bash + /dev/cu.usbmodem101 ecda3b60a4dccb3f 2341:056b Arduino Nano ESP32 + ``` + The port here is `/dev/cu.usbmodem101`. Copy this. + +1. Now, run the following the command. Make sure to replace `` with the port of our device obtained in the previous step. + ```bash + mpremote connect mip install github:arduino/arduino-modulino-mpy + ``` + + Upon completion, we should see something like this in the terminal, to verify the success of the installation: + ![Successful installation.](assets/package-installed.png) + +2. Great job. We have now installed the Modulino package on our board! + +**Troubleshooting:** +- Make sure your board is connected to your computer. +- Make sure it is **not** connected in the Arduino Lab for MicroPython, as this might disturb the connection. +- If you are unable to run `mpremote` in the terminal, this means it is not installed. +- If you are unable to run `python` in the terminal, make sure you have installed Python (you can download and install it [here](https://www.python.org/downloads/)) +- If you have installed Python and it is still not working, try running `python3` and `pip3` instead. +- If you installed Python while having the terminal open, try closing the terminal and re-opening it. +- If you run `mpremote` and there's no board appearing in the list, try re-installing the firmware on your board as it might have failed during installation. + +## MicroPython Labs + +We can now verify that everything was installed correctly. Go to [MicroPython Labs](https://lab-micropython.arduino.cc/) and click on the connect icon in the top left corner. + +![MicroPython Labs](./assets/microPythonLabs.png) + +Select the board and press select "connect". We should now be connected to our Arduino board. + +***If we experience any issues, try disconnecting and connecting the board again and reinstall MicroPython using the [MicroPython Installer](https://labs.arduino.cc/en/labs/micropython-installer).*** + +To verify that the Modulino package has been installed correctly, click on the file icon in the top bar of the Labs editor. + +We should see a folder called `lib` and a file called `boot.py`. Go ahead and press on the `lib` folder and we should see several files and a folder called `modulino`. + +![MicroPython Lab Files](./assets/microPythonLabsFiles.png) + +If we see this, it means the package has been installed successfully. + +## Next Steps + +Now that we have successfully installed everything it's time to program our first Modulino. Below are links to the documentation for all Modulinos. They are also accessible in the side menu at [Arduino Docs - MicroPython](https://docs.arduino.cc/micropython/), under "Modulinos". + +- [Modulino Distance](/micropython/modulinos/modulino-distance) +- [Modulino Pixels](/micropython/modulinos/modulino-pixels) +- [Modulino Buzzer](/micropython/modulinos/modulino-buzzer) +- [Modulino Buttons](/micropython/modulinos/modulino-buttons) +- [Modulino Knob](/micropython/modulinos/modulino-knob) +- [Modulino Movement](/micropython/modulinos/modulino-movement) +- [Modulino Thermo](/micropython/modulinos/modulino-thermo) \ No newline at end of file diff --git a/content/micropython/05.modulinos/02.modulino-distance/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/02.modulino-distance/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..222f58f283 Binary files /dev/null and b/content/micropython/05.modulinos/02.modulino-distance/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/02.modulino-distance/assets/how-it-works.gif b/content/micropython/05.modulinos/02.modulino-distance/assets/how-it-works.gif new file mode 100644 index 0000000000..0ed09b97b6 Binary files /dev/null and b/content/micropython/05.modulinos/02.modulino-distance/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/02.modulino-distance/modulino-distance.md b/content/micropython/05.modulinos/02.modulino-distance/modulino-distance.md new file mode 100644 index 0000000000..a5435f1570 --- /dev/null +++ b/content/micropython/05.modulinos/02.modulino-distance/modulino-distance.md @@ -0,0 +1,58 @@ +--- +title: 'Modulino Distance' +description: 'Get started with the Modulino Distance using MicroPython' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Time of Flight, Sensors] +--- + +In this tutorial, we will get started with the Modulino Distance, which can measure the distance to an object. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino using MicroPython +- learn how to program the Modulino Distance. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Distance](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Distance to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Distance Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoDistance +from time import sleep_ms + +distance = ModulinoDistance() + +while True: + print(f"📏 Distance: {distance.distance} cm") + sleep_ms(50) +``` + +## How it works + +The Modulino Distance is a sensor that measures the time it takes for light to travel from the module to the object and back, using a tiny laser and a light sensor. The distance sensor is also known as a Time of Flight (ToF) sensor. + +The sensor can be used for a variety of projects, including gesture triggers, obstacle detection robots and motion detection. + +***Note: For extra shipping protection, some sensors come with a small yellow plastic cover on the Modulino Distance sensor. If you notice this plastic piece still in place, please remove it to ensure more accurate readings.*** + +![REPL](./assets/how-it-works.gif) \ No newline at end of file diff --git a/content/micropython/05.modulinos/03.modulino-pixels/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/03.modulino-pixels/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..5358750973 Binary files /dev/null and b/content/micropython/05.modulinos/03.modulino-pixels/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/03.modulino-pixels/assets/how-it-works.gif b/content/micropython/05.modulinos/03.modulino-pixels/assets/how-it-works.gif new file mode 100644 index 0000000000..d7df361956 Binary files /dev/null and b/content/micropython/05.modulinos/03.modulino-pixels/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/03.modulino-pixels/modulino-pixels.md b/content/micropython/05.modulinos/03.modulino-pixels/modulino-pixels.md new file mode 100644 index 0000000000..df05bfe9f8 --- /dev/null +++ b/content/micropython/05.modulinos/03.modulino-pixels/modulino-pixels.md @@ -0,0 +1,97 @@ +--- +title: 'Modulino Pixels' +description: 'Get started with the Modulino Pixels using MicroPython' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, RGB, Pixel Strip] +--- + +In this tutorial, we will get started with the Modulino Pixels and control its RGB LEDs. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino board. +- learn how to program the Modulino Pixels. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Pixels](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Pixels to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Pixels Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoPixels, ModulinoColor +from time import sleep + +pixels = ModulinoPixels() + +for index in range(0, 8): + color_wheel_colors = [ + (255, 0, 0), + (255, 85, 0), + (255, 255, 0), + (0, 255, 0), + (0, 255, 255), + (0, 0, 255), + (255, 0, 255), + (255, 0, 0) + ] + pixels.set_rgb(index, *color_wheel_colors[index], 100) +pixels.show() +sleep(1) + +pixels.set_all_rgb(255, 0, 0, 100) +pixels.show() +sleep(1) + +pixels.set_all_color(ModulinoColor.GREEN, 100) +pixels.show() +sleep(1) + +pixels.set_all_color(ModulinoColor.BLUE, 100) +pixels.show() +sleep(1) + + +# Night Rider animation + +for j in range(0, 3): + for i in range(0, 8): + pixels.clear_all() + pixels.set_rgb(i, 255, 0, 0, 100) + pixels.show() + sleep(0.05) + + for i in range(7, -1, -1): + pixels.clear_all() + pixels.set_rgb(i, 255, 0, 0, 100) + pixels.show() + sleep(0.05) + +# Turn off all LEDs +pixels.clear_all() +pixels.show() +``` + +## How it works + +The Modulino Pixels is a series of addressable RGB LEDs. These can be controlled by setting the brightness or the color of each LED. + +![LED Animation](./assets/how-it-works.gif) \ No newline at end of file diff --git a/content/micropython/05.modulinos/04.modulino-buzzer/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/04.modulino-buzzer/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..23329e20f0 Binary files /dev/null and b/content/micropython/05.modulinos/04.modulino-buzzer/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/04.modulino-buzzer/assets/how-it-works.gif b/content/micropython/05.modulinos/04.modulino-buzzer/assets/how-it-works.gif new file mode 100644 index 0000000000..f8ecb1ef03 Binary files /dev/null and b/content/micropython/05.modulinos/04.modulino-buzzer/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/04.modulino-buzzer/modulino-buzzer.md b/content/micropython/05.modulinos/04.modulino-buzzer/modulino-buzzer.md new file mode 100644 index 0000000000..56fe8262d1 --- /dev/null +++ b/content/micropython/05.modulinos/04.modulino-buzzer/modulino-buzzer.md @@ -0,0 +1,102 @@ +--- +title: 'Modulino Buzzer' +description: 'Get started with the Modulino Buzzer using MicroPython' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Piezo, Speaker] +--- + +In this tutorial, we will get started with the Modulino Buzzer, a piezo speaker that can output sound. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino board. +- learn how to program the Modulino Buzzer. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Buzzer](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Buzzer to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Buzzer Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoBuzzer +from time import sleep + +buzzer = ModulinoBuzzer() + +# Super Mario Bros theme intro +melody = [ + (ModulinoBuzzer.NOTES["E5"], 125), + (ModulinoBuzzer.NOTES["REST"], 25), + (ModulinoBuzzer.NOTES["E5"], 125), + (ModulinoBuzzer.NOTES["REST"], 125), + (ModulinoBuzzer.NOTES["E5"], 125), + (ModulinoBuzzer.NOTES["REST"], 125), + (ModulinoBuzzer.NOTES["C5"], 125), + (ModulinoBuzzer.NOTES["E5"], 125), + (ModulinoBuzzer.NOTES["REST"], 125), + (ModulinoBuzzer.NOTES["G5"], 125), + (ModulinoBuzzer.NOTES["REST"], 375), + (ModulinoBuzzer.NOTES["G4"], 250) +] + +for note, duration in melody: + buzzer.tone(note, duration, blocking=True) + +# Wait 2 seconds before playing the next melody +sleep(2) + +# Police siren sound effect +def generate_siren(frequency_start, frequency_end, total_duration, steps, iterations): + siren = [] + mid_point = steps // 2 + duration_rise = total_duration // 2 + duration_fall = total_duration // 2 + + for _ in range(iterations): + for i in range(steps): + if i < mid_point: + # Easing in rising part + step_duration = duration_rise // mid_point + (duration_rise // mid_point * (mid_point - i) // mid_point) + frequency = int(frequency_start + (frequency_end - frequency_start) * (i / mid_point)) + else: + # Easing in falling part + step_duration = duration_fall // mid_point + (duration_fall // mid_point * (i - mid_point) // mid_point) + frequency = int(frequency_end - (frequency_end - frequency_start) * ((i - mid_point) / mid_point)) + + siren.append((frequency, step_duration)) + + return siren + +# 4 seconds up and down siren, with 200 steps and 2 iterations +siren_melody = generate_siren(440, 880, 4000, 200, 2) + +for note, duration in siren_melody: + buzzer.tone(note, duration, blocking=True) +``` + +## How it works + +The Modulino Buzzer is a tiny speaker that can output sound waves. + +The speaker is called a "piezo", which comes from piezoelectricity. When you apply voltage to the speaker with a specific frequency, you generate a specific sound. Changing the frequency will change the tone of the speaker. + +![How it works](./assets/how-it-works.gif) \ No newline at end of file diff --git a/content/micropython/05.modulinos/05.modulino-buttons/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/05.modulino-buttons/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..df5f8c1003 Binary files /dev/null and b/content/micropython/05.modulinos/05.modulino-buttons/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/05.modulino-buttons/assets/how-it-works.gif b/content/micropython/05.modulinos/05.modulino-buttons/assets/how-it-works.gif new file mode 100644 index 0000000000..7fa604c55c Binary files /dev/null and b/content/micropython/05.modulinos/05.modulino-buttons/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/05.modulino-buttons/modulino-buttons.md b/content/micropython/05.modulinos/05.modulino-buttons/modulino-buttons.md new file mode 100644 index 0000000000..74839f5294 --- /dev/null +++ b/content/micropython/05.modulinos/05.modulino-buttons/modulino-buttons.md @@ -0,0 +1,73 @@ +--- +title: 'Modulino Buttons' +description: 'Get started with the Modulino Buttons using MicroPython' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Pushbuttons, Digital Input] +--- + +In this tutorial, we will get started with the Modulino Buttons, a three-button Modulino. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino board. +- learn how to program the Modulino Buttons. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Buttons](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Buttons to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Buttons Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoButtons + +buttons = ModulinoButtons() + +buttons.on_button_a_press = lambda : print("Button A pressed") +buttons.on_button_a_long_press = lambda : print("Button A long press") +buttons.on_button_a_release = lambda : print("Button A released") + +buttons.on_button_b_press = lambda : print("Button B pressed") +buttons.on_button_b_long_press = lambda : print("Button B long press") +buttons.on_button_b_release = lambda : print("Button B released") + +buttons.on_button_c_press = lambda : print("Button C pressed") +buttons.on_button_c_long_press = lambda : print("Button C long press") +buttons.on_button_c_release = lambda : print("Button C released") + + +while True: + buttons_state_changed = buttons.update() + + if(buttons_state_changed): + led_a_status = buttons.is_pressed(0) # Turn LED A on if button A is pressed + led_b_status = buttons.is_pressed(1) # Turn LED B on if button B is pressed + led_c_status = buttons.is_pressed(2) # Turn LED C on if button C is pressed + buttons.set_led_status(led_a_status, led_b_status, led_c_status) +```` +## How it works + +The Modulino Buttons is a three-button module, each button capable of having a HIGH or LOW state. Additionally, this Modulino has 3 yellow LEDs which can also be controlled independently. + +The button is used in pretty much every electronic circuit, as it is the easiest way to switch between states! The most common example is a light switch, where a button press activates a light. + +![REPL](./assets/how-it-works.gif) \ No newline at end of file diff --git a/content/micropython/05.modulinos/06.modulino-knob/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/06.modulino-knob/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..227059ae1e Binary files /dev/null and b/content/micropython/05.modulinos/06.modulino-knob/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/06.modulino-knob/assets/how-it-works.gif b/content/micropython/05.modulinos/06.modulino-knob/assets/how-it-works.gif new file mode 100644 index 0000000000..e07fba5d7b Binary files /dev/null and b/content/micropython/05.modulinos/06.modulino-knob/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/06.modulino-knob/modulino-knob.md b/content/micropython/05.modulinos/06.modulino-knob/modulino-knob.md new file mode 100644 index 0000000000..e7b7b58eb3 --- /dev/null +++ b/content/micropython/05.modulinos/06.modulino-knob/modulino-knob.md @@ -0,0 +1,69 @@ +--- +title: 'Modulino Knob' +description: 'Get started with the Modulino Knob using MicroPython' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Rotary Encoder] +--- + +In this tutorial, we will get started with the Modulino Knob, a rotating knob with a button. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino board. +- learn how to program the Modulino Knob. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Knob](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Knob to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Knob Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoKnob +from time import sleep + +knob = ModulinoKnob() +knob.value = 5 # (Optional) Set an initial value +knob.range = (-10, 10) # (Optional) Set a value range + +knob.on_press = lambda: print("🔘 Pressed!") +knob.on_release = lambda: (knob.reset(), print("🔘 Released!")) +knob.on_rotate_clockwise = lambda steps, value: print(f"🎛️ Rotated {steps} steps clockwise! Value: {value}") +knob.on_rotate_counter_clockwise = lambda steps, value: print(f"🎛️ Rotated {steps} steps counter clockwise! Value: {value}") + +while True: + if(knob.update()): + print("👀 Knob value or state changed!") + + sleep(0.1) +```` + +## How it works + +The Modulino Knob is a rotary encoder that increases, or decreases, a number based on which direction it is rotating. + +When the knob moves into a new position, it sends a signal to the Arduino board with the new position. + +Turning it right increases the number (for example from 1 to 2). +Turning it left decreases the number (for example from 2 to 1) +Clicking it will also register a button click (HIGH on click). + +![REPL](./assets/how-it-works.gif) diff --git a/content/micropython/05.modulinos/07.modulino-movement/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/07.modulino-movement/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..69e167da90 Binary files /dev/null and b/content/micropython/05.modulinos/07.modulino-movement/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/07.modulino-movement/assets/how-it-works.gif b/content/micropython/05.modulinos/07.modulino-movement/assets/how-it-works.gif new file mode 100644 index 0000000000..4e1de64552 Binary files /dev/null and b/content/micropython/05.modulinos/07.modulino-movement/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/07.modulino-movement/modulino-movement.md b/content/micropython/05.modulinos/07.modulino-movement/modulino-movement.md new file mode 100644 index 0000000000..f6ff2a37e0 --- /dev/null +++ b/content/micropython/05.modulinos/07.modulino-movement/modulino-movement.md @@ -0,0 +1,58 @@ +--- +title: 'Modulino Movement' +description: 'Get started with using the Modulino Movement' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Movement, IMU] +--- + +In this tutorial, we will get started with the Modulino Movement, measuring acceleration and positioning. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino board. +- learn how to program the Modulino Movement. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Movement](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Movement to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Movement Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoMovement +from time import sleep_ms + +movement = ModulinoMovement() + +while True: + print("🏃 Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*movement.accelerometer)) + print("🌐 Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*movement.gyro)) + print("") + sleep_ms(100) +```` + +## How it works + +The Modulino Movement can measure acceleration, which means it measures the rate of change of velocity of an object in terms of its linear acceleration along multiple axes. + +The Modulino Movement can, in other words, detect when something moves, and how fast it moves. It is a sensitive sensor that can also measure vibration. + +![How it works](./assets/how-it-works.gif) \ No newline at end of file diff --git a/content/micropython/05.modulinos/08.modulino-thermo/assets/CIRCUIT-BREAKOUT.png b/content/micropython/05.modulinos/08.modulino-thermo/assets/CIRCUIT-BREAKOUT.png new file mode 100644 index 0000000000..9ee923f95f Binary files /dev/null and b/content/micropython/05.modulinos/08.modulino-thermo/assets/CIRCUIT-BREAKOUT.png differ diff --git a/content/micropython/05.modulinos/08.modulino-thermo/assets/how-it-works.gif b/content/micropython/05.modulinos/08.modulino-thermo/assets/how-it-works.gif new file mode 100644 index 0000000000..4d85230e5b Binary files /dev/null and b/content/micropython/05.modulinos/08.modulino-thermo/assets/how-it-works.gif differ diff --git a/content/micropython/05.modulinos/08.modulino-thermo/modulino-thermo.md b/content/micropython/05.modulinos/08.modulino-thermo/modulino-thermo.md new file mode 100644 index 0000000000..fd53da6bf8 --- /dev/null +++ b/content/micropython/05.modulinos/08.modulino-thermo/modulino-thermo.md @@ -0,0 +1,61 @@ +--- +title: 'Modulino Thermo' +description: 'Get started with the Modulino Thermo using MicroPython' +author: 'Hannes Siebeneicher, Sebastian Romero' +tags: [MicroPython, Environmental Sensor] +--- + +In this tutorial, we will get started with the Modulino Thermo, reading surrounding temperature and humidity. + +***Note that the installation of the Modulino package is not covered in this tutorial. For details on how to install this, visit the [MicroPython - Modulino Package Installation tutorial](/micropython/modulinos/installation).*** + +## Goals + +The goals of this tutorial are: + +- learn how to connect a Modulino to an Arduino board. +- learn how to program the Modulino Thermo. + +## Hardware & Software Needed + +For this tutorial, we will need the following hardware: +- [Modulino Thermo](https://store.arduino.cc/products/plug-and-make-kit) +- [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32?queryID=undefined) or [Arduino Nano RP2040 Connect](https://store.arduino.cc/en-se/products/arduino-nano-rp2040-connect) + +We will also need the following software: +- [MicroPython Labs](https://lab-micropython.arduino.cc/) +- [Modulino MicroPython Package](https://github.com/arduino/arduino-modulino-mpy) + +## Connect the Modulino + +Before we start programming, we will need to connect our Modulino Thermo to our Arduino board. For this we can follow the circuit diagram below: + +![Circuit Diagram](./assets/CIRCUIT-BREAKOUT.png) + +## Modulino Thermo Code Example + +Copy the code below and run it in Arduino MicroPython labs, while connected to our board. + +```python +from modulino import ModulinoThermo +from time import sleep + +thermo_module = ModulinoThermo() + +while True: + temperature = thermo_module.temperature + humidity = thermo_module.relative_humidity + + if temperature != None and humidity != None: + print(f"🌡️ Temperature: {temperature:.1f} °C") + print(f"💧 Humidity: {humidity:.1f} %") + print() + + sleep(2) +```` + +## How it works + +The Modulino Thermo can read both the temperature and humidity around you. This is a great component when you want to track the changes in indoor environments. + +![How it works](./assets/how-it-works.gif) \ No newline at end of file diff --git a/content/micropython/05.modulinos/modulinos.md b/content/micropython/05.modulinos/modulinos.md new file mode 100644 index 0000000000..52d2a838c0 --- /dev/null +++ b/content/micropython/05.modulinos/modulinos.md @@ -0,0 +1,3 @@ +--- +title: Modulinos +--- \ No newline at end of file diff --git a/content/micropython/06.communication/communication.md b/content/micropython/06.communication/communication.md new file mode 100644 index 0000000000..9cad20ffc7 --- /dev/null +++ b/content/micropython/06.communication/communication.md @@ -0,0 +1,4 @@ +--- +title: Communication +description: Learn how to use serial protocols with MicroPython +--- \ No newline at end of file diff --git a/content/micropython/06.communication/i2c/assets/circuitAccelerometer.png b/content/micropython/06.communication/i2c/assets/circuitAccelerometer.png new file mode 100644 index 0000000000..bfc2d6177d Binary files /dev/null and b/content/micropython/06.communication/i2c/assets/circuitAccelerometer.png differ diff --git a/content/micropython/06.communication/i2c/assets/i2c.png b/content/micropython/06.communication/i2c/assets/i2c.png new file mode 100644 index 0000000000..b61f1c5ada Binary files /dev/null and b/content/micropython/06.communication/i2c/assets/i2c.png differ diff --git a/content/micropython/06.communication/i2c/assets/repl-i2c-sensor.gif b/content/micropython/06.communication/i2c/assets/repl-i2c-sensor.gif new file mode 100644 index 0000000000..c86776baff Binary files /dev/null and b/content/micropython/06.communication/i2c/assets/repl-i2c-sensor.gif differ diff --git a/content/micropython/06.communication/i2c/i2c.md b/content/micropython/06.communication/i2c/i2c.md new file mode 100644 index 0000000000..5c68da9d12 --- /dev/null +++ b/content/micropython/06.communication/i2c/i2c.md @@ -0,0 +1,107 @@ +--- +title: Inter-Integrated Circuit (I2C) +description: Learn how to use I2C on Micropython +author: Pedro Sousa Lima +--- + +Inter-Integrated Circuit, or **I2C**, is one of the most widely used serial communication protocols, especially in the Arduino ecosystem. It enables multiple devices to communicate over just two wires, making it both efficient and versatile as you can easily add new modules more easily as the connections all happen across the same bus and standetizes them across manufacturers (and product lines). + + +## How I2C Works +I2C communication relies on two wires: +- **SDA (Serial Data):** Transfers data between devices. +- **SCL (Serial Clock):** Synchronizes data transmission. + +Each device on an I2C bus has a unique address, allowing the controller to communicate directly with a specific device. This capability makes it possible to connect up to 128 devices on the same two wires (128 is the maximum number of different addresses you can have as the address is a 7 bit value and you can only express 128 unique values using 7 bits). + +![I2C Diagram](assets/i2c.png) + +### Key Features of I2C + +1. **Two-Wire Simplicity:** Reduces hardware complexity. +2. **Address-Based Communication:** Each device has a unique address. +3. **Bidirectional Communication:** Enables data transfer in both directions. + + +## Example: Reading Sensor Data Using I2C + +In this example, we will connect an **LIS3DHTR accelerometer** to an Arduino and read its data via I2C. + +**Circuit Diagram:** +![LIS3DHTR circuit.](assets/circuitAccelerometer.png) + +**Setup Instructions:** +1. Connect the LIS3DHTR to your board as shown in the circuit diagram. +2. Install the required `lis3dh` module by running the following command: + + ```python + mip.install("https://raw.githubusercontent.com/tinypico/tinypico-micropython/master/lis3dh%20library/lis3dh.py") + ``` + +3. Copy the following code to your `main.py` file and run it. + +**Code Example:** +```python +import lis3dh, time, math +from machine import Pin, I2C + +i2c = I2C(sda=Pin(8), scl=Pin(9)) +imu = lis3dh.LIS3DH_I2C(i2c, address=0x19) + +last_convert_time = 0 +convert_interval = 100 #ms +pitch = 0 +roll = 0 + +# Convert acceleration to Pitch and Roll +def convert_accell_rotation( vec ): + x_Buff = vec[0] # x + y_Buff = vec[1] # y + z_Buff = vec[2] # z + + global last_convert_time, convert_interval, roll, pitch + + # We only want to re-process the values every 100 ms + if last_convert_time < time.ticks_ms(): + last_convert_time = time.ticks_ms() + convert_interval + + roll = math.atan2(y_Buff , z_Buff) * 57.3 + pitch = math.atan2((- x_Buff) , math.sqrt(y_Buff * y_Buff + z_Buff * z_Buff)) * 57.3 + + # Return the current values in roll and pitch + return ( roll, pitch ) + +# If we have found the LIS3DH +if imu.device_check(): + # Set range of accelerometer (can be RANGE_2_G, RANGE_4_G, RANGE_8_G or RANGE_16_G). + imu.range = lis3dh.RANGE_2_G + + # Loop forever printing values + while True: + # Read accelerometer values (in m / s ^ 2). Returns a 3-tuple of x, y, + # z axis values. Divide them by 9.806 to convert to Gs. + x, y, z = [value / lis3dh.STANDARD_GRAVITY for value in imu.acceleration] + print("x = %0.3f G, y = %0.3f G, z = %0.3f G" % (x, y, z)) + + # Convert acceleration to Pitch and Roll and print values + p, r = convert_accell_rotation( imu.acceleration ) + print("pitch = %0.2f, roll = %0.2f" % (p,r)) + + # Small delay to keep things responsive but give time for interrupt processing. + time.sleep(0.1) +``` + +**Expected Output:** +In the REPL terminal, you will see accelerometer data displayed every second. + +![Expected Output](assets/repl-i2c-sensor.gif) + +``` +x = 0.001 G, y = -0.002 G, z = 1.000 G +pitch = -0.12, roll = 0.04 +``` + +## Summary + +I2C is a highly efficient protocol that enables multiple devices to communicate on just two wires. In this example, we demonstrated how to read data from an I2C-connected sensor, opening the door to integrating even more devices into your Arduino projects. +