Browse Source

SoilMoisture, Camera (and GPS) added

master
Luis Waldhauser 1 year ago
parent
commit
7452d6aae8

+ 5
- 1
requirements.txt View File

Werkzeug==2.2.3 Werkzeug==2.2.3
zipp==3.15.0 zipp==3.15.0
python-ev3dev2==2.1.0.post1 python-ev3dev2==2.1.0.post1
pytest
pytest
pip==23.1.2
# spidev==3.6
# picamera==1.13
numpy==1.19.5

+ 1
- 0
software/roboter/raspy/defines.py View File

"ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE", "ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE",
"ROBOT_DATA_ERROR": "ROBOT/DATA/ERROR", "ROBOT_DATA_ERROR": "ROBOT/DATA/ERROR",
"ROBOT_DATA_ROBOTREADY": "ROBOT/DATA/ROBOTREADY", "ROBOT_DATA_ROBOTREADY": "ROBOT/DATA/ROBOTREADY",
"ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE",


"BACKEND_ACTION_DRIVE": "BACKEND/ACTION/DRIVE", "BACKEND_ACTION_DRIVE": "BACKEND/ACTION/DRIVE",
"BACKEND_ACTION_DRIVEPALL": "BACKEND/ACTION/DRIVEALL", "BACKEND_ACTION_DRIVEPALL": "BACKEND/ACTION/DRIVEALL",

+ 28
- 9
software/roboter/raspy/functions.py View File

sensorData = Sensors.readSensors() sensorData = Sensors.readSensors()
except Exception as e: except Exception as e:
logging.error(str(e)) logging.error(str(e))
# TODO Error message MQTT
client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1) client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)


sensorData["PlantID"] = plantID sensorData["PlantID"] = plantID
logging.error(f"Robot Error {errorCode} occurred") logging.error(f"Robot Error {errorCode} occurred")
logging.info("Drive Plant aborted, Robot at starting position") logging.info("Drive Plant aborted, Robot at starting position")
client.publish(Topics["ROBOT_DATA_ERROR"], "Drive Plant aborted, Robot at starting position", qos=1) client.publish(Topics["ROBOT_DATA_ERROR"], "Drive Plant aborted, Robot at starting position", qos=1)
#TODO decide about robot occupied message
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1) client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)


return return
logging.info("Measuring Sensors") logging.info("Measuring Sensors")
measure_send_data(plantID, actionID, client) measure_send_data(plantID, actionID, client)


# FIXME Send Picture
# sendPicture()

logging.info("Robot driving home") logging.info("Robot driving home")
errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back.py {plantID}') errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back.py {plantID}')


logging.error(f"Robot Error {errorCode} occurred") logging.error(f"Robot Error {errorCode} occurred")
logging.info(f"Drive Home aborted, Robot at plant {plantID}") logging.info(f"Drive Home aborted, Robot at plant {plantID}")
client.publish(Topics["ROBOT_DATA_ERROR"], f"Drive Home aborted, Robot at plant {plantID}", qos=1) client.publish(Topics["ROBOT_DATA_ERROR"], f"Drive Home aborted, Robot at plant {plantID}", qos=1)
#TODO decide about robot occupied message
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1) client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
return return


logging.info("Robot home") logging.info("Robot home")


#TODO decide about robot occupied message
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1) client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)




#region MQTT callbacks #region MQTT callbacks


# TODO Test with all sensors
def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage): def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
""" """
Function to drive to plant according to request Function to drive to plant according to request
Starting Drive in Thread to not block main programm Starting Drive in Thread to not block main programm


Args: Args:
clients (mqtt.Client): current mqtt client
client (mqtt.Client): current mqtt client
userdata (_type_): _description_ userdata (_type_): _description_
message (mqtt.MQTTMessage): received DRIVE message with PlantID and ActionID message (mqtt.MQTTMessage): received DRIVE message with PlantID and ActionID
""" """
actionID = dictMessage["ActionID"] actionID = dictMessage["ActionID"]


logging.info(f"Received Drive-request to plant {plantID}, ActionID: {actionID}") logging.info(f"Received Drive-request to plant {plantID}, ActionID: {actionID}")

#TODO decide about robot occupied message
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "False", qos=1) client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "False", qos=1)
thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, client), daemon=True) thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, client), daemon=True)
Function to send actual GPS position via MQTT in form of POSITION Function to send actual GPS position via MQTT in form of POSITION


Args: Args:
clients (mqtt.Client): current mqtt client
client (mqtt.Client): current mqtt client
userdata (_type_): _description_ userdata (_type_): _description_
message (mqtt.MQTTMessage): received message message (mqtt.MQTTMessage): received message
""" """
5V -> 0% 5V -> 0%


