FilipDominec / rp2daq

Raspberry Pi Pico firmware for universal hardware control & measurement, along with a user-friendly Python frontend
MIT License
27 stars 4 forks source link

Digital Input #15

Closed epsi1on closed 6 months ago

epsi1on commented 7 months ago

Hi, I was trying to add a x10 attenuation button to the oscilloscope. using a 2-contact switch which one of those is unused.

image

Screenshot from 2024-04-15 08-25-09

image

switch have two contacts which one of them is free (as image). how is good for me to know that whether this switch is pressed or not (want to detect key press automatically on PC)?

Thanks

epsi1on commented 7 months ago

I think i should try to create a custom firmware which send the digital read with each package (like once or 100 times per second). while ADC have a full 500ksps rate, the digital read will be like 100 times per second. Thanks anyways

FilipDominec commented 7 months ago

The gpio_on_change function reports whenever the user changes the state of the switch, as demonstrated in one of the examples. No need for constant polling.

epsi1on commented 7 months ago

The gpio_on_change function reports whenever the user changes the state of the switch, as demonstrated in one of the examples. No need for constant polling.

Thanks. Can I use it while ADC stream is transferring from PICO to PC (while oscilloscope is working)?

FilipDominec commented 7 months ago

Yes, but such a message will not interrupt an already incoming ADC message. That is, you may get part of data wrong if the user toggles the switch during acquisition.

A possible fix could be to interpolate the event time tag into the ADC stream (which is also accurately time tagged). But there are so many things to be implemented if you are making a real oscilloscope...

epsi1on commented 7 months ago

could you please give more information about how to use gpio_on_change to detect keypress while adc sampling stream is sending to PC? (i.e. infinite=1 in AdcConfig).

FilipDominec commented 7 months ago

Hi, sorry for the delay. Before you set up the ADC acquisition, you have to setup your hardware sensitivity key detection. In real application, the switch will be connected on pin SENS_PIN (with hardware pull up). To try out, I generate some PWM signal on the very same pin - a fully working example in Python follows.

#!/usr/bin/python3  
#-*- coding: utf-8 -*-

## Usual initialization
import rp2daq
import time
rp = rp2daq.Rp2daq()
SENS_PIN = 1

# Auxiliary for testing: Let's prepare PWM output for some artificial button-like signal on GPIO
print("Configuring PWM channel to make artificial 5kHz square wave (and waiting for it to settle)")
rp.pwm_configure_pair(gpio=SENS_PIN, 
        clkdiv=255, # clock at 1.000 MHz
        wrap_value=65535) # one rising, one falling edge at ca. 14.9 Hz  
time.sleep(.08) # unclear why, but 100 ms is safe
rp.pwm_set_value(SENS_PIN, 40000) 

## The trick: Set up to monitor the pin status asynchronously 
sensitivity = rp.gpio_in(SENS_PIN)['value'] ## get initial value
def gpio_on_change_callback(**args):
    global sensitivity # needed to change the value of a global variable (better use threading module for thread-safe solution)
    if args['gpio'] == SENS_PIN:
        #print( args)
        sensitivity = (1 if args['events']==8 else 0)
        #print('user toggled sensitivity to', sensitivity)
rp.gpio_on_change(SENS_PIN, on_rising_edge=1, on_falling_edge=1, _callback=gpio_on_change_callback)

## Now your arbitrary code can access the `sensitivity` variable whenever needed
for x in range(300):
    time.sleep(.01) # note we do NOT poll the device, and can fully focus e.g. on ADC data
    print(f'{time.time():.4f}: Current value of the "sensitivity" pin: {sensitivity}', end='\r', flush=1)

## Cleaning up at end 
print() # scroll off
rp.pwm_set_value(SENS_PIN, 0)  # stop PWM output at the end

With this issued on the start of your program, the global variable sensitivity should automatically be updated whenever the user toggles the switch.

While such a task is this easy in the provided Python interface, for C# or whatever other frontend language of choice you will have to first eavesdrop the few bytes of binary messages generated by Python and hard-code them in C# - as you already know. You will also have to parse the return values for the callback. This can be done, provided you stick to some given version of firmware (rp2daq's binary interface can and will change in new versions).

Even if you stick to one firmware, I provide no guarantee that your approach of hard-coded messaging for frontend languages other than Python doesn't become a headache in your future programming projects, but I am happy you got your oscilloscope running.

epsi1on commented 6 months ago

Working like a charm. I had some wrong readings which was fixed by de bouncing the switch with a capacitor. Thanks ...