Getting Started with CircuitPython

MicroPython

CircuitPython is a spin-off of the well-known MicroPython. An efficient implementation of Python 3, with a small subset of the Python Stdlib, optimised for microcontrollers (Cortex-based MCU, for example).

Even thought Python 3 is a powerful language, this implementation fits in 256KB of Flash and uses around 16KB of RAM. So it is suitable for the majority of the mid-range ARM-based microcontrollers.

The main difference between MicroPython and CircuitPython, is that the latest is sponsored and maintained by Adafruit. One of the global leaders developing boards and add-ons for microcontrollers’ enthusiasts. Apart from that:

  • It’s based on MicroPython (stable) releases, and not the master branch.
  • It’s implementation is focus on Adafruit products (basically Atmel’s M0, M4 devices and ESP8266).
  • Floats and Doubles are enabled by default.
  • USB is natively supported on all boards (with capable hardware).
  • Does not support concurrency.

CircuitPython comes pre-installed on many Adafruit boards, but if it’s not present, or you have moved away from it (going to Arduino), you can always installed a CircuitPython (or MicroPython) bootloader that can be downloaded from:

Take into consideration that there are specific builds for each kind of board / CPU. Moreover, some Adafruit libraries, are not supported on MicroPython, for example the Bus Device library.

The Integrated Development Environment

CircuitPython (and MicroPython too) comes with an integrated REPL (Read-Eval-Print-Loop) that can be accessed using the built-in USB-Serial port present in all devices. But, some of this microcontrollers present a USB Drive where we can download Python (and other kind of) files, so the board can used them.

Adafruit recommends using the Mu Editor, but I find it very limited and mainly oriented to beginners when it comes to programming languages. Most of use (developers) use Visual Studio code, and more sophisticated IDEs, with features like:

  • Integrated version control (Git)
  • Autocomplete
  • Linters
  • Automatic code formatter
  • Included Markdown editor / preview for documentation

That’s why using an IDE like Visual Studio Code makes more sense when writing an advanced application. An extension for VS Code can be found on its MarketPlace. It’s compatible with CircuitPython latests stable release (5.3.x), it’s Open Source, but it has a few issues.

Visual Studio Code with CircuitPython extension demonstrating demo autocomplete feature.
Board selection in Visual Studio Code with CircuitPython extension.

Feel free to start coding with Mu if you want to start with a more stable IDE, which also was design specifically for CircuitPython.

Mu Editor (with Dark mode).
Mu Editor has different modes based on the target platform.

Libraries and Examples

Take into consideration downloading and installing Adafruit’s CircuitPython libraries, which can be fount at https://circuitpython.org/libraries. Also, it’s always a good idea to start looking at some examples in order to get familiar with it. A bundle with a lot of examples can be download from https://github.com/adafruit/Adafruit_CircuitPython_Bundle.

Keeping Circuit Python library up-to-date

CircUp is a dependency management tool for CircuitPython developed by Adafruit. It has a very simple CLI that let’s you list, install, remove and even update, any dependency needed inside your device.

Moreover, the version of each installed library is saved in a requirements.txt file in the working directory, so it’s really simple to keep dependencies organised and versiones on Git.

Installation is done using pip, either directly or using virtualenv. Python 3.5 or higher is requiered.

pip3 install --user circup
Usage: circup [OPTIONS] COMMAND [ARGS]...
  A tool to manage and update libraries on a CircuitPython device.
Options:
  --verbose  Comprehensive logging is sent to stdout.
  --version  Show the version and exit.
  --help     Show this message and exit.
Commands:
  freeze     Output details of all the modules found on the connected...
  install    Install a named module onto the device.
  list       Lists all out of date modules found on the connected...
  show       Show a list of available modules in the bundle.
  uninstall  Uninstall a named module(s) from the connected device.
  update     Update modules on the device. Use --all to automatically update
             all modules.

ESP32: Using the Internal Flash File System

ESP32 File System

The ESP32 contains a lightweight filesystem specially design for microcontrollers called Serial Peripheral Interface Flash File System. This File System, also known as SPIFFS for its initials, is implemented on top of a Flash chip connected directly to the SPI bus.

