How to create a Custom Zerynth Virtual Machine
As you probably already know, the mission of Zerynth is to speed up IoT development, enabling Python for Microcontrollers.
For this reason, the porting of the Zerynth Virtual Machine on different boards is a daily activity for us. If you take a look at the Zerynth Supported Devices page, you can see that at the moment we support more than 30 different boards! And the list is growing fast.
Anyway, one of the most asked questions by our users is:
“Can I use Zerynth with my own custom board or with a not yet officially supported board?”
Well, the answer is Yes.
Based on feedback from many users we decided it was time to allow you to create a custom Zerynth Virtual Machine for your own hardware solutions if they are based on already supported chips (at the moment this feature is available only for boards based on ESP32. We’ll enable this feature also for ARM microcontrollers very soon. Contact us for more info).
In this article, we’ll see how. Keep reading!
1. Add a Custom Zerynth Virtual Machine
Let’ say we want to enable the Olimex ESP32-EVB to be programmed in Python using Zerynth. [Note that this board is already officially supported by Zerynth, but we can use it as an example].
Basically, the customization process involves editing a template file (in YAML format) where many settings like pin mapping and onboard peripherals can be specified. All these aspects can be managed directly from Zerynth Studio. You can also use the Zerynth Toolchain if you prefer (more info here).
First of all, you have to click on the “wrench” icon on the left panel. Then you can access the drop-down menu on the right side of the panel title and choose how to create a new Virtual Machine:
- from scratch (“Add VM” option)
- by importing VM packages created by other users (“Import VM (from file)” option)
- by importing the custom VM from a Github repository (“Import VM (from Github)” option)
By selecting option 1 a popup dialog is displayed asking for some info:
- the name of the custom VM (must be at most 31 lowercase characters with at most one underscore)
- the name of the custom device hosting the custom VM (it will appear on the Device Management Widget)
- the customizable VM to use as a starting point. In this case, we used the ESP32-WROOM32, that is the MCU mounted on the Olimex ESP32-EVB.
2. Edit the YAML template
Once added, the custom VM will appear in the panel with a series of buttons (in order from left to right):
- edit button: open the YAML template file where the VM customization takes place. The standard template is heavily commented and contains all the info to successfully configure a custom VM
- compile button: before being able to use a custom VM, it must be compiled starting from the info contained in the YAML template.
- remove button: permanently deletes the custom VM. Note that custom VMs are not saved to the Zerynth servers, so be careful!
The template specifies parameters for using Zerynth with PCBs based on the ESP32 WROOM module.
By changing the settings inside the template, a custom GPIO routing, the peripheral list and many more details can be customized.
- the “pinmap” section contains the list of physical pins with their Zerynth names.
- the “pinclasses” section specifies additional functionalities for each physical pin in the “pinmap” section.
- the “peripherals” section contains the available peripherals and their details.
- the “device” section contains info for automatic device discovery. Most of the parameters have the correct values and must not be changed. Two parameters that are missing in this template are:
– vids: a list of uppercase hexadecimal numbers (not prefixed by 0x) representing the USB VID codes used for automatic discovery of the custom device
– pids: a list of uppercase hexadecimal numbers (not prefixed by 0x) representing the USB PID codes used for automatic discovery of the custom device
VIDS and PIDS can be discovered by opening the terminal, typing the command “ztc device discover” and searching your device. Note that VIDS and PIDS parameters make sense if the custom device has a usb-to-serial converter onboard linked to a serial port of the ESP-WROOM32.
Note that the ESP32 features comprehensive pin remapping functionality. This allows peripherals to be mapped onto almost any available GPIO pins. Following you can see the pin exposed on the Olimex ESP32-EVB, according to its schematic. Note that you have also to set all the pins used for on-board functionalities.
For a detailed guide of what peripheral can be assigned to what pins please read “Appendix A – ESP32 Pin Lists” of the ESP32 datasheet.
3. Compile the Custom Zerynth Virtual Machine
Now you have to compile the template file to binary form, clicking on the “Compile” button.
Once compiled, a new device type is created together with the VM in order to allow automatic discovery of the custom device for seamless integration in Zerynth Studio and other third-party IDEs.
4. Virtualize the board
The new VM will behave as a normal VM and the standard Zerynth flow of device registration, VM creation and virtualization will be available.
5. Export the Custom Zerynth Virtual Machine
Once compiled you can also export the VM in order to share it with your team. You can do it in 2 ways:
- clicking on “export” button. It creates a package containing the custom VM details. Such package can be shared with other Zerynth users enabling them to use the custom VM.
- clicking on “Github” button. It pushes the custom VM to a Github repository. Take a look at this repo to see that one generated for the Olimes ESP32-EVB: https://github.com/lfcerf/custom-board-zerynth-olimex_esp32evb
6. Program Your Device!
That’s it, now you can program your device in Python thanks to Zerynth.
Let’s try to switch ON/OFF one of the two relays mounted on the board.
Just clone the example, set the right pin (the pin D33 in this case), uplink the code and you’re done. Enjoy!
# loop forever
digitalWrite(D33, HIGH) # turn the LED ON by setting the voltage HIGH
sleep(1000) # wait for a second
digitalWrite(D33, LOW) # turn the LED OFF by setting the voltage LOW
sleep(1000) # wait for a second