Introduction
As a developer who likes the safety net of IDEs, having to connect and disconnect from device ports and pressing buttons on hardware disrupts the thinking process for me. I'd rather not have to think if files are where they belong on the tiny FLASH of the microcontroller I'm using. I do not want to think too much if my code is being git tracked well enough, all that should just work, and my main focus should be on creating decent, well documented code.
Working with Micropython on small embedded microcontrollers can be a great way to get your prototype working. For me, it's a way to dip my toes in to the software side of the robots I create. With the RP2040 from Raspberry Pi, I created a custom PCB, and then wrote a custom micropython UF2 image for that hardware to reflect my work on it. For the next part, where I write the actual code in Micropython for this microcontroller, I want the following features,
- 1. The code must be Git tracked. It will have individual libraries and sub example folders, though I don't want to track individual submodules as I will not be editing any third party libraries. For the libraries that I create on my own, I'm fine with copying them from one folder and using as the case be.
- I should have some code completion and syntax check.
- 2. Uploading the code should be simple enough, at max, it should be a few key presses, and not be the arduous process of putting the RP2040 in to boot mode or unplugging and plugging again and again shenanigans.
- 3. Not only the main code, but the libraries I use must be put in the FLASH of the RP2040 under appropriate locations.
- 4. REPL should be accessible.
To think of these requirements individually, they are not that hard to accomplish. With shell, I could achieve each. But that is not coding! For me, I do not want to think of the above requirements, I want to write code. I do not want to add files to my git repo after each save, I do not want to debug why the REPL isn't connecting. My requirements need to be satisfied by an Integrated Development Environment.
The IDE choices I have are limited, and I'll list their pros and cons below.
1.Thonny IDE The most recommended IDE to be used with Micropython and RP2040.
Pros:
- Simple and easy to use.
- Code Upload and REPL are easily accessible.
Cons:
- No Git Integration.
- Code Completion and Syntax error is lacking.
2.Visual Studio Code Excellent IDE which is otherwise my go-to for all other projects.
Pros:
- Git Integration.
- Code Completion and Python Syntax Error Checking.
- Simple and Easy too.
Cons:
- Due to recent changes, the Extension used to upload code directly from the IDE to RP2040, Pico-Go, has been taken off the MarketPlace. So code upload and REPL cannot be accessed from the IDE.
3.PyCharm The IDE which I've never used before, but has great support from the looks of it.
Pros:
- Git Integration
- Code Completion and Python Syntax Error Checking.
- Code Upload and REPL are easily accessible.
Cons:
- Not so easy to set-up the projects.
Thonny and VSCode let me down for their cons, so it was now time to check-out PyCharm. It has some hoops I had to jump through, so this documentation is a record of how I got through them. In the below sections, I'll discuss the process, issues, and how to get through them, as well as mention the shortcomings I noted otherwise which still persist with this IDE. Do note these instructions and process are for MacBook, though the specific parts are still generic enough to be replicated on Windows and Linux System if you look them up over the internet.
Project Structure
For me, I want to create a Project named NimbusRobot, with multiple example folders, each containing their own python files and library folder.
This is the example folder structure, I'll show how to create the complete one below with Git tracking.
Step 1: Installing PyCharm on Mac
This is probably the easiest step. Visit PyCharm website and download the.dmg file for your Mac. Double Click it and install the IDE in your applications folder. Done!
Step 2: Setting up the IDE for Git
tracking
1. Open the IDE, and navigate to Plugins, then search for Micropython in the Search bar. Install it. You might be asked to reload the IDE, go for it.
2. From PyCharm's main screen, select Projects and create a new project. I've made mine inside ~/Documents/PyCharmProjects/ folder as NimbusRobot
3. Inside the Project just created. We'll first initialise Git. For this, right click on Version Control, and select Create Git Repository. In the pop-up window that opens up, select the project folder you created in 2. above. For me, it's the ~/Documents/PyCharmProjects/NimbusRobot as made above. This will create the 'master' branch in your project folder. Close the Git tab for now from the "-" sign on the right.
4. Create a README.md file in your project. This can be done by right clicking on your project name and adding a new file. PyCharm will smartly ask you if you wish to include this in Git tracking, which I do, so I select Add to this. Now this file will be in Git tracking. I also created a folder named images where I'll save images to be added in this Repo and used in other markdown files. I want this folder tracked too.
5. Personally, I do not want to track the /venv/ folder. So right click on it and from under "Git", select "Add to.gitignore". PyCharm will ask you to create a.gitignore file and then tracks it too. If you check under your file structure, there will be a .idea folder, saving the settings for the PyCharm IDE. You can add this folder to your.gitignore file as well.
For now, this is it. We've set up PyCharm for Git integration. We'll keep adding and removing files from the tracking as necessary for each sub project/example we create. I'll visit this section again when we actually upload the code to our Github account.
Step 3: Set-up Project for Micropython.
We'll use the previously installed Micropython Plugin now.
1. Select Preferences from PyCharm at top right. Then, under Languages and Frameworks, click on Micropython. Enable the Micropython support and select "Raspberry Pi Pico" from Device Type. Do not close the window yet.
2. Plugin your RP2040 board via USB, (not in BOOT mode). then search for the device in your /dev/ folder. For me, it's /dev/tty.usbmodem14201. Add this to the Device Path. Then click Apply and then OK
3. The code (which we'll write in next step), is uploaded from a "Run Flash..." Command. We'll discuss that too in next step. To access the REPL, you can click on Tools, then MicroPython,MicroPython REPL. This can be a tiresome task to do over and over. So I set a shortcut for it. (Don't worry if you can't access the REPL right now, it will come after the project has been set completely.)
4. To set the shortcut for the REPL, select the Preferences from PyCharm. Under Keymap, search for MicroPython in right side search bar, and then right click on MicroPython REPL to Add Keyboard Shortcut. I've set mine to "Command+Shift+, " PyCharm will tell you if the shortcut you've selected is used elsewhere or not. Once done, click on okay. You'll notice clicking your set shortcut will not work now. For this, we need to set up the project.
Step 4: Creating Sub-Directory Project
1. Right click on project name and create a new sub-folder. I've named mine Example_001_LED. Inside this folder, create a file named main.py with the appropriate python code. You'll notice PyCharm will warn you of required packages. Click on the Missing Required MicroPython packages to add them.
import time
from machine import Pin
from nrpd import *
led = Pin(BLUELED_PIN, Pin.OUT)
while True:
led.toggle()
time.sleep(1)
The above code has a library named "nrpd", I added this to my custom MicroPython UF2 Image. You can remove this line and edit BLUELED_PIN to whichever pin you'd connect an LED to. If you'd like to know how I added that library to micropython from boot, check my other tutorial.
2. Right click on the Example_001_LED folder and and from the bottom, under "Mark Directory As", select "Sources Root".
3. Suppose you'd want some library to be uploaded along with your main.py file. Create a Directory named lib under the Example_001_LED folder. Then add your python file there. For this example case, I'm adding a file named test.py which saves a single value to be accessed from main.
test.py:
testValue = 42
main.py:
import time
from machine import Pin
from nrpd import *
from lib import test
led = Pin(BLUELED_PIN, Pin.OUT)
print("Hello, World! Value from test.py: {Value:}".format(Value=test.testValue))
while True:
led.toggle()
time.sleep(1)
Step 5: Uploading code to RP2040 board
1. With the RP2040 Board plugged in (not in BOOT mode), right click on the Example_001_LED folder and select Run "Flash Example_001_LED" In the Run Window that pops up, you'll see two files being uploaded once done, the LED will start blinking.
Step 6: Access REPL
From the shortcut created in Step 4
you can access the REPL Window. This will immediately halt the running program and give you access to the REPL. You can reset the board by pressing "Ctrl+D", and if done so for above code, the output of the print statement will show we do have put the test.py
Step 7: Uploading Code to Github
The best instructions for this step can be found here.
1. Click on Git on bottom left and click on Commit Local changes. In the Changes Window that opens next, make sure all the files you've tracked so far are selected for git commit. Add a comment and Commit your code.
2. Add your GitHub account as explained in the above link.
3. Click on Git on top panel and select GitHub, then ShareProjectonGitHub Add the repository name, remote origin, and a description for the project. Then click share.
4. Once you made a change in a file, click on "Commit" in right hand pane, add a comment for your changes, then commit and/or push as needed to remote branch.
There you have it. We have an IDE capable of Git tracking, Code Suggesting, Syntax Highlighting, Code Uploading and REPL access. In the next step, I mention the common pitfalls I fell in.
Common Pitfalls
The following common pitfalls should be avoided:
- When uploading the code, make sure you're executing the run command or the run command shortcut from the correct folder location. In the above code, if you execute the Run command from the location of the main.py file, only that file will be uploaded to the RP2040 FLASH, causing errors. Always run the command from the folder name, NOT the main folder name of (NimbusRobot in my case), but the one you set as "Sources Root" in
Step 4.2
above. - Each time you create a new sub-folder under the NimbusRobot folder, you'll need to change the "Sources Root" Folder to the new sub-folder.
- If you're creating an entirely new Project, Git tracking and Micropython Plugin will need to be re-enabled.
- When uploading the code, make sure the REPL has be disconnected. The shortcut for that on MacBook is "Ctrl+]" without the quotes. If not done this, the upload will either fail or hang.
- It's a good practice to remove unnecessary files from your RP2040 flash. Go under Tools, MicroPython, and "Remove all files from Micropython Device" now and then.
- If you feel the code is hung, you can enter the REPL and do a soft reboot with "Ctrl+D", and any error if caught will be shown in REPL window. Close the REPL with "Ctrl+]" and correct your code.
- If you are unsure what your Directory structure is or how much of the FLASH space is used, for now, the only nice way available is using Thonny. I know, it's not perfect, but this use case is rare if you do things right and the need to know space is rather infrequent if you have enough space on your FLASH.
What about running the code which is not main.py?
A great feature of Thonny is you can run the current script without making it main.py, which runs every time your board resets. This feature is not so simple to achieve in PyCharm from what I've found. But there is a way to do it. After uploading your file which is not named main.py, you can enter the REPL import the script with script name, which will get the code running. This is not ideal, but an acceptable shortcoming for now.
What about adding README.md to individual sub-folders?
If you try to add a README.md to the the individual sub-folders, and then upload the code to the microcontroller, the flash code will upload the markdown file as well, taking away precious space. One way to avoid this is to add README.md files as.README.md file. This lets you have the documentation without adding it to the FLASH.
Results
The above method is a one time approach to solving a number of issues, and for most part, it works flawlessly. Large codebase will benefit from this one time effort in to getting PyCharm working with your RP2040 board. I'll still mention the issues that can be improved:
1. REPL should disconnect automatically when code upload is ongoing. I think configuring the Run Command for the code flashing has some solution to it, but I've not ventured in to it.
2. Executing Current Script should be made easier somehow. If you know how to do this, please let me know.
3. There is no way to know current directory structure of the flash, the contents within, or their sizes.
4. If your code is pre-built in to Micropython as in my case with the nrpd.py file, PyCharm will not recognise its contents. This is true for other IDEs as well, so I either need to move this file back to the lib folder or find another solution.
5. Uploading code needs care so that all files are uploaded. Or else at least the ones which have been edited from their versions on the RP2040 Flash.
Conclusions
The above method shows how one can configure PyCharm to work with MicroPython and RP2040 on a MacBook. With lack of such support from other IDEs, for now, this will be my go-to approach for my Nimbus Robot Project. I hope this documentation helps the reader, and if you see some inaccuracies, redundancies, or fallacies, or if you face some issues following the procedure, do contact me and I'll do my best to help. Thanks for reading.
Comments