summaryrefslogtreecommitdiffstats
path: root/pressure_control
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-10-22 21:28:57 +0200
committerMichael Buesch <mb@bu3sch.de>2008-10-22 21:28:57 +0200
commit82e34364219cc2114247eb2c42ba86cad70276d1 (patch)
treee40b2bc83eb51b62b6f7c4ed2a8a67720716f221 /pressure_control
parent4b0babc1b1daaece0d8de672f98adaf6cff5cdac (diff)
downloadcnc-82e34364219cc2114247eb2c42ba86cad70276d1.tar.xz
cnc-82e34364219cc2114247eb2c42ba86cad70276d1.zip
Add more pressure_control stuff
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Diffstat (limited to 'pressure_control')
-rw-r--r--pressure_control/firmware/main.c37
-rw-r--r--pressure_control/firmware/main.h1
-rw-r--r--pressure_control/firmware/remote.c79
-rw-r--r--pressure_control/firmware/remote.h20
-rwxr-xr-xpressure_control/remote/pctl-remote171
5 files changed, 233 insertions, 75 deletions
diff --git a/pressure_control/firmware/main.c b/pressure_control/firmware/main.c
index 3dab38e..ef4c81e 100644
--- a/pressure_control/firmware/main.c
+++ b/pressure_control/firmware/main.c
@@ -58,6 +58,15 @@ void get_pressure_config(struct pressure_config *ret)
irq_restore(sreg);
}
+void set_pressure_config(struct pressure_config *new_cfg)
+{
+ uint8_t sreg;
+
+ sreg = irq_disable_save();
+ memcpy(&cfg, new_cfg, sizeof(cfg));
+ irq_restore(sreg);
+}
+
void get_pressure_state(struct pressure_state *ret)
{
uint8_t sreg;
@@ -140,21 +149,21 @@ static void check_pressure(void)
uint16_t abs_offset;
bool is_too_big;
- if (!cfg.autoadjust_enable)
- return;
-
- offset = (int32_t)state.mbar - (int32_t)cfg.desired;
- abs_offset = abs(offset);
- is_too_big = (offset >= 0);
-
- if (abs_offset > cfg.hysteresis) {
- /* Adjust the pressure */
- adjust_pressure(abs_offset, !is_too_big);
- } else {
- /* The pressure is OK. Make sure the valves are
- * all idle. */
- valves_force_state(VALVES_IDLE);
+ if (cfg.autoadjust_enable) {
+ offset = (int32_t)state.mbar - (int32_t)cfg.desired;
+ abs_offset = abs(offset);
+ is_too_big = (offset >= 0);
+
+ if (abs_offset > cfg.hysteresis) {
+ /* Adjust the pressure */
+ adjust_pressure(abs_offset, !is_too_big);
+ } else {
+ /* The pressure is OK. Make sure the valves are
+ * all idle. */
+ valves_force_state(VALVES_IDLE);
+ }
}
+//FIXME remote_pressure_change_notification(state.mbar, cfg.hysteresis);
}
int main(void)
diff --git a/pressure_control/firmware/main.h b/pressure_control/firmware/main.h
index abdfa8f..9f5cef1 100644
--- a/pressure_control/firmware/main.h
+++ b/pressure_control/firmware/main.h
@@ -31,6 +31,7 @@ struct pressure_state {
};
void get_pressure_config(struct pressure_config *cfg);
+void set_pressure_config(struct pressure_config *cfg);
void get_pressure_state(struct pressure_state *state);
#endif /* MAIN_H_ */
diff --git a/pressure_control/firmware/remote.c b/pressure_control/firmware/remote.c
index d759e7a..b012b4a 100644
--- a/pressure_control/firmware/remote.c
+++ b/pressure_control/firmware/remote.c
@@ -89,30 +89,21 @@ static void send_message(struct remote_message *msg)
usart_tx_buf(msg, sizeof(*msg));
}
-static void send_message_error(uint8_t error_code)
-{
- struct remote_message msg;
-
- memset(&msg, 0, sizeof(msg));
- msg.id = MSG_ERROR;
- msg.error.code = error_code;
-
- send_message(&msg);
-}
-
static void handle_received_message(void)
{
struct remote_message reply;
uint16_t calc_crc;
+ uint8_t err = MSG_ERR_NONE;
calc_crc = crc16_block_update(0xFFFF, &rx_msg,
sizeof(rx_msg) - sizeof(rx_msg.crc));
calc_crc ^= 0xFFFF;
if (calc_crc != rx_msg.crc) {
/* CRC mismatch. */
- send_message_error(MSG_ERR_CHKSUM);
- return;
+ err = MSG_ERR_CHKSUM;
+ goto out;
}
+
memset(&reply, 0, sizeof(reply));
switch (rx_msg.id) {
@@ -156,7 +147,49 @@ static void handle_received_message(void)
reply.config.flags |= (1 << CFG_FLAG_AUTOADJUST_ENABLE);
send_message(&reply);
break;
- } }
+ }
+ case MSG_SET_DESIRED_PRESSURE: {
+ struct pressure_config conf;
+
+ cli();
+ get_pressure_config(&conf);
+ conf.desired = rx_msg.pressure.mbar;
+ set_pressure_config(&conf);
+ sei();
+ break;
+ }
+ case MSG_SET_HYSTERESIS: {
+ struct pressure_config conf;
+
+ cli();
+ get_pressure_config(&conf);
+ conf.hysteresis = rx_msg.pressure.mbar;
+ set_pressure_config(&conf);
+ sei();
+ break;
+ }
+ case MSG_SET_CONFIG_FLAGS: {
+ struct pressure_config conf;
+
+ cli();
+ get_pressure_config(&conf);
+ conf.autoadjust_enable = !!(rx_msg.config.flags & (1 << CFG_FLAG_AUTOADJUST_ENABLE));
+ set_pressure_config(&conf);
+ sei();
+ break;
+ }
+ default:
+ err = MSG_ERR_NOCMD;
+ break;
+ }
+
+out:
+ if (rx_msg.flags & (1 << MSG_FLAG_REQ_ERRCODE)) {
+ memset(&reply, 0, sizeof(reply));
+ reply.id = MSG_ERROR;
+ reply.error.code = err;
+ send_message(&reply);
+ }
}
/* RX interrupt */
@@ -182,6 +215,7 @@ ISR(USART_RXC_vect)
rx_msg_count = 0;
mb();
rx_msg_valid = 1;
+ break;
}
}
}
@@ -217,6 +251,23 @@ void remote_work(void)
}
}
+void remote_pressure_change_notification(uint16_t mbar,
+ uint16_t hysteresis)
+{
+ struct remote_message msg;
+
+ static uint16_t prev_value;
+
+ if (abs((int32_t)mbar - (int32_t)prev_value) <= hysteresis)
+ return;
+ prev_value = mbar;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.id = MSG_CURRENT_PRESSURE;
+ msg.pressure.mbar = mbar;
+ send_message(&msg);
+}
+
static void usart_init(void)
{
uint8_t dummy;
diff --git a/pressure_control/firmware/remote.h b/pressure_control/firmware/remote.h
index af18abf..46d35ff 100644
--- a/pressure_control/firmware/remote.h
+++ b/pressure_control/firmware/remote.h
@@ -23,11 +23,17 @@ enum remote_message_id {
MSG_GET_CONFIG_FLAGS,
MSG_CONFIG_FLAGS,
MSG_SET_CONFIG_FLAGS,
+ MSG_SET_VALVE,
};
enum remote_message_error {
- MSG_ERR_NONE = 0,
- MSG_ERR_CHKSUM,
+ MSG_ERR_NONE = 0, /* No error */
+ MSG_ERR_CHKSUM, /* Checksum error */
+ MSG_ERR_NOCMD, /* Unknown command */
+};
+
+enum remote_message_flags {
+ MSG_FLAG_REQ_ERRCODE = 0,
};
enum remote_message_config_flags {
@@ -36,7 +42,8 @@ enum remote_message_config_flags {
struct remote_message {
uint8_t id;
- uint8_t __padding0[3];
+ uint8_t flags;
+ uint8_t __padding0[2];
union {
struct {
@@ -51,6 +58,10 @@ struct remote_message {
struct {
uint32_t flags;
} __attribute__((packed)) config;
+ struct {
+ uint8_t nr; /* Valve ID */
+ uint8_t state;
+ } __attribute__((packed)) valve;
uint8_t __padding1[32];
} __attribute__((packed));
@@ -62,6 +73,9 @@ struct remote_message {
void print_pgm(const prog_char *msg);
#define print(string_literal) print_pgm(PSTR(string_literal))
+void remote_pressure_change_notification(uint16_t mbar,
+ uint16_t hysteresis);
+
void remote_work(void);
void remote_init(void);
diff --git a/pressure_control/remote/pctl-remote b/pressure_control/remote/pctl-remote
index 9dba6f2..e3d8dcf 100755
--- a/pressure_control/remote/pctl-remote
+++ b/pressure_control/remote/pctl-remote
@@ -49,10 +49,14 @@ MSG_SET_HYSTERESIS = 12
MSG_GET_CONFIG_FLAGS = 13
MSG_CONFIG_FLAGS = 14
MSG_SET_CONFIG_FLAGS = 15
+MSG_SET_VALVE = 16
# Message error codes
-MSG_ERR_NONE = 0
-MSG_ERR_CHKSUM = 1
+MSG_ERR_NONE = 0 # No error
+MSG_ERR_CHKSUM = 1 # Checksum error
+MSG_ERR_NOCMD = 2 # Unknown command
MSG_ERR_NOREPLY = -1 # internal. Not sent over wire.
+# Message flags
+MSG_FLAG_REQ_ERRCODE = 0
# Config flags
CFG_FLAG_AUTOADJUST_ENABLE = 0
@@ -92,7 +96,9 @@ def parseArgs():
class RemoteProtocol(QObject):
def __init__(self, ttyfile):
QObject.__init__(self)
+ global remote
+ remote = self
self.serial = Serial(ttyfile, CONFIG_BAUDRATE,
CONFIG_BYTESIZE, CONFIG_PARITY,
CONFIG_STOPBITS)
@@ -101,7 +107,7 @@ class RemoteProtocol(QObject):
self.connect(self.pollTimer, SIGNAL("timeout()"), self.poll)
self.pollTimer.start(50)
- reply = self.sendMessageSyncReply(MSG_PING, "", MSG_PONG)
+ reply = self.sendMessageSyncReply(MSG_PING, 0, "", MSG_PONG)
if not reply:
print "Communication with device failed. No reply to PING request."
sys.exit(1)
@@ -127,22 +133,22 @@ class RemoteProtocol(QObject):
if not self.checksumMessage(msg):
return
id = ord(msg[0])
+ mainwnd.statusBar().showMessage(self.tr("Received message %u" % id))
if (id == MSG_LOGMESSAGE):
str = self.getPayload(msg).rstrip('\0')
mainwnd.centralWidget().log.addText(str)
- if (id == MSG_PING):
- sendMessage(MSG_PING, [])
if (id == MSG_CURRENT_PRESSURE):
mainwnd.centralWidget().parseCurrentPressureMsg(msg)
+ #TODO
def getPayload(self, msg):
return msg[4:-2]
- def sendMessage(self, id, payload):
+ def sendMessage(self, id, flags, payload):
"""Send a message"""
assert(len(payload) <= MSG_PAYLOAD_SIZE)
# Create the header
- msg = "%c\0\0\0" % id
+ msg = "%c%c\0\0" % (id, flags)
# Add the payload
msg += payload
# Pad the payload up to the constant size
@@ -158,19 +164,19 @@ class RemoteProtocol(QObject):
# Send the message
assert(len(msg) == MSG_SIZE)
self.serial.write(msg)
+ mainwnd.statusBar().showMessage(self.tr("Sent message %u" % id))
- def sendMessageSyncReply(self, id, payload, replyId):
+ def sendMessageSyncReply(self, id, flags, payload, replyId):
"""Send a message and synchronously wait for the reply."""
self.pollTimer.stop()
- self.sendMessage(id, payload)
+ self.sendMessage(id, flags, payload)
timeout = QDateTime.currentDateTime().addSecs(2)
while True:
if QDateTime.currentDateTime() >= timeout:
msg = None
break
if self.serial.inWaiting() < MSG_SIZE:
- app.processEvents()
- QThread.msleep(50)
+ QThread.msleep(1)
continue
msg = self.serial.read(MSG_SIZE)
if not self.checksumMessage(msg):
@@ -183,13 +189,40 @@ class RemoteProtocol(QObject):
self.pollTimer.start()
return msg
- def sendMessageSyncError(self, id, payload):
+ def sendMessageSyncError(self, id, flags, payload):
"""Sends a message and synchronously waits for the MSG_ERROR reply."""
- reply = self.sendMessageSyncReply(id, payload, MSG_ERROR)
+ flags |= (1 << MSG_FLAG_REQ_ERRCODE)
+ reply = self.sendMessageSyncReply(id, flags, payload, MSG_ERROR)
if not reply:
return MSG_ERR_NOREPLY
return ord(self.getPayload(reply)[0])
+ def configFlagsFetch(self):
+ reply = self.sendMessageSyncReply(MSG_GET_CONFIG_FLAGS, 0, "",
+ MSG_CONFIG_FLAGS)
+ if not reply:
+ return None
+ reply = remote.getPayload(reply)
+ flags = ord(reply[0]) | (ord(reply[1]) << 8) | \
+ (ord(reply[2]) << 16) | (ord(reply[3]) << 24)
+ return flags
+
+ def configFlagsSet(self, flags):
+ data = "%c%c%c%c" % ((flags & 0xFF), ((flags >> 8) & 0xFF),
+ ((flags >> 16) & 0xFF), ((flags >> 24) & 0xFF))
+ err = self.sendMessageSyncError(MSG_SET_CONFIG_FLAGS, 0, data)
+ return err
+
+ def setValve(self, valveNr, state):
+ data = "%c%c" % (valveNr, (state != 0))
+ i = 5 # Retry a few times
+ while i != 0:
+ err = self.sendMessageSyncError(MSG_SET_VALVE, 0, data)
+ if err == MSG_ERR_NONE:
+ break
+ i -= 1
+ return err
+
def __crc16_update_buffer(self, crc, buf):
for c in buf:
crc ^= ord(c)
@@ -202,7 +235,7 @@ class RemoteProtocol(QObject):
class StatusBar(QStatusBar):
def showMessage(self, msg):
- QStatusBar.showMessage(self, msg, 10000)
+ QStatusBar.showMessage(self, msg, 3000)
class LogBrowser(QTextEdit):
def __init__(self, parent=None):
@@ -239,12 +272,22 @@ class MainWidget(QWidget):
h.addStretch()
layout.addLayout(h)
- self.autoCheckbox = QCheckBox(self.tr("Automatically adjust pressure"), self)
- layout.addWidget(self.autoCheckbox)
+ h = QHBoxLayout()
+ label = QLabel(self.tr("Hysteresis:"), self)
+ h.addWidget(label)
+ self.hystSpin = QDoubleSpinBox(self)
+ self.hystSpin.setMinimum(0.1)
+ self.hystSpin.setMaximum(8)
+ self.hystSpin.setSingleStep(0.1)
+ self.hystSpin.setSuffix(self.tr(" Bar"))
+ self.connect(self.hystSpin, SIGNAL("valueChanged(double)"),
+ self.desiredHysteresisChanged)
+ h.addWidget(self.hystSpin)
+ h.addStretch()
+ layout.addLayout(h)
h = QHBoxLayout()
label = QLabel(self.tr("Desired pressure:"), self)
- h.addStretch()
h.addWidget(label)
self.pressureSpin = QDoubleSpinBox(self)
self.pressureSpin.setMinimum(1)
@@ -254,30 +297,37 @@ class MainWidget(QWidget):
self.connect(self.pressureSpin, SIGNAL("valueChanged(double)"),
self.desiredPressureChanged)
h.addWidget(self.pressureSpin)
+ self.autoCheckbox = QCheckBox(self.tr("Automatically adjust pressure"), self)
+ self.connect(self.autoCheckbox, SIGNAL("stateChanged(int)"),
+ self.autoadjustChanged)
+ h.addWidget(self.autoCheckbox)
+ h.addStretch()
layout.addLayout(h)
h = QHBoxLayout()
- label = QLabel(self.tr("Hysteresis:"), self)
- h.addStretch()
- h.addWidget(label)
- self.hystSpin = QDoubleSpinBox(self)
- self.hystSpin.setMinimum(0.1)
- self.hystSpin.setMaximum(8)
- self.hystSpin.setSingleStep(0.1)
- self.hystSpin.setSuffix(self.tr(" Bar"))
- self.connect(self.hystSpin, SIGNAL("valueChanged(double)"),
- self.desiredHysteresisChanged)
- h.addWidget(self.hystSpin)
+ self.inButton = QPushButton(self.tr("IN-Valve"), self)
+ self.connect(self.inButton, SIGNAL("pressed()"),
+ self.inValvePressed)
+ self.connect(self.inButton, SIGNAL("released()"),
+ self.inValveReleased)
+ h.addWidget(self.inButton)
+ self.outButton = QPushButton(self.tr("OUT-Valve"), self)
+ h.addWidget(self.outButton)
+ self.connect(self.outButton, SIGNAL("pressed()"),
+ self.outValvePressed)
+ self.connect(self.outButton, SIGNAL("released()"),
+ self.outValveReleased)
layout.addLayout(h)
self.log = LogBrowser(self)
layout.addWidget(self.log)
+ self.autoadjustChanged(Qt.Unchecked)
self.setLayout(layout)
def initializeState(self):
# Get the current pressure
- reply = remote.sendMessageSyncReply(MSG_GET_CURRENT_PRESSURE, "",
+ reply = remote.sendMessageSyncReply(MSG_GET_CURRENT_PRESSURE, 0, "",
MSG_CURRENT_PRESSURE)
if not reply:
print "Failed to fetch current pressure. No reply."
@@ -285,7 +335,7 @@ class MainWidget(QWidget):
self.parseCurrentPressureMsg(reply)
# Get the desired pressure
- reply = remote.sendMessageSyncReply(MSG_GET_DESIRED_PRESSURE, "",
+ reply = remote.sendMessageSyncReply(MSG_GET_DESIRED_PRESSURE, 0, "",
MSG_DESIRED_PRESSURE)
if not reply:
print "Failed to fetch desired pressure. No reply."
@@ -295,7 +345,7 @@ class MainWidget(QWidget):
self.pressureSpin.setValue(float(mbar) / 1000)
# Get the hysteresis
- reply = remote.sendMessageSyncReply(MSG_GET_HYSTERESIS, "",
+ reply = remote.sendMessageSyncReply(MSG_GET_HYSTERESIS, 0, "",
MSG_HYSTERESIS)
if not reply:
print "Failed to fetch hysteresis. No reply."
@@ -305,17 +355,12 @@ class MainWidget(QWidget):
self.hystSpin.setValue(float(mbar) / 1000)
# Get the config flags
- reply = remote.sendMessageSyncReply(MSG_GET_CONFIG_FLAGS, "",
- MSG_CONFIG_FLAGS)
- if not reply:
+ flags = remote.configFlagsFetch()
+ if flags == None:
print "Failed to fetch config flags. No reply."
sys.exit(1)
- reply = remote.getPayload(reply)
- flags = ord(reply[0]) | (ord(reply[1]) << 8) | \
- (ord(reply[2]) << 16) | (ord(reply[3]) << 24)
if flags & (1 << CFG_FLAG_AUTOADJUST_ENABLE):
self.autoCheckbox.setCheckState(Qt.Checked)
- #TODO
self.initialized = True
@@ -324,24 +369,62 @@ class MainWidget(QWidget):
mbar = ord(msg[0]) | (ord(msg[1]) << 8)
self.curPressure.display(float(mbar) / 1000)
- def desiredPressureChanged(self):
+ def desiredPressureChanged(self, value):
if not self.initialized:
return
- mbar = int(self.pressureSpin.value() * 1000)
+ mbar = int(value * 1000)
data = "%c%c" % ((mbar & 0xFF), ((mbar >> 8) & 0xFF))
- err = remote.sendMessageSyncError(MSG_SET_DESIRED_PRESSURE, data)
+ err = remote.sendMessageSyncError(MSG_SET_DESIRED_PRESSURE, 0, data)
if err != MSG_ERR_NONE:
self.log.addText(self.tr("Failed to change pressure. Error=%u\n" % err))
- def desiredHysteresisChanged(self):
+ def desiredHysteresisChanged(self, value):
if not self.initialized:
return
- mbar = int(self.hystSpin.value() * 1000)
+ mbar = int(value * 1000)
data = "%c%c" % ((mbar & 0xFF), ((mbar >> 8) & 0xFF))
- err = remote.sendMessageSyncError(MSG_SET_HYSTERESIS, data)
+ err = remote.sendMessageSyncError(MSG_SET_HYSTERESIS, 0, data)
if err != MSG_ERR_NONE:
self.log.addText(self.tr("Failed to change hysteresis. Error=%u\n" % err))
+ def autoadjustChanged(self, state):
+ self.pressureSpin.setEnabled(state == Qt.Checked)
+ self.inButton.setEnabled(state == Qt.Unchecked)
+ self.outButton.setEnabled(state == Qt.Unchecked)
+ if not self.initialized:
+ return
+ flags = remote.configFlagsFetch()
+ if flags == None:
+ self.log.addText(self.tr("Failed to fetch config flags\n"))
+ return
+ if state == Qt.Checked:
+ flags |= (1 << CFG_FLAG_AUTOADJUST_ENABLE)
+ else:
+ flags &= ~(1 << CFG_FLAG_AUTOADJUST_ENABLE)
+ err = remote.configFlagsSet(flags)
+ if err != MSG_ERR_NONE:
+ self.log.addText(self.tr("Failed to set config flags\n"))
+
+ def inValvePressed(self):
+ err = remote.setValve(0, 1)
+ if err != MSG_ERR_NONE:
+ self.log.addText(self.tr("Failed to switch valve 0 ON\n"))
+
+ def inValveReleased(self):
+ err = remote.setValve(0, 0)
+ if err != MSG_ERR_NONE:
+ self.log.addText(self.tr("Failed to switch valve 0 OFF\n"))
+
+ def outValvePressed(self):
+ err = remote.setValve(1, 1)
+ if err != MSG_ERR_NONE:
+ self.log.addText(self.tr("Failed to switch valve 1 ON\n"))
+
+ def outValveReleased(self):
+ err = remote.setValve(1, 0)
+ if err != MSG_ERR_NONE:
+ self.log.addText(self.tr("Failed to switch valve 1 OFF\n"))
+
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
bues.ch cgit interface