Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2 channels ADC #2

Open
cheeta111 opened this issue Dec 4, 2017 · 6 comments
Open

2 channels ADC #2

cheeta111 opened this issue Dec 4, 2017 · 6 comments

Comments

@cheeta111
Copy link

Hi!
I'm Jaime, I have been talking to you in you website. So I want to achieve a 12.8khz sampling rate data on two channels. Then I want to process this data using the FFT, this I guess I have to do it in the c code.
So I want to use the 2 ADC to get the data, then put the data on the memory and after that take the data and process with FFT.
I hope this information help you to understand what I want to accomplish.
I am using Beaglebone black wireless and this kernel version: "Linux beaglebone 4.4.82-bone19 #1 Mon Aug 14 21:56:51 UTC 2017 armv7l GNU/Linux".

At the moment, the questions I would like to ask are:

  1. What do I should aim on your code to get the 2 ADC working?
  2. Is your assembler code only for the ADC or are you using the pru0 and pru1 for another matters?
  3. In your code, you use pru0 and pru1, but I'm not sure what pru0 is doing.
  4. I am not sure which is the sampling rate that you are using.
  5. In lockbox.c , you are using the spi. May it be because you use the spi for another part of the project?

Thanks in advance,

Regards,

Jaime

@lneuhaus
Copy link

lneuhaus commented Dec 5, 2017

Hi Jaime,

if you can do the FFT in C, that definitely makes it much easier to implement.

General comments:
My code architecture assumes that a client computer (modern desktop pc or laptop) runs python to create a shell per ssh on the Beaglebone black over ethernet. Using shell commands, the client runs a C-program on the beaglebone which handles loading the code into PRUs. Once loaded, a few basic commands such as read/write from memory are available to exchange data and commands between the PRU and the client program. All the remaining read-out logic and higher math is coded in python on the client computer to make it as simple as possible. If you stick to that architecture, you should simply modify the code to create a simple 2-channel oscilloscope on the PRU's that fill the shared memory with samples and retrieve these values onto the client pc, and add a higher level code on top of the acquired scope traces doing the FFT in Python. If your client PC is no more than 5 years old, this should be fast enough for nice real-time plotting even if you sample with >100 kHz. If instead you are looking for a standalone application on the beaglebone, you should code the FFT (using libraries) in C, directly using the data from the shared PRU/ARM memory. In any case, your task will be to program an oscilloscope on the PRU, that is make a ring buffer in shared memory and fill it with subsequent sampes from the ADCs, along with a write pointer indicating where the last sample was stored.

@lneuhaus
Copy link

lneuhaus commented Dec 5, 2017

Now to your questions:

  1. What do I should aim on your code to get the 2 ADC working?
    The relevant code for handling the ADCs rus on PRU1 and starts here:


    The way this works is that when the PRU code is loaded, it sets up a certain ADC configuration which is later called with a single "launch" command, and later its result is retrieved. Whether you use one or two ADCs is simply a matter of what configuration you choose here. The subsequent lines are somewhat commented, where I got all information from the TRM (http://www.ti.com/lit/ug/spruh73p/spruh73p.pdf - not sure this is the right one for your version of Beaglebone, pages 1827++ in the linked document).

  2. Is your assembler code only for the ADC or are you using the pru0 and pru1 for another matters?
    The assembler code in my repo is used to read ADCs, but also to output data to the r30 register (which i had connected to a DAC). Therefore, some parts of the PRU1 code are for the output, and some even for feeding the input to the output. The idea was to create a FIR filter as well (using multiplication), but I never got there. If you like, I can provide a branch of the repo where I clean away all non-ADC parts.

  3. In your code, you use pru0 and pru1, but I'm not sure what pru0 is doing.
    I was using pru0 as a timer, sleeping a certain number of cycles (190 or so), and then writing a value to a register of pru1. the line XIN 14,Z0,4 in the code of pru1 "retrieves" this value from pru0, and therefore sleeps until the value is ready. Thus, pru0 defines a rate at which it writes to pru1, and thus limits the sampling rate at which pru1 sets up ADC acquisitions to 1/(5ns*cycles in pru0). This was useful because I wanted a sampling rate that is syncronized with the PRU clock. In your case, you may be able to rely purely on the ADC clock and operate the ADCs in continuous mode.

  4. I am not sure which is the sampling rate that you are using.
    As said above, the ADCs in my code are used in single-shot mode and the sampling rate is defined by the number of cycles per loop in the pru0 code. Counting the numbers of instructions per loop in


    you get 200, which gives a sampling rate of 1 MHz. I was able to reduce the number of instructions without weird behaviour up to about 1.6 MHz sampling rate.

  5. In lockbox.c , you are using the spi. May it be because you use the spi for another part of the project?Yes, the spi was used to control a digital potentiometer and DACs for offset generation, none of this should be your concern.

Sorry for the cryptic code and unclear descriptions. If you have some code snippets of your own to share I may be able to help there. I currently dont have my beaglebone at hand, otherwise I could help you test my code.

Give me a day and I can post a cleaned-up branch with reduced code to get minimum functionality.

@lneuhaus
Copy link

lneuhaus commented Dec 5, 2017

Btw, all assembler instructions are documented here, as you probably know:
https://elinux.org/images/d/da/Am335xPruReferenceGuide.pdf

@cheeta111
Copy link
Author

cheeta111 commented Dec 13, 2017

I've been out of my town this week and I couldn't answer sooner, I want to say thanks for you help.
I would be very grateful if you could make that branch without Non-ADC parts.
I would rather test your code first if you could help me to do it

regards,
Jaime

@cheeta111
Copy link
Author

I've got another question,
How do you get such a higher sampling rate? because I thought that the maximum sampling rate for the adc was 200ksps and it couldn't be higher.

regards,
Jaime
pd: I don't sure if you are noticing these messages.

@lneuhaus
Copy link

Hi,
the sampling rate of 1.6 MSps is normal if you use only one ADC input.

The chip architecture is that eight (i guess there are 8) ADC inputs go into a multiplexer, which selects which one is sampled by the single AD-converter on the chip (which can work up to ~1.6 MHz). You can program a sequence of different inputs being sampled one after another. If you sample all 8 inputs, you end up with a final sampling rate of 1.6 MHz / 8 = 200 kHz.

I have to see if I can get you some code over the holidays, quite busy here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants