More ADC Inputs using PIO Sigma Delta

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
cebersp
Posts: 30
Joined: Mon Feb 08, 2021 12:07 pm

More ADC Inputs using PIO Sigma Delta

Post by cebersp » Wed Feb 17, 2021 11:03 am

Hi, this can give you additional Adc channels.
It needs 2 Pins per channel, 2 resistors and 2 capacitors.
Pico Sigma Delta ADC.JPG
Pico Sigma Delta ADC.JPG (82.49 KiB) Viewed 2886 times
The charge of the two condensers is balanced by the current through the input resistor 1meg and the current through the feedback resistor 220k. PIO code tries to hold the voltage at the input pin at its low/high threshold.
It is possible to measure higher and negative voltages, if you use an adapted input resistor.

Have fun! Christof

Code: Select all

title= "pioAdcB" # by CWE
# Adc sigma delta type

from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
from time import sleep

maxTime=1_000_000

@asm_pio(sideset_init=PIO.OUT_LOW)
def cap_prog():
    mov(y, osr) # OSR must be preloaded with max
    mov(x, osr)  
    
    label("test_pin") # 
    jmp(pin, "is_set") 
    jmp(y_dec, "not_set") # just count it 1
    label("not_set")
    #nop() .side(1)
    jmp(x_dec,"test_pin") .side(1) # 2
    jmp("save_result")
    
    label("is_set")
    # nop() .side(0)
    nop() # 1
    jmp(x_dec,"test_pin") .side(0) #2
    
    label("save_result")
    mov(isr, y) #.side(0) # save result; pin low
    push(noblock)

    


class PIOCAP:
    def __init__(self, sm_id, outPin, inPin, max_count, count_freq):
        self._sm = StateMachine(sm_id, cap_prog, freq=2 * count_freq, sideset_base=Pin(outPin), jmp_pin=Pin(inPin,Pin.IN))
        # Use exec() to load max count into ISR
        self._sm.put(max_count)
        self._sm.exec("pull()")
        #self._sm.exec("mov(isr, osr)")
        self._sm.active(1)
        self._max_count = max_count
        
    def getCap(self):
        #self._sm.exec("push()")
        return self._sm.get()

cap = PIOCAP(0, 22, 17, max_count=(maxTime), count_freq=50_000_000)

mittel=0
while True:
    onTime= maxTime-cap.getCap()
    mittel=(9*mittel+onTime)/10
    #print(onTime, mittel, (onTime/maxTime))
    print(onTime, 7.309-1.4369e-5*onTime)
    sleep(0.1)


Post Reply