QuadratureDecoder - PIO based Encoder Library for the RP2040

Overview

QuadratureDecoder - PIO based Encoder Library for the RP2040

Test Setup with Function Generator

Overview

The QuadratureDecoder C++ class can be used to count quadrature encoder signal transitions in the background using the RP2040's PIO and DMA hardware. The features of this class include:

  • Keeping track of the quadrature encoder transitions without using any CPU cycles.
  • Samples the encoder pins at 11.36 MHz (125 MHz / 11 PIO instructions).
    • Counts falling and rising edges encountered on both of the encoder signals.
    • Maximum encoder frequency supported is therefore 11.36MHz / 4 = 2.84MHz
    • The photo above shows a function generator setup to verify that this library does function up to the 2.84MHz limit.
  • Each state machine in the PIO can be used to track an individual encoder so a single PIO can be used to track 4 encoders.

Hardware Resources Utilized

  • Most of one PIO instance is needed just for the program used by the state machines to count encoder transitions. It only leaves 4 instruction slots free.
  • 1 PIO state machine for each 2-pin quadrature encoder to be counted.
  • 1 DMA channel for each 2-pin quadrature encoder to be counted.

How it Works

PIO

; Must start at 0 so that the following jump table can be jumped into with a
; 'mov pc, isr' instruction.
.origin 0
    ; 16 element jump table based on 4-bit encoder last state and current state.
    jmp delta0      ; 00-00
    jmp minus1      ; 00-01
    jmp plus1       ; 00-10
    jmp delta0      ; 00-11
    jmp plus1       ; 01-00
    jmp delta0      ; 01-01
    jmp delta0      ; 01-10
    jmp minus1      ; 01-11
    jmp minus1      ; 10-00
    jmp delta0      ; 10-01
    jmp delta0      ; 10-10
    jmp plus1       ; 10-11
    jmp delta0      ; 11-00
    jmp plus1       ; 11-01
    jmp minus1      ; 11-10
    jmp delta0      ; 11-11

; Program actually starts here.
.wrap_target
delta0:
public start:
    mov isr, null       ; Make sure that the input shift register is cleared when table jumps to delta0.
    in y, 2             ; Upper 2-bits of address are formed from previous encoder pin readings
    mov y, pins         ; Lower 2-bits of address are formed from current encoder pin readings. Save in Y as well.
    in y, 2
    mov pc, isr         ; Jump into jump table which will then jump to delta0, minus1, or plus1 labels.
minus1:
    jmp x-- output      ; Decrement x
    jmp output
plus1:
    mov x, ~x           ; Increment x by calculating x=~(~x - 1)
    jmp x-- next2
next2:
    mov x, ~x
output:
    mov isr, x          ; Push out updated counter.
    push noblock
.wrap

X Register - 32-bit Count

The X register is used to track the current encoder count. Each time it is updated, its value is pushed out onto the state machine's RX FIFO.

Y Register - Previous 2-pin State

The Y register holds the previous 2-bit state of the encoder pins.

ISR

The input shift register is used to left shift in the previous 2-bit value of the encoder pins and the current 2-bit value of the encoder pins.

Jump Table

The 4-bit value in the ISR is used to index into the 16 element jump table at the beginning of the PIO program. Each element in the table will jump to the plus1, minus1, or delta0 label depending on whether the encoder has transitioned clockwise, counter-clockwise, or not at all.

DMA

The PIO state machine takes care of counting the encoder signal transitions and pushes out counter updates to its RX FIFO. Rather than using the CPU to constantly read out the counter updates from the FIFO, a DMA channel is used instead. It copies the latest count into the correct m_counters[] array element of the QuadratureDecoder object.

The DMA channel is configured to make 0xFFFFFFFF such transfers in the background. This does mean that it would stop working after 4,294,967,295 counter updates. To remedy that issue, the QuadratureDecoder::getCount() method will restart the DMA transfer once it has completed more than 2,147,483,648 transfers. My testing showed that this restart doesn't cause any missed encoder counts updates, even if the restart frequency is increased to once per second.

You might also like...
Quite OK Image (QOI) format encoder/decoder

This project implements encoding and decoding the "Quite OK Image" (QOI) format in the Ć programming language. Ć can be automatically translated to pu

Turing-ring is a simple Turing Machine using just a Nano, a NeoPixel ring and a rotary encoder+push-button The ring is the tape and the UI.
Turing-ring is a simple Turing Machine using just a Nano, a NeoPixel ring and a rotary encoder+push-button The ring is the tape and the UI.

Turing-ring Turing-ring is a simple Turing Machine using just a Nano, a NeoPixel ring and a rotary encoder+push-button The ring is the tape and the UI

Minimalist protocol buffer decoder and encoder in C++

protozero Minimalistic protocol buffer decoder and encoder in C++. Designed for high performance. Suitable for writing zero copy parsers and encoders

Fast single source file BC7/BPTC texture encoder with perceptual metric support

Note: Since this repo was created, we've released two new codecs with better BC7 encoders: https://github.com/richgel999/bc7enc_rdo https://github.com

Raspberry Pi Pico (RP2040) and Micro-ROS (ROS 2) Integration

The Pico is an amazing microcontroller and I couldn't wait for ROS 2 support or Arduino Core, so here is my approach. Once the Arduino Core for RP2040 is out it will be easier to use micro_ros_arduino.

built-in CMSIS-DAP debugger tailored especially for the RP2040 “Raspberry Pi Pico”

RP2040 has two ARM Cortex-M0+ cores, and the second core normally remains dormant. pico-debug runs on one core in a RP2040 and provides a USB CMSIS-DAP interface to debug the other core. No hardware is added; it is as if there were a virtual debug pod built-in.

Using a RP2040 Pico as a basic logic analyzer, exporting CSV data to read in sigrok / Pulseview

rp2040-logic-analyzer This project modified the PIO logic analyzer example that that was part of the Raspberry Pi Pico examples. The example now allow

I add my Pi Pico (RP2040) stuff here.

Pico Stuff I add my Pi Pico (RP2040) stuff here. There are complete apps and libraries for sensors or complicated tasks. Libraries BMP180: Header-only

Raspberry Pi Pico Arduino core, for all RP2040 boards
Raspberry Pi Pico Arduino core, for all RP2040 boards

Arduino-Pico Raspberry Pi Pico Arduino core, for all RP2040 boards This is a port of the RP2040 (Raspberry Pi Pico processor) to the Arduino ecosystem

Owner
Adam Green
Embedded Systems/Robotics Hobbyist - I can be reached via email at yahoo.com - My account there is adamgrym
Adam Green
conversion from absolute encoder and incremental encoder, control two robotis dynamixel motors, testing qserialport library in qt

Q_dxl This example is created for testing: Serial connection Testing two dynamixel motors (eg. MX-28AT) Doing the conversion from absolute encoder (of

ibov 1 Oct 30, 2021
uSDR implementation based on a RP2040 Pi Pico

uSDR-pico A uSDR implementation based on a RP2040 Pi Pico. This code is experimental, intended to investigate how the HW and SDK work with an applicat

null 94 Jan 7, 2023
Enable LoRaWAN communications on your Raspberry Pi Pico or any RP2040 based board. 📡

pico-lorawan Enable LoRaWAN communications on your Raspberry Pi Pico or any RP2040 based board using a Semtech SX1276 radio module. Based on the Semte

Sandeep Mistry 76 Dec 30, 2022
Capture audio from a microphone on your Raspberry Pi Pico or any RP2040 based board. 🎤

pico-microphone Capture audio from a microphone on your Raspberry Pi Pico or any RP2040 based board. ?? Hardware RP2040 board Raspberry Pi Pico Microp

Sandeep Mistry 132 Dec 27, 2022
32blit SDK boilerplate for the PicoSystem RP2040-based handheld

PicoSystem 32blit Boilerplate This is a basic template for starting 32blit projects for the Pimoroni PicoSystem. It shows a minimal code layout and as

32blit 15 Nov 14, 2022
Firmware for Acorn Archimedes RP2040-based podule

Acorn Archimedes Pipe Podule firmware v0.1 5 October 2021 This repository contains firmware for the Arc Pipe Podule. (PCB design files can be found in

Matt Evans 5 Dec 5, 2022
A C library for RP2040-powered boards to control LCDs via the I2C protocol

picoi2clcd A C library to control I2C LCD displays using the Rapsberry Pi Pico (or really any board using the RP2040 microcontroller). License All of

Kosmas Raptis 2 Oct 16, 2021
Arduino code to interface with quadrature-encoder mice, specifically the Depraz mouse

Depraz Mice on USB via Arduino This code lets you connect a Depraz mouse to a modern computer via USB. The Depraz mouse has a male DE-9 connector but

John Floren 6 Aug 12, 2022
Cheap 3D Printed Absolute Encoder Knob

A cheap, 3D printed absolute position encoder knob based on a low-cost AS5600 breakout module. Demo firmware using a TTGO T-Display ESP32 board is pro

Scott Bezek 156 Nov 30, 2022
PHP Encoder, protect PHP scripts in PHP 8 and PHP 7, High Performance, Compitable with X86_64, MIPS, ARM platform and Ubuntu/Centos/OpenWRT system.

What's FRICC2? FRICC2 is a PHP Script encryption tool. When you are developing a commercial software using PHP, the script can be distributed as encry

Hoowa Sun 43 Dec 12, 2022