Skip to content

Commit

Permalink
Code cleanup with ATOM
Browse files Browse the repository at this point in the history
  • Loading branch information
weinzmi committed Jan 2, 2019
1 parent f539eeb commit 2032898
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 57 deletions.
139 changes: 88 additions & 51 deletions src/machine.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
########################################################################
# machine.py is used to handle the state machine for ergoFACE, states, triggers, conditions,...
# machine.py is used to handle the state machine
# for ergoFACE, states, triggers, conditions,...
########################################################################
import logging
import os, sys, inspect, io
import os
import sys
import inspect
import io
import watt
import time
import pygraphviz
from IPython.display import Image, display, display_png
from transitions import Machine
from transitions.extensions import GraphMachine
from transitions.extensions import HierarchicalGraphMachine
from IPython.display import Image, display, display_png

Expand All @@ -18,9 +19,11 @@
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('transitions').setLevel(logging.INFO)


cmd_folder = os.path.realpath(
os.path.dirname(
os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0])))
os.path.abspath(os.path.split(inspect.getfile
(inspect.currentframe()))[0])))

if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)
Expand All @@ -37,20 +40,21 @@ class ergoFACE(object):
['pedaling',
'paused',
'finished',
'error'
]
'error']
}
]

def __init__(self, name):

# Initialize Graph machine - put in here twice for easy testing w/o graph
self.machine = HierarchicalGraphMachine(model=self,
states=ergoFACE.states,
initial='ergoFACE loading',
show_auto_transitions=False, # default value is False
title="ergoFace state diagram",
show_conditions=True)
# Initialize Graph machine
# put in here twice for easy testing w/o graph
self.machine = HierarchicalGraphMachine(
model=self,
states=ergoFACE.states,
initial='ergoFACE loading',
show_auto_transitions=False,
title="ergoFace state diagram",
show_conditions=True)

# Initialize the state machine
# self.machine = Machine(model=self,
Expand All @@ -61,45 +65,76 @@ def __init__(self, name):
# Transitions between the states

# raspberry is started up and ergoFACE can start.
self.machine.add_transition(trigger='AUTOMATIC', source='ergoFACE loading', dest='program loading',
before='initialise',
after='load_program')
self.machine.add_transition(
trigger='AUTOMATIC',
source='ergoFACE loading',
dest='program loading',
before='initialise',
after='load_program')

# as soon as there is a RPM signal detected, we are in training
self.machine.add_transition('LOADED', 'program loading', 'training',
conditions='rpm_OK')

self.machine.add_transition('RPM', ['training_paused', 'training_finished', 'training'], 'training_pedaling',
conditions='rpm_OK',
after='run_program')

self.machine.add_transition('NO_RPM', 'training_pedaling', 'training_paused',
before='pause_program')

self.machine.add_transition('RESET', ['training', 'training_error'], 'program loading',
conditions=['rpm_OK'],
after='load_program')

self.machine.add_transition('RESET', 'ergoFACE error', 'ergoFACE loading',
before='restart_ergoFACE')

self.machine.add_transition('ERROR', ['program loading', 'ergoFACE loading', 'training'], 'ergoFACE error',
after='restart_ergoFACE')

self.machine.add_transition('ERROR', ['training_paused', 'training_pedaling', 'training_finished'],
'training_error',
before='restart_ergoFACE')

self.machine.add_transition('FINISH', 'training_pedaling', 'training_finished')

self.machine.add_transition('NO_RPM', 'training', 'training_paused',
before='GPIO_PWM_WRITE_0')
self.machine.add_transition(
'LOADED',
'program loading',
'training',
conditions='rpm_OK')

self.machine.add_transition(
'RPM',
['training_paused', 'training_finished', 'training'],
'training_pedaling',
conditions='rpm_OK',
after='run_program')

self.machine.add_transition(
'NO_RPM',
'training_pedaling',
'training_paused',
before='pause_program')

self.machine.add_transition(
'RESET',
['training', 'training_error'],
'program loading',
conditions=['rpm_OK'],
after='load_program')

self.machine.add_transition(
'RESET',
'ergoFACE error',
'ergoFACE loading',
before='restart_ergoFACE')

self.machine.add_transition(
'ERROR',
['program loading', 'ergoFACE loading', 'training'],
'ergoFACE error',
after='restart_ergoFACE')

self.machine.add_transition(
'ERROR',
['training_paused', 'training_pedaling', 'training_finished'],
'training_error',
before='restart_ergoFACE')

self.machine.add_transition(
'FINISH',
'training_pedaling',
'training_finished')

self.machine.add_transition(
'NO_RPM',
'training',
'training_paused',
before='GPIO_PWM_WRITE_0')

# draw the whole graph
self.machine.get_graph().draw('ergoFACE_transition_diagram.png', prog='dot')
self.machine.get_graph().draw(
'ergoFACE_transition_diagram.png', prog='dot'
)

# micro programs that are executed depending on the Callback resolution and execution order
# https://github.com/pytransitions/transitions#callback-resolution-and-execution-order
# micro programs that are executed depending on the Callback resolution
# and execution order

# graph object is created by the machine
def show_graph(self, **kwargs):
Expand All @@ -108,11 +143,13 @@ def show_graph(self, **kwargs):
display(Image(stream.getvalue()))

def initialise(self):
print("ergoFACE -------- Welcome, Initialising ergoFACE")
print(
"ergoFACE -------- Welcome, Initialising ergoFACE")
# confirm = str(input("set Trigger to go to Status Program loading : "))

def load_program(self):
print("ergoFACE -------- Watt program loader,\n\rplease select your program:")
print(
"ergoFACE -------- Watt program loader,\n\rplease select your program:")
watt.module_load()

def rpm_OK(self):
Expand Down
1 change: 1 addition & 0 deletions src/pwm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
########################################################################
import RPi.GPIO as GPIO


class Ergopwm:

LedPin = 12
Expand Down
20 changes: 14 additions & 6 deletions src/watt.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import pwm
import yamlordereddictloader


def module_load():
# this module is used for listing & seletion of watt programs
# set variables to "global" for handling in other classes, e.g.: machine.py - class ergoFACE
# set variables to "global" for handling in other classes,
# e.g.: machine.py - class ergoFACE
global fileName
global fileList
global dirName
Expand Down Expand Up @@ -50,6 +52,7 @@ def get_user_input():
except ValueError:
print("wattwatt ------------ Invalid input. Please try again!")


def module_run():
# this module is used for loading & run of watt programs

Expand All @@ -63,10 +66,12 @@ def module_run():
global cyclecount

# create instance of class; open the yaml stream of the file selected
myyamlload = yaml.load(open(dirName + fileList[fileName]), Loader=yamlordereddictloader.Loader)
myyamlload = yaml.load(open(dirName + fileList[fileName]),
Loader=yamlordereddictloader.Loader)
# create instance of class
myergopwm = pwm.Ergopwm()
# cycle time used for loop control of watt program sequence parsing, MUST BE 1 SECOND BECAUSE OF YAML STRUCTURE
# cycle time used for loop control of watt program sequence parsing,
# MUST BE 1 SECOND BECAUSE OF YAML STRUCTURE
# !!!! cycle time for loop control of PWM signal is connected to this
cycle = 1
# !!!! hardcoded RPM value; has to be changed to RPM GPIO input
Expand All @@ -87,13 +92,16 @@ def module_run():
# get the duration and watt from yaml file
duration = myyamlload['Prog'][seq_id]['Duration']
watt = myyamlload['Prog'][seq_id]['Watt']
print("watt ------------ ", watt+offset, "Watt will be applied for", duration, "seconds")
print("watt ------------ ", watt+offset,
"Watt will be applied for", duration, "seconds")
# GPIO output loop of PWM signal
for cyclecount in range(duration):
# loop for seq in yaml file, later if/else is used for running and pausing the sequence count
# loop for seq in yaml file, later if/else is used for running and
# pausing the sequence count
if rpm >= rpm_limit:
# check for RPM limit
print("watt ------------ ", watt+offset, "W --- @ ---", rpm, "RPM")
print("watt ------------ ", watt+offset,
"W --- @ ---", rpm, "RPM")
for i in range(1, cycle*100+1):
# write the GPOIs; convert 800w to 100%
# !!!! this must be in central config yaml
Expand Down

0 comments on commit 2032898

Please sign in to comment.