Author Topic: How to take inputs faster using Raspberry Pi  (Read 2224 times)

0 Members and 1 Guest are viewing this topic.

Offline john1998Topic starter

  • Newbie
  • Posts: 9
  • Country: in
How to take inputs faster using Raspberry Pi
« on: July 04, 2018, 12:01:38 am »
I am trying to detect different frequency signals using a Raspberry Pi and an ADC converter (PCF8591). My initial guess was the highest frequency I could detect would be limited by the speed of the I2C bus (which is about 400000 bauds). But when I run the setup, I could only get sampling speeds of around 10000 samples/sec. This value lies very close to the time taken to run an empty for loop in python (which is about 10^(-5) seconds which is equivalent to 10^(5) samples/sec).

I wanted to reach higher frequency domain (around 10 MHz) and using a better ADC won't be of much help since the limitation is set by the program itself. I wanted to know if my conclusion is correct or not. I have a feeling I am very wrong and doing something stupid. Any guidance will be much appreciated. Below is the python code I am using for signal detection.





Code: [Select]
#!/usr/bin/python
# -*- coding:utf-8 -*-
import smbus
import time
import matplotlib.pyplot as plt

start = time.time()

address = 0x48
A0 = 0x40
A1 = 0x41
A2 = 0x42
A3 = 0x43
bus = smbus.SMBus(1)
bus.write_byte_data(address,0,0b00010000)#control byte to tell ADC to act as a differential input

voltage_value = [ ]
time_value = [ ] 

try:
    while True:
        bus.write_byte(address,A0) 
        value = bus.read_byte(address)
        voltage_value.append(value)
        time_value.append(time.time()-start)
        #print("AOUT:%1.3f  " %(value*3.3/255))
        #print(value)
        #time.sleep(0.1)
except KeyboardInterrupt:
    voltage_value = [x*3.3/255 for x in voltage_value]
    plt.plot(time_value,voltage_value)
    plt.ylabel('Voltage')
    plt.xlabel('Time')
    plt.show()

    with open('output.txt', 'w') as f:
        for v,t in zip(voltage_value,time_value):
            f.write(str(v)+' '+str(t)+'\n')

 

Offline David Chamberlain

  • Regular Contributor
  • *
  • Posts: 249
Re: How to take inputs faster using Raspberry Pi
« Reply #1 on: July 04, 2018, 03:13:43 am »
Im running i2c on the Pi at 400k but im using c rather than python so thats probably the issue. You have timed it your self as well.
 

Offline Dubbie

  • Supporter
  • ****
  • Posts: 1115
  • Country: nz
Re: How to take inputs faster using Raspberry Pi
« Reply #2 on: July 04, 2018, 04:36:45 am »
I've found the raspberry pi to be useless at anything that requires precision timing. There is just too much else going on.
I'd just use the cheapest arm cortex and use the timers to count conditioned pulses from your input. You can use a second timer to gate it. If you set it up as an i2C slave or something, you could just treat it as a peripheral.
You should easily be able to measure 10Mhz accurately that way.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14466
  • Country: fr
Re: How to take inputs faster using Raspberry Pi
« Reply #3 on: July 04, 2018, 01:50:10 pm »
This value lies very close to the time taken to run an empty for loop in python (which is about 10^(-5) seconds which is equivalent to 10^(5) samples/sec).

Haven't you answered your own question?

That said, even if you can get *much* faster execution using a language like C (so that would be your first step), you will still get bitten by timing uncertainties due to the fact that the OSs available for the RPi don't have a real-time kernel. So if you're relying on a simple loop to get accurate sample rates, you're out of luck. (Even with a real-time kernel, depending on your timing requirements, it may not satisfy them.) By the way which OS are you using? (I'm guessing Raspbian?)

This is unfortunate that NO official real-time kernel that I know of is available for the RPi. You may try compiling your own but good luck with that (choosing the right set of patches for the RPi, making it reliable). I'm just guessing that if no official real-time kernel has been released (and I even haven't found any non-official ones), that must be a tough ride. Would be interested to hear from someone who has successfully built one.

Some people have released info on using the RPi without any OS - bare metal. I don't recommend this approach unless you're a very seasoned programmer and have time to waste.

