Skip to content

Instantly share code, notes, and snippets.

@Stormix
Created July 7, 2020 06:24
Show Gist options
  • Save Stormix/c4514688b69f4aad6306abe1f5c874f9 to your computer and use it in GitHub Desktop.
Save Stormix/c4514688b69f4aad6306abe1f5c874f9 to your computer and use it in GitHub Desktop.
Ping360: Fetching the distance for a given angle
from sensor import Ping360
# Global Variables
device = "/dev/ttyUSB0" # the serial port
baudrate = 115200
gain = 0
numberOfSamples = 200 # Number of points
transmitFrequency = 740 # Default frequency
sonarRange = 1 # in m
speedOfSound = 1500 # in m/s
# The function definitions are at the bottom
samplePeriod = calculateSamplePeriod(sonarRange, numberOfSamples, speedOfSound)
transmitDuration = adjustTransmitDuration(sonarRange, samplePeriod, speedOfSound)
# Initialize sensor
sensor = Ping360(device, baudrate)
print("Initialized Sensor: %s" % sensor.initialize())
# Set sonar parameters
sensor.set_gain_setting(gain)
sensor.set_transmit_frequency(transmitFrequency)
sensor.set_transmit_duration(transmitDuration)
sensor.set_sample_period(samplePeriod)
sensor.set_number_of_samples(numberOfSamples)
# Get sonar response
angle = 0 # in Grad
data = getSonarData(sensor, angle) # A list of intensities from (0 - 255) for the given angle
# To get the distance, just set a threshold, let's say 150, and get the index of the list value that is superior to that threshold
# The index+1 represents the number of samples which then can be used to deduce the range
# for detectedIntensity in data:
# if detectedIntensity >= threshold:
# detectedIndex = data.index(detectedIntensity)
# break
distance = calculateRange((1 + detectedIndex), samplePeriod, speedOfSound)
def calculateRange(numberOfSamples, samplePeriod, speedOfSound, _samplePeriodTickDuration=25e-9):
# type: (float, int, float, float) -> float
"""
Calculate the range based in the duration
"""
return numberOfSamples * speedOfSound * _samplePeriodTickDuration * samplePeriod / 2
def getSonarData(sensor, angle):
"""
Transmits the sonar angle and returns the sonar intensities
Args:
sensor (Ping360): Sensor class
angle (int): Gradian Angle
Returns:
list: Intensities from 0 - 255
"""
sensor.transmitAngle(angle)
data = bytearray(getattr(sensor, '_data'))
return [k for k in data]
def calculateRange(numberOfSamples, samplePeriod, speedOfSound, _samplePeriodTickDuration=25e-9):
# type: (float, int, float, float) -> float
"""
Calculate the range based in the duration
"""
return numberOfSamples * speedOfSound * _samplePeriodTickDuration * samplePeriod / 2
def calculateSamplePeriod(distance, numberOfSamples, speedOfSound, _samplePeriodTickDuration=25e-9):
# type: (float, int, int, float) -> float
"""
Calculate the sample period based in the new range
"""
return 2 * distance / (numberOfSamples * speedOfSound * _samplePeriodTickDuration)
def adjustTransmitDuration(distance, samplePeriod, speedOfSound, _firmwareMinTransmitDuration=5):
# type: (float, float, int, int) -> float
"""
@brief Adjust the transmit duration for a specific range
Per firmware engineer:
1. Starting point is TxPulse in usec = ((one-way range in metres) * 8000) / (Velocity of sound in metres
per second)
2. Then check that TxPulse is wide enough for currently selected sample interval in usec, i.e.,
if TxPulse < (2.5 * sample interval) then TxPulse = (2.5 * sample interval)
(transmit duration is microseconds, samplePeriod() is nanoseconds)
3. Perform limit checking
Returns:
float: Transmit duration
"""
duration = 8000 * distance / speedOfSound
transmit_duration = max(
2.5 * getSamplePeriod(samplePeriod) / 1000, duration)
return max(_firmwareMinTransmitDuration, min(transmitDurationMax(samplePeriod), transmit_duration))
def transmitDurationMax(samplePeriod, _firmwareMaxTransmitDuration=500):
# type: (float, int) -> float
"""
@brief The maximum transmit duration that will be applied is limited internally by the
firmware to prevent damage to the hardware
The maximum transmit duration is equal to 64 * the sample period in microseconds
Returns:
float: The maximum transmit duration possible
"""
return min(_firmwareMaxTransmitDuration, getSamplePeriod(samplePeriod) * 64e6)
def getSamplePeriod(samplePeriod, _samplePeriodTickDuration=25e-9):
# type: (float, float) -> float
""" Sample period in ns """
return samplePeriod * _samplePeriodTickDuration
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment