SoilMoisture, Camera (and GPS) added
This commit is contained in:
parent
43fbbfcbbb
commit
7452d6aae8
@ -30,3 +30,7 @@ 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
|
@ -21,6 +21,7 @@ Topics = {
|
|||||||
"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",
|
||||||
|
@ -21,7 +21,6 @@ def measure_send_data(plantID, actionID, client: mqtt.Client):
|
|||||||
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
|
||||||
@ -48,7 +47,6 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client):
|
|||||||
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
|
||||||
@ -56,6 +54,9 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client):
|
|||||||
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}')
|
||||||
|
|
||||||
@ -63,25 +64,24 @@ def drive_plant_thread(plantID, actionID, client: mqtt.Client):
|
|||||||
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
|
||||||
"""
|
"""
|
||||||
@ -93,8 +93,6 @@ def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
|
|||||||
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)
|
||||||
@ -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
|
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
|
||||||
"""
|
"""
|
||||||
@ -129,7 +127,7 @@ def get_BatteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
|
|||||||
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
|
||||||
"""
|
"""
|
||||||
@ -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)
|
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
|
@ -3,6 +3,8 @@ import adafruit_dht
|
|||||||
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
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ def readDHT22():
|
|||||||
|
|
||||||
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
|
||||||
@ -57,8 +59,36 @@ def readTSL2561():
|
|||||||
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
|
||||||
@ -69,6 +99,7 @@ def readSensors():
|
|||||||
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
|
||||||
@ -76,6 +107,7 @@ def readSensors():
|
|||||||
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:
|
||||||
@ -83,12 +115,20 @@ def readSensors():
|
|||||||
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)
|
||||||
@ -96,16 +136,25 @@ def readSensors():
|
|||||||
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
|
||||||
|
|
||||||
return picture
|
camera.start_preview()
|
||||||
|
camera.capture("picture.png")
|
||||||
|
print("Camera on")
|
||||||
|
camera.stop_preview()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
# TODO - read position with sensor
|
# TODO - read position with sensor
|
||||||
@ -118,3 +167,18 @@ def readPosition():
|
|||||||
"""
|
"""
|
||||||
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…
x
Reference in New Issue
Block a user