mccdaq / daqhats

MCC DAQ HAT Library for Raspberry Pi
Other
125 stars 88 forks source link

sample rate issue #38

Closed nayanagg closed 2 years ago

nayanagg commented 2 years ago

Hi, How can I ensure that if I set a 1000Hz sampling rate then mcc118 is emitting 1000Hz only to raspberry pi

jeffreyg3 commented 2 years ago

If I understand what you are asking, the 1KHz sampling rate is limited to the MCC 118 only as that is where it is being used. The Raspberry Pi receives only the resulting data.

nayanagg commented 2 years ago

So, how can I achieve a 1kHz sampling rate of sensor data to raspberry pi?

jeffreyg3 commented 2 years ago

you use the library call mcc118_a_in_scan_start(uint8_t address, uint8_t channel_mask, uint32_t samples_per_channel, double sample_rate_per_channel, uint32_t options). See the examples: finite_scan and/or continuous_scan, available in both C and python.

nayanagg commented 2 years ago

Hi, Please help me in differentiate b/w
a_in_read(channel, options=<OptionFlags.DEFAULT: 0>) & a_in_scan_read(samples_per_channel, timeout) Function. As i want exactly 1000SPS from MCC118 into my raspberry pi 3A+ for computation.

jeffreyg3 commented 2 years ago

If you are looking to acquire 1000 samples per second, then use a_in_scan(). it uses the mcc118's on board clock to control the sampling rate where a_in_read() uses the RPi's clock to acquire 1 sample at a time. if the RPi has something else to do (like a screen or memory refresh for example), the timing can slip. As stated in my previous, see the examples: finite_scan.py and/or continuous_scan.py, available in both C and python.

nayanagg commented 2 years ago

Hi,

I'm using a_in_scan_read with the following parameters:-

num_channels=2 samples_per_channel = 1000 options = OptionFlags.CONTINUOUS scan_rate = 1000.0 actual_scan_rate = hat.a_in_scan_actual_rate(num_channels, scan_rate) hat.a_in_scan_start(channel_mask, samples_per_channel, scan_rate,options) read_result = hat.a_in_scan_read(samples_per_channel,0) Hardware used : Raspberry Pi 3A+

the issue is after running for some time it throws an error "buffer overrun".

jeffreyg3 commented 2 years ago

Well I don't know how long "some time" is in seconds, minutes, and or hours. A buffer overrun is normally caused by having too many applications running on your system or your app is doing too much and not allowing the driver to be serviced, or, your system is not up to the task you are asking it to do.

Running Python is not the fastest programing language as it is interpreted. C is a better option.

I am running the MCC 118 python example app, continuous_scan.py, The only change I made was to reduce the channel count to 2. It has now been running for 20 minutes, no problems. Granted, I do not have an RPi 3A+, I have a RPi 4B Please run that example (as is) and let me know if you still see the buffer overrun.

nayanagg commented 2 years ago

Actually, I'm sending each value to the android app via bluetooth.

jeffreyg3 commented 2 years ago

Does the app I recommended, continuous_scan.py work correctly with no changes, ie no data overruns?

jacoblapenna commented 2 years ago

Based on the documentation and the values you specified above, the scan buffer size is set to 10,000 in your case. A buffer of 10,000, at a sample rate of 1 kHz, would be full in 10 seconds. If you do not call a_in_scan_read() within 10 seconds, you will get the error you described. Moreover, from what you said above, you are only ever reading 1000 samples from the buffer at a time. If you do not ensure that your a_in_scan_read() call is carried out at least every second, you will have a memory leak (i.e. the buffer will fill up eventually, causing the error you have). It is usually wiser to call a_in_scan_read(-1). As per the documentation, this will return everything in the buffer every time the function is called (rather than just the first 1000 samples). Because the raspberry pi is not a real time system, you will get a different length list returned every time. You simply account for this in whatever process loop you are writing on your end. In addition, the buffer size is set to the table specified in the documentation, or samples_per_channel, whichever is greater. I usually chose samples_per_channel to be conservatively larger than the longest time I foresee collecting data times the sample rate, provided my Pi has enough memory. For example, if I want to record for 30 minutes, I conservatively use an hour, or 3600 seconds. I then set samples_per_channel to 3600 * sr, where sr is the sample rate.

That said, without seeing a stack trace, the buffer overrun could be coming from anywhere in your program (i.e. your code).

NOTE: I have no affiliation with MCC.