Pages

Friday, 12 February 2021

Raspberry Pi Pico - simple projects

Introducing fungen - an AF function generator.

Lots of pioneers are now creating tutorials and sample projects for the Raspberry Pi Pico and the Pimoroni Tiny2040.

One of my first mini-projects is fungen - a Pico-based AF (audio frequency) function generator that uses the Pico's PIO (programmable I/O) to generate a waveform.

The Pico's head start


The Pico was announced just a few days ago. It arrived out of the blue complete with lots of interesting add-ons available, and with excellent documentation.

The reference documentation is full of useful examples, including several that take advantage of the Pico's powerful PIO. PIO allows users to set up custom input-output capability, and one of the examples shows how to use PIO to implement PWM (Pulse width modulation).

The Pico already has plenty of PWM-capable pins, but I wondered if I could hack the PWM code to turn the Pico into a simple signal generator.

Indeed you can, and that's how fungen works.

I made a couple of minor changes to the  PIO PWM sample code and wrote a short program on my workstation that generated the values I needed to to generate a sine wave. Next I wired up a very simple low-pass fiter from a capacitor and resistor. I fired up my BitScope micro USB-based oscilloscope, loaded my code onto the Pico using the thonny editor, and took a look at the output.

It worked!


Of course a useful signal generator lets you vary the frequency of its output. That's usually done using a knob that turns a potentiometer. Could I use that with the Pico?

I worried that the reading of the voltage would interrupt the process of generating the sine wave. I quickly realised that the Pico has a multi-core. Could I use the second code to read the pot?

I couldn't find a micropython example of multi-threaded code for the Pico, but Ben Everard quickly came to my rescue. He's written some code that uses both cores, and it turns out to be really easy.


Multi-threading on the Pico


Here's the current code for  the function generator.
# Example of using PIO for function generation using hacked PWM example

from machine import ADC
from time import sleep_us, sleep_ms
import _thread

from pio_dac import PIOPWM

# Pin GP22 is output
pwm = PIOPWM(0, 22, max_count=250, count_freq=10_000_000)

sines = [
    124, 127, 130, 133, 136, 139, 142, 145, 148, 152,
    155, 158, 161, 164, 167, 170, 172, 175, 178, 181,
    184, 186, 189, 192, 194, 197, 200, 202, 204, 207,
    209, 211, 214, 216, 218, 220, 222, 224, 226, 227,
    229, 231, 232, 234, 235, 237, 238, 239, 240, 241,
    242, 243, 244, 245, 246, 246, 247, 247, 248, 248,
    248, 248, 249, 249, 248, 248, 248, 248, 247, 247,
    246, 246, 245, 244, 243, 242, 241, 240, 239, 238,
    237, 235, 234, 232, 231, 229, 227, 226, 224, 222,
    220, 218, 216, 214, 211, 209, 207, 204, 202, 200,
    197, 194, 192, 189, 186, 184, 181, 178, 175, 172,
    170, 167, 164, 161, 158, 155, 152, 148, 145, 142,
    139, 136, 133, 130, 127, 124, 120, 117, 114, 111,
    108, 105, 102, 99, 95, 92, 89, 86, 83, 80,
    77, 75, 72, 69, 66, 63, 61, 58, 55, 53,
    50, 48, 45, 43, 40, 38, 36, 33, 31, 29,
    27, 25, 23, 21, 20, 18, 16, 15, 13, 12,
    10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
    1, 0, 0, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, 0, 0, 1, 1, 2, 3, 4,
    5, 6, 7, 8, 9, 10, 12, 13, 15, 16,
    18, 20, 21, 23, 25, 27, 29, 31, 33, 36,
    38, 40, 43, 45, 48, 50, 53, 55, 58, 61,
    63, 66, 69, 72, 75, 77, 80, 83, 86, 89,
    92, 95, 99, 102, 105, 108, 111, 114, 117, 120,
]


pot = ADC(26)
delay = [400]


def read_pot():
    while True:
        v = pot.read_u16()
        delay[0] = 20 + (400 * v)// 65000
        sleep_ms(100)


_thread.start_new_thread(read_pot, ())

while True:
    for i in range(0, 250, 25):
        pwm.set(sines[i])
        sleep_us(delay[0])

It uses pio-dac.py which is the hacked version of the PWM example. You'll find all the code (and some other examples) on GitHub.

I'll blog about more of the examples over the next few days. If you want to keep track of what I'm up to, follow me (@rareblog) on twitter.

No comments:

Post a comment