Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import RPi.GPIO as GPIO # Import GPIO library
- import time # Import time library
- import threading
- import signal
- import math
- import numpy as np
- # IGNORE:
- class PiSoftPwm(threading.Thread):
- def __init__(
- self,
- baseTime,
- nbSlices,
- gpioPin,
- gpioScheme,
- ):
- """
- Init the PiSoftPwm instance. Expected parameters are :
- - baseTime : the base time in seconds for the PWM pattern. You may choose a small value (i.e 0.01 s)
- - nbSlices : the number of divisions of the PWM pattern. A single pulse will have a min duration of baseTime * (1 / nbSlices)
- - gpioPin : the pin number which will act as PWM ouput
- - gpioScheme : the GPIO naming scheme (see RPi.GPIO documentation)
- """
- self.sliceTime = baseTime / nbSlices
- self.baseTime = baseTime
- self.nbSlices = nbSlices
- self.gpioPin = gpioPin
- self.terminated = False
- self.toTerminate = False
- GPIO.setmode(gpioScheme)
- def start(self, nbSlicesOn):
- """
- Start PWM output. Expected parameter is :
- - nbSlicesOn : number of divisions (on a total of nbSlices - see init() doc) to set HIGH output on the GPIO pin
- Exemple : with a total of 100 slices, a baseTime of 1 second, and an nbSlicesOn set to 25, the PWM pattern will
- have a duty cycle of 25%. With a duration of 1 second, will stay HIGH for 1*(25/100) seconds on HIGH output, and
- 1*(75/100) seconds on LOW output.
- """
- self.nbSlicesOn = nbSlicesOn
- GPIO.setup(self.gpioPin, GPIO.OUT)
- self.thread = threading.Thread(None, self.run, None, (), {})
- self.thread.start()
- def run(self):
- """
- Run the PWM pattern into a background thread. This function should not be called outside of this class.
- """
- while self.toTerminate == False:
- GPIO.setmode(GPIO.BCM)
- if self.nbSlicesOn > 0:
- GPIO.output(self.gpioPin, GPIO.HIGH)
- time.sleep(self.nbSlicesOn * self.sliceTime)
- if self.nbSlicesOn < self.nbSlices:
- GPIO.output(self.gpioPin, GPIO.LOW)
- time.sleep((self.nbSlices - self.nbSlicesOn)
- * self.sliceTime)
- self.terminated = True
- def changeNbSlicesOn(self, nbSlicesOn):
- """
- Change the duration of HIGH output of the pattern. Expected parameter is :
- - nbSlicesOn : number of divisions (on a total of nbSlices - see init() doc) to set HIGH output on the GPIO pin
- Exemple : with a total of 100 slices, a baseTime of 1 second, and an nbSlicesOn set to 25, the PWM pattern will
- have a duty cycle of 25%. With a duration of 1 second, will stay HIGH for 1*(25/100) seconds on HIGH output, and
- 1*(75/100) seconds on LOW output.
- """
- self.nbSlicesOn = nbSlicesOn
- def changeNbSlices(self, nbSlices):
- """
- Change the number of slices of the PWM pattern. Expected parameter is :
- - nbSlices : number of divisions of the PWM pattern.
- Exemple : with a total of 100 slices, a baseTime of 1 second, and an nbSlicesOn set to 25, the PWM pattern will
- have a duty cycle of 25%. With a duration of 1 second, will stay HIGH for 1*(25/100) seconds on HIGH output, and
- 1*(75/100) seconds on LOW output.
- """
- if self.nbSlicesOn > nbSlices:
- self.nbSlicesOn = nbSlices
- self.nbSlices = nbSlices
- self.sliceTime = self.baseTime / self.nbSlices
- def changeBaseTime(self, baseTime):
- """
- Change the base time of the PWM pattern. Expected parameter is :
- - baseTime : the base time in seconds for the PWM pattern.
- Exemple : with a total of 100 slices, a baseTime of 1 second, and an nbSlicesOn set to 25, the PWM pattern will
- have a duty cycle of 25%. With a duration of 1 second, will stay HIGH for 1*(25/100) seconds on HIGH output, and
- 1*(75/100) seconds on LOW output.
- """
- self.baseTime = baseTime
- self.sliceTime = self.baseTime / self.nbSlices
- def stop(self):
- """
- Stops PWM output.
- """
- self.toTerminate = True
- while self.terminated == False:
- # Just wait
- time.sleep(0.01)
- GPIO.output(self.gpioPin, GPIO.LOW)
- GPIO.setup(self.gpioPin, GPIO.IN)
- # IGNORE
- class Motor():
- def __init__(self):
- # MC33932 pins
- self.PWMA = 25
- self.PWMB = 22
- self._IN1 = 24
- self._IN2 = 23
- self._IN3 = 17
- self._IN4 = 27
- # Initialize PWMA PWMB
- GPIO.setmode(GPIO.BCM)
- GPIO.setup(self.PWMA, GPIO.OUT)
- GPIO.setup(self.PWMB, GPIO.OUT)
- GPIO.setup(self._IN1, GPIO.OUT)
- GPIO.setup(self._IN2, GPIO.OUT)
- GPIO.setup(self._IN3, GPIO.OUT)
- GPIO.setup(self._IN4, GPIO.OUT)
- GPIO.output(self.PWMA, True)
- GPIO.output(self.PWMB, True)
- # Initialize PWM outputs
- self.OUT_1 = PiSoftPwm(0.1, 100, self._IN1, GPIO.BCM)
- self.OUT_2 = PiSoftPwm(0.1, 100, self._IN2, GPIO.BCM)
- self.OUT_3 = PiSoftPwm(0.1, 100, self._IN3, GPIO.BCM)
- self.OUT_4 = PiSoftPwm(0.1, 100, self._IN4, GPIO.BCM)
- # Close pwm output
- self.OUT_1.start(0)
- self.OUT_2.start(0)
- self.OUT_3.start(0)
- self.OUT_4.start(0)
- self.frequency = 0.01
- self.duty = 20
- def Setting(self, frequency, duty):
- self.frequency = frequency
- self.duty = duty
- def Go_1(self, duty=100, freq=0.01):
- self.OUT_1.changeBaseTime(freq)
- self.OUT_2.changeBaseTime(freq)
- self.OUT_1.changeNbSlicesOn(duty)
- self.OUT_2.changeNbSlicesOn(0)
- def Back_1(self,duty=100, freq=0.01):
- self.OUT_1.changeBaseTime(freq)
- self.OUT_2.changeBaseTime(freq)
- self.OUT_1.changeNbSlicesOn(0)
- self.OUT_2.changeNbSlicesOn(duty)
- def Go_2(self,duty=100,freq=0.01):
- self.OUT_3.changeBaseTime(freq)
- self.OUT_4.changeBaseTime(freq)
- self.OUT_3.changeNbSlicesOn(duty)
- self.OUT_4.changeNbSlicesOn(0)
- def Back_2(self,duty=100, freq=0.01):
- self.OUT_3.changeBaseTime(freq)
- self.OUT_4.changeBaseTime(freq)
- self.OUT_3.changeNbSlicesOn(0)
- self.OUT_4.changeNbSlicesOn(duty)
- def Stop(self):
- self.OUT_1.changeNbSlicesOn(0)
- self.OUT_2.changeNbSlicesOn(0)
- self.OUT_3.changeNbSlicesOn(0)
- self.OUT_4.changeNbSlicesOn(0)
- # change under advisement
- TIMEOUT_BETWEEN_ULTRASOUND = 0.1
- # IGNORE
- class UltrasoundSensor(threading.Thread):
- def __init__(self, trig_pin, echo_pin):
- self.trig_pin = trig_pin
- self.echo_pin = echo_pin
- self.terminated = False
- self.toTerminate = False
- self.val = -1
- def start(self):
- self.thread = threading.Thread(None, self.run, None, (), {})
- self.thread.start()
- return self
- def stop(self):
- self.toTerminate = True
- while self.terminated == False:
- time.sleep(0.01)
- def setup(self):
- GPIO.setmode(GPIO.BCM)
- GPIO.setup(self.trig_pin, GPIO.OUT) # Set pin as GPIO out
- GPIO.setup(self.echo_pin, GPIO.IN) # Set pin as GPIO in
- def sense(self):
- return self.val
- def run(self):
- self.setup()
- while not self.toTerminate:
- self.setup()
- # Return distance in cm
- GPIO.output(self.trig_pin, False)
- time.sleep(0.05)
- self.setup()
- GPIO.output(self.trig_pin, True) # Set self.trig_pin as HIGH
- time.sleep(0.0001) # Delay of 0.00001 seconds
- self.setup()
- GPIO.output(self.trig_pin, False)
- pulse_start = pulse_end = None
- start_time = time.time()
- while GPIO.input(self.echo_pin) == 0 and time.time() \
- - start_time <= TIMEOUT_BETWEEN_ULTRASOUND: # Check whether the self.echo_pin is LOW
- pulse_start = time.time() # Saves the last known time of LOW pulse
- start_time = time.time()
- while GPIO.input(self.echo_pin) == 1 and time.time() \
- - start_time <= TIMEOUT_BETWEEN_ULTRASOUND:
- pulse_end = time.time()
- if pulse_start is None or pulse_end is None:
- self.val = -1
- continue
- pulse_duration = pulse_end - pulse_start
- distance = pulse_duration * 17150
- self.val = distance - .5
- time.sleep(0.1)
- self.terminated = True
- ## actual start
- #constants
- wait_for_press = True
- POWER = 83
- calibrate = True
- # always run
- motor1=None
- def resetMotors(signalnum=None, handler=None):
- global motor1
- motor1.OUT_1.stop()
- motor1.OUT_2.stop()
- motor1.OUT_3.stop()
- motor1.OUT_4.stop()
- GPIO.cleanup()
- exit(0)
- def find_mode(data):
- try:
- if data is None or len(data) == 0:
- return [0]
- from collections import Counter
- mo = Counter(data).most_common()
- if len(mo) == 0:
- return data
- return [mo]
- except Exception as e:
- print(e)
- def remove_outliers(data, m=2):
- if len(data) == 0:
- return []
- return data[abs(data - np.mean(data)) < m * np.std(data)]
- def go():
- global motor1
- sensor1=sensor2=sensor3=None
- try:
- GPIO.setmode(GPIO.BCM)
- GPIO.setup(3, GPIO.IN)
- if wait_for_press:
- time_cnt = 0
- while True:
- if time_cnt % 20 == 0:
- print("Waiting for button press %i"% int(time_cnt/20))
- if not GPIO.input(3):
- break
- time_cnt += 1
- time.sleep(0.05)
- print("Waiting 5 second then start!")
- distances_left = []
- distances_mid = []
- distances_right =[]
- diffs_left = []
- diffs_mid =[]
- diffs_right = []
- left_duty = 100
- right_duty = 100
- sensor1 = UltrasoundSensor(12,16).start()
- sensor2 = UltrasoundSensor(12,20).start()
- sensor3 = UltrasoundSensor(12,21).start()
- motor1 = Motor()
- time.sleep(5)
- # Called on process interruption. Set all pins to "Input" default mode.
- # motor1.Go_2()
- min_distance = 20
- start = time.time()
- print("MEH")
- while time.time() - start < 40 and GPIO.input(3):
- left_sensor = sensor1.sense()
- mid_sensor = sensor2.sense()
- right_sensor = sensor3.sense()
- distances_left.append(int(left_sensor - 1))
- diffs_left.append(int(left_sensor - 1))
- distances_mid.append(int(mid_sensor))
- diffs_mid.append(int(mid_sensor))
- distances_right.append(int(right_sensor - 5))
- diffs_right.append(int(right_sensor -5 ))
- print("t0")
- #distances_left = remove_outliers(distances_left)
- print("t1")
- #diffs_left = remove_outliers(diffs_left)
- print("t2")
- #distances_mid = remove_outliers(distances_mid)
- print("t3")
- #diffs_mid = remove_outliers(diffs_mid)
- #distances_right = remove_outliers(distances_right)
- #diffs_right = remove_outliers(diffs_right)
- if len(distances_left) > 10:
- distances_left.pop(0)
- if len(distances_mid) > 10:
- distances_mid.pop(0)
- if len(distances_right) > 10:
- distances_right.pop(0)
- if len(diffs_left) > 20:
- diffs_left.pop(0)
- if len(diffs_mid) > 20:
- diffs_mid.pop(0)
- if len(diffs_right) > 20:
- diffs_right.pop(0)
- # Predict the future O_O
- if len(diffs_left) < 5 or len(diffs_right) < 5 or len(diffs_mid) < 5:
- left_diff = 0
- mid_diff = 0
- right_diff = 0
- else:
- left_fit = np.polyfit(np.arange(len(diffs_left)),diffs_left,1)
- left_fit_fn = np.poly1d(left_fit)
- left_diff = left_fit_fn.c[0]
- mid_fit = np.polyfit(np.arange(len(diffs_mid)), diffs_mid, 1)
- mid_fit_fn = np.poly1d(mid_fit)
- mid_diff = mid_fit_fn.c[0]
- right_fit = np.polyfit(np.arange(len(diffs_right)), diffs_right, 1)
- right_fit_fn = np.poly1d(right_fit)
- right_diff = right_fit_fn.c[0]
- #
- print("justbefore")
- mo_left = find_mode(distances_left)
- print("CAKE")
- mo_mid = find_mode(distances_mid)
- mo_right = find_mode(distances_right)
- distance_left = sorted(mo_left)[len(mo_left)//2] + left_diff
- distance_mid = sorted(mo_mid)[len(mo_mid)//2] + mid_diff
- distance_right = sorted(mo_right)[len(mo_right)//2] + right_diff
- print("Sensor 1: %dcm, Sensor 2: %dcm, Sensor 3: %dcm, Dist left: %dcm, Dist mid: %dcm, Dist right: %dcm, Grad left: %dcm, Grad mid: %dcm, Grad right: %dcm" % (left_sensor, mid_sensor, right_sensor, distance_left, distance_mid, distance_right, left_diff, mid_diff, right_diff))
- print(sorted(distances_left))
- distance_right = min(abs(distance_right), 100)
- distance_mid = min(abs(distance_mid), 100)
- distance_left = min(abs(distance_left), 100)
- distance_diff = distance_right-distance_left
- t_power =POWER* math.e**(-(abs(distance_diff)-0.01)/((20-0.01)/(-math.log(0.03, math.e))))
- if abs(distance_diff) > 3:
- if distance_diff >= 0:
- power_right = max(t_power, POWER*.3)
- power_left = max(POWER-t_power, POWER*.3)
- else:
- power_left = max(t_power, POWER*.3)
- power_right = max(POWER-t_power, POWER*.3)
- else:
- power_left = power_right = t_power
- print(str(power_left) + ":"+ str(power_right) + "---" + str(t_power))
- if not calibrate:
- motor1.Go_1(duty=power_left)
- motor1.Go_2(duty=power_right)
- #if distance_left < min_distance:
- #left_duty = (left_duty -1) % 100
- #right_duty = (right_duty + 1) % 100
- # motor1.Go_2(duty=POWER*0.7)
- # motor1.Go_1(duty=POWER)
- #elif distance_right < min_distance:
- #right_duty = (right_duty - 1 ) % 100
- #left_duty = (left_duty + 1) % 100
- # motor1.Go_2(duty=POWER)
- # motor1.Go_1(duty=POWER*0.7)
- #else:
- # motor1.Go_1(duty=POWER)
- # motor1.Go_2(duty=POWER)
- #motor1.Go_1(duty=left_duty)
- #motor1.Go_2(duty=right_duty)
- time.sleep(0.05)
- except:
- print(sys.exc_info()[0])
- finally:
- print("FINALLY...")
- resetMotors()
- if sensor1 is not None:
- sensor1.stop()
- if sensor2 is not None:
- sensor2.stop()
- if sensor3 is not None:
- sensor3.stop()
- GPIO.cleanup()
- if __name__=="__main__":
- signal.signal(signal.SIGTERM, resetMotors)
- signal.signal(signal.SIGINT, resetMotors)
- signal.signal(signal.SIGHUP, resetMotors)
- signal.signal(signal.SIGQUIT, resetMotors)
- try:
- go()
- finally:
- resetMotors()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement