Monday, July 23, 2018

Espressif ESP32 Tutorial - Programming (Eclipse)

Eclipse (Photon)





The Eclipse IDE is one of the most popular desktop development environments. Being free and open source helps! It also supports most of the common programming languages through Language Server-based plugins. The current release is called Photon.

The C/C++ Development Toolkit (CDT) is a collection of Eclipse-based features that provides the capability to create, edit, navigate, build, and debug projects that use C and/or C++ as a programming language.

The CDT does not include the necessary compilers and debuggers to convert C/C++ code into executable programs and to debug those programs, but it does provide the frameworks that allow such tools to be integrated in a consistent fashion. We will be using the CDT version of Eclipse to program the ESP-32.


Installing the Eclipse IDE





The Eclipse IDE gives you a graphical integrated development environment (IDE) for writing, compiling and debugging ESP-IDF projects. It is quite a bit easier to use than the command line ESP-IDF provided by Espressif. It is also more sophisticated and better suited to larger projects than the Arduino IDE.

As Eclipse doesn't provide an ESP-32 compiler or the ability to flash the DevKit, you will need to have already installed the ESP-IDF tool chain for your operating system. If you haven't done this, refer to our earlier tutorial on the ESP-IDF.

Using ESP-IDF with Eclipse on Windows requires different configuration steps. See the Eclipse IDE on Windows guide if you are using Windows. The following is an overview of the steps for those using a Mac. This content is based on the material from the Espressif ESP-IDF Programming Guide but I have noted any areas where I had difficulty and included screenshots to make some of the explanations clearer.

1. Download the Eclipse Installer for your platform from eclipse.org.

2. Create a working directory, uncompress the download and run the installer app.

mkdir -p ~/eclipse
cd ~/eclipse
tar -xzf ~/Downloads/eclipse-inst-mac64.tar.gz 
open -a 'Eclipse Installer.app'

3. When running the Eclipse Installer, choose “Eclipse for C/C++ Development” (in the documentation you’ll see this referred to as CDT.)

4. When running the installer, you may get the following error.


Note that this is NOT referring to the Java Runtime Environment which you would update via System Preferences.


If you get the JVM error, you need to update the Java Development Kit

After that you should be rewarded with the following installation screen when you run the provided install app.



Setting up Eclipse





After the new Eclipse installation launches, follow these steps:

1. Import a New Project

Eclipse uses the Makefile capability in ESP-IDF. This means you need to start by creating an ESP-IDF project. You can use the skeleton project from github or one of the example projects in the esp-idf examples subdirectory. We will use our old mate Blink again. Refer to our previous tutorial on the ESP-IDF if you don't know how to copy an example project.

Once Eclipse is running, choose File -> Import...

In the dialog that pops up, choose “C/C++” -> “Existing Code as Makefile Project” and click Next.



On the next page, in the “Existing Code Location” field, use the directory of your IDF project. Don’t specify the path to the ESP-IDF directory itself (we will do that in Project Properties). The directory you specify should contain a file named “Makefile” (the project Makefile).



On the same page, under “Toolchain for Indexer Settings” choose “Cross GCC”. Then click Finish.

2. Project Properties



The new project will appear in the left hand Project Explorer column. Right-click the project and choose Properties from the context menu.

Click on the “Environment” properties page under “C/C++ Build”. Click “Add…” and enter name BATCH_BUILD and value 1.

Click “Add…” again, and enter name IDF_PATH. The value should be the full path where ESP-IDF is installed. If you completed our previous ESP-IDF tutorial, you shouldn't have to do this step as the path will already be updated from the .profile preferences file.



Edit the PATH environment variable. Keep the current value, and append the path to the Xtensa toolchain installed as part of IDF setup, if this is not already listed on the PATH. 

A typical path to the toolchain looks like /home/user-name/esp/xtensa-esp32-elf/bin. Note that you need to add a colon : before the appended path.

On macOS, add a PYTHONPATH environment variable and set it to:

/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages. 

This is so that the system Python, which has pyserial installed as part of the setup steps, overrides any built-in Eclipse Python. I didn't need to do this on my Mac.

Navigate to “C/C++ General” -> “Preprocessor Include Paths” property page:

Click the “Providers” tab

In the list of providers, click “CDT Cross GCC Built-in Compiler Settings”. Under “Command to get compiler specs”, replace the text ${COMMAND} at the beginning of the line with xtensa-esp32-elf-gcc. This means the full “Command to get compiler specs” should be xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}".



In the list of providers, click “CDT GCC Build Output Parser” and type xtensa-esp32-elf- at the beginning of the Compiler command pattern. This means the full Compiler command pattern should be xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)



Navigate to “C/C++ General” -> “Indexer” property page:

Uncheck “Allow heuristic resolution of includes”. When this option is enabled Eclipse sometimes fails to find correct header directories.



3. Building in Eclipse

Before your project is first built, Eclipse may show a lot of errors and warnings about undefined values. This is because some source files are automatically generated as part of the esp-idf build process. These errors and warnings will go away after you build the project.

Click OK to close the Properties dialog in Eclipse.

Outside Eclipse, open a command line prompt. Navigate to your project directory, and run make menuconfig to configure your project’s esp-idf settings. This step currently has to be run outside Eclipse.

If you try to build without running a configuration step first, esp-idf will prompt for configuration on the command line - but Eclipse is not able to deal with this, so the build will hang or fail.

Back in Eclipse, choose Project -> Build All to build your project.

TIP: If your project had already been built outside Eclipse, you may need to do a Project -> Clean before choosing Project -> Build. This is so Eclipse can see the compiler arguments for all source files. It uses these to determine the header include paths.

4. Flash from Eclipse

You can integrate the “make flash” target into your Eclipse project to flash using esptool.py from the Eclipse UI:

Right-click your project in Project Explorer (important to make sure you select the project, not a directory in the project, or Eclipse may find the wrong Makefile.)

Select Build Targets -> Create… from the context menu.
Type “flash” as the target name. Leave the other options as their defaults.



Make sure that the ESP-32 is connected and the correct serial port  has been selected using menuconfig then use Project -> Build Target -> Build (Shift+F9) to build the custom flash target, which will compile and flash the project.





Your program will be compiled and flashed to the ESP-32 and the results shown in the CDT build console.

Note that you will need to use “make menuconfig” to set the serial port and other config options for flashing. “make menuconfig” still requires the command line terminal (see the instructions for your platform on the Espressif site or refer to our ESP-IDF tutorial.)



Follow the same steps to add bootloader and partition_table targets, if necessary.

Sunday, July 22, 2018

Espressif ESP32 Tutorial - Programming (ESP-IDF)

Overview


The native software development framework for the ESP-32 is called the Espressif IoT Development Framework (ESP-IDF). If you want maximum functionality and compatibility this is what you should use. It is a bit more "hard core" than some of the other programming options but it does help you better understand what is happening under the hood.

The ESP-IDF functionality includes menu based configuration, compiling and firmware download to ESP32 boards.




What you Need


To develop applications for ESP32 you will need:
  • A PC loaded with either Windows, Linux or the Mac operating system
  • Toolchain to build the Application for ESP32
  • ESP-IDF that essentially contains the API for ESP32 and scripts to operate the Toolchain
  • A text editor to write programs (Projects) in C, e.g. Eclipse
  • The ESP32 board itself and a USB cable to connect it to the PC
The quickest way to start development with the ESP32 is by installing a prebuilt toolchain. Head over to the Espressif site and follow the provided instructions for your OS. I will outline the process for Mac.

Install Prerequisites


  • install pip:
    sudo easy_install pip
    
  • install pyserial:
    sudo pip install pyserial

Tool Chain Setup


The ESP32 toolchain for macOS is available for download from the Espressif website:
Download this file, then extract it into the ~/esp directory:
mkdir -p ~/esp
cd ~/esp
tar -xzf ~/Downloads/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz
The tool chain will be extracted into the ~/esp/xtensa-esp32-elf/directory.

To use it, you will need to update your PATH environment variable in the ~/.profile file. To make xtensa-esp32-elf available for all terminal sessions, add the following line to your ~/.profile file:
export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin
You can edit the .profile file using nano (e.g. nano ~/.profile). While you are here add the IDF_PATH environment variable to make the ESP-IDF available as well. To include the IDF_PATH  add the following line to the ~/.profile file:
export IDF_PATH=~/esp/esp-idf
Quitting Terminal will make this change effective.
Note
If you have /bin/bash set as login shell, and both the .bash_profile and .profile files exist, then update .bash_profile instead.
Run the following command to check if IDF_PATH is set:
printenv IDF_PATH
The path previously entered into the ~/.profile file (or set manually) should be printed out.
Alternatively, you may create an alias for the above command. This way you can get access the tool chain only when you need it. 

To do this, add this alternate line to your ~/.profile file:
alias get_esp32="export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin" 
Then when you need the tool chain you can just type get_esp32 on the command line and the tool chain will be added to your PATH. You can do something similar for IDF_PATH.



Get the ESP-IDF


Besides the toolchain (that contains programs to compile and build the application), you also need ESP32 specific API / libraries. They are provided by Espressif in ESP-IDF repository. To get it, open terminal, navigate to the directory you want to put ESP-IDF, and clone it using git clonecommand:
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
ESP-IDF will be downloaded into ~/esp/esp-idf.


Establish a Serial Connection


Connect the ESP32 board to the PC using the USB cable. Once again, the following are for the Mac, if you have another OS then follow the instructions on the Espressif web site.


To check the device name for the serial port of your ESP32 board, run this command:
ls /dev/cu.*

On my MacBook Pro (early 2015) running High Sierra, the port on the Duinotech ESP32 Dev Board was not recognized. If this happens, you may need to install the drivers for the USB-serial converter for this board. It uses a CP2102 IC, and the drivers are found on the Silicon Labs CP2102 website:

https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers.

After you download the correct driver version for your OS. You will need to install it. On the Mac this involves, unzipping the archive, mounting the DMG disk image and then running the Silicon Labs VCP Driver.pkg. You will need to give permission to run this driver in the Security and Privacy preference (this will pop up). You should now be able to see the port.


On my Mac, the port name was: /dev/cu.SLAB_USBtoUART



Hello World Project



We will use the getstarted/hello_world project from the
examples directory in IDF.
Copy get-started/hello_world to the ~/esp directory:
cd ~/esp
cp -r $IDF_PATH/examples/get-started/hello_world .
You can find a range of other example projects in the examples directory in ESP-IDF. There are examples for:

  • Ethernet
  • Mesh
  • Protocols
  • System
  • Bluetooth
  • Getting Started
  • Peripherals
  • Storage
  • WiFi
These example project directories can be copied in the same way as shown above.
Important
The esp-idf build system does not support spaces in paths to esp-idf or to the projects.
In Terminal, change to the hello_world directory by typing cd ~/esp/hello_world. Then start the project configuration utility using menuconfig:
cd ~/esp/hello_world
make menuconfig
All going well, the following menu will be displayed:

In the menu, navigate to:

 Serial flasher config > Default serial port 

to configure the serial port that your ESP32 is connected to. 

Enter the name that you had above (e.g. /dev/cu.SLAB_USBtoUART). Confirm selection by pressing enter, save the configuration by selecting < Save > and then exit the config application by selecting < Exit >.
Here are couple of tips on the navigation and use of menuconfig:
  • Use up & down arrow keys to navigate the menu.
  • Use Enter key to go into a submenu, Escape key to go out or to exit.
  • Type ? to see a help screen. Enter key exits the help screen.
  • Use Space key, or Y and N keys to enable (Yes) and disable (No) configuration items with checkboxes “[*]
  • Pressing ? while highlighting a configuration item displays help about that item.
  • Type / to search the configuration items.

Build and Flash


Now you can build and flash the application. Run:
make flash
This will compile the application and all the ESP-IDF components, generate bootloader, partition table, and application binaries, and flash these binaries to your ESP32 board.
esptool.py v2.0-beta2
Flashing binaries to serial port /dev/ttyUSB0 (app at offset 0x10000)...
esptool.py v2.0-beta2
Connecting........___
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Attaching SPI flash...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0220
Compressed 11616 bytes to 6695...
Wrote 11616 bytes (6695 compressed) at 0x00001000 in 0.1 seconds (effective 920.5 kbit/s)...
Hash of data verified.
Compressed 408096 bytes to 171625...
Wrote 408096 bytes (171625 compressed) at 0x00010000 in 3.9 seconds (effective 847.3 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 82...
Wrote 3072 bytes (82 compressed) at 0x00008000 in 0.0 seconds (effective 8297.4 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting...
If there are no issues, at the end of build process, you should see messages describing progress of loading process. Finally, the end module will be reset and “hello_world” application will start.

Monitor


To check if the “hello_world” application is indeed running, type make monitor. This command will launch the IDF Monitor application:
$ make monitor
MONITOR
--- idf_monitor on /dev/ttyUSB0 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57
...
Several lines on, after start up and the diagnostic log, you should see “Hello world!” printed out by the application.

To exit the monitor use shortcut Ctrl+].

Blink Project


For direct comparison with the Arduino IDE in the previous post, we will also give the Blink project a crack. The process is very similar to hello_world.

Copy get-started/blink to the ~/esp directory:
cd ~/esp
cp -r $IDF_PATH/examples/get-started/blink .
In Terminal, change to the blink directory by typing cd ~/esp/blink. Then start the project configuration utility using menuconfig:
cd ~/esp/blink
make menuconfig
As for the hello_world example above, set the default serial port to the correct value, then save and exit.

Before building and flashing the ESP32, we just need to check which LED is going to blink. If you open up blink.c in your favourite text editor, you will see the line:

#define BLINK_GPIO CONFIG_BLINK_GPIO
So you can either run "make menuconfig" to select the GPIO to blink, or just change the number here. Since I already had the file open, I changed the number and saved the file.

It is interesting to compare the code required to blink a LED in native ESP-32 C versus Arduino C. The ESP-32 version is shown below.

#define BLINK_GPIO 2

void blink_task(void *pvParameter)
{
    /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
       muxed to GPIO on reset already, but some default to other
       functions and need to be switched to GPIO. Consult the
       Technical Reference for a list of pads and their default
       functions.)
    */
    gpio_pad_select_gpio(BLINK_GPIO);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    while(1) {
        /* Blink off (output low) */
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        /* Blink on (output high) */
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void app_main()
{
    xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
}
While not being a lot harder than doing it with Arduino C++, it is certainly less readable. The standard Arduino library hides a lot of the boiler plate code. I've reproduced the standard Arduino blink code below for comparison.

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

Now you can build and flash the blink application. Run:
make flash
After a lot of scrolling on Terminal the blink binary will be flashed to your ESP-32 and the Dev Board reset. assuming you have a LED connected to pin 2, it should now be blinking.




Conclusion

So the obvious conclusion from all this is that if you want to do simple applications and you are already familiar with the Arduino IDE and language, then the Arduino IDE plus the ESP-32 extension is probably your best route.

If you want maximum functionality and compatibility, and are not afraid of a command line interface (CLI), then I would use the ESP-IDF.

Next up we look at trying to get the best of both worlds. Combining native compatibility with a GUI which includes features like code completion. This option still requires the ESP-IDF behind the scenes so installing this will get you ahead of the curve in the next tutorial.