And all that said, using a small microcontroller for those tasks will be much easier.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: How to take inputs faster using Raspberry Pi
« Reply #4 on: July 04, 2018, 03:42:47 pm »
There is a version of FreeRTOS that runs on the Pi hardware but I'm pretty sure that Linux is right out the window.
The real-time stuff needs to be pushed off onto another processor (Arduino?  STM32Fxx?  mbed?) that communicates with the Pi.
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: How to take inputs faster using Raspberry Pi
« Reply #5 on: July 04, 2018, 04:05:55 pm »
 john1998
  Think you are missing the simple

I2C is the max speed limit.
If you look at data sheet for PCF8591 you will find
fSCL SCL clock frequency - - 100 kHz Max on page 20

If you set SCL to 400k on Raspberry Pi then you are trying to run the PCF8591 SCL clock above the max this is unknown what happens to all the specifications for this chip.

Second the 100k or 400k is the bit rate for the communications.
It takes many bits for each sample.
Look at page 8
I2C uses many bits
You can not send or receive faster then you can talk.

You want faster then this, the next step up is
Serial Peripheral Interface (SPI)
Here the Raspberry PI can talk faster, but again you will most likely reach a limit with the ADC/DAC chip limits for SPI

Quote
wanted to reach higher frequency domain (around 10 MHz) and using a better ADC won't be of much help since the limitation is set by the program itself.

You can not reach software limit if the hardware sets the limit.

For just raw data from an 8-bit ADC using a serial interface you would need an 80 Meg. + clock.

Even USB 2.0 is not real fast in bytes per second ( bulk transfer is around 40 million bytes per second)

Ethernet at 1G us around 100 million bytes per second raw.

Actual rate becomes lower due to overhead.

C
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: How to take inputs faster using Raspberry Pi
« Reply #6 on: July 04, 2018, 06:34:21 pm »
Get PIC16F1*. You'll be surprised how fast it is compared to the speeds you're getting.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: How to take inputs faster using Raspberry Pi
« Reply #7 on: July 04, 2018, 08:39:09 pm »
I must not have read the first post properly but I still don't know how many samples per second you want.  I'm not talking communications bit rate but AD sample rate.

If a sample involves more than 1 byte that also needs to be discussed.  At higher sample rates, serial comms doesn't make sense.  That's why they make parallel ADCs.  You hook these up to the DMA channel on one of the STM32Fxx parts and it might actually work.

But first we need sample rate...


 

Offline Dubbie

  • Supporter
  • ****
  • Posts: 1115
  • Country: nz
Re: How to take inputs faster using Raspberry Pi
« Reply #8 on: July 04, 2018, 08:52:42 pm »
I was assuming that OP didn't particularly care about the samples themselves, but rather wanted the frequency value, similar to a frequency counter might display.
I figure i2C is more than fast enough for this. I think we need more info from OP.
 

Offline NiHaoMike

  • Super Contributor
  • ***
  • Posts: 9015
  • Country: us
  • "Don't turn it on - Take it apart!"
    • Facebook Page
Re: How to take inputs faster using Raspberry Pi
« Reply #9 on: July 04, 2018, 10:35:49 pm »
Beaglebone Black can sample 16 bits at a rate of 100MHz, but I'm not sure how to synchronize the sample clock to an ADC. A FPGA board is even faster.
Cryptocurrency has taught me to love math and at the same time be baffled by it.

Cryptocurrency lesson 0: Altcoins and Bitcoin are not the same thing.
 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 4422
  • Country: dk
Re: How to take inputs faster using Raspberry Pi
« Reply #10 on: July 04, 2018, 10:55:59 pm »
Beaglebone Black can sample 16 bits at a rate of 100MHz, but I'm not sure how to synchronize the sample clock to an ADC. A FPGA board is even faster.

Beagle bone is "cheating" it has extra processor doing nothing but io
 

Offline NiHaoMike

  • Super Contributor
  • ***
  • Posts: 9015
  • Country: us
  • "Don't turn it on - Take it apart!"
    • Facebook Page
Re: How to take inputs faster using Raspberry Pi
« Reply #11 on: July 05, 2018, 04:47:34 am »
The I/O coprocessor is precisely what makes the Beaglebone Black a good logic analyzer.
Cryptocurrency has taught me to love math and at the same time be baffled by it.

Cryptocurrency lesson 0: Altcoins and Bitcoin are not the same thing.
 

Offline senso

  • Frequent Contributor
  • **
  • Posts: 951
  • Country: pt
    • My AVR tutorials
Re: How to take inputs faster using Raspberry Pi
« Reply #12 on: July 06, 2018, 12:10:44 pm »
Beaglebone Black can sample 16 bits at a rate of 100MHz, but I'm not sure how to synchronize the sample clock to an ADC. A FPGA board is even faster.

Beagle bone is "cheating" it has extra processor doing nothing but io

I have read somewhere that the Pi CPU also as an equivalent to the TI RPU units, but there is zero docs on how to use them.
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6255
  • Country: fi
    • My home page and email address
Re: How to take inputs faster using Raspberry Pi
« Reply #13 on: July 06, 2018, 09:49:49 pm »
Note: I am a hobbyist only, with lots of software development experience, but relatively little hardware development experience: hobby gadgets only. So take that into account when considering my opinions below!

Aside from the BeagleBones and PocketBeagles with integrated PRUs, I've found that it is much better to use a separate microcontroller with native USB support as a slave device to provide the real-time signal handling.

Depending on the kernel used, an userspace application can suffer from latencies between 1ms (HID) to 10ms (kernels compiled with HZ=100, even under just a slight load), worst case. Installing the userspace service daemon with a realtime priority, and using C and sensible programming techniques, including multithreading, in normal operation the latency is on the order of 0.1ms, roundtrips less than 0.2ms. Using a low-latency kernel, or one with HZ=250 to 1000, should clear any latency issues. (Assuming there is sufficient CPU power to do what you want, of course.)

I've got excellent results using Teensies, especially Teensy LC and Teensy 3.2 (I'm not affiliated, just a happy customer); the forum there is quite active, including the developer of the microcontrollers.  You program them in the Arduino environment, using the optimized Teensyduino extension package. (Paul Stoffregen, the Teensy developer, is quite active in Arduino development.)

Do note that with Teensy LC/3.2, one is limited to USB 1.1 speeds, i.e. 12 MBits/s, or about a million bytes per second. On the other hand, you can use an ADuM3160/4160 -based USB isolator, like the one by Olimex or the Chinese implementations using ADuM3160/4160; the Chinese $10 ones I bought off eBay were all quite okay (the circuit being quite simple, there isn't much one can do horribly wrong).  The Olimex one is nice in that if you need more than the 350 mA or so (obtained from the USB bus via isolated DC-DC converter), you can use an 8V to 15V DC power supply to supply up to 750mA (at 5V) on the device side. The supply needs to be isolated from AC ground, of course, so do check. (I believe some may have a suppression capacitor that ties the negative output to AC ground. However, in Europe, the legal ones with just two prongs should be completely isolated.)  The Chinese ones may have less efficient (cheaper) isolated DC-DC converters, so do check how much you can draw from those; typically it is between 250mA and 350mA, depending on the converter used.  I do believe there are some even in the sub-$10 range that can provide 350mA with less than 500mA draw from host, but I'm not an EE, and only recently acquired testing equipment that allows me to measure that, so at this point, that is just a belief, not verified fact.

To get over the 1 MiB/s limit, I've obtained a Cypress EZ-USB FX2LP devkit (theoretically able to reach the 480Mbit/s or over 40 MiB/s), but haven't had yet time to play with it to see how good it is in practice.   Do note that the cheaper USB isolators won't work for this!  Before I got my Analog Discovery 2, I was thinking of using this, and an Si866x-isolated ADC frontend (isolating the digital signals from the ADC, letting the entire frontend use the target ground as ground level), for high-speed differential ADC. Now I don't need to.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14466
  • Country: fr
Re: How to take inputs faster using Raspberry Pi
« Reply #14 on: July 07, 2018, 04:09:10 pm »
Just for the record, for those adventurous enough to consider going bare metal with the RPi, this is a nice tutorial: http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf