Browse Source

SoilMoisture, Camera (and GPS) added

master
Luis Waldhauser 1 year ago
parent
commit
7452d6aae8

+ 5
- 1
requirements.txt View File

@@ -29,4 +29,8 @@ urllib3==1.26.14
Werkzeug==2.2.3
zipp==3.15.0
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

@@ -21,6 +21,7 @@ Topics = {
"ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE",
"ROBOT_DATA_ERROR": "ROBOT/DATA/ERROR",
"ROBOT_DATA_ROBOTREADY": "ROBOT/DATA/ROBOTREADY",
"ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE",

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

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

@@ -21,7 +21,6 @@ def measure_send_data(plantID, actionID, client: mqtt.Client):
sensorData = Sensors.readSensors()
except Exception as e:
logging.error(str(e))
# TODO Error message MQTT
client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)

sensorData["PlantID"] = plantID
@@ -48,7 +47,6 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client):
logging.error(f"Robot Error {errorCode} occurred")
logging.info("Drive Plant aborted, Robot at starting position")
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)

return
@@ -56,6 +54,9 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client):
logging.info("Measuring Sensors")
measure_send_data(plantID, actionID, client)

# FIXME Send Picture
# sendPicture()

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

@@ -63,25 +64,24 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client):
logging.error(f"Robot Error {errorCode} occurred")
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)
#TODO decide about robot occupied message
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
return

logging.info("Robot home")

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


#region MQTT callbacks

# TODO Test with all sensors
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

Args:
clients (mqtt.Client): current mqtt client
client (mqtt.Client): current mqtt client
userdata (_type_): _description_
message (mqtt.MQTTMessage): received DRIVE message with PlantID and ActionID
"""
@@ -93,8 +93,6 @@ def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
actionID = dictMessage["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)
thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, client), daemon=True)
@@ -107,7 +105,7 @@ def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage):
Function to send actual GPS position via MQTT in form of POSITION

Args:
clients (mqtt.Client): current mqtt client
client (mqtt.Client): current mqtt client
userdata (_type_): _description_
message (mqtt.MQTTMessage): received message
"""
@@ -129,7 +127,7 @@ def get_BatteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
5V -> 0%

Args:
clients (mqtt.Client): current mqtt client
client (mqtt.Client): current mqtt client
userdata (_type_): _description_
message (mqtt.MQTTMessage): received message
"""
@@ -151,4 +149,25 @@ def get_BatteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
}
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

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

@@ -3,6 +3,8 @@ import adafruit_dht
import adafruit_tsl2561
import board
import json
import spidev
from picamera import PiCamera
from defines import SENSORDATA


@@ -34,7 +36,7 @@ def readDHT22():

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

Raises:
Exception: If TSL2561 not connected properly
@@ -57,8 +59,36 @@ def readTSL2561():
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
@@ -69,6 +99,7 @@ def readSensors():
Raises:
Exception: DHT22 not connected
Exception: TSL2561 not connected
Exception: YL69 not connected

Returns:
dict: Sensordata
@@ -76,6 +107,7 @@ def readSensors():
sensorData = SENSORDATA
errorMessage = ""

# read DHT22
try:
sensorData["AirTemperature"], sensorData["AirHumidity"] = readDHT22()
except Exception as e:
@@ -83,12 +115,20 @@ def readSensors():
sensorData["AirTemperature"] = 0
errorMessage = str(e) + "\n"

# read TSL2561
try:
sensorData["Brightness"] = readTSL2561()
except Exception as e:
sensorData["Brightness"] = 0 # otherwise old value
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
if errorMessage != "":
raise Exception(errorMessage)
@@ -96,16 +136,25 @@ def readSensors():
return sensorData


# TODO - take picture function
# TODO - Test needed
def takePicture():
"""
Take picture and return picture
Returns:
_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
@@ -118,3 +167,18 @@ def readPosition():
"""
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