Created
July 7, 2020 06:24
-
-
Save Stormix/c4514688b69f4aad6306abe1f5c874f9 to your computer and use it in GitHub Desktop.
Ping360: Fetching the distance for a given angle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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