diff --git a/software/roboter/ev3/drive_arm.py b/software/roboter/ev3/drive_arm.py index d3955a7..b0ed571 100644 --- a/software/roboter/ev3/drive_arm.py +++ b/software/roboter/ev3/drive_arm.py @@ -1,4 +1,13 @@ #!/usr/bin/env python3 + +""" +created by waldhauser + +This file contains the programm to drive the arm back to middle +This file is needed for the color code drive operation +The plant where the robot is has to be passed as argument +""" + from ev3dev2.motor import Motor, OUTPUT_B, OUTPUT_C, SpeedPercent import sys diff --git a/software/roboter/ev3/drive_back.py b/software/roboter/ev3/drive_back.py index 0c4d647..09a3983 100644 --- a/software/roboter/ev3/drive_back.py +++ b/software/roboter/ev3/drive_back.py @@ -1,4 +1,13 @@ #!/usr/bin/env python3 + +""" +created by waldhauser + +This file contains the programm to drive the arm back to middle and drive the robot back to home +This file is needed for the hard code driving operations +The plant where the robot is has to be passed as argument +""" + from ev3dev2.motor import Motor, LargeMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent from ev3dev2.sensor.lego import TouchSensor, UltrasonicSensor from ev3dev2.sensor import INPUT_1, INPUT_4 @@ -31,8 +40,6 @@ while True: motorRight.on(SpeedPercent(-25)) break - - sensorTouch.wait_for_pressed(timeout_ms=None, sleep_ms=10) motorLeft.off() motorRight.off() \ No newline at end of file diff --git a/software/roboter/ev3/drive_back_straight.py b/software/roboter/ev3/drive_back_straight.py index a23b75c..8ec5cda 100644 --- a/software/roboter/ev3/drive_back_straight.py +++ b/software/roboter/ev3/drive_back_straight.py @@ -1,4 +1,14 @@ #!/usr/bin/env python3 + +""" +created by waldhauser + +This file contains the programm to drive the robot back to the starting position +This file is needed for the color code drive operation +No arguments are needed +The end is determined by the UltraSonic- and TouchSensor +""" + from ev3dev2.motor import LargeMotor, OUTPUT_A, OUTPUT_D, SpeedPercent from ev3dev2.sensor.lego import TouchSensor, UltrasonicSensor from ev3dev2.sensor import INPUT_1, INPUT_4 diff --git a/software/roboter/ev3/drive_plant.py b/software/roboter/ev3/drive_plant.py index ab61c49..2217413 100644 --- a/software/roboter/ev3/drive_plant.py +++ b/software/roboter/ev3/drive_plant.py @@ -1,9 +1,11 @@ #!/usr/bin/env pybricks-micropython -''' -Script to drive robot to plant. -Plant number is passed as argument. -''' +""" +created by waldhauser + +This file contians the programm to drive to a specific plant based on the color codes +The plant where the robot is has to be passed as argument +""" from ev3dev2.motor import Motor, LargeMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent from ev3dev2.sensor.lego import ColorSensor diff --git a/software/roboter/ev3/drive_plant_gc.py b/software/roboter/ev3/drive_plant_gc.py deleted file mode 100644 index 242e0f7..0000000 --- a/software/roboter/ev3/drive_plant_gc.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env pybricks-micropython -from pybricks.hubs import EV3Brick -from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, - InfraredSensor, UltrasonicSensor, GyroSensor) -from pybricks.parameters import Port, Stop, Direction, Button, Color -from pybricks.tools import wait, StopWatch, DataLog -from pybricks.robotics import DriveBase -from pybricks.media.ev3dev import SoundFile, ImageFile - -import sys - - -def fun_1(ev3): - pass - - -def fun_2(a,b): - return 1 - -def move_1(mo_forward_1, mo_forward_2, mo_le_ri, mo_up_down): - wait(2000) - #move forward - mo_forward_1.run_target(500, 1250,wait=False) - mo_forward_2.run_target(500, 1250) - - #move arm - mo_le_ri.run_target(200,-50) - - #move sensors - mo_up_down.run_target(500,2500) - wait(2000) - mo_up_down.run_target(500,0) - - #move arm - mo_le_ri.run_target(200,0) - - #move backwards - mo_forward_1.run_target(500, 0,wait=False) - mo_forward_2.run_target(500, 0) - - - - -def move_2(): - pass -def move_3(): - pass - - - - -ev3 = EV3Brick() - -motor_forward_1 = Motor(Port.A) -motor_forward_2 = Motor(Port.D) -motor_le_ri = Motor(Port.B, Direction.COUNTERCLOCKWISE, [8, 56]) #with gear for angle -motor_up_down = Motor(Port.C) - -#n = int(sys.argv[1]) - -#if n == 1: -move_1(motor_forward_1,motor_forward_2,motor_le_ri,motor_up_down) - - - diff --git a/software/roboter/ev3/plant_1.py b/software/roboter/ev3/plant_1.py index a8eb80d..36091ef 100644 --- a/software/roboter/ev3/plant_1.py +++ b/software/roboter/ev3/plant_1.py @@ -1,5 +1,11 @@ #!/usr/bin/env pybricks-micropython +""" +created by waldhauser + +This file contians the programm to drive a specfic plant with a certain distance to drive +""" + from ev3dev2.motor import Motor, LargeMotor, ServoMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent motorRight = LargeMotor(OUTPUT_A) diff --git a/software/roboter/ev3/plant_2.py b/software/roboter/ev3/plant_2.py index a33cc9d..90eb948 100644 --- a/software/roboter/ev3/plant_2.py +++ b/software/roboter/ev3/plant_2.py @@ -1,5 +1,11 @@ #!/usr/bin/env pybricks-micropython +""" +created by waldhauser + +This file contians the programm to drive a specfic plant with a certain distance to drive +""" + from ev3dev2.motor import Motor, LargeMotor, ServoMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent motorRight = LargeMotor(OUTPUT_A) diff --git a/software/roboter/ev3/plant_3.py b/software/roboter/ev3/plant_3.py index 6df695d..71fffce 100644 --- a/software/roboter/ev3/plant_3.py +++ b/software/roboter/ev3/plant_3.py @@ -1,5 +1,11 @@ #!/usr/bin/env pybricks-micropython +""" +created by waldhauser + +This file contians the programm to drive a specfic plant with a certain distance to drive +""" + from ev3dev2.motor import Motor, LargeMotor, ServoMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent motorRight = LargeMotor(OUTPUT_A) diff --git a/software/roboter/ev3/plant_4.py b/software/roboter/ev3/plant_4.py index 04304ad..cb13208 100644 --- a/software/roboter/ev3/plant_4.py +++ b/software/roboter/ev3/plant_4.py @@ -1,5 +1,11 @@ #!/usr/bin/env pybricks-micropython +""" +created by waldhauser + +This file contians the programm to drive a specfic plant with a certain distance to drive +""" + from ev3dev2.motor import Motor, LargeMotor, ServoMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent motorRight = LargeMotor(OUTPUT_A) diff --git a/software/roboter/ev3/plant_5.py b/software/roboter/ev3/plant_5.py index 1d9b6c9..1ef52c0 100644 --- a/software/roboter/ev3/plant_5.py +++ b/software/roboter/ev3/plant_5.py @@ -1,5 +1,11 @@ #!/usr/bin/env pybricks-micropython +""" +created by waldhauser + +This file contians the programm to drive a specfic plant with a certain distance to drive +""" + from ev3dev2.motor import Motor, LargeMotor, ServoMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent motorRight = LargeMotor(OUTPUT_A) diff --git a/software/roboter/ev3/plant_6.py b/software/roboter/ev3/plant_6.py index bc42413..95c336f 100644 --- a/software/roboter/ev3/plant_6.py +++ b/software/roboter/ev3/plant_6.py @@ -1,5 +1,11 @@ #!/usr/bin/env pybricks-micropython +""" +created by waldhauser + +This file contians the programm to drive a specfic plant with a certain distance to drive +""" + from ev3dev2.motor import Motor, LargeMotor, ServoMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, OUTPUT_D, SpeedPercent motorRight = LargeMotor(OUTPUT_A) diff --git a/software/roboter/raspy/functions.py b/software/roboter/raspy/functions.py index 2d32e27..1e7d70f 100644 --- a/software/roboter/raspy/functions.py +++ b/software/roboter/raspy/functions.py @@ -1,3 +1,10 @@ +""" +created by waldhauser + +This file contains the functions for the mainProg.py. +The functions are part of three groups, MQTT-callbacks, functions for external threads and one normal function. +""" + import paho.mqtt.client as mqtt import json import threading @@ -29,21 +36,27 @@ def measure_send_data(plantID, actionID, client: mqtt.Client): sensorData["ActionID"] = actionID client.publish(Topics["ROBOT_DATA_SENSORDATA"], json.dumps(sensorData, indent=4), qos=1) +#region Thread +# Functions to be executed in external Thread to not block the mainProg +# Functions contain the drive and sensor measurement operations def drive_plant_thread(plantID, actionID, client: mqtt.Client): """ Function to drive to plant according to number from MQTT message in thread + Drive programm based on hardcoded drive programms specific for each plant + Only possible to drive to one plant per execution Meassure and publish data via MQTT Drive home to starting point + ***If color codes are working properly this function is not needed anymore*** + Args: plantID (_type_): plant to measure actionID (_type_): current ID of driving action client (mqtt.Client): current mqtt client for publishing """ - # FIXME Change to color code driving + errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/plant_{plantID}.py') - # errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_plant.py {plantID}') if errorCode != 0: if errorCode == 65280: @@ -84,12 +97,16 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client): def drive_plant_all_thread(plantIDs: list, actionID, client: mqtt.Client): """ - Function to drive to plants according to numbers from MQTT message in thread + Function to drive to plants according to numbers from MQTT message in thread, one or more plants possible + PlantIDs have to be in ascending order + Drive programm based on color codes in the flowerbed Meassure and publish data for all plants via MQTT Drive home to starting point + ***If color codes are working properly, only this function is needed for drive operations*** + Args: - plantIDs (list): Plants to drive to + plantIDs (list): Plants to drive to, plants have to be in ascending order actionID (_type_): ActionID from Backend for whole drive action client (mqtt.Client): current MQTT client """ @@ -118,6 +135,7 @@ def drive_plant_all_thread(plantIDs: list, actionID, client: mqtt.Client): return + # Read Sensors and store data, take picture logging.info("Measuring Sensors") try: sensordata = {} @@ -167,14 +185,19 @@ def drive_plant_all_thread(plantIDs: list, actionID, client: mqtt.Client): logging.info("Robot home") client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1) +#endregion #region MQTT callbacks +# Functions to be called by the MQTT callbacks +# Starting the drive operations in threads or executing the small operations directly def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage): """ Function to drive to plant according to request Starting Drive in Thread to not block main programm + ***If color codes are working properly this function is not needed anymore*** + Args: client (mqtt.Client): current mqtt client userdata (_type_): _description_ @@ -198,6 +221,8 @@ def drive_plant_all(client: mqtt.Client, userdata, message: mqtt.MQTTMessage): Function to drive to plants according to request Starting Drive in Thread to not block main programm + ***If color codes are working properly, only this function is needed for drive operations*** + Args: client (mqtt.Client): current MQTT client userdata (_type_): _description_ @@ -214,11 +239,14 @@ def drive_plant_all(client: mqtt.Client, userdata, message: mqtt.MQTTMessage): thread = threading.Thread(target= drive_plant_all_thread, args=(plantIDs, actionID, client), daemon=True) thread.start() + def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): """ Callback function for GPS position request Function to send actual GPS position via MQTT in form of POSITION + ***Not implemented, available GPS-sensor was not working*** + Args: client (mqtt.Client): current mqtt client userdata (_type_): _description_ @@ -237,7 +265,9 @@ def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): def get_batteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage): """ Callback function for battery status request - Function to read battery status from ev3 and send via MQTT in form of BATTERY + Function to read battery status from EV3 and send via MQTT in form of BATTERY + Reading battery level via SSH script execution + Battery level shown in Volts: 8,5V -> 100% 5V -> 0% @@ -255,9 +285,9 @@ def get_batteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage): client.publish(Topics["ROBOT_DATA_ERROR"], "Robot not connected", qos=1) return - batteryLevel = round(batteryLevel / 1000000, 2) # Voltage + batteryLevel = round(batteryLevel / 1000000, 2) # Conversion to Volt batteryLevel = batteryLevel - 5 - batteryLevel = round(batteryLevel / 3.5, 3) *100 # Percentage + batteryLevel = round(batteryLevel / 3.5, 3) *100 # Conversion to Percentage, 8,5V -> 100%, 5V -> 0% battery = { "Battery": batteryLevel @@ -270,6 +300,8 @@ def sendPicture(client: mqtt.Client): """ Takes picture and publish via MQTT + ***Pictures can not be send until now -> assumption of reaching maximum payload limit*** + Args: client (mqtt.Client): current mqtt client """ diff --git a/software/roboter/raspy/mainProg.py b/software/roboter/raspy/mainProg.py index 054dba7..cd47e1b 100644 --- a/software/roboter/raspy/mainProg.py +++ b/software/roboter/raspy/mainProg.py @@ -1,12 +1,12 @@ """ -created by waldluis +created by waldlhauser This file contains the main script for the RaspberryPi of smart garden project -It has the task to control the EV3 robot and take measurements with the mounted sensor +It has the task to control the EV3 robot and take measurements with the mounted sensors The sensor data is published to MQTT topics to be available for the backend server Used protocol for interaction: mqtt (paho-mqtt module) Interaction with the EV3 via SSH - """ +""" import paho.mqtt.client as mqtt import functions diff --git a/software/roboter/raspy/raspy_sensors.py b/software/roboter/raspy/raspy_sensors.py index 47e5242..54980a7 100644 --- a/software/roboter/raspy/raspy_sensors.py +++ b/software/roboter/raspy/raspy_sensors.py @@ -1,4 +1,11 @@ -# from picamera import PiCamera +""" +created by waldhauser + +This file contains the functions to read the sensors DHT22, TSL2561, earth humidity with MCP3008 ADC and RaspberryPi camera +Every sensor can be read on its own +Reading all sensors is possible with the readSensors() function and provides the data in the format of SENSORDATA dictionary +""" + import adafruit_dht import adafruit_tsl2561 import board @@ -83,7 +90,6 @@ def readMCP3008(): percentage = round(((1100 - percentage) / 1100) *100, 2) # 680 -> 100% moisture, 1780 -> 0% moisture if percentage > 100 or percentage < 0: # If not connected values above 100% appear - percentage = 0 raise Exception("YL69 not connected") return percentage @@ -92,6 +98,7 @@ def readMCP3008(): def readSensors(sensorData): """ Read DHT22, TSL2561 and Humidity Sensor + Dictionary is passed to ensure that values are available when errors occur Args: sensorData (dictionary): Dictionary of type SENSORDATA @@ -107,25 +114,25 @@ def readSensors(sensorData): try: sensorData["AirTemperature"], sensorData["AirHumidity"] = readDHT22() except Exception as e: - sensorData["AirHumidity"] = 0 # otherwise old value + sensorData["AirHumidity"] = 0 # No value returend if error occurs -> setting dummy value sensorData["AirTemperature"] = 0 - errorMessage = str(e) + "\n" + errorMessage = str(e) + "\n" # Appending received error message to later forward all occured errors # read TSL2561 try: sensorData["Brightness"] = readTSL2561() except Exception as e: - sensorData["Brightness"] = 0 # otherwise old value - errorMessage = errorMessage + str(e) + "\n" + sensorData["Brightness"] = 0 # No value returend if error occurs -> setting dummy value + errorMessage = errorMessage + str(e) + "\n" # Appending received error message to later forward all occured errors # read YL-69 try: sensorData["SoilMoisture"] = readMCP3008() except Exception as e: - sensorData["SoilMoisture"] = 0 - errorMessage = errorMessage + str(e) + "\n" + sensorData["SoilMoisture"] = 0 # No value returend if error occurs -> setting dummy value + errorMessage = errorMessage + str(e) + "\n" # Appending received error message to later forward all occured errors - # combined error message + # raise combined error message if errorMessage != "": raise Exception(errorMessage) @@ -133,9 +140,8 @@ def readSensors(sensorData): def takePicture(): """ - Take picture and return picture - Returns: - _type_: _description_ + Take picture and store as "picture.png" in current folder + """ try: camera = PiCamera() @@ -146,14 +152,14 @@ def takePicture(): camera.capture("picture.png") camera.stop_preview() - return - # TODO - read position with sensor def readPosition(): """ Read and return Position + ***Not implemented, available GPS-sensor was not working*** + Returns: _type_: _description_ """ @@ -162,7 +168,6 @@ def readPosition(): # Testing - def main(): value = SENSORDATA try: