Ping1D get_profile provides empty profile_data array

Hi, I am using the Ping1D echosounder and altimeter to measure ice growth in a tank. I have been trying to get the code below to run — it successfully ran through once, but since then the script has failed to run and gives the following Type Error: ‘NoneType’ object is not subscriptable. It sometimes works and populates the profile_data array created by get_profile() when just running the commands in the console, but every time I try to run the script it fails.

indent preformatted text by 4 spaces
myPing = Ping1D()
ping_S = myPing.connect_serial('/dev/tty.usbserial-DM022A5O', 115200)
myPing.set_speed_of_sound(1481000)
myPing.set_mode_auto(0)
myPing.set_range(0,1000)
myPing.set_gain_setting(4)
myPing.set_ping_interval(5000)

distp = []
confp = []
timerp = []


data = myPing.get_profile()
pro = []
for i in data['profile_data']:
    pro.append(i)
perfil = np.array(pro,ndmin=2).T
z = np.array(np.linspace(0,data['scan_length'],200),ndmin=2).T



count = 0

while(count<2):
  data = myPing.get_profile()

  distp.append(data['distance'])

  print(data['distance'])

  pro = []
  for i in data['profile_data']:
      pro.append(i)
  zi = np.array(np.linspace(0,data['scan_length'],200),ndmin=2).T
    
  perfil = np.append(perfil,np.array(pro,ndmin=2).T,axis=1)
  z = np.append(z,np.array(zi,ndmin=2),axis=1)
 

  t.sleep(1)

  print("next")

Hi,

First, check the initialize function, this function will return true when a device is detected and initialized correctly.

Make sure to check get_profile, it may fail sometimes resulting in a None.

Hi Patrick,

I’ve checked the initialize function and it is returning True each time. The get_profile is definitely failing frequently, and I am a bit concerned by this. I’ve run the simple code below to try problem solving where things begin going wrong. It ran successfully through three times, and then failed (no changes were made to the script — I just ran it four times in a row and it failed on the fourth run) throwing the “TypeError: ‘NoneType’ object is not subscriptable” for the data[‘profile_data’] line.

myPing = Ping1D()
ping_S = myPing.connect_serial('/dev/tty.usbserial-DM022A5O', 115200)
myPing.set_speed_of_sound(1481000)
myPing.set_mode_auto(0)
myPing.set_range(0,1000)
myPing.set_gain_setting(4)
myPing.set_ping_interval(5000)


myPing.initialize()
data = myPing.get_profile()
data['profile_data']

Hi @lkg,

As I said, get_profile may fail returning None.
You should check the output if valid or not and recall the request, remember that ping-python is a high level library, so it tries to abstract the sensor functionality, but communication errors are still a thing.
You should do:

data = None
while not data:
    data = myPing.get_profile()
    time.sleep(1)

After that data should be valid.

1 Like

Hi Patrick,

I had implemented the code below, which seemed to have resolved it, but the way you suggested works as well. Thank you!

try:
    data = myPing.get_profile()
except TypeError:
    continue

Since your TypeError here is about a NoneType object (None) not being subscriptable, your try-except block doesn’t actually do anything except add a tiny bit of delay from overhead (the call to get_profile doesn’t try to do any subscripting, that happens later when you do data[...]).

I would strongly suggest using @patrickelectric’s solution as it makes sure that a NoneType object can never reach the code where you’re trying to access parts of the data. It might be worth making a wait_profile function so that you can be sure that (or perhaps this is worth being added to the ping-python library if it’s a common usage requirement?).

As an example:

def wait_profile(ping, verbose_limit=10):
    """ Waits for and returns a successful Ping profile read. 

    'verbose_limit' determines the minimum number of waits to notify about.
        Setting the value to 0 notifies even when no waits were required.
    """
    count = 0
    while "reading unsuccessful":
        data = ping.get_profile()
        if data is None:
            count += 1
            time.sleep(1)
        else:
            break

    if count >= verbose_limit:
        print('waited ' + str(count) + ' times')

    return data

although it may be helpful to reduce the sleep time if you consistently have only a single wait each call.

1 Like

This topic was automatically closed after 45 hours. New replies are no longer allowed.