Read multiple ADC channel simultaneously

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Meide
Posts: 8
Joined: Thu Dec 08, 2016 9:50 am

Re: Read multiple ADC channel simultaneously

Post by Meide » Mon Jan 09, 2017 10:09 am

Hi,

Sorry for reply only now but I was on hollidays. I am back at work now and I've tried your code.
I've tried it with a signal of 200 Hz and 1V amplitude with the same connections as you. Here are my results for the channel 1 :
http://zupimages.net/viewer.php?id=17/02/47xg.jpg
http://zupimages.net/viewer.php?id=17/02/91pk.jpg
(I ploted chan1 vs t)

As you can see they are not as good as yours. There are more data collected at the pick of the signal and I don't know why... And also I sent a signal of 1V amplitude and I don't know why that collect a 2500mV amplitude here.

Maybe I didn't understand totally how works your code, can you explain it a bit ?
I don't know what the 'def' command is exactly doing.
Why do we have to use the X5 port ? I don't really understand what is it for ..

Thank you again, all this help me a lot !

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Read multiple ADC channel simultaneously

Post by pythoncoder » Tue Jan 10, 2017 6:57 am

Re pin X5 I am simply using the Pyboard DAC to generate the sawtooth waveform as I have only sine and square wave generators. I routinely use the Pyboard to generate arbitrary waveforms for test purposes.

The key to the code is to use a timer callback to perform the ADC reads as timing accuracy is crucial. As for your plots it's hard to comment. I'd check the waveforms with an oscilloscope and be sure that you are sampling at a rate substantially higher than the waveform frequency. Aliasing can be the cause of problems in sampled data systems - if you're unfamiliar with this I'd recommend doing some reading on basic sampling theory.
Peter Hinch
Index to my micropython libraries.

Meide
Posts: 8
Joined: Thu Dec 08, 2016 9:50 am

Re: Read multiple ADC channel simultaneously

Post by Meide » Tue Jan 10, 2017 10:33 am

Ok I understand better how it works now.
So I dit the same as you and I obtained this results (for the chanel 1,signal generated by the pyboard):
http://zupimages.net/viewer.php?id=17/02/4tdb.jpg
The result is pretty good but how do you explain that we collected more data at the beginning ?
This doesn't come from Aliasing right ? Because aliasing is when you collect too slow in comparison of the signal frequency so if it was aliasing we should see gap but not irregularities like these no ?

I tried to do the same sending the signal with an oscilloscope (10Hz frequency). Here is a photo of my system :
http://zupimages.net/viewer.php?id=17/02/73pi.jpg
http://zupimages.net/viewer.php?id=17/02/feia.jpg
http://zupimages.net/viewer.php?id=17/02/rrzj.jpg
With this system, I obtain these results for the chanel 1:
http://zupimages.net/viewer.php?id=17/02/t3yd.jpg
If we make a zoom at the beginning:
http://zupimages.net/viewer.php?id=17/02/rj89.jpg
We can see the same phenomenon, from 0.7*10^6 us to 0.8*10^6 us we are collecting more data and after we can see irregularities in the collection. How do you explain this ?

I was thinking that maybe I am missing something fundamental that's why I put all the system pictures.
If you don't understand something, pls tell me, I will try to explain.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Read multiple ADC channel simultaneously

Post by pythoncoder » Wed Jan 11, 2017 4:25 pm

If you're running the same code as me and getting different results then I'm baffled. Sorry. :(
Peter Hinch
Index to my micropython libraries.

Meide
Posts: 8
Joined: Thu Dec 08, 2016 9:50 am

Re: Read multiple ADC channel simultaneously

Post by Meide » Thu Jan 12, 2017 9:59 am

Do you mean that you don't have the same irregularities as me if you print the measure points in your graph ?
I've just copied and passed your code in the main files of my sd card, I've connected X5 and Y12 and then I've connected the pyboard to my computer. Did I do something wrong ?
(For this grah: http://zupimages.net/viewer.php?id=17/02/4tdb.jpg)

Meide
Posts: 8
Joined: Thu Dec 08, 2016 9:50 am

Re: Read multiple ADC channel simultaneously

Post by Meide » Thu Jan 12, 2017 10:11 am

Ohhhh ! I found why I had these irregularities !
It was because the pyboard was starting and at the same time trying to apply the main.py of the sd card.
So I put a sleep of 2 seconds at the beginning of the code and it finally works perfectly !
http://zupimages.net/viewer.php?id=17/02/ftpr.jpg

Thank you a lot for all your help :D :D

Meide
Posts: 8
Joined: Thu Dec 08, 2016 9:50 am

Re: Read multiple ADC channel simultaneously

Post by Meide » Mon Jan 16, 2017 12:25 pm

Hi,
I made some speed test with this code and I want now to try another alternative.. To see which one is faster and what is the difference of speed between both.
I want to write directly on the file and not stock the data on a buffer.
So I tried this code which is an adaptation of our previous code:

Code: Select all

import array
import os
import pyb
import utime
import micropython
micropython.alloc_emergency_exception_buf(100)

NSAMPLES = 5000

adc2=pyb.ADC(pyb.Pin.board.Y11)
adc1=pyb.ADC(pyb.Pin.board.Y12)
tim = pyb.Timer(4)

i = 0
def cb(timer):
    global i
    with open('chanel1.dash','w') as f:
        s1 = str(adc1.read())
        f.write(s1+'\n')
        
    with open('chanel2.dash','w') as h:
        s2 = str(adc2.read())
        h.write(s2+'\n')

    with open('t.dash','w') as j:
        s3 = str(utime.ticks_us())
        j.write(s3+'\n')
    i += 1
    if i >= NSAMPLES:
        timer.deinit()

tim.init(freq=5000, callback=cb)

start = utime.ticks_us()
while i < NSAMPLES:
    pass

end1 = utime.ticks_us()
print((end1 - start) // NSAMPLES)
maxd = 0
for n, s in enumerate(buf1):
    if n > 0:
        maxd = max(maxd, abs(s - buf1[n -1]))
print('Maximum difference between consecutive samples: {} theoretical: {}'.format(maxd, 4096//256)) 

end2=utime.ticks_us()

with open('t1.dash','w') as r:
    s4=str(end1 - start)
    s5=str(end2 - start)
    r.write(s4+'\n'+s5)
Unfortunately, this code isn't working, I have an indention error during the definition of 'def'. Maybe someone know why and how to correct it ?

Thank you

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Read multiple ADC channel simultaneously

Post by Roberthh » Mon Jan 16, 2017 9:50 pm

I have an indention error during the definition of 'def'.
a) Are you sure that you have not mixes of space and tab?
b) Line 20 contains 7 spaces only. That should not be a problem, since it's space only. I can't test it now.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Read multiple ADC channel simultaneously

Post by pythoncoder » Tue Jan 17, 2017 7:26 am

The indentation error is simply a matter of checking for the right amount of spaces on each line. Avoid using tabs as mixing tabs and spaces is a recipe for these errors.

There are bigger problems with this code. Firstly, opening a file in 'w' mod will cause its entire contents to be overwritten. Presumably you want append mode.

More importantly you're sampling at 5KHz. You're expecting an awful lot to happen in 200us: opening three files, writing data to them, and closing them again. Writing files takes time, and that time may not be deterministic. I'd buffer the samples in RAM using arrays, writing the data out on completion. In that case 'w' mode will be OK.

As for storing the times in RAM, you may well find that the times are entirely predictable as the callback is triggered by an interrupt.
Peter Hinch
Index to my micropython libraries.

Post Reply