Libpruio GPIO + ADC

I’m trying to make a custom function using the Libpruio library on a BBB that does the following sequence:

  1. Poll the state of a GPIO pin
  2. Start ADC sampling when pin goes low

Essentially I’m trying to combine the functionality of the following two examples from libpruio:
RB File

When looking through the documentation for the PRUIO constructor and config, it seems like the settings for gpio reading and ADC reading conflict. Should I make two separate instances of PRUIO for each task or is there a better way to harmonize the two?


Only one instance is allowed/necessary.

What kind of conflict?

Do you need to ADC sample endless (RB mode)? Otherwise have a look at the trigger features in MM mode.

Ah drats, that’s what I thought.

I need the ADC in RB mode + one GPIO pin which will trigger the ADC measurement. We’re sampling data at like 20kHz, 50k points.

I guess where I’m really confused is the config function for libpruio. We have parameters we put in to dictate how number of samples, sampling frequency, etc for RB mode. The parameters used in the config function for GPIO set up are different according to the button example I linked (only 1 sample as opposed to many samples dictated by ADC). How can I set up both at the same time?

OK, you need RB mode. But who is ‘We’?

20kHz, 50k (#channels?) can get measured in MM mode. No need for watching the trigger pin by ARM software; this feature is already in-build in libpruio (check example triggers).

I can’t see any conflict. Note: the button example is working in IO mode, while the rb_file example is working RB mode. That’s the reason for the different parameters.

The PruIo::config() function sets parameters for the ADC measurment. In contrast, the GPIO pin gets specified by function Gpio::config(); since it’s an input pin this should get called before the PruIo::config() function call.

Ah I see thanks for the explanation. So if I call the two separate config functions as you suggested it will implement both? I think my misunderstanding was that I thought I had to call everything in one config function otherwise it would overwrite.

I was not aware that MM mode had this functionality I will definitely try to implement it! “We” meaning my research team. I was using RB mode because a previous student on my research project used it but I’ll probably try switching to MM mode based on this recommendation.

That’s not wrong, but only related to ADC and run mode settings (PruIo::config() ). Digital I/O is separate (Gpio::config(), Cap::config(), Qep::config(), …), and should get called before PruIo::config().

In MM mode you need not care about the current writing position. Measurement always start at 0 (zero) and ends at the last sample specified (by the costs of less flexibility due to a pre-defined fixed number of samples). You can time-shift the trigger event. That is starting measurement after a certain +/- latency, meaning before or after the GPIO event happens.

Thank you so much for all the help! I got MM mode to work and so far so good. One more question, I also need to send a command to another sensor over serial after I receive that GPIO event, is there capability to do this in libpruio? Is there another method I should use? I’ve tried looking out there for how I can set up serial communication on the beaglebone, but most methods use remoteproc. Since I have libpruio set up, I am using the uio-pruss driver and have disabled remoteproc, so that is where I am currently stuck.

Serial data transfer is not under the scope of libpruio.

You may either use linux features on the ARM (easy), or (in case of very hard real-time requirements) the other PRUSS for that task.

In order to get the trigger waiting state create a parallel thread that polls PruIo::DRam[0] value while function PruIo::mm_start() is waiting in the main thread for the end of the measurement. The measurement starts when that value gets smaller than your last trigger. Ie using one (the first) trigger: the event happens when DRam[0] gets smaller than PRUIO_MSG_MM_TRG1.

Note: Do not poll too fast. When the ARM is reading that memory address, the PRU cannot write. Add some sleep time to the polling loop (ie 1 µs = 200 PRU cycles).