simple solder selection
This commit is contained in:
parent
2dba6d5bac
commit
61462a50a4
|
@ -3,6 +3,8 @@
|
||||||
#include <LiquidCrystal.h>
|
#include <LiquidCrystal.h>
|
||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Pin assignments for SainSmart LCD Keypad Shield
|
//Pin assignments for SainSmart LCD Keypad Shield
|
||||||
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
|
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
|
||||||
DFR_Key keypad;
|
DFR_Key keypad;
|
||||||
|
@ -16,13 +18,6 @@ OvenCtl::OvenCtl() {
|
||||||
actual_dt = 0.f;
|
actual_dt = 0.f;
|
||||||
|
|
||||||
|
|
||||||
// timestamps of event beginnings/ends
|
|
||||||
Ts_time_start = 0;
|
|
||||||
Ts_time_end = 0;
|
|
||||||
Tl_time_start = 0;
|
|
||||||
Tl_time_end = 0;
|
|
||||||
Tp_time_start = 0;
|
|
||||||
Tp_time_end = 0;
|
|
||||||
|
|
||||||
// thermostat
|
// thermostat
|
||||||
set_min = 0;
|
set_min = 0;
|
||||||
|
@ -30,7 +25,7 @@ OvenCtl::OvenCtl() {
|
||||||
set_dt_min = 0;
|
set_dt_min = 0;
|
||||||
set_dt_max = 0;
|
set_dt_max = 0;
|
||||||
|
|
||||||
op_state = OP_CONFIG;
|
oven_mode = OM_CONFIG;
|
||||||
profile_state = START_STATE;
|
profile_state = START_STATE;
|
||||||
error_condition = 0;
|
error_condition = 0;
|
||||||
is_oven_heating = false;
|
is_oven_heating = false;
|
||||||
|
@ -43,10 +38,6 @@ OvenCtl::OvenCtl() {
|
||||||
lcd.begin(16, 2);
|
lcd.begin(16, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OvenCtl::reset() {
|
|
||||||
digitalWrite(7, LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OvenCtl::send_state() {
|
void OvenCtl::send_state() {
|
||||||
Serial.write(time & 0xff);
|
Serial.write(time & 0xff);
|
||||||
|
@ -80,16 +71,23 @@ void OvenCtl::recv_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OvenCtl::dispatch_input_config(int cmd) {
|
void OvenCtl::dispatch_remote_cmd(COMMAND cmd) {
|
||||||
if (cmd == 255)
|
switch (cmd) {
|
||||||
|
case SEND_CONFIG:
|
||||||
send_config();
|
send_config();
|
||||||
else if (cmd == 254)
|
break;
|
||||||
|
case RECV_CONFIG:
|
||||||
recv_config();
|
recv_config();
|
||||||
else if (cmd == 250)
|
break;
|
||||||
reset();
|
case SEND_STATE:
|
||||||
else if (cmd == 253)
|
recv_config();
|
||||||
|
break;
|
||||||
|
case RECV_STEPS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OvenCtl::handle_stand_alone_state() {
|
void OvenCtl::handle_stand_alone_state() {
|
||||||
time++;
|
time++;
|
||||||
|
@ -112,18 +110,20 @@ void OvenCtl::handle_remote_state() {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void OvenCtl::loop() {
|
void OvenCtl::loop() {
|
||||||
int cmd = -1;
|
// int cmd = -1;
|
||||||
|
|
||||||
switch (op_state) {
|
switch (oven_mode) {
|
||||||
case OP_CONFIG:
|
case OM_CONFIG:
|
||||||
// if (profile.handle_config_state())
|
// if (profile.handle_config_state())
|
||||||
// set_start_state();
|
// set_start_state();
|
||||||
break;
|
break;
|
||||||
case OP_STAND_ALONE:
|
case OM_CALIBRATION:
|
||||||
|
break;
|
||||||
|
case OM_STAND_ALONE:
|
||||||
// if (profile.handle_config_state())
|
// if (profile.handle_config_state())
|
||||||
// set_start_state();
|
// set_start_state();
|
||||||
// break;
|
// break;
|
||||||
case OP_REMOTE:
|
case OM_REMOTE:
|
||||||
// if (profile.handle_config_state())
|
// if (profile.handle_config_state())
|
||||||
// set_start_state();
|
// set_start_state();
|
||||||
break;
|
break;
|
||||||
|
@ -133,24 +133,13 @@ void OvenCtl::loop() {
|
||||||
// set_error_state();
|
// set_error_state();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (Serial.available() > 0) {
|
|
||||||
cmd = Serial.read();
|
|
||||||
if (cmd == 255)
|
|
||||||
send_config();
|
|
||||||
else if (cmd == 254)
|
|
||||||
send_state();
|
|
||||||
else if (cmd == 253)
|
|
||||||
recv_config();
|
|
||||||
else if (cmd == 252)
|
|
||||||
reset();
|
|
||||||
// else if (cmd == 251)
|
// else if (cmd == 251)
|
||||||
// set_start_state();
|
// set_start_state();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
control_oven();
|
control_oven();
|
||||||
if (profile_state > 0) {
|
if (oven_mode != OM_CONFIG) {
|
||||||
print_status();
|
print_status();
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
@ -214,14 +203,17 @@ void OvenCtl::print_status() {
|
||||||
|
|
||||||
|
|
||||||
void OvenCtl::control_oven() {
|
void OvenCtl::control_oven() {
|
||||||
if (temperature <= set_min + actual_hysteresis && !is_oven_heating) {
|
if (is_oven_heating) {
|
||||||
is_oven_heating = true;
|
if (temperature >= set_min + actual_hysteresis) {
|
||||||
// Serial.println("Oven turned on");
|
|
||||||
}
|
|
||||||
else if (temperature >= set_min + actual_hysteresis && is_oven_heating) {
|
|
||||||
is_oven_heating = false;
|
is_oven_heating = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (temperature <= set_min + actual_hysteresis) {
|
||||||
|
is_oven_heating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OvenCtl::set_temp(int min, int max, int dt_min, int dt_max) {
|
void OvenCtl::set_temp(int min, int max, int dt_min, int dt_max) {
|
||||||
|
|
|
@ -7,10 +7,18 @@
|
||||||
#define OP_STAND_ALONE 1
|
#define OP_STAND_ALONE 1
|
||||||
#define OP_REMOTE 2*/
|
#define OP_REMOTE 2*/
|
||||||
|
|
||||||
enum OP_STATE {
|
enum OVEN_MODE {
|
||||||
OP_CONFIG,
|
OM_CONFIG,
|
||||||
OP_STAND_ALONE,
|
OM_CALIBRATION,
|
||||||
OP_REMOTE
|
OM_STAND_ALONE,
|
||||||
|
OM_REMOTE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum COMMAND {
|
||||||
|
SEND_CONFIG,
|
||||||
|
RECV_CONFIG,
|
||||||
|
SEND_STATE,
|
||||||
|
RECV_STEPS
|
||||||
};
|
};
|
||||||
|
|
||||||
#define E_DT_MIN 1 // temperature dt too small
|
#define E_DT_MIN 1 // temperature dt too small
|
||||||
|
@ -55,19 +63,13 @@ public:
|
||||||
// void set_config_state();
|
// void set_config_state();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// system time, timestamps and temperatures from sensors
|
// system time, timestamps and temperatures from sensors
|
||||||
int time; // profile seconds
|
int time; // profile seconds
|
||||||
int temperature; // actual oven temp
|
int temperature; // actual oven temp
|
||||||
int last_temperature; // last oven temp
|
int last_temperature; // last oven temp
|
||||||
float actual_dt; // actual difference from last to actual temperatur
|
float actual_dt; // actual difference from last to actual temperatur
|
||||||
|
|
||||||
// timestamps of event beginnings/ends
|
|
||||||
int Ts_time_start;
|
|
||||||
int Ts_time_end;
|
|
||||||
int Tl_time_start;
|
|
||||||
int Tl_time_end;
|
|
||||||
int Tp_time_start;
|
|
||||||
int Tp_time_end;
|
|
||||||
|
|
||||||
// thermostat
|
// thermostat
|
||||||
float set_min;
|
float set_min;
|
||||||
|
@ -84,7 +86,7 @@ private:
|
||||||
|
|
||||||
// state machine
|
// state machine
|
||||||
unsigned int error_condition;
|
unsigned int error_condition;
|
||||||
OP_STATE op_state;
|
OVEN_MODE oven_mode;
|
||||||
PROFILE_STATE profile_state;
|
PROFILE_STATE profile_state;
|
||||||
boolean is_oven_heating;
|
boolean is_oven_heating;
|
||||||
|
|
||||||
|
@ -127,13 +129,11 @@ private:
|
||||||
// void check_Tp_duration_min();
|
// void check_Tp_duration_min();
|
||||||
// void check_Tp_duration_max();
|
// void check_Tp_duration_max();
|
||||||
|
|
||||||
|
// commands
|
||||||
void send_state();
|
void send_state();
|
||||||
void send_config();
|
void send_config();
|
||||||
void reset();
|
|
||||||
|
|
||||||
void recv_config();
|
void recv_config();
|
||||||
|
void dispatch_remote_cmd(COMMAND cmd);
|
||||||
void dispatch_input_config(int);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
import sys, os, random
|
import sys, os, random
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ class Solder(object):
|
||||||
self.psteps = []
|
self.psteps = []
|
||||||
self.durations = dict()
|
self.durations = dict()
|
||||||
self.rates = dict()
|
self.rates = dict()
|
||||||
|
self.name = None
|
||||||
|
|
||||||
#start = self.add_state("start", 25)
|
#start = self.add_state("start", 25)
|
||||||
#ps = self.add_state("preheat start", 150)
|
#ps = self.add_state("preheat start", 150)
|
||||||
|
@ -47,6 +49,12 @@ class Solder(object):
|
||||||
#self.add_rate((pe, tal), 1)
|
#self.add_rate((pe, tal), 1)
|
||||||
#self.add_rate((tal, end), -2)
|
#self.add_rate((tal, end), -2)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return unicode(self.name)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
def add_state(self, name, temp):
|
def add_state(self, name, temp):
|
||||||
s = State(name, temp)
|
s = State(name, temp)
|
||||||
|
@ -131,6 +139,7 @@ class Solder(object):
|
||||||
xmltree = etree.parse(filename)
|
xmltree = etree.parse(filename)
|
||||||
root = xmltree.getroot()
|
root = xmltree.getroot()
|
||||||
s = Solder()
|
s = Solder()
|
||||||
|
s.name = root[0].attrib["name"]
|
||||||
for state in root[0].findall("state"):
|
for state in root[0].findall("state"):
|
||||||
s.add_state(state.attrib["name"], int(state.attrib["temperature"]))
|
s.add_state(state.attrib["name"], int(state.attrib["temperature"]))
|
||||||
for duration in root[0].findall("duration"):
|
for duration in root[0].findall("duration"):
|
||||||
|
@ -147,7 +156,21 @@ class Solder(object):
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
class SolderListModel(QtCore.QAbstractListModel):
|
||||||
|
def __init__(self, parent=None, *args):
|
||||||
|
""" datain: a list where each item is a row
|
||||||
|
"""
|
||||||
|
super(SolderListModel, self).__init__(parent, *args)
|
||||||
|
self.listdata = [Solder.unpack(os.path.join("solder_types", p)) for p in os.listdir("solder_types")]
|
||||||
|
|
||||||
|
def rowCount(self, parent=QtCore.QModelIndex()):
|
||||||
|
return len(self.listdata)
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
if index.isValid() and role == QtCore.Qt.DisplayRole:
|
||||||
|
return QtCore.QVariant(self.listdata[index.row()].name)
|
||||||
|
else:
|
||||||
|
return QtCore.QVariant()
|
||||||
|
|
||||||
class MyDynamicMplCanvas(FigureCanvas):
|
class MyDynamicMplCanvas(FigureCanvas):
|
||||||
"""A canvas that updates itself every second with a new plot."""
|
"""A canvas that updates itself every second with a new plot."""
|
||||||
|
@ -293,23 +316,32 @@ class ApplicationWindow(QtGui.QMainWindow):
|
||||||
self.help_menu.addAction('&About', self.about)
|
self.help_menu.addAction('&About', self.about)
|
||||||
|
|
||||||
self.main_widget = QtGui.QWidget(self)
|
self.main_widget = QtGui.QWidget(self)
|
||||||
|
self.profile_widget = QtGui.QWidget(self)
|
||||||
|
|
||||||
self.dpi = 100
|
self.dpi = 100
|
||||||
|
|
||||||
#pl = QtGui.QVBoxLayout(self.main_widget)
|
pl = QtGui.QHBoxLayout(self.profile_widget)
|
||||||
#self.p
|
self.solder_model = SolderListModel(self)
|
||||||
|
self.solder_view = QtGui.QListView()
|
||||||
|
self.solder_view.setModel(self.solder_model)
|
||||||
|
|
||||||
|
self.connect(self.solder_view, QtCore.SIGNAL("clicked(QModelIndex)"), self.solder_selected)
|
||||||
|
pl.addWidget(self.solder_view)
|
||||||
|
|
||||||
l = QtGui.QVBoxLayout(self.main_widget)
|
l = QtGui.QVBoxLayout(self.main_widget)
|
||||||
#sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100)
|
|
||||||
self.dc = MyDynamicMplCanvas(self.main_widget, width=5, height=4, dpi=self.dpi)
|
self.dc = MyDynamicMplCanvas(self.main_widget, width=5, height=4, dpi=self.dpi)
|
||||||
#l.addWidget(sc)
|
l.addWidget(self.profile_widget, 1)
|
||||||
l.addWidget(self.dc)
|
l.addWidget(self.dc, 10)
|
||||||
|
|
||||||
self.main_widget.setFocus()
|
self.main_widget.setFocus()
|
||||||
self.setCentralWidget(self.main_widget)
|
self.setCentralWidget(self.main_widget)
|
||||||
|
|
||||||
self.statusBar().showMessage("All hail matplotlib!", 2000)
|
self.statusBar().showMessage("All hail matplotlib!", 2000)
|
||||||
|
|
||||||
|
def solder_selected(self, index):
|
||||||
|
if index.isValid():
|
||||||
|
self.dc.solder = self.solder_model.listdata[index.row()]
|
||||||
|
|
||||||
def save_plot(self):
|
def save_plot(self):
|
||||||
file_choices = "PNG (*.png)|*.png"
|
file_choices = "PNG (*.png)|*.png"
|
||||||
|
|
||||||
|
@ -326,13 +358,9 @@ class ApplicationWindow(QtGui.QMainWindow):
|
||||||
def about(self):
|
def about(self):
|
||||||
QtGui.QMessageBox.about(self, "About %s" % progname,
|
QtGui.QMessageBox.about(self, "About %s" % progname,
|
||||||
u"""%(prog)s version %(version)s
|
u"""%(prog)s version %(version)s
|
||||||
Copyright \N{COPYRIGHT SIGN} 2005 Florent Rougon, 2006 Darren Dale
|
Copyright \N{COPYRIGHT SIGN} 2012 Stefan Kögl
|
||||||
|
|
||||||
This program is a simple example of a Qt4 application embedding matplotlib
|
reflowctl frontend"""
|
||||||
canvases.
|
|
||||||
|
|
||||||
It may be used and modified with no restriction; raw copies as well as
|
|
||||||
modified versions may be distributed without limitation."""
|
|
||||||
% {"prog": progname, "version": progversion})
|
% {"prog": progname, "version": progversion})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue