simple solder selection

This commit is contained in:
Stefan Kögl 2012-11-15 19:08:59 +01:00
parent 2dba6d5bac
commit 61462a50a4
3 changed files with 93 additions and 73 deletions

View File

@ -3,6 +3,8 @@
#include <LiquidCrystal.h>
#include "profile.h"
//Pin assignments for SainSmart LCD Keypad Shield
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
DFR_Key keypad;
@ -16,13 +18,6 @@ OvenCtl::OvenCtl() {
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
set_min = 0;
@ -30,7 +25,7 @@ OvenCtl::OvenCtl() {
set_dt_min = 0;
set_dt_max = 0;
op_state = OP_CONFIG;
oven_mode = OM_CONFIG;
profile_state = START_STATE;
error_condition = 0;
is_oven_heating = false;
@ -43,10 +38,6 @@ OvenCtl::OvenCtl() {
lcd.begin(16, 2);
}
void OvenCtl::reset() {
digitalWrite(7, LOW);
}
void OvenCtl::send_state() {
Serial.write(time & 0xff);
@ -80,16 +71,23 @@ void OvenCtl::recv_config() {
}
void OvenCtl::dispatch_input_config(int cmd) {
if (cmd == 255)
void OvenCtl::dispatch_remote_cmd(COMMAND cmd) {
switch (cmd) {
case SEND_CONFIG:
send_config();
else if (cmd == 254)
break;
case RECV_CONFIG:
recv_config();
else if (cmd == 250)
reset();
else if (cmd == 253)
break;
case SEND_STATE:
recv_config();
break;
case RECV_STEPS:
break;
default:
;
}
}
void OvenCtl::handle_stand_alone_state() {
time++;
@ -112,18 +110,20 @@ void OvenCtl::handle_remote_state() {
*
*/
void OvenCtl::loop() {
int cmd = -1;
// int cmd = -1;
switch (op_state) {
case OP_CONFIG:
switch (oven_mode) {
case OM_CONFIG:
// if (profile.handle_config_state())
// set_start_state();
break;
case OP_STAND_ALONE:
case OM_CALIBRATION:
break;
case OM_STAND_ALONE:
// if (profile.handle_config_state())
// set_start_state();
// break;
case OP_REMOTE:
case OM_REMOTE:
// if (profile.handle_config_state())
// set_start_state();
break;
@ -133,24 +133,13 @@ void OvenCtl::loop() {
// 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)
// set_start_state();
}
control_oven();
if (profile_state > 0) {
if (oven_mode != OM_CONFIG) {
print_status();
delay(1000);
}
@ -214,14 +203,17 @@ void OvenCtl::print_status() {
void OvenCtl::control_oven() {
if (temperature <= set_min + actual_hysteresis && !is_oven_heating) {
is_oven_heating = true;
// Serial.println("Oven turned on");
}
else if (temperature >= set_min + actual_hysteresis && is_oven_heating) {
if (is_oven_heating) {
if (temperature >= set_min + actual_hysteresis) {
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) {

View File

@ -7,10 +7,18 @@
#define OP_STAND_ALONE 1
#define OP_REMOTE 2*/
enum OP_STATE {
OP_CONFIG,
OP_STAND_ALONE,
OP_REMOTE
enum OVEN_MODE {
OM_CONFIG,
OM_CALIBRATION,
OM_STAND_ALONE,
OM_REMOTE
};
enum COMMAND {
SEND_CONFIG,
RECV_CONFIG,
SEND_STATE,
RECV_STEPS
};
#define E_DT_MIN 1 // temperature dt too small
@ -55,19 +63,13 @@ public:
// void set_config_state();
private:
// system time, timestamps and temperatures from sensors
int time; // profile seconds
int temperature; // actual oven temp
int last_temperature; // last oven temp
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
float set_min;
@ -84,7 +86,7 @@ private:
// state machine
unsigned int error_condition;
OP_STATE op_state;
OVEN_MODE oven_mode;
PROFILE_STATE profile_state;
boolean is_oven_heating;
@ -127,13 +129,11 @@ private:
// void check_Tp_duration_min();
// void check_Tp_duration_max();
// commands
void send_state();
void send_config();
void reset();
void recv_config();
void dispatch_input_config(int);
void dispatch_remote_cmd(COMMAND cmd);
};
#endif

50
qtplot.py → reflowctl_gui.py Normal file → Executable file
View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
#!/usr/bin/python
import sys, os, random
@ -31,6 +32,7 @@ class Solder(object):
self.psteps = []
self.durations = dict()
self.rates = dict()
self.name = None
#start = self.add_state("start", 25)
#ps = self.add_state("preheat start", 150)
@ -47,6 +49,12 @@ class Solder(object):
#self.add_rate((pe, tal), 1)
#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):
s = State(name, temp)
@ -131,6 +139,7 @@ class Solder(object):
xmltree = etree.parse(filename)
root = xmltree.getroot()
s = Solder()
s.name = root[0].attrib["name"]
for state in root[0].findall("state"):
s.add_state(state.attrib["name"], int(state.attrib["temperature"]))
for duration in root[0].findall("duration"):
@ -147,7 +156,21 @@ class Solder(object):
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):
"""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.main_widget = QtGui.QWidget(self)
self.profile_widget = QtGui.QWidget(self)
self.dpi = 100
#pl = QtGui.QVBoxLayout(self.main_widget)
#self.p
pl = QtGui.QHBoxLayout(self.profile_widget)
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)
#sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100)
self.dc = MyDynamicMplCanvas(self.main_widget, width=5, height=4, dpi=self.dpi)
#l.addWidget(sc)
l.addWidget(self.dc)
l.addWidget(self.profile_widget, 1)
l.addWidget(self.dc, 10)
self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)
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):
file_choices = "PNG (*.png)|*.png"
@ -326,13 +358,9 @@ class ApplicationWindow(QtGui.QMainWindow):
def about(self):
QtGui.QMessageBox.about(self, "About %s" % progname,
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
canvases.
It may be used and modified with no restriction; raw copies as well as
modified versions may be distributed without limitation."""
reflowctl frontend"""
% {"prog": progname, "version": progversion})