AboutServicesProjectsBlog
Projects
Hanging Plotter
First Steps - Pinning an idea down and checking assumptions
Post Print Iterations
ESP32 development in NixOS using VSCode
Spinning a Stepper
Android development on NixOS
Connecting an ESP32 to android with bluetooth
Using an ESP32 as a logic analyzer
Using an Arduino as a logic analyzer
Driving steppers with the RMT module
Using Nix to write rust on the esp32
Using a smooth stepper driver on the esp32 in rust
Translating an esp32+esp-idf bluetooth example to rust
Musings on packaging build system via splitting independent libraries

ESP32 development in NixOS using VSCode

3rd article in Hanging Plotter
SoftwareEmbeddedEsp32NixOS
2020-3-12

Setting up an esp32 development environment in nixos using vscode and ESP-IDF

With the basic hardware assembled the remaining tasks include:

  1. Sending code to the esp32 (blinking LED aka hello world)
  2. Wiring the stepper
  3. Spinning the stepper
  4. Powering from a battery
  5. Controlling from an app

We will be tackling step 1 in this post.

Platform setup

My desktop is dual booted with Windows 10 and NixOS (a rather neat linux distro based around a more deterministic package manager). With extensive experience writing code using Windows Subsystem for Linux I can confidently say please no more, let's use linux. Unfortunately this means I will have to reboot to switch between CAD and Code. Not the end of the world!

ESP32: via vscode

Since other development is going through VSCode I started with the Espressif IDF plugin for vscode and ended with an absolutely heinous slog through my lack of understanding about nix.

After combing through extensive attempts and documentation this post along with 10 hours of new understanding I managed to get an LED blinking.

The nix deps are composed of three files,

  • esp-idf.nix - The development sdk for esp32
  • esp32-toolchain.nix - The compiler etc to target the esp32
  • shell.nix - Setting up the development environment with the above

esp-idf.nix

{ stdenv, fetchFromGitHub, pkgs, makeWrapper }:

let
  version = "v4.1-dev";

  pypkgs = python-packages: with python-packages; [
    pyserial
    click
    cryptography
    future
    pyparsing
    pyelftools
    setuptools
  ];
  python = pkgs.python2.withPackages pypkgs;

in stdenv.mkDerivation rec {
  name = "esp-idf";

  src = fetchFromGitHub {
    owner = "espressif";
    repo = "esp-idf";
    rev  = "${version}";
    fetchSubmodules = true;
    sha256 = "0d1iqxz1jqz3rrk2c5dq33wp1v71d9190wv3bnigxlp5kcsj0j1w";
  };

  buildInputs = [
    python
  ];

  propagatedBuildInputs = [
    pkgs.cmake
    pkgs.ninja
    pkgs.gcc
    pkgs.git
    pkgs.ncurses
    pkgs.flex
    pkgs.bison
    pkgs.gperf
    pkgs.ccache
    python
  ];

  phases = [ "unpackPhase" "installPhase" "fixupPhase" ];

  installPhase = ''
    cp -r . $out
  '';

  meta = with stdenv.lib; {
    description = "ESP IDF";
    homepage = https://docs.espressif.com/projects/esp-idf/en/stable/get-started/linux-setup.html;
    license = licenses.gpl3;
  };
}

esp-toolchain.nix

{ stdenv, fetchurl, makeWrapper, buildFHSUserEnv }:

let
  fhsEnv = buildFHSUserEnv {
    name = "esp32-toolchain-env";
    targetPkgs = pkgs: with pkgs; [ zlib ];
    runScript = "";
  };
in

stdenv.mkDerivation rec {
  name = "esp32-toolchain";
  version = "2019r2";

  src = fetchurl {
    # https://github.com/espressif/esp-idf/blob/release/v4.1/tools/tools.json#L27
    url = "https://dl.espressif.com/dl/xtensa-esp32-elf-gcc8_2_0-esp-2019r2-linux-amd64.tar.gz";
    sha256 = "1pzv1r9kzizh5gi3gsbs6jg8rs1yqnmf5rbifbivz34cplfprm76";
  };

  buildInputs = [ makeWrapper ];

  phases = [ "unpackPhase" "installPhase" ];

  installPhase = ''
    cp -r . $out
    for FILE in $(ls $out/bin); do
      FILE_PATH="$out/bin/$FILE"
      if [[ -x $FILE_PATH ]]; then
        mv $FILE_PATH $FILE_PATH-unwrapped
        makeWrapper ${fhsEnv}/bin/esp32-toolchain-env $FILE_PATH --add-flags "$FILE_PATH-unwrapped"
      fi
    done
  '';

  meta = with stdenv.lib; {
    description = "ESP32 toolchain";
    homepage = https://docs.espressif.com/projects/esp-idf/en/stable/get-started/linux-setup.html;
    license = licenses.gpl3;
  };
}

shell.nix

{ pkgs ? import <nixpkgs> {} }:
let
  esp-idf = (pkgs.callPackage ./esp-idf.nix {});
  esp32-toolchain = (pkgs.callPackage ./esp32-toolchain.nix {});
in
  pkgs.mkShell {
    buildInputs = [
      esp-idf
      esp32-toolchain
    ];
    shellHook = ''
set -e

export IDF_PATH=${esp-idf}

export NIX_CFLAGS_LINK=-lncurses
export PATH=$PATH:$IDF_PATH/tools
    '';
}

github repo

After plugging in the device via USB a quick ls shows a tempting device:

ls -d /dev/tty*
...
/dev/ttyUSB0

Testing the toolchain:

cp -r $IDF_PATH/examples/getting-started/blink .
# chmod omitted
cd blink
idf.py build
sudo idf.py -p /dev/ttyUSB0 flash

And with that the esp32 is blinking. Excellent! Next step is wiring up and controlling the stepper.

PreviousNext
Featured Projects
GeneratorHandwheel Repair
Company Info
About UsContactAffiliate DisclosurePrivacy Policy
Specific Solutions LLC
Portland, OR