Nick George
all/

PlatformIO and Emacs

First published: July 16, 2017
Last updated: January 8, 2023

Setting up PlatformIO-Emacs integration

I play around with the Teensy development board a lot and I used to write code for it using the Arduino IDE. Now that I use Emacs for nearly everything else, I figured it was time to setup an environment for programming these development boards as well!

What you need

for this project, I decided to use PlatformIO. PlatformIO is an excellent python library for programming embedded devices and microcontrollers. I used it from the command line when I was writing arduino code on the raspberrypi and it worked great, so here I am setting it up for Emacs.

Setup

This is pretty much straight out of the PlatformIO-mode documentation, but I added the use-package installation and arduino-mode for editing to my emacs config

  ;; emacs-lisp
  (use-package irony-eldoc)
  (use-package irony-mode) 
  (use-package platformio-mode)
  ;; edit ino files with adruino mode. 
  (add-to-list 'auto-mode-alist '("\\.ino$" . arduino-mode)) 
  ;; Enable irony for all c++ files, and platformio-mode only
  ;; when needed (platformio.ini present in project root).
  (add-hook 'c++-mode-hook (lambda ()
                             (irony-mode)
                             (irony-eldoc)
                             (platformio-conditionally-enable)))

  ;; Use irony's completion functions.
  (add-hook 'irony-mode-hook
            (lambda ()
              (define-key irony-mode-map [remap completion-at-point]
                'irony-completion-at-point-async)

              (define-key irony-mode-map [remap complete-symbol]
                'irony-completion-at-point-async)

              (irony-cdb-autosetup-compile-options)))

Also, you need projectile so make sure that is installed as well.

Make sure you install platformIO core as well

#bash
pip install platformio

I believe that PlatformIO is currently moving from legacy Python to Python 3, but the transition is not complete yet so for the time being we have to run this off legacy python. I use virtualenvs for python development, but when I install libraries that Emacs will use I typically install system wide to avoid problems.

Useage

New projects

Now you can init a project by opening a shell, making a directory for your project and typing

#bash
platformio init --ide emacs --board teensy31

Replace teensy31 with whatever board you will be using. The board IDs are listed here. PlatformIO will create a cookiecutter-like template project for you looking like the following

|--lib/
|   |-readme.txt
|
|- platformio.ini
|
|--src/

Any libraries you make go in their own directories under lib/ and your main code goes under the src/ under the project parent directory. PlatformIO explains this with the directory tree in the readme with an example.

|--lib
|  |--Bar
|  |  |--docs
|  |  |--examples
|  |  |--src
|  |     |- Bar.c
|  |     |- Bar.h
|  |--Foo
|  |  |- Foo.c
|  |  |- Foo.h
|  |- readme.txt --> THIS FILE
|- platformio.ini
|--src
   |- main.c

Then in `src/main.c` you should use:

#include <Foo.h>
#include <Bar.h>

// rest H/C/CPP code

If you are using a Teensy31 and use cookiecutter, try my (rough) cookiecutter template, which will make automatically create the main.ino file and .projectile for Emacs integration.

Compiling and uploading

from a shell, you would type

# bash
platformio run
platformio run target upload

easy enough. In the Emacs version, you M-x platformio-build and M-x platformio-upload. Quick caveat you need to be in a git or projectile project for this to work. So the base directory has to have .git directory or a .projectile. This is included with my cookiecutter template.

Serial monitor

One of the main reasons I kept using the Arduino IDE was the excellent serial port monitoring support. Well it turns out platformIO does that too! To setup, open a shell and type

#bash
platformio device list
/dev/cu.Bluetooth-Incoming-Port
-------------------------------
Hardware ID: n/a
Description: n/a

/dev/cu.usbmodem2589921
-----------------------
Hardware ID: USB VID:PID=16C0:0483 SER=2589920 LOCATION=20-2
Description: USB Serial

As you can see platformio detects my Bluetooth port and the serial usb port that the device is connected to.

To test, I added the simple serial program as main.ino

  // C or arduino language
  void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);
  }

  void loop() {
    Serial.println("Hello platformio");
    delay(1000);
    // put your main code here, to run repeatedly:

  }

Then I monitored with

# bash
platformio device monitor
-- Miniterm on /dev/cu.usbmodem2589921  9600,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
Hello platformio
Hello platformio
Hello platformio
Hello platformio

--- exit ---

and it will then begin to monitor the port just like Arduino IDE does! For options, see the documentation.

That's it for now, I will update this as I use more features.