Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to take inputs faster using Raspberry Pi

Status
Not open for further replies.

john1998

Newbie level 6
Newbie level 6
Joined
Jun 8, 2018
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
152
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:
#!/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')
 

Hi,

I assume the Python code is too slow, and additionally you can't rely on the timing.
Every new piece of code will influence the timing and every interrupt will influence timing, too.
But sampling with unreliable timing often is useless, you can't do any frequency analysis and you can't do distortion measurement, the unreliable timing will cause noise.

Thus you need a software independent timing.... a hardware controlled timing.
I recommend to use a FIFO or an SRAM acting as buffer for the sampled data.

All in all not a very simple task...and you need a faster interface.

Klaus
 
Firstly, note that when referring to the "Raspberry PI" you are not being too accurate, since there are some hardware platform variants, based on different microcontrollers (Cortex A7, Cortex A53, ARM11).

In addition, if you want to handle output pins of the microcontroller with a higher speed, at first sight this should not be done from within an operating system (assuming Linux in your case) but rather in baremetal programming (eg, compiled in C) .

However, due to the PI intrinsic 32-bits CPU complexity along with with its stuffs that impact the instructions fetch - which I'm particularly unaware of (Guessing: Pipeline, DMA, etc...), one would expect a weakest performance in terms of the I/O speed if compared with a clean and simplest 8-bit RISC architecture for example, running at the same clock rate.

In that case, it would be advisable to implement bus access via dedicated built-in I2C peripheral at the core, if it exists and/or their pins are available there.
 
Well linux isn't a good real time OS, Python is a slow scripting language and the PI isn't the fastest computer...otherwise I don't think you're doing anything wrong.

My limited understanding is that Linux has some real time extensions/support but just isn't meant for real time. However there are ways to dedicate threads to certain cores which can help. I imagine python isn't the platform for this and C/C++ is the way to go.

Also I understand the PI is limited in terms of ports, for example its basically USB and little else correct? I could imagine other processors out there have a SPI interface that can be linked to a timer and DMA and could therefore drive a SPI ADC with good timing accuracy independent of the OS.

As mentioned if you're doing any frequency domain analysis (FFT etc) then you're going to need very good timing accuracy and simply may not be able to do on this platform.

Adding a co-processor of some sort in the form of an FPGA or DSP could solve it. Although it adds a lot of work (unless you're quite familiar with this stuff), a DSP with good on-board ADC and a USB interface to talk to the PI isn't actually expensive from a BOM point of view.
 

Well linux isn't a good real time OS, Python is a slow scripting language and the PI isn't the fastest computer...otherwise I don't think you're doing anything wrong.

My limited understanding is that Linux has some real time extensions/support but just isn't meant for real time. However there are ways to dedicate threads to certain cores which can help. I imagine python isn't the platform for this and C/C++ is the way to go.

Although Linux has notorious limitations inherent to preemptive operational systems in terms of the execution of tasks in real time, it is possible to get around this problem through tricky artifices, such as the use of some interrupt (Serial, I/O, Timer, etc ...) triggered at precise intervals (eg, timed by crystal) that can interrupt the currently running thread and redirect execution of the process to the desired routine. Needless to say that the process to be assigned with such a priority should be of rapid completion. I already used this feature and it worked quite satisfactorily. In that case, an RX interrupt on the UART was raised in the OS from an external board that was timed by a crystal, and the Desktop computer responded immediately, unlike before when the intervals were irregular.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top