def speak_and_rotate(): sound = Sound() os.system('setfont Lat15-TerminusBold14') mL = LargeMotor('outB') mL.stop_action = 'hold' mR = LargeMotor('outC') mR.stop_action = 'hold' print('Hello, my name is EV3D4!') str_en = 'Hello, my name is E V 3 D 4!' opts = '-a 200 -s 150 -p 70 -v' sound.speak(str_en, espeak_opts=opts + 'en+f5') sleep(2) str_en = "Performing perimeter scan" sound.speak(str_en, espeak_opts=opts + 'en+f5') # Sound.speak('Hello, my name is Evie, 3 D 4!').wait() mL.run_to_rel_pos(position_sp=1662, speed_sp=300) mR.run_to_rel_pos(position_sp=-1662, speed_sp=300) #mL.wait_while('running') #mR.wait_while('running') sleep(1) str_en = "At your command Big Daddy" sound.speak(str_en, espeak_opts=opts + 'en+f5') sleep(1)
else: cs2_black['0'] = False t = Thread(target=notBlack, args=(cs, cs2)) t.start() sleep(1) while (True): while (cs_black['0'] or cs2_black['0']): sleep(0.4) lm.run_forever(speed_sp=150, stop_action="hold") lm2.run_forever(speed_sp=150, stop_action="hold") lm.stop(stop_action="hold") lm2.stop(stop_action="hold") if (i['0'] == 1): while (cs_black['0'] == False and cs2_black['0'] == False): lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=7, speed_sp=200, stop_action="hold") lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=30, speed_sp=500, stop_action="hold") elif (i['0'] == 2): while (cs_black['0'] == False and cs2_black['0'] == False): lm.run_to_rel_pos(position_sp=7, speed_sp=200, stop_action="hold") lm2.run_to_rel_pos(position_sp=0, stop_action="hold") lm.run_to_rel_pos(position_sp=30, speed_sp=500, stop_action="hold") lm2.run_to_rel_pos(position_sp=0, stop_action="hold")
derivative = (error - previous_error) / dt u = (Kp * error) + (Ki * integral) + (Kd * derivative) t = Thread(target=notBlack, args=(cs, cs2)) t.start() sleep(1) while (True): while (cs_black['0'] or cs2_black['0']): sleep(1) lm.run_forever(speed_sp=SpeedPercent(100), stop_action="hold") lm2.run_forever(speed_sp=SpeedPercent(100), stop_action="hold") lm.stop(stop_action="hold") lm2.stop(stop_action="hold") if (i['0'] == 1): while (cs_black['0'] == False and cs2_black['0'] == False): lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=6, speed_sp=300, stop_action="hold") lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=15, speed_sp=600, stop_action="hold") elif (i['0'] == 2): while (cs_black['0'] == False and cs2_black['0'] == False): lm.run_to_rel_pos(position_sp=6, speed_sp=300, stop_action="hold") lm2.run_to_rel_pos(position_sp=0, stop_action="hold") lm.run_to_rel_pos(position_sp=15, speed_sp=600, stop_action="hold") lm2.run_to_rel_pos(position_sp=0, stop_action="hold")
from ev3dev2.motor import LargeMotor, OUTPUT_A, OUTPUT_B, SpeedPercent, MoveTank from ev3dev2.sensor import INPUT_1 from ev3dev2.sensor.lego import TouchSensor from ev3dev2.led import Leds from ev3dev2.sound import Sound sound = Sound() sound.speak('Welcome to the E V 3 dev project!') sound.speak('Hi Tim id like to drive') #!/usr/bin/env python3 # so that script can be run from Brickman from ev3dev.ev3 import * from time import sleep #text to speech Sound.speak('Hello, my name is E V 3!').wait() m = LargeMotor('outC') m2 = LargeMotor('outB') m.run_to_rel_pos(position_sp=-3600, speed_sp=900, stop_action="hold") m2.run_to_rel_pos(position_sp=-3600, speed_sp=900, stop_action="hold") sleep(5) # Give the motor time to move m.run_to_rel_pos(position_sp=36000, speed_sp=900, stop_action="hold") m2.run_to_rel_pos(position_sp=36000, speed_sp=900, stop_action="hold") sleep(5) # Give the motor time to move
t = Thread(target=notBlack, args=(cs, cs2)) t.start() # keyboard.is_pressed('ENTER') != while (True): sleep(1) while (cs_black['0'] or cs2_black['0']): lm.run_forever(speed_sp=SpeedPercent(100), stop_action="hold") lm2.run_forever(speed_sp=SpeedPercent(100), stop_action="hold") # lm.run_to_rel_pos(position_sp=50, speed_sp=SpeedPercent(40), stop_action="hold") # lm2.run_to_rel_pos(position_sp=50, speed_sp=SpeedPercent(40), stop_action="hold") if (i['0'] == 1): while (cs_black['0'] == False and cs2_black['0'] == False): lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=3, speed_sp=SpeedPercent(100), stop_action="hold") # sleep(5) # s.beep() # # lm.run_forever(stop_action="hold") # # lm2.run_forever(speed_sp=SpeedPercent(100), stop_action="hold") # # lm.run_to_rel_pos(position_sp=2, stop_action="hold") # # lm2.run_to_rel_pos(position_sp=3, speed_sp=SpeedPercent(100), stop_action="hold") pass elif (i['0'] == 2): while (cs_black['0'] == False and cs2_black['0'] == False): lm.run_to_rel_pos(position_sp=3, speed_sp=SpeedPercent(100),
if (i['0'] == 1): while (cs_black['0'] == False and cs2_black['0'] == False): error = target_value - cs.value() integral += (error * dt) derivative = (error - previous_error) / dt u = (Kp * error) + (Ki * integral) + (Kd * derivative) previous_error = error if speed + abs(u) > 1000: if u >= 0: u = 1000 - speed else: u = speed - 1000 if u >= 0: lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=7, speed_sp=speed-u, stop_action="hold") else: lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=7, speed_sp=speed+u, stop_action="hold") lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=8, speed_sp=600, stop_action="hold") elif (i['0'] == 2): while (cs_black['0'] == False and cs2_black['0'] == False): error = target_value - cs.value() integral += (error * dt) derivative = (error - previous_error) / dt u = (Kp * error) + (Ki * integral) + (Kd * derivative)
# u zero: on target, drive forward # u positive: too bright, turn right # u negative: too dark, turn left u['0'] = Kp['0']*error['0'] + Ki['0']*integ['0'] + Kd['0']*deriv['0'] lastError['0'] = error['0'] if(u['0'] >= 0): lm.run_forever(speed_sp=200+u['0'], stop_action="hold") lm2.run_forever(speed_sp=200-u['0'], stop_action="hold") else: lm.run_forever(speed_sp=200-u['0'], stop_action="hold") lm2.run_forever(speed_sp=200+u['0'], stop_action="hold") if (z['0'] == 2 and q['0'] == 0): while (z['0'] != 1 or q['0'] != 1): lm.run_to_rel_pos(position_sp=0, stop_action="hold") lm2.run_to_rel_pos(position_sp=1, speed_sp=400, stop_action="hold") continue elif (z['0'] == 3 and q['0'] == 0): while (z['0'] != 1): lm.run_to_rel_pos(position_sp=1, speed_sp=400, stop_action="hold") lm2.run_to_rel_pos(position_sp=0, stop_action="hold") continue elif (q['0'] == 3): while (cs2.value() < 20): lm.run_to_rel_pos(position_sp=1, speed_sp=400, stop_action="hold") lm2.run_to_rel_pos(position_sp=0, stop_action="hold") continue elif (q['0'] == 2): while (cs.value() < 20): lm.run_to_rel_pos(position_sp=0, stop_action="hold")
start_pos = 0 end_pos = 0 start_time = 0.0 end_time = 0.0 m = LargeMotor(OUTPUT_A) time.sleep(0.1) m.reset() time.sleep(0.1) start_time = time.time() m.stop_action ='coast' m.ramp_up_sp = 2000 #### supported on BrickPi3; ramp_up seems to work but ramp_down...not so well, at least with stop_action='brake' m.ramp_down_sp = 1000 #### supported on BrickPi3; ramp_up seems to work but ramp_down...not so well, at least with stop_action='brake' t1=time.time() for i in range(10, 500, 10): print("START --------> m.on...", round((time.time() - t1), 4)) #m.on_to_position(SpeedDPS(200), (i * 360), brake=False, block=True) ### this method FAILS TO BLOCK with PiStorms m.run_to_rel_pos(position_sp=(i * 360), speed_sp=900, stop_action="coast") ### no claim of blocking m.wait_until_not_moving() #m.on_for_degrees(SpeedDPS(900), (i * 360), brake=False, block=True) ### this method FAILS TO BLOCK with PiStorms #m.on_for_seconds(SpeedDPS(900), 15, brake=False, block=True) print ("target pos = ", (i * 360), "; actual pos = ", m.position, round((time.time() - t1), 4)) #print ("target pos = n/a (on_for_seconds); actual pos = ", m.position, round((time.time() - t1), 4)) time.sleep(.1) time.sleep(10) m.off()
class DeVestenBot(): '''Basisklasse voor de robot van De Vesten''' # settings voor data logging SERVER_IP = '10.42.0.1' # dit is zo op Linux met een bluetoothverbinding, geen idee voor de rest SERVER_PORT = 2444 # één twee drie vieren hahaha def __init__(self): # motors self.motor_links_poort = OUTPUT_B self.motor_rechts_poort = OUTPUT_C self.motor_links = LargeMotor(self.motor_links_poort) self.motor_rechts = LargeMotor(self.motor_rechts_poort) self.geluid = sound.Sound() self.motor_grijper = MediumMotor(OUTPUT_A) # sensors self.gyro = GyroSensor(address=INPUT_2) self.touch = TouchSensor(address=INPUT_1) self.kleur = ColorSensor(address=INPUT_3) # start data logger in eigen thread t_data_logger = threading.Thread(target=self.data_logger) t_data_logger.start() # slechte oplossing gyro probleem self.laatst_gemeten_hoek = 0 self.gyro.mode = self.gyro.MODE_GYRO_RATE time.sleep(1) self.gyro.mode = self.gyro.MODE_GYRO_ANG # # data logging # def data_logger(self): MOTOR_LINKS = 'MOTOR_LINKS' MOTOR_RECHTS = 'MOTOR_RECHTS' GRIJPER = 'GRIJPER' GYRO = 'GYRO' AFSTAND = 'AFSTAND' KLEUR = 'KLEUR' DRUK = 'DRUK' sensor_data = { MOTOR_LINKS: None, MOTOR_RECHTS: None, GRIJPER: None, GYRO: None, AFSTAND: None, KLEUR: None, DRUK: None } def get_sensor_data(): sensor_data['TIMESTAMP'] = round(time.clock(), 2) sensor_data[MOTOR_LINKS] = round(self.motor_links.degrees) sensor_data[MOTOR_RECHTS] = round(self.motor_rechts.degrees) sensor_data[GRIJPER] = round(self.motor_grijper.degrees) sensor_data[GYRO] = round(self.get_gyro_hoek()) sensor_data[AFSTAND] = round(self.meet_afstand_in_cm(), 2) sensor_data[KLEUR] = self.get_kleur() sensor_data[DRUK] = self.is_druksensor_ingedrukt() return sensor_data def get_sensor_data_as_json(): return json.dumps(get_sensor_data()) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: try: s.connect((self.SERVER_IP, self.SERVER_PORT)) while True: s.sendall(get_sensor_data_as_json().encode()) time.sleep(0.1) except ConnectionRefusedError: self.log( "Kon geen verbinding maken met de server voor het dashboard." ) # # Functies ivm rijden # def rij_centimeters(self, centimeters): ''' geef het aantal centimeters dat de bot moet rijden de wielen hebben een diameter van 5,6 cm een volledige rotatie is daarom 5,6 * PI cm = 17,5929188601 cm Een rotatie van 1° komt overeen met 17,5929188601 cm / 360° = 0,048869219 cm om 1 cm te rijden moeten we dus 20,462778421° draaien, helaas heeft de motor maar een precisie van 1° dus er zal een afwijking zijn. De bot zal rijden op een kwart van de maximale snelheid ''' afwijking = 1.02 #correctiefactor, experimenteel te bepalen. hoek_voor_een_cm = 20.462778421 graden = centimeters * hoek_voor_een_cm * afwijking robot_tank_drive = MoveTank(left_motor_port=self.motor_links_poort, right_motor_port=self.motor_rechts_poort) robot_tank_drive.on_for_degrees(left_speed=25, right_speed=25, degrees=graden) def noodstop(self): ''' Gebruik deze functie als je wil dat de robot stopt. Elke actie op de wielen die nog bezig is wordt afgesloten en de robot zal remmen, dit wil zeggen dat hij niet uitbolt maar actief zal proberen te stoppen. ''' self.log("### (noodstop)") self.motor_links.stop(stop_action='brake') self.motor_rechts.stop(stop_action='brake') def rij_tot_kleur_gelijk_aan(self, kleur): ''' Rijdt rechtdoor tot de gegeven kleur herkent wordt. .. code:: python bot.rij_tot_kleur_gelijk_aan(bot.kleur.COLOR_RED) ''' def _rij(self): self.log("### in _rij: run forever") robot_tank_drive = MoveTank( left_motor_port=self.motor_links_poort, right_motor_port=self.motor_rechts_poort) robot_tank_drive.on(left_speed=50, right_speed=50) t_rij = threading.Thread(target=_rij, args=(self, )) t_rij.start() while self.get_kleur() != kleur: self.log(str(self.get_kleur())) pass self.noodstop() def rij_tot_kleur_verschillend_van(self, kleur): ''' Rij rechtdoor tot de gegeven kleur niet meer gemeten wordt. .. code:: python bot.rij_tot_kleur_verschillend_van(bot.kleur.COLOR_RED) ''' def _rij(self): self.log("### in _rij: run forever") robot_tank_drive = MoveTank( left_motor_port=self.motor_links_poort, right_motor_port=self.motor_rechts_poort) robot_tank_drive.on(left_speed=50, right_speed=50) t_rij = threading.Thread(target=_rij, args=(self, )) t_rij.start() while self.get_kleur() == kleur: self.log(str(self.get_kleur())) pass self.noodstop() # # Functies ivm draaien # def draai_graden(self, graden): ''' Draai de robot het gegeven aantal graden. Deze functie gebruikt de gyro-sensor en omdat deze nogal traag is en neiging heeft tot driften is deze functie nogal complex. De robot zal eerst trachten het correcte aantal graden te draaien, vervolgens wachten tot de gyro een stabiele uitlezing geeft en daarna een eventuele correctie toepassen. Moest de gyro beginnen driften zal de uitlezing gestopt worden na 1 seconde, de afwijking in dat geval is enkele graden (ongeveer 3). Let op dat de afwijking cumulatief is, hoe meer gedraai hoe groter de afwijking, vooral als er veel in dezelfde richting gedraaid wordt. ''' # deze waarden kan je tunen SNELHEID_HOOG = 70 SNELHEID_LAAG = 30 MAX_GYRO_METING_ITERATIES = 10 #als de gyro begint te driften duurt het eeuwig, stop daarom na 10 metingreeksen (1 seconde) # deze niet veranderen WIJZERZIN = 1 TEGENWIJZERZIN = -1 def _wacht_tot_gyro_meting_stabiel(): self.log("debug: wacht tot gyro meting stabiel...") def _gyro_stabiel(metingen): def _meting_volledig(): if len(metingen) == 10: return True else: return False def _10_metingen_gelijk(): self.log(str(meting_ring)) for i in range(1, 10): if metingen[i] != metingen[0]: self.log("debug: gyro NIET stabiel, wachten....") return False self.log("debug: gryo stabiel") return True if _meting_volledig(): return _10_metingen_gelijk() else: return False meting_ring = collections.deque(maxlen=10) iteraties = 0 while _gyro_stabiel(meting_ring) == False: if iteraties >= MAX_GYRO_METING_ITERATIES: self.log( "debug: max iteraties bereikt, gyro is aan het driften: stop wachten" ) break meting_ring.append(self.get_gyro_hoek()) iteraties = iteraties + 1 time.sleep(0.1) def _roteer_robot_graden(hoek, snelheid): def _reset_gyro(): self.log("debug: gyro resetten...") self.gyro.mode = self.gyro.MODE_GYRO_RATE _wacht_tot_gyro_meting_stabiel() self.gyro.mode = self.gyro.MODE_GYRO_ANG _wacht_tot_gyro_meting_stabiel() self.log("debug: gyro reset voltooid.") def _get_rotatie_zin(graden): if graden > 0: return WIJZERZIN return TEGENWIJZERZIN def _wacht_tot_gewenste_hoek_bereikt(hoek): def _blijf_draaien(graden): if _get_rotatie_zin(graden) == WIJZERZIN: if self.get_gyro_hoek() < graden: return True else: if self.get_gyro_hoek() > graden: return True return False while _blijf_draaien(hoek): self.log(str(self.get_gyro_hoek())) pass def _draai_robot_in_thread(zin, snelheid): def _draai_robot(zin, snelheid): self.motor_links.run_forever(speed_sp=snelheid * zin, stop_action='brake') self.motor_rechts.run_forever(speed_sp=-snelheid * zin, stop_action='brake') t_draaien = threading.Thread(target=_draai_robot, args=(zin, snelheid)) t_draaien.start() _reset_gyro() _draai_robot_in_thread(_get_rotatie_zin(hoek), snelheid) _wacht_tot_gewenste_hoek_bereikt(hoek) self.noodstop() def _corrigeer_overshot(): _wacht_tot_gyro_meting_stabiel() overshoot_correctie = graden - self.get_gyro_hoek() _roteer_robot_graden(overshoot_correctie, SNELHEID_LAAG) _roteer_robot_graden(graden, SNELHEID_HOOG) _corrigeer_overshot() def draai_graden_geen_gyro(self, graden): ''' Gebruik deze functie om de robot te draaien zonder gebruik te maken van de gyro-sensor. Afhankelijk van de robot en sensor kan dit nauwkeuriger zijn, geef het aantal graden dat de robot moet draaien, wijzerzin is positief. De robot heeft een breedte van 15cm, maar we nemen het midden van de wielen als de buitenste maat voor de cirkel die we gebruiken in de berekening. Een wiel is 2,8cm breed, 2 halve wielen aftrekken van 15cm geeft 12,2cm. Voor een volledige draai van 360° moet elk wiel dus 12,2*PI (= 38,3274303738) cm rijden in tegengestelde zin. 1° draaien is dus 0,106465084 cm voor elk wiel en dat komt overeen met 2,178571423° wielrotatie ''' wielrotatie_per_graad = 2.178571423 correctiefactor = 0.981 wielrotatie = wielrotatie_per_graad * graden * correctiefactor wielrotatie_links = wielrotatie wielrotatie_rechts = wielrotatie * -1 self.motor_links.run_to_rel_pos(position_sp=wielrotatie_links, stop_action="hold", speed_sp=75) self.motor_rechts.run_to_rel_pos(position_sp=wielrotatie_rechts, stop_action="hold", speed_sp=75) self.motor_links.wait_while('running') self.motor_rechts.wait_while('running') def draai_links(self): '''Draai de robot 90° naar links, een kleine afwijking (tot 3°) is mogelijk, meestal door overshoot.''' self.draai_graden(-90) def draai_rechts(self): '''Draai de robot 90° naar rechts, een kleine afwijking (tot 3°) is mogelijk, meestal door overshoot.''' self.draai_graden(90) def keer_om(self): '''Draai de robot 180° naar rechts, een kleine afwijking (tot 3°) is mogelijk, meestal door overshoot.''' self.draai_graden(180) # # Functies ivm de grijper # def grijper_open(self): '''Zet de grijper omhoog.''' self.motor_grijper.on_for_degrees(degrees=180, speed=50) self.motor_grijper.off() def grijper_sluit(self): '''Doe de grijper omlaag.''' self.motor_grijper.on_for_degrees(degrees=-180, speed=50) self.motor_grijper.off() # # Functies ivm de sensoren # # Ultrasoon def meet_afstand_in_cm(self): sensor = UltrasonicSensor(INPUT_4) afstand = sensor.distance_centimeters return afstand # Druksensor def is_druksensor_ingedrukt(self): '''antwoord met True als de sensor ingedrukt is, anders False''' return self.touch.is_pressed # Kleursensor def get_kleur(self): return self.kleur.color # Gyroscoop def get_gyro_hoek(self): ''' Het uitlezen van de gyro geeft soms een lege waarde terug wat resulteert in ValueErrors aangezien er een integer verwacht wordt. Gebruik steeds deze functie om de gyro uit te lezen om dit te voorkomen. ''' hoek = self.laatst_gemeten_hoek try: hoek = self.gyro.angle self.laatst_gemeten_hoek = hoek except ValueError: self.log("ValueError opgevangen, int verwacht maar was: " + str(hoek)) return hoek # # Functies voor output die de robot kan doen # # Console logging (remote) def log(self, text_to_print): '''print output naar console in VSCode''' print(text_to_print, file=sys.stderr) # Scherm # TODO # Geluid def spreek(self, zin, wacht=False): ''' Text to speech, geef de zin die de robot moet zeggen als parameter. Deze functie werkt assynchroon dus de robot gaat verder met zijn anderen handelingen terwijl hij spreekt. Wil je die niet gebruik dan "wacht=True". ''' def _spreek(): self.geluid.speak(zin) if (wacht): _spreek().wait() else: _spreek() def speel(self, wav, wacht=False): ''' Speel een wav file. Deze functie is asynchroon, wil je dat je robot wacht tot het geluid klaar is met spelen gebruik dan "wacht=True". Let er op dat de file niet te groot is, het duurt dan langer om je programma te starten (bij elke start van een script worden alle files geupload naar de robot) en het geheugen is beperkt. Met Audacity kan je 16 bit mono wavs maken. ''' def _speel(): self.geluid.play(wav) if (wacht): _speel().wait() else: _speel().play(wav) # # Ev3dev ondersteunt nog veel meer manieren om je robot geluid te laten maken, zo is er bv nog de mogelijkheid om beepjes # te maken, noten op de juiste toon en met de gewenste duur te spelen en zelfs hele muziekstukken. Moest dit je interesseren # kan dit een leuke oefening zijn om zelf een functie te implementeren die dit toestaat. De help tekst van de Sound library # kan je op weg helpen. # def exit_program(self): ''' Sluit je programma en alle threads af zodat je dat niet manueel moet doen in VS Code. ''' time.sleep(2) os._exit(0)
# Global Software Product Development # !/usr/bin/env python3 from ev3dev2.motor import LargeMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, SpeedPercent, MoveTank from ev3dev2.sensor import INPUT_1, INPUT_2, INPUT_3, INPUT_4 from ev3dev2.sensor.lego import TouchSensor, GyroSensor from ev3dev2.led import Leds from time import sleep # Variable Assignments ts = TouchSensor(INPUT_1) leds = Leds() lift = LargeMotor(OUTPUT_A) # Forklift mL = LargeMotor(OUTPUT_B) # Left Motor mR = LargeMotor(OUTPUT_C) # Right Motor print('Hello, my name is EV3!') Sound.speak('Hello, my name is EV3!').wait() mL.run_to_rel_pos(position_sp=840, speed_sp=250) mR.run_to_rel_pos(position_sp=-840, speed_sp=250) mL.wait_while('running') mR.wait_while('running')