SPIFFS supports basic operations on files, like opening, close, read and write, and a very rudimentary implementation of directories. You will find that several project uses this File System in order to serve pages (and files) in a Web Server.

Requirements

First of all we need to install a few dependencies. The most important is the File System uploader tool, which can be used from the Arduino IDE, Visual Studio Code, or command line. The steps for performing this installation can be found at project repository on GitHub.

If you are using Visual Studio Code, as I do, install the following extension: ESP8266FS. From the command line:

code --install-extension vscode-esp8266fs

Do not forget to install Arduino-ESP32 Core https://github.com/espressif/arduino-esp32#installation-instructions

Project configuration

When using the Arduino IDE, just selecting the board in the Board Manager will do the job. But when using Visual Studio Code, we have to set some values on .vscode/arduino.json.

{
    "sketch": "main.ino",
    "board": "esp32:esp32:featheresp32",
    "configuration": "FlashFreq=80m,UploadSpeed=921600,DebugLevel=none,PartitionScheme=default,FlashSize=4MB,FlashMode=keep",
    "port": "/dev/tty.SLAB_USBtoUART",
    "output": "output"
}

With this configuration 1M of Flash will be used for SPIFFS and the rest (3M out of 4M) for your code.

Testing the plugin configuration

In Arduino IDE using the Data Uploader is straightforward. But on Visual Studio Code the plugin should be configured carefully in order to work. The following is my Visual Studio Code configuration (settings.json) which is quite verbose for testing purposes.

{
   ...
    "esp8266fs.espota.debug": true,
    "esp8266fs.esptool.executable": "/Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/esptool.py",
    "esp8266fs.esptool.verbosity": "vvv",
    "esp8266fs.logLevel": "debug",
    "esp8266fs.mkspiffs.executable": "/Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/mkspiffs/mkspiffs",
    "esp8266fs.preferencesPath": "/Users/kimi/Library/Arduino15",
    "esp8266fs.arduinoUserPath": "/Users/kimi/Documents/Arduino",
    "esp8266fs.spiffsImage": "./spiffs.image",
    "esptool.py.spi_connection": "SPI",
    "esptool.py.compress": "true",
    "esptool.py.verify": "false",
   ...
}
ESP32 has not been installed correctly

Testing the Data Upload can be done by List SPIFFS command. cmd + shift P and select ESP8266FS: List SPIFFS. If you get an error saying

ESP32 has not been installed correctly – see https://github.com/espressif/arduino-esp32