Args: Args:
clients (mqtt.Client): current mqtt client
client (mqtt.Client): current mqtt client
userdata (_type_): _description_ userdata (_type_): _description_
message (mqtt.MQTTMessage): received message message (mqtt.MQTTMessage): received message
""" """
} }
client.publish(Topics["ROBOT_DATA_BATTERY"], json.dumps(battery, indent=4), qos=1) client.publish(Topics["ROBOT_DATA_BATTERY"], json.dumps(battery, indent=4), qos=1)


# TODO Test needed
def sendPicture(client: mqtt.Client):
"""
Takes picture and publish via MQTT

Args:
client (mqtt.Client): current mqtt client
"""
try:
Sensors.takePicture()
except Exception as e:
logging.error(str(e))
client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)

with open("picture.txt", "rb") as f:
file = f.read()
byteArr = bytearray(file)
print(byteArr)
client.publish(Topics["ROBOT_DATA_IMAGE"], byteArr)
print("Published")

#endregion #endregion

+ 69
- 5
software/roboter/raspy/raspy_sensors.py View File

import adafruit_tsl2561 import adafruit_tsl2561
import board import board
import json import json
import spidev
from picamera import PiCamera
from defines import SENSORDATA from defines import SENSORDATA






def readTSL2561(): def readTSL2561():
""" """
Reads TSL2561 brightness in Lux
Reads TSL2561 brightness in Lux and returns integer value


Raises: Raises:
Exception: If TSL2561 not connected properly Exception: If TSL2561 not connected properly
return brightness return brightness




def readMCP3008():
"""
Reads YL-69 via MCP3008 ADC soil moisture in percent and returns float value
Raises:
Exception: If YL-69 not connected properly

Returns:
float: soil moisture [%]
"""

channel = 0 # Input channel into MCP3008 ADC
try:
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000
except:
raise Exception("YL69 not connected")

val = spi.xfer2([1,(8+channel) << 4, 0])
data = ((val[1] & 3) << 9) +val[2]
percentage = data - 680 # Return values between ~1780 and ~680
percentage = round((1100 - percentage) / 1100, 2) # 680 -> 100% moisture, 1780 -> 0% moisture

if percentage > 1 or percentage < 0: # If not connected values above 100% appear
percentage = 0
raise Exception("YL69 not connected")

return percentage


# TODO SoilMoisture Sensor Function




# TODO Function for all sensors # TODO Function for all sensors
Raises: Raises:
Exception: DHT22 not connected Exception: DHT22 not connected
Exception: TSL2561 not connected Exception: TSL2561 not connected
Exception: YL69 not connected


Returns: Returns:
dict: Sensordata dict: Sensordata
sensorData = SENSORDATA sensorData = SENSORDATA
errorMessage = "" errorMessage = ""


# read DHT22
try: try:
sensorData["AirTemperature"], sensorData["AirHumidity"] = readDHT22() sensorData["AirTemperature"], sensorData["AirHumidity"] = readDHT22()
except Exception as e: except Exception as e:
sensorData["AirTemperature"] = 0 sensorData["AirTemperature"] = 0
errorMessage = str(e) + "\n" errorMessage = str(e) + "\n"


# read TSL2561
try: try:
sensorData["Brightness"] = readTSL2561() sensorData["Brightness"] = readTSL2561()
except Exception as e: except Exception as e:
sensorData["Brightness"] = 0 # otherwise old value sensorData["Brightness"] = 0 # otherwise old value
errorMessage = errorMessage + str(e) + "\n" errorMessage = errorMessage + str(e) + "\n"


# read YL-69
try:
sensorData["SoilMoisture"] = readMCP3008()
except Exception as e:
sensorData["SoilMoisture"] = 0
errorMessage = errorMessage + str(e) + "\n"

# combined error message # combined error message
if errorMessage != "": if errorMessage != "":
raise Exception(errorMessage) raise Exception(errorMessage)
return sensorData return sensorData




# TODO - take picture function
# TODO - Test needed
def takePicture(): def takePicture():
""" """
Take picture and return picture Take picture and return picture
Returns: Returns:
_type_: _description_ _type_: _description_
""" """
picture = ""
try:
camera = PiCamera()
except:
raise Exception("Camera not connected")
return
camera.start_preview()
camera.capture("picture.png")
print("Camera on")
camera.stop_preview()


return picture
return




# TODO - read position with sensor # TODO - read position with sensor
""" """
position = "" position = ""
return position return position


# Testing

def main():
value = SENSORDATA
try:
takePicture()
except Exception as e:
print(str(e))

print(value)

if __name__ == "__main__":
main()

Loading…
Cancel
Save