0

I wanted to measure voltage with command chan = and write the voltage value to array which has dimensions 128x128 and contains 16384 voltage values. I set ADS1115 sample rate to 128 samples per second. The time of data acquisition should be 128 seconds x 128 samples = 16384 total samples.

The problem is that the program is not working for 128 seconds and it stops much earlier. I suppose, there are some problems elsewhere.

The code look like this:

import numpy as np
import time
from matplotlib import pyplot as plt

import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
from timeit import default_timer as timer


i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
ads.gain = 8
ads.mode = ADS.Mode.CONTINUOUS
ads.data_rate = 128
chan = AnalogIn(ads, ADS.P0, ADS.P1)

trig = AnalogIn(ads, ADS.P2, ADS.P3)


level = 192 # trigger level

totalElapsed = 0

buffer = []

while True:

     if (trig.value > level):
     
         start = timer()
         thisTime =  timer() - start

         while(len(buffer) < 16384):
 
              buffer.append(chan.value)
              
              totalElapsed += thisTime
              
              print(">>>>>>>>>>>> Total Elapsed: " + str(totalElapsed) + "s")

         # Make into numpy array and reshape to (128,128)
         a = np.array(buffer).reshape((128,128))

         # Reverse alternate rows
         for r in range(1,128,2):
            a[r] = a[r][::-1]


         #Generate image
         plt.imsave('/home/rpi/Downloads/mystm_pic.tiff', a, cmap='afmhot') # file location

         plt.imshow(a, cmap='afmhot')

         plt.show()

To sum up, I want to measure voltage and write its value to array until the array is fully filled, i. e. 16384 written measured voltages in time 128 seconds, assuming speed of 128 samples/second.

Thank you very much for help and your suggestions.

Edit:

The correct code should like this?

import numpy as np
import time
from matplotlib import pyplot as plt

import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
from timeit import default_timer as timer

RATE = 128
SAMPLES = 16384    

i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
ads.gain = 8
ads.mode = ADS.Mode.CONTINUOUS
ads.data_rate = RATE
chan = AnalogIn(ads, ADS.P0, ADS.P1)

trig = AnalogIn(ads, ADS.P2, ADS.P3)


level = 192 # trigger level

sample_interval = 1.0 / ads.data_rate

repeats = 0
skips = 0

data = [None] * SAMPLES

start = time.monotonic()
time_next_sample = start + sample_interval



if (trig.value > level):
     

    for i in range(SAMPLES):
 
         while time.monotonic() < (time_next_sample): 
              pass

         data[i] = chan.value

         # Loop timing
         time_last_sample = time.monotonic()
         time_next_sample = time_next_sample + sample_interval
         if time_last_sample > (time_next_sample + sample_interval):
            skips += 1
            time_next_sample = time.monotonic() + sample_interval

         # Detect repeated values due to over polling
         if data[i] == data[i - 1]:
            repeats += 1

    end = time.monotonic()
    total_time = end - start


    # Make into numpy array and reshape to (128,128)
    a = np.array(data).reshape((128,128))

    # Reverse alternate rows
    for r in range(1,128,2):
       a[r] = a[r][::-1]

    print(">>>>>>>>>>>> Total Elapsed: " + str(total_time) + "s")    

         #Generate image
    plt.imsave('/home/rpi/Downloads/mystm_pic.tiff', a, cmap='afmhot') # file location

    plt.imshow(a, cmap='afmhot')

    plt.show()
2
  • What errors does it output? Commented Jun 11, 2023 at 21:27
  • @TheTridentGuy It just stops too early. Commented Jun 11, 2023 at 21:39

1 Answer 1

1

When you request AnalogIn.value, you’ll get the latest measured value. If you call this in quick succession, you’ll simply repeatedly get the same measurement - it does not automatically wait for the ADC to finish reading. Thus, by calling it in a loop, you’re just going to fill the buffer as quickly as the Pi can perform 16384 I2C reads to your ADC.

As far as I can tell, the AdaFruit drivers don’t have any mechanism to properly synchronize with the ADC. Thus, you’ll have to implement your own timing setup: in each loop, you will want to delay for 1/128 seconds before the next read. You can do this by checking time.monotonic() in a loop; that will be more reliable than using time.sleep().

See https://github.com/adafruit/Adafruit_CircuitPython_ADS1x15/blob/main/examples/ads1x15_fast_read.py for a complete example of the timing loop in action.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your explanation. Tell me, if my corrected code is ok?
Looks reasonable. Note that the logic around skips and repeats is there just in case you want to measure your data quality, since the timing loop is not guaranteed to give you exactly one sample per iteration - however, it should be quite close, and for most purposes should work fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.