Finally got an update for the project. I managed to make the state machine and all the activity diagrams ready to run the python code and added a buzzer to alert me when some user interaction has to be done.
Here you see the dependencies of the SousVide class to "external" "state machine" and "internal" classes.
One big state machine,... coming up:
and finally for all interested the XMI-Export from my Enterprise Architect model and some example code (generated from the model)
"""
# Model File: file:///C:/Projects/Python/SousVide/SousVide.eap
# Model Path: Model.LCD Menu.SousVide.SousVide
#
# Montag, 7. März 2016 - 09:43:43
"""from enum import Enum
import time
# Include for relation to classifier Adafruit_CharLCDimport Adafruit_CharLCD as LCD
# Include for relation to classifier FSMfrom FSM import *
# Include for relation to classifier timefrom time import *
# Include for relation to classifier RPi.GPIOimport RPi.GPIO as GPIO
# Include for relation to classifier osimport os as os
# Include for relation to classifier TempSensorfrom TempSensor import *
# Include for relation to classifier sysimport sys as sys
# Include for relation to classifier time_unitfrom time_unit import *
# Include for signalsfrom Signals import *
...
...
"""
# Activity CheckSingleClick of class SousVide
"""defCheckSingleClick(self, button):
return_1 = False# start of activity codeif(self.lcd.is_pressed(button)):
while(True):
self.ButtonWaitTime()
ifnot (self.lcd.is_pressed(button)):
break
return_1 = Trueelse:
return_1 = Falsereturn return_1
...
...
...
"""
# Handles the state machine
"""defStateMachineFnc(self, stm, msg):
evConsumed = Falseif (stm.mainState.activeSubState == SousVide_StateMachine_States.SousVide_StateMachine_StateMachine_FINAL_1):
""" empty block """elif (stm.mainState.activeSubState == SousVide_StateMachine_States.SousVide_StateMachine_Running):
if (stm.Running.activeSubState == SousVide_StateMachine_States.SousVide_StateMachine_alert_user_end):
if(FSM.checkTimeEvent(stm.alert_user_end, 500, time_unit.TIME_MILLISECONDS) != False):
evConsumed = True# transition effect for transition alert user end -> alert user end
self.BuzzerAlert()
# end of transition effect for transition alert user end -> alert user end# alert user end -> alert user end
stm.Running.activeSubState = SousVide_StateMachine_States.SousVide_StateMachine_alert_user_end
stm.alert_user_end.startTime = FSM.getTime()
elif( self.CheckSingleClick(LCD.SELECT)):
evConsumed = True# alert user end -> wait for user
stm.Running.activeSubState = SousVide_StateMachine_States.SousVide_StateMachine_wait_for_user
# entry actions for state wait for user
self.EndMessage()
# end of entry actions for state wait for userelif (stm.Running.activeSubState...
...
...
As mentioned before, I want this project to be as modular and reusable as possible.
Because of this I made a quick detour to get more out of this.
I made a simple navigation program that uses the LCD and the buttons on the LCD plate.
Implemented functionality:
Show the IP of the raspberry (no need for an external display,.. besides the LCD)
A crude file explorer (only functions enter/exit folder and start another python script)
Reboot system
Shutdown system
Exit program
All this was done with the help of a state machine and a python script code generator (lucky me,.. I work in a company that produces such software).
Here you see the domain model with all classes needed and the main state machine.
The state machine consists of two "main" states the first is the "show menu" and the second "show cmd output".
The "root menu" has the above listed functions hard coded. Every command (besides "exit") is a simple shell command that gets executed and the return value will be stored inside a "cmdOutput" list.
This Output list will then be show inside the "show cmd output", this enables the state machine to show me the Raspberries IP (hostname -I) or give me the ability to scroll across a file list (ls -p -a).
With the help of the "Navigate" node I then can enter/exit folders and execute python scripts.
Since I want the project to be as modular and reusable as possible, I built some encasing for each component and custom wiring to plug everything together.
At first I bought a distribution box large enough to fit the relay inside and at least 4 power outlets on top.
Currently I only mounted two power outlets and had to do some adaptations to be able to switch each socket individually.
A Lego case (in red) for the Raspberry was obvious. For more flexibility I made an extension cord for the GPIO Pins with enough room to plug in the relay, the temperature sensor and the LCD Display (also in a Lego case). The power supply for the Raspberry proofed to be sufficient to also power the relay.
Next thing on the agenda, will be the modeling of the state machine to run the LCD Display.
Since the Raspberry GPIO only support 3.3V and the Sainsmart relay module need 5V to switch the relay I used a ULN2803A and an external power supply (the same I use to power the Raspberry PI, since it supports more then enough amps) to operate the optical switches and protect the Raspberries GPIO.
To run a test on the whole thing I put together a small Python script.
Python Script:
import RPi.GPIO as gpio
import time
# peter ports = [6,12,13,19,16,26,20,21]# port list """
# GPIO-6 ==> relay 1
# GPIO-12 ==> relay 2
# GPIO-13 ==> relay 3
# GPIO-19 ==> relay 4
# GPIO-16 ==> relay 5
# GPIO-26 ==> relay 6
# GPIO-20 ==> relay 7
# GPIO-21 ==> relay 8
"""
ports = [6,12,13,19,16,26,20,21]
#set pins to BCM mode
gpio.setmode(gpio.BCM)
#setup all pins for outputfor port in ports:
gpio.setup(port, gpio.OUT)
#set all pins to high (relay close NO, open NC)
print("high")
for port in ports:
gpio.output(port, gpio.HIGH)
time.sleep(3)
#set alls pins to low (relay open NO, close NC)
print("low")
for port in ports:
gpio.output(port, gpio.LOW)
# free gpio pins
gpio.cleanup()