Take into consideration that the Path of the ESP32 Tool is generated by splitting the Board key on .vscode/arduino.json in order to get three parameters: Package, Architecture and Board (ref: https://github.com/kash4kev/vscode-esp8266fs/…/esp8266fs.js#L467).

As my board is an Adafruit HUZZAH32, and my board config is

{
   ...
   "board": "esp32:esp32:featheresp32",
   ...
}

the three key parameters will be:

{
   "package": "esp32",
   "architecture": "esp32",
   "board": "featheresp32",
}

This parameters will be used by the ESP8266FS plugin to create the path where ESP tools are installed. In my setup it will result in /Users/kimi/Documents/Arduino/hardware/esp32/esp32. But, based on the ESP32 Arduino core tutorial, my hardware definition is installed on /Users/kimi/Documents/Arduino/hardware/espressif/esp32.

My workaround to this issue was to create a symbolic link so the esp32 directory was points to espressif.

ln -s espressif esp32
Couldn’t find match for argument

Another common error is Couldn’t find match for argument when running mkspiffs, which is a tool found in the ESP32 Arduino Core SDK that handles the creation, upload and download (among other responsibilities) of images.

This issue is already reported on GitHub at https://github.com/kash4kev/vscode-esp8266fs/issues/15. The workaround as explain there, is to disable the configuration esp8266fs.mkspiffs.allFiles.

Packing information into an Image

In your project directory, next to your main Arduino file, create a directory called data. All files stored in that folder will be transfer to your ESP32 microcontroller when uploading the File System.

All our data files are not transferred one by one to the ESP32, but inside an Image. In order to create that image we should pack those files using mkspiffs. The ESP8266FS extension has a command for doing that, but be can also use the command line tool.

The benefits of using the command line tool are clear, the operation can be automated inside a script.

/<Path To Arduino>/hardware/espressif/esp32/tools/mkspiffs/mkspiffs --create /<Your Arduino Project Directory>/data --size 0x30000 --page 256 --block 4096 /<Your Arduino Project Directory>/spiffs.image

Uploading files

Remember that uploading files from your Computer will replace the files present in your ESP32.

You will also find a handy command in the Visual Studio Code extension for uploading your currently created image. But if you want to do that using the command line, the following execution will do the trick.

/<Path To Arduino>/hardware/espressif/esp32/tools/esptool/esptool -vvv -ca 0x3D0000 -cd  -cp /dev/tty.SLAB_USBtoUART -cb 921600 -cf /<Your Arduino Project Directory>/spiffs.image

Where /dev/tty.SLAB_USBtoUART is the USB Serial port where I have my ESP32 connected. The result of running this command may look like

--- Uploading SPIFFS file with esptool.py ---
Python Executable: "python"
SPIFFS Uploading Image... (/Users/kimi/Works/eaceto.dev/embedded/ESP32/P1/spiffs.image)
  [SPIFFS] Python   : python
  [SPIFFS] EspTool  : /Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/esptool.py
  [SPIFFS] address  : 0x290000
  [SPIFFS] port     : /dev/tty.SLAB_USBtoUART
  [SPIFFS] speed    : 921600
  [SPIFFS] before   : default_reset
  [SPIFFS] after    : hard_reset
  [SPIFFS] flashMode: keep
  [SPIFFS] flashFreq: 80m
  [SPIFFS] flashSize: 4MB
Running: python /Users/kimi/Documents/Arduino/hardware/espressif/esp32/tools/esptool.py --chip esp32 --baud 921600 --port /dev/tty.SLAB_USBtoUART --before default_reset --after hard_reset write_flash --flash_mode keep --flash_freq 80m --flash_size 4MB 0x290000 /Users/kimi/Works/eaceto.dev/embedded/ESP32/P1/spiffs.image
esptool.py v2.8
Serial port /dev/tty.SLAB_USBtoUART
Connecting....
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Compressed 196608 bytes to 537...
Writing at 0x00290000... (100 %)
Wrote 196608 bytes (537 compressed) at 0x00290000 in 0.0 seconds (effective 136297.5 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
ESP8266 SPIFFS interface finished.

Verifying what it’s inside an image

If you want to check which files are included in an image file, you can list them by running

<Path To Arduino>/hardware/espressif/esp32/tools/mkspiffs/mkspiffs --list --page 256 --block 4096 <Path to>/spiffs.image

Downloading an image form the ESP32 to your Computer

May be one of the most important steps when writing an image to the ESP32 is verifying that it was correctly done. For doing this you have to find how many bytes where written the uploading the image to the ESP32. This information can be found on the output of the write_flash operation. And as important as how many it is, where. This information it is also present in the same debug output.

In my previous example this two values where 196608 bytes and starting address 0x290000. So the command to execute in order to read that segment of Flash is:

<Path To Arduino>/hardware/espressif/esp32/tools/esptool.py --chip esp32 --baud 921600 --port /dev/tty.SLAB_USBtoUART read_flash  0x290000 196608 downloaded.image

Output

iFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
196608 (100 %)
196608 (100 %)
Read 196608 bytes at 0x290000 in 2.5 seconds (641.6 kbit/s)...
Hard resetting via RTS pin...

Using the command explained in Verifying what’s inside the image we can see which files are inside the image

<Path To Arduino>/hardware/esp32/esp32/tools/mkspiffs/mkspiffs --list --page 256 --block 4096 downloaded.image

Output

159 /config_test.json

Next steps…

In the following post I will show how to read a JSON file and obtain a configuration parameter that will be use to configure the WiFi network to which our ESP32 will be connected.

Stay tuned!

Rollback from MicroPython to Arduino on ESP32

Arduino logo

I hope you find MicroPython is VERY useful and perfect for you. But just in case it doesn’t, or for any reason you want to rollback to Arduino. Here is how to do it.

Requisites

ESPTool (already installed if you went from Arduino to MicroPython)

pip3 install esptool

If there is a permissions problem doing this, try to run pip3 install either by using “sudo” or “–user” flag.

Steps

The following example assumes the USB port can be found at /dev/cu.SLAB_USBtoUART, but you may find it at /dev/ttyUSB0

  1. Erase your ESP32 Flash.
$ esptool.py --port /dev/cu.SLAB_USBtoUART erase_flash
esptool.py v2.8
Serial port /dev/cu.SLAB_USBtoUART
Connecting........__
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 4.1s
Hard resetting via RTS pin...

  2. Thanks it! You can now go back to Arduino IDE and build and run programs on your ESP32 board!

Another useful ESPTool’s sub command

ESPTool let us retrieve the MAC address of the device from our host. This can be used for several things, like for example creating specific setup files. In order to read the ESP32 MAC address, run ESPTool with the subcommand “read_mac” as shown below

$ esptool.py --port /dev/cu.SLAB_USBtoUART read_mac
esptool.py v2.8
Serial port /dev/cu.SLAB_USBtoUART
Connecting........__
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:9d:24:28
Uploading stub...
Running stub...
Stub running...
MAC: 24:0a:c4:9d:24:28
Hard resetting via RTS pin...

MicroPython on an ESP32

MicroPython

Requirements

Software on the host

ESPTools and Adafruit AMPY are required. Both can be installed using pip3. The recommended version of Python on the host is Python 3.7

pip3 install esptool --upgrade
pip3 install adafruit-ampy --upgrade

Firmware for the ESP32 module

MicroPython for ESP32. The latests firmware (compatible with ESP-IDF v4.x) when writing can be found at http://micropython.org/resources/firmware/esp32-idf4-20191220-v1.12.bin

Installation

First of all erase your ESP32 completely by running the following command. Where /dev/ttyUSB0 is the Virtual COM port created by your board.

$ esptool.py --chip esp32 -p /dev/ttyUSB0 erase_flash
esptool.py v2.8
Serial port /dev/ttyUSB0
Connecting....
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 1.8s
Hard resetting via RTS pin...

Then, write the flash with the download image (esp32-idf4-20191220-v1.12.bin is this example).

$ esptool.py --chip esp32 -p /dev/ttyUSB0 write_flash -z 0x1000 esp32-idf4-20191220-v1.12.bin
esptool.py v2.8
Serial port /dev/ttyUSB0
Connecting....
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 24:0a:c4:0c:94:78
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1408512 bytes to 894711...
Wrote 1408512 bytes (894711 compressed) at 0x00001000 in 78.9 seconds (effective 142.9 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...

Testing

After successfully flashing your ESP32 module, connect it to a Serial Monitor at 115200 baud. I like to use the embedded serial monitor that Arduino IDE has.

Perform a hard reset and you should see a console output like the one below:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
Falling back to built-in command interpreter.
OK
>ets Jun  8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4988
load:0x40078000,len:10404
load:0x40080400,len:5680
entry 0x400806bc
 [0;32mI (519) cpu_start: Pro cpu up. [0m
 [0;32mI (519) cpu_start: Application information: [0m
 [0;32mI (519) cpu_start: Compile time:     Dec 20 2019 07:56:38 [0m
 [0;32mI (523) cpu_start: ELF file SHA256:  0000000000000000... [0m
 [0;32mI (529) cpu_start: ESP-IDF:          v4.0-beta1 [0m
 [0;32mI (534) cpu_start: Starting app cpu, entry point is 0x40083014 [0m
 [0;32mI (0) cpu_start: App cpu up. [0m
 [0;32mI (544) heap_init: Initializing. RAM available for dynamic allocation: [0m
 [0;32mI (551) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM [0m
 [0;32mI (557) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM [0m
 [0;32mI (563) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM [0m
 [0;32mI (569) heap_init: At 3FFBDB5C len 00000004 (0 KiB): DRAM [0m
 [0;32mI (575) heap_init: At 3FFCC8A0 len 00013760 (77 KiB): DRAM [0m
 [0;32mI (582) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM [0m
 [0;32mI (588) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM [0m
 [0;32mI (594) heap_init: At 40099FB8 len 00006048 (24 KiB): IRAM [0m
 [0;32mI (601) cpu_start: Pro cpu start user code [0m
 [0;32mI (619) spi_flash: detected chip: generic [0m
 [0;32mI (619) spi_flash: flash io: dio [0m
 [0;32mI (620) cpu_start: Chip Revision: 1 [0m
 [0;33mW (621) cpu_start: Chip revision is higher than the one configured in menuconfig. Suggest to upgrade it. [0m
 [0;32mI (632) cpu_start: Starting scheduler on PRO CPU. [0m
 [0;32mI (0) cpu_start: Starting scheduler on APP CPU. [0m
MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32
Type "help()" for more information.
>>> 

Integrated Development Environment

Any Python IDE may be useful for programming in MicroPython (or CircuitPython if you are using an Adafruit compatible board). I personally recommend using Mu (https://codewith.mu/). Mu is programmed in Python, so it works on Windows, Linux and macOS. It also has a portable (pen drive friendly version) which it makes it ideal for students that uses university computers.

Select ESP MicroPython. This preference can be changed later.

Testing the module can be done using the Python REPL that be have already flashed. For example, importing the machine package can give us access to getting and settings properties of our board. For example, the Huzzah32 (ESP32) board runs at 240MHz, but when flashing MicroPython the clock is set at 160Mhz. That can be check running:

MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32
Type "help()" for more information.
>>> import machine
>>> machine.freq()
160000000
>>> 

Increasing the CPU frequency back to 240MHz can be done calling the same function as shown below:

>>> machine.freq(240000000)    # set frequency back to 240MHz
I (1604452) pm_esp32: Frequency switching config: CPU_MAX: 240, APB_MAX: 240, APB_MIN: 240, Light sleep: DISABLED
>>> machine.freq()
240000000
>>> 

Setting up ESP32 development environment in Linux (with Arduino IDE)

Arduino logo

Installing the IDE

Arduino logo

Download Arduino IDE from https://www.arduino.cc/en/Main/Software. The latest version when writing this a article is 1.8.12 (https://www.arduino.cc/download_handler.php?f=/arduino-1.8.12-linux64.tar.xz).

Extract the content of the tar.xz file where you want to have your Arduino IDE, and then, execute install.sh. If there is an error, like:

$ ./install.sh
Adding desktop shortcut, menu item and file associations for Arduino IDE...
ln: failed to create symbolic link '/usr/local/bin/arduino': Permission denied
Adding s

try to re run the script as root

$ sudo ./install.sh 

Installing the USB drivers

There are mainly two types of USB chips that may be used as Serial to USB converters, one from FTDI and the other one from SiLabs. In order to find out which chip your ESP32 board has, disconnect the board from your PC and run lsusb.

$ lsusb
Bus 002 Device 002: ID 0bda:0411 Realtek Semiconductor Corp. 4-Port USB 3.0 Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 046d:c534 Logitech, Inc. Unifying Receiver
Bus 001 Device 010: ID 0bda:5411 Realtek Semiconductor Corp. 4-Port USB 2.0 Hub
Bus 001 Device 004: ID 8087:0aaa Intel Corp.
Bus 001 Device 003: ID 048d:8297 Integrated Technology Express, Inc. ITE Device(8595)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Then, connect the board and repeat the command.

$ lsusb
Bus 002 Device 002: ID 0bda:0411 Realtek Semiconductor Corp. 4-Port USB 3.0 Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 046d:c534 Logitech, Inc. Unifying Receiver
Bus 001 Device 012: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP2102/CP2109 UART Bridge Controller [CP210x family]
Bus 001 Device 010: ID 0bda:5411 Realtek Semiconductor Corp. 4-Port USB 2.0 Hub
Bus 001 Device 004: ID 8087:0aaa Intel Corp.
Bus 001 Device 003: ID 048d:8297 Integrated Technology Express, Inc. ITE Device(8595)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

The new device, in this case a CP210x (Cygnal Integrated CP2102 / CP2109 UART Bridge Controller [CP210x family], is your ESP32 board.

Bus 001 Device 012: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP2102/CP2109 UART Bridge Controller [CP210x family]

Install USB driver for your board.

Adding ESP32 Boards to Arduino IDE

Arduino IDE does not support ESP32 boards (and many other 3rd party boards) by default. But adding an additional board to Arduino IDE, in this case, an ESP32 board is as easy as:

  • Start Arduino IDE and open Preferences window
  • In Additional Board Manager URLs, add the following link:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  • You can add several board definitions, separating URLs with comma
  • Open Boards Manager from Tools; Boards; and install the ESP32 platform.
  • After installation, select your ESP32 board from Tools; Board menu.

UC3B @ High Speed

From time to time I forget how to set the UC3B CPU to run at full speed. The EVK1101 comes with a 12MHz crystal, and I use the same crystal for my board because it is a nice number that let me easily reach the 48Mhz needed for driving the USB port correctly. So I will not change it, but I will try to get the most of the CPU.
The UC3B comes with the following oscilators:

  • 2 PLL [80MHz – 240MHz]
  • Crystal Osc. [0.4MHz – 20MHz] (but I will let it fixed at 12MHz)
  • Crystal Osc. [32KHz] (The RTC clock)
  • RC Osc. [115KHz] (May be useful for low power consumption apps, but not this case.)

The Power Management unit handles all clock generators. A close look at the part of the unit responsible for driving CPU, HSB, PBA and PBB clocks is shown here:

So if we want to run our UC3B as fast as cars do in “The Fast & The Furious” (but without Nitro), we have to use PLL. The rules for setting PLL propertly are:

  1. Crystal must be between 0.4MHz and 16MHz
  2. PLL multiplication factor goes from 3 to 15
  3. PLL frequency must go from 80MHz to 240MHz

PLL output frecuency is the result of  ((Crystal frequency/ OSC_DIVIDE) *  PLL_MUL_FACTOR). As the datasheet states the maximum frequency for the UC3B is 60MHz. So the following should configuration can be applied in order to get 60MHz for CPU and 30MHz for PBA (USB will use PBB and PLL1 in order to get 48Mhz from the 12Mhz source)

Crystal Osc: 12MHz
PLL multiplication factor: 9
PLL divisor: 1
PLL0 = (12MHZ / 1) * (9+1) = 120MHz (and we are safe at this frequency)
PLL0 output divided by two = 1 (yes)
CPU frequency = PLL0 output /2 = 60MHz
PBA frequency = 30MHz (Pheriperial Bus A clock)

 
In order to get this configuration we have to choices. We can do it manually, or we can tell ASF (AVR Software Framework) to set the registers based on our needs.
The old way:

And the simplest way of configuring the frequency we want is by doing the following.

 
 
 
 
 
 
 
Of course, both ways do the same thing. But this lastest one, lets the ASF do the maths and the configuration for you.
It is important not to forget to set the CPU frequency for NewLib and to initialize the USB clock after setting the main clock source.
 

First contact with AVR Studio 5 (beta)

After years of being the lastest (and only) official IDE for AVR microcontrollers, Atmel decided to launch a new version of the famous AVR Studio. Of course between this AVR Studio 5 release (which is still beta) and AVR Studio 4, Atmel tried a new IDE for AVR32 based on Eclipse.
From my point of view the AVR32 Studio based on Eclipse was the best decision Atmel did. It brought something new all the developers that love and use AVR products. The fact is that having an IDE based on Eclipse (which is based on Java) let users run the IDE in several platforms and not only Windows (as AVR Studio 4 did). Moreover, Atmel delivered an AVR32 Toolchain for Windows and Linux, and the lastest one was easily ported to OS X.
The new version of AVR Studio (5) is based on…. Visual Studio! Yes… it can only runs on Windows (don’t try Wine, it’s like trying to drive a new BMW X5 with an old FIAT 600 engine, you will not go very far). But, let’s judge it by  how it works, and not how it was constructed.

As you might image when listening that it was based on Visual Studio, the ASM/C/C++ compiler is integrated with the instaler. And also the software framework, even though this last one is only available for AVR32 and the XMega series. There is no ASF for the 8bit family (yet).

Once the project is created, everything is very similar to AVR Studio 4. May be this is one of the reason why Atmel choose Visual Studio instead of Eclipse for the new IDE.

At a glance there are a few interesting things that were necessary to have. For example, you can import an AVR Studio 4 project into this new IDE.

As it happens with AVR32 Studio (based on Eclipse) you have a few predefined code snippets, and can add yours.

The project properties panel is more complete, you can choose different microcontrollers, and configure the toolchain in the same way you do it with Eclipse (for AVR32)

To sum up, AVR Studio 5 it’s a better IDE than Studio 4, it’s not perfect or portable to other platforms, but it gives me a good impression.

Software Framework comes to rescue: FAT32

Embedded applications make intense use of information these days, both for reading configurations and writing logs and process’ results. Developers tend to use built-in FLASH or small EEPROM memories to archive these tasks but as information gets complex, systems’ features grow and programming is done in high level languages, the need of a reliable and flexible solution takes more importance.
Is in this situation when embedded systems designers incorporates technologies available in personal computers, servers and mobile devices. Using mass storage devices like USB keys, USB-SATA disks and memory cards is a great solution for several problems including portability, capacity and reliability.
The Atmel’s AVR32 Software Framework incorporates low level drivers for SD/MMC cards, AT45DB memories and a USB mini Host driver capable of communicating with USB keys and disks. Moreover FAT12/16/32 is present as a high level API that can be connected to any low level driver.
Creating a file inside a directory, and writing something inside is as simple as this

For making use of these drivers and components the project must be configured with the following features:

  • Drivers
    • PM
    • SPI
    • USART
    • GPIO
    • INTC
  • Components
    • SD/MMC Memory Card
  • Services
    • FAT File System
    • Memory Control Access Services

Then it is necessary to set CONFIG/conf_access.h properly to activate the SD/MMC logic unit.

/*! name Activation of Logical Unit Numbers
*/
//! @{
#define LUN_0 DISABLE //!< On-Chip Virtual Memory.
#define LUN_1 DISABLE //!< AT45DBX Data Flash.
#define LUN_2 ENABLE //!< SD/MMC Card over SPI.
#define LUN_3 DISABLE
#define LUN_4 DISABLE
#define LUN_5 DISABLE
#define LUN_6 DISABLE
#define LUN_7 DISABLE
#define LUN_USB DISABLE //!< Host Mass-Storage Memory.
//! @}


/*! name Activation of Interface Features
*/
//! @{
#define ACCESS_USB DISABLED //!< MEM <-> USB interface.
#define ACCESS_MEM_TO_RAM ENABLED //!< MEM <-> RAM interface.
#define ACCESS_STREAM DISABLED //!< Streaming MEM <-> MEM interface.
#define ACCESS_STREAM_RECORD DISABLED //!< Streaming MEM <-> MEM interface in record mode.
#define ACCESS_MEM_TO_MEM DISABLED //!< MEM <-> MEM interface.
#define ACCESS_CODEC DISABLED //!< Codec interface.
//! @}

And then call this SPI initialization code from your main code:

/*! brief Initializes SD/MMC resources: GPIO, SPI and SD/MMC.
*/
static void sd_mmc_resources_init(void) {
// GPIO pins used for SD/MMC interface
static const gpio_map_t SD_MMC_SPI_GPIO_MAP = { { SD_MMC_SPI_SCK_PIN,
SD_MMC_SPI_SCK_FUNCTION }, // SPI Clock.
{ SD_MMC_SPI_MISO_PIN, SD_MMC_SPI_MISO_FUNCTION }, // MISO.
{ SD_MMC_SPI_MOSI_PIN, SD_MMC_SPI_MOSI_FUNCTION }, // MOSI.
{ SD_MMC_SPI_NPCS_PIN, SD_MMC_SPI_NPCS_FUNCTION } // Chip Select NPCS.
};
// SPI options.
spi_options_t spiOptions = {
.reg = SD_MMC_SPI_NPCS,
.baudrate = SD_MMC_SPI_MASTER_SPEED, // Defined in conf_sd_mmc_spi.h.
.bits = SD_MMC_SPI_BITS, // Defined in conf_sd_mmc_spi.h.
.spck_delay = 0, .trans_delay = 0, .stay_act = 1, .spi_mode = 0,
.modfdis = 1 };
// Assign I/Os to SPI.
gpio_enable_module(SD_MMC_SPI_GPIO_MAP, sizeof(SD_MMC_SPI_GPIO_MAP)
/ sizeof(SD_MMC_SPI_GPIO_MAP[0]));
// Initialize as master.
spi_initMaster(SD_MMC_SPI, &spiOptions);
// Set SPI selection mode: variable_ps, pcs_decode, delay.
spi_selectionMode(SD_MMC_SPI, 0, 0, 0);
// Enable SPI module.
spi_enable(SD_MMC_SPI);
// Initialize SD/MMC driver with SPI clock (PBA).
sd_mmc_spi_init(spiOptions, PBA_HZ);
}

Simple 2D Graphics functions

So finally I have uploaded a first release of my 2D graphic engine for microcontrollers. Even though I would like to make it portable to several displays the code has some optimizations in order to improve rendering speed. The display used in this project is the Nokia 128×128 LCD that you can see in other projects in this page, and basically some functions write raw data to the display taking advantage of the memory layout and the fact that when you write a pixel, the pointer to the current position in LCD’s RAM moves automatically to the next one.
Last but not least, there is a beta version of this engine that includes rotations, but it needs more testing and fixing. And there is a plan for a 3D Engine, but up to now my applications doesn’t require 3D.
Geometry [Header]
Geometry [Source]
Engine 2D [Header]
Engine 2D [Source]

Blackberry's Pearl controlled with ARM7

I found really interesting a small protoboard created by Sparkfun that allows you to easily connect a Pearl (the one made famous by RIM / Blackberry devices) with a microcontroller. This time I choose the LPC2138 from NXP because I also have a complete 2D graphic engine for interfacing the LPC2138 with a Nokia 128×128 LCD with 16 bits per pixel. One issue with this device is that a small movement on the pearl is detected. And sometimes you want to move in a direction but this little ball moves in more than one direction at a time. So the big problem was designing a software able to detect the movements correctly, providing anti bouncing and a way to easily modify how many pulses of the pearl are detected as one movement.



void pearl_Task() {
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_LEFT_PIN))) && (pearl_state_left == 0)) {
        pearl_dir_left_changes++;
        pearl_state_left = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_LEFT_PIN)))
                  && (pearl_state_left == 1)) {
        pearl_dir_left_changes++;
        pearl_state_left = 0;
    }
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_RIGHT_PIN))) && (pearl_state_right == 0)) {
        pearl_dir_right_changes++;
        pearl_state_right = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_RIGHT_PIN)))
                  && (pearl_state_right == 1)) {
        pearl_dir_right_changes++;
        pearl_state_right = 0;
    }
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_DOWN_PIN))) && (pearl_state_down == 0)) {
        pearl_dir_down_changes++;
        pearl_state_down = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_DOWN_PIN)))
                  && (pearl_state_down == 1)) {
        pearl_dir_down_changes++;
        pearl_state_down = 0;
    }
    if ((!(PEARL_INPUT_PIN & (1 << PEARL_UP_PIN))) && (pearl_state_up == 0)) {
        pearl_dir_up_changes++;
        pearl_state_up = 1;
    }
    else if (((PEARL_INPUT_PIN & (1 << PEARL_UP_PIN)))
                  && (pearl_state_up == 1)) {
        pearl_dir_up_changes++;
        pearl_state_up = 0;
    }
}


This task can be perform in a main loop, or can be called by a timer when it overflows (as I do in my code). The following piece of code is an example of how to ask if a movement in a particular direction was performed.



unsigned char pearl_IsMovingLeft() {
	if (pearl_dir_left_changes >= PEARL_DIR_LEFT_LIMIT) {
		pearl_dir_left_changes = 0;
		return 1;
	}
	return 0;
}


Where if PEARL_DIR_LEFT_LIMIT is between 3 or 5 and you run the pearl task every 50mSec the movement is quite smooth.

Pearl (Blackberry’s Trackball) Driver [Header]

Pearl (Blackberry’s Trackball) Driver [Source]

Trackball schematic