kopia lustrzana https://github.com/jamesgao/kiln_controller
add ds18b20 reading to firmware
rodzic
c1208f0e60
commit
1671c965e0
|
@ -1,6 +0,0 @@
|
||||||
Raspberry Pi controlled Kiln
|
|
||||||
============================
|
|
||||||
|
|
||||||
This project implements a wifi-accessible temperature controller for a ceramic firing kiln.
|
|
||||||
|
|
||||||
Please see the BOM for all the parts we purchased for this project. Additional circuit diagrams and 3D models will be forthcoming.
|
|
|
@ -3,7 +3,7 @@
|
||||||
#define PIN_STEP2 8
|
#define PIN_STEP2 8
|
||||||
#define PIN_STEP3 7
|
#define PIN_STEP3 7
|
||||||
#define PIN_STEP4 6
|
#define PIN_STEP4 6
|
||||||
#define PIN_AUXTEMP A1
|
#define PIN_AUXTEMP 2
|
||||||
#define PIN_TEMP_CS 4
|
#define PIN_TEMP_CS 4
|
||||||
#define PIN_LOADCELL A3
|
#define PIN_LOADCELL A3
|
||||||
#define PIN_FLAME_A A2
|
#define PIN_FLAME_A A2
|
||||||
|
@ -12,8 +12,17 @@
|
||||||
|
|
||||||
#define STEP_SPEED 275//in steps per second
|
#define STEP_SPEED 275//in steps per second
|
||||||
#define TEMP_UPDATE 250 //milliseconds
|
#define TEMP_UPDATE 250 //milliseconds
|
||||||
#define MOTOR_TIMEOUT 5000 //milliseconds
|
#define AUX_UPDATE 1000 //milliseconds
|
||||||
|
#define MOTOR_TIMEOUT 60000 //milliseconds
|
||||||
|
|
||||||
|
#define NUM_AUXTEMP 2
|
||||||
|
|
||||||
|
#define NO_PORTB_PINCHANGES
|
||||||
|
#define NO_PORTC_PINCHANGES
|
||||||
|
#define DISABLE_PCINT_MULTI_SERVICE
|
||||||
|
|
||||||
|
#include <OneWire.h>
|
||||||
|
#include <DallasTemperature.h>
|
||||||
#include <Stepper.h>
|
#include <Stepper.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
@ -28,7 +37,7 @@ struct Status {
|
||||||
float main_temp;
|
float main_temp;
|
||||||
float ambient;
|
float ambient;
|
||||||
float weight;
|
float weight;
|
||||||
float aux_temp[2];
|
float aux_temp[NUM_AUXTEMP];
|
||||||
} status;
|
} status;
|
||||||
uint8_t* status_data = (uint8_t*) &status;
|
uint8_t* status_data = (uint8_t*) &status;
|
||||||
|
|
||||||
|
@ -36,22 +45,34 @@ const float step_interval = 1. / STEP_SPEED * 1000.; //milliseconds
|
||||||
|
|
||||||
//intermediate variables
|
//intermediate variables
|
||||||
Adafruit_MAX31855 thermo(PIN_TEMP_CS);
|
Adafruit_MAX31855 thermo(PIN_TEMP_CS);
|
||||||
Stepper stepper(2048, PIN_STEP1, PIN_STEP3, PIN_STEP2, PIN_STEP4);
|
Stepper stepper(2048, PIN_STEP4, PIN_STEP2, PIN_STEP3, PIN_STEP1);
|
||||||
|
pushbutton reglimit = pushbutton(PIN_REGLIMIT, 5);
|
||||||
|
OneWire oneWire(PIN_AUXTEMP);
|
||||||
|
DallasTemperature sensors(&oneWire);
|
||||||
|
DeviceAddress aux_addr[NUM_AUXTEMP];
|
||||||
|
|
||||||
char i2c_command;
|
char i2c_command;
|
||||||
float next_step;
|
float next_step;
|
||||||
unsigned long next_temp;
|
unsigned long next_temp;
|
||||||
|
unsigned long next_aux = 0;
|
||||||
unsigned char motor_active = false;
|
unsigned char motor_active = false;
|
||||||
unsigned long stepper_target = 0;
|
unsigned long stepper_target = 0;
|
||||||
unsigned int n_clicks = 0; //Number of full rotations
|
unsigned long num_aux = 0;
|
||||||
|
int n_clicks = 0; //Number of full rotations
|
||||||
boolean limit_state = false;
|
boolean limit_state = false;
|
||||||
unsigned long limit_last;
|
unsigned long limit_last;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
//setup ignition mosfet
|
||||||
|
pinMode(PIN_IGNITE, OUTPUT);
|
||||||
|
digitalWrite(PIN_IGNITE, LOW);
|
||||||
|
status.ignite = 0.;
|
||||||
|
|
||||||
status.flame = false;
|
status.flame = false;
|
||||||
status.weight = 0.;
|
status.weight = 0.;
|
||||||
status.aux_temp[0] = 0.;
|
status.aux_temp[0] = -1.;
|
||||||
status.aux_temp[1] = 0.;
|
status.aux_temp[1] = -1.;
|
||||||
|
sensors.begin();
|
||||||
|
|
||||||
//Setup I2C
|
//Setup I2C
|
||||||
Wire.begin(0x08);
|
Wire.begin(0x08);
|
||||||
|
@ -61,33 +82,32 @@ void setup() {
|
||||||
//Set up regulator stepper
|
//Set up regulator stepper
|
||||||
status.motor = 0;
|
status.motor = 0;
|
||||||
|
|
||||||
//setup regulator limit switch
|
//set initial thermocouple temperature
|
||||||
pinMode(PIN_REGLIMIT, INPUT);
|
|
||||||
digitalWrite(PIN_REGLIMIT, HIGH);
|
|
||||||
|
|
||||||
//setup ignition mosfet
|
|
||||||
pinMode(PIN_IGNITE, OUTPUT);
|
|
||||||
digitalWrite(PIN_IGNITE, LOW);
|
|
||||||
status.ignite = false;
|
|
||||||
|
|
||||||
//set initial temperature
|
|
||||||
delay(500);
|
delay(500);
|
||||||
update_temp();
|
update_temp();
|
||||||
next_temp = millis() + TEMP_UPDATE;
|
next_temp = millis() + TEMP_UPDATE;
|
||||||
|
|
||||||
|
//Setup auxtemp ds18b20 sensors
|
||||||
|
num_aux = sensors.getDeviceCount();
|
||||||
|
num_aux = NUM_AUXTEMP < num_aux ? NUM_AUXTEMP : num_aux;
|
||||||
|
for (int i = 0; i < num_aux; i++) {
|
||||||
|
sensors.getAddress(aux_addr[i], i);
|
||||||
|
sensors.setResolution(aux_addr[i], 12);
|
||||||
|
status.aux_temp[i] = 0.;
|
||||||
|
}
|
||||||
|
if (num_aux > 0) {
|
||||||
|
sensors.setWaitForConversion(false);
|
||||||
|
sensors.requestTemperatures();
|
||||||
|
next_aux = millis() + AUX_UPDATE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dir;
|
int dir;
|
||||||
unsigned long now;
|
unsigned long now;
|
||||||
void loop() {
|
void loop() {
|
||||||
now = millis();
|
now = millis();
|
||||||
if (digitalRead(PIN_REGLIMIT) == LOW) {
|
reglimit.update();
|
||||||
if (limit_last == 0) {
|
status.aux_temp[1] = reglimit.n_clicks;
|
||||||
limit_last = millis();
|
|
||||||
} else if ((millis() - limit_last) > 5) {
|
|
||||||
n_clicks += dir;
|
|
||||||
limit_last = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stepper_target != status.motor && now > next_step) {
|
if (stepper_target != status.motor && now > next_step) {
|
||||||
dir = status.motor < stepper_target ? 1 : -1;
|
dir = status.motor < stepper_target ? 1 : -1;
|
||||||
|
@ -95,7 +115,7 @@ void loop() {
|
||||||
|
|
||||||
//Limit switch tripped
|
//Limit switch tripped
|
||||||
if (stepper_target == 0) {
|
if (stepper_target == 0) {
|
||||||
if (n_clicks == 0)
|
if (reglimit.n_clicks == 0)
|
||||||
status.motor = 0;
|
status.motor = 0;
|
||||||
} else {
|
} else {
|
||||||
status.motor += dir;
|
status.motor += dir;
|
||||||
|
@ -119,6 +139,12 @@ void loop() {
|
||||||
next_temp += TEMP_UPDATE;
|
next_temp += TEMP_UPDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//update auxtemp
|
||||||
|
if (num_aux > 0 && now > next_aux) {
|
||||||
|
update_aux();
|
||||||
|
next_aux += AUX_UPDATE;
|
||||||
|
}
|
||||||
|
|
||||||
//check flame status
|
//check flame status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,9 +160,14 @@ void update_temp() {
|
||||||
thermo.readAll(status.main_temp, status.ambient);
|
thermo.readAll(status.main_temp, status.ambient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_aux() {
|
||||||
|
for (int i = 0; i < num_aux; i++) {
|
||||||
|
status.aux_temp[i] = sensors.getTempC(aux_addr[i]);
|
||||||
|
}
|
||||||
|
sensors.requestTemperatures();
|
||||||
|
}
|
||||||
|
|
||||||
void i2c_update() {
|
void i2c_update() {
|
||||||
//update temperatures
|
|
||||||
|
|
||||||
if (i2c_command == 'M') {
|
if (i2c_command == 'M') {
|
||||||
Wire.write((byte*) &(status.motor), 4);
|
Wire.write((byte*) &(status.motor), 4);
|
||||||
} else if (i2c_command == 'I') {
|
} else if (i2c_command == 'I') {
|
||||||
|
@ -170,7 +201,8 @@ void i2c_action(int nbytes) {
|
||||||
set_regulator(*((unsigned int*) buffer));
|
set_regulator(*((unsigned int*) buffer));
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
digitalWrite(PIN_IGNITE, buffer[0]);
|
analogWrite(PIN_IGNITE, buffer[0]);
|
||||||
|
status.ignite = buffer[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class pushbutton : public CallBackInterface
|
class pushbutton : public CallBackInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
uint8_t n_clicks;
|
int n_clicks;
|
||||||
uint8_t pin;
|
uint8_t pin;
|
||||||
unsigned int interval;
|
unsigned int interval;
|
||||||
unsigned long last;
|
unsigned long last;
|
||||||
|
@ -11,8 +11,6 @@ class pushbutton : public CallBackInterface
|
||||||
n_clicks = 0;
|
n_clicks = 0;
|
||||||
last = 0;
|
last = 0;
|
||||||
init();
|
init();
|
||||||
state = digitalRead(pin);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
void cbmethod() {
|
void cbmethod() {
|
||||||
last = millis();
|
last = millis();
|
||||||
|
@ -31,12 +29,11 @@ class pushbutton : public CallBackInterface
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int dir;
|
int dir;
|
||||||
boolean state;
|
|
||||||
|
|
||||||
void init () {
|
void init () {
|
||||||
pinMode(pin, INPUT);
|
pinMode(pin, INPUT);
|
||||||
digitalWrite(pin, HIGH);
|
digitalWrite(pin, HIGH);
|
||||||
PCintPort::attachInterrupt(pin, this, FALLING);
|
PCintPort::attachInterrupt(pin, this, CHANGE);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,174 +0,0 @@
|
||||||
#define PIN_IGNITE 10
|
|
||||||
#define PIN_STEP1 9
|
|
||||||
#define PIN_STEP2 8
|
|
||||||
#define PIN_STEP3 7
|
|
||||||
#define PIN_STEP4 6
|
|
||||||
#define PIN_AUXTEMP A1
|
|
||||||
#define PIN_TEMP_CS 4
|
|
||||||
#define PIN_LOADCELL A3
|
|
||||||
#define PIN_FLAME_A A2
|
|
||||||
#define PIN_FLAME_D 1
|
|
||||||
#define PIN_REGLIMIT 5
|
|
||||||
|
|
||||||
#define STEP_SPEED 275//in steps per second
|
|
||||||
#define TEMP_UPDATE 250 //milliseconds
|
|
||||||
#define MOTOR_TIMEOUT 5000 //milliseconds
|
|
||||||
|
|
||||||
#define NO_PORTB_PINCHANGES
|
|
||||||
#define NO_PORTC_PINCHANGES
|
|
||||||
#define DISABLE_PCINT_MULTI_SERVICE
|
|
||||||
|
|
||||||
#include <Stepper.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <Adafruit_MAX31855.h>
|
|
||||||
#include <ooPinChangeInt.h>
|
|
||||||
#include "pushbutton.h"
|
|
||||||
|
|
||||||
struct Status {
|
|
||||||
unsigned char ignite;
|
|
||||||
unsigned char flame;
|
|
||||||
unsigned int motor;
|
|
||||||
float main_temp;
|
|
||||||
float ambient;
|
|
||||||
float weight;
|
|
||||||
float aux_temp[2];
|
|
||||||
} status;
|
|
||||||
uint8_t* status_data = (uint8_t*) &status;
|
|
||||||
|
|
||||||
const float step_interval = 1. / STEP_SPEED * 1000.; //milliseconds
|
|
||||||
|
|
||||||
//intermediate variables
|
|
||||||
Adafruit_MAX31855 thermo(PIN_TEMP_CS);
|
|
||||||
Stepper stepper(2048, PIN_STEP4, PIN_STEP2, PIN_STEP3, PIN_STEP1);
|
|
||||||
pushbutton reglimit = pushbutton(PIN_REGLIMIT, 5);
|
|
||||||
|
|
||||||
char i2c_command;
|
|
||||||
float next_step;
|
|
||||||
unsigned long next_temp;
|
|
||||||
unsigned char motor_active = false;
|
|
||||||
unsigned long stepper_target = 0;
|
|
||||||
int n_clicks = 0; //Number of full rotations
|
|
||||||
boolean limit_state = false;
|
|
||||||
unsigned long limit_last;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
status.flame = false;
|
|
||||||
status.weight = 0.;
|
|
||||||
status.aux_temp[0] = 0.;
|
|
||||||
status.aux_temp[1] = 0.;
|
|
||||||
|
|
||||||
//Setup I2C
|
|
||||||
Wire.begin(0x08);
|
|
||||||
Wire.onRequest(i2c_update);
|
|
||||||
Wire.onReceive(i2c_action);
|
|
||||||
|
|
||||||
//Set up regulator stepper
|
|
||||||
status.motor = 0;
|
|
||||||
|
|
||||||
//setup ignition mosfet
|
|
||||||
pinMode(PIN_IGNITE, OUTPUT);
|
|
||||||
digitalWrite(PIN_IGNITE, LOW);
|
|
||||||
status.ignite = false;
|
|
||||||
|
|
||||||
//set initial temperature
|
|
||||||
delay(500);
|
|
||||||
update_temp();
|
|
||||||
next_temp = millis() + TEMP_UPDATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dir;
|
|
||||||
unsigned long now;
|
|
||||||
void loop() {
|
|
||||||
now = millis();
|
|
||||||
reglimit.update();
|
|
||||||
status.aux_temp[0] = reglimit.n_clicks;
|
|
||||||
|
|
||||||
if (stepper_target != status.motor && now > next_step) {
|
|
||||||
dir = status.motor < stepper_target ? 1 : -1;
|
|
||||||
stepper.step(dir);
|
|
||||||
|
|
||||||
//Limit switch tripped
|
|
||||||
if (stepper_target == 0) {
|
|
||||||
if (reglimit.n_clicks == 0)
|
|
||||||
status.motor = 0;
|
|
||||||
} else {
|
|
||||||
status.motor += dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_step += step_interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
//put motor to sleep after timeout
|
|
||||||
if (motor_active && (now - next_step) > MOTOR_TIMEOUT) {
|
|
||||||
digitalWrite(PIN_STEP1, LOW);
|
|
||||||
digitalWrite(PIN_STEP2, LOW);
|
|
||||||
digitalWrite(PIN_STEP3, LOW);
|
|
||||||
digitalWrite(PIN_STEP4, LOW);
|
|
||||||
motor_active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//update temperature
|
|
||||||
if (now > next_temp) {
|
|
||||||
update_temp();
|
|
||||||
next_temp += TEMP_UPDATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check flame status
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_regulator(unsigned long pos) {
|
|
||||||
motor_active = true;
|
|
||||||
reglimit.setDir(status.motor < pos ? 1 : -1);
|
|
||||||
if (stepper_target == status.motor)
|
|
||||||
next_step = millis(); //Start stepping immediately
|
|
||||||
stepper_target = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_temp() {
|
|
||||||
thermo.readAll(status.main_temp, status.ambient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_update() {
|
|
||||||
//update temperatures
|
|
||||||
|
|
||||||
if (i2c_command == 'M') {
|
|
||||||
Wire.write((byte*) &(status.motor), 4);
|
|
||||||
} else if (i2c_command == 'I') {
|
|
||||||
Wire.write((byte*) &(status.ignite), 1);
|
|
||||||
} else if (i2c_command == 'T') {
|
|
||||||
Wire.write((byte*) &(status.main_temp), 4);
|
|
||||||
} else if (i2c_command == 'F') {
|
|
||||||
Wire.write((byte*) &(status.flame), 1);
|
|
||||||
} else {
|
|
||||||
Wire.write(status_data, sizeof(struct Status));
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_command = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte buffer[32];
|
|
||||||
void i2c_action(int nbytes) {
|
|
||||||
i2c_command = Wire.read();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while (Wire.available()) {
|
|
||||||
buffer[i++] = Wire.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nbytes == 1) {
|
|
||||||
return; //Command already stored, no arguments
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (i2c_command) {
|
|
||||||
case 'M':
|
|
||||||
set_regulator(*((unsigned int*) buffer));
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
analogWrite(PIN_IGNITE, buffer[0]);
|
|
||||||
status.ignite = buffer[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_command = 0;
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
#include "protocol.h"
|
|
||||||
|
|
||||||
char Comm::buffer[BUFFER_LENGTH+1];
|
|
||||||
int Comm::_nacts;
|
|
||||||
char Comm::_commands[MAX_ACTIONS];
|
|
||||||
char* (*Comm::_actions[MAX_ACTIONS])(int, char*);
|
|
||||||
char Comm::_current_cmd;
|
|
||||||
int Comm::_current_len;
|
|
||||||
|
|
||||||
Comm::Comm(int addr) {
|
|
||||||
Wire.begin(addr);
|
|
||||||
Wire.onReceive(_handle_request);
|
|
||||||
Wire.onRequest(_handle_response);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Comm::action(char cmd, char* (*func)(int, char*)) {
|
|
||||||
if (_nacts >= MAX_ACTIONS)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
_actions[_nacts] = func;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Comm::_handle_request(int nbytes) {
|
|
||||||
_current_cmd = Wire.read();
|
|
||||||
_current_len = nbytes-1;
|
|
||||||
for (int i = 0; i < nbytes-1; i++) {
|
|
||||||
buffer[i] = Wire.read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Comm::_handle_response() {
|
|
||||||
for (int i = 0; i < MAX_ACTIONS; i++) {
|
|
||||||
if (_commands[i] == _current_cmd) {
|
|
||||||
_actions[i](_current_len, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Wire.write(buffer);
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
#ifndef PROTOCOL_H
|
|
||||||
#define PROTOCOL_H
|
|
||||||
|
|
||||||
#include "Wire.h"
|
|
||||||
|
|
||||||
#define MAX_ACTIONS 16
|
|
||||||
|
|
||||||
class Comm {
|
|
||||||
private:
|
|
||||||
static char buffer[BUFFER_LENGTH+1];
|
|
||||||
static int _nacts;
|
|
||||||
static char _commands[MAX_ACTIONS];
|
|
||||||
static char* (*_actions[MAX_ACTIONS])(int, char*);
|
|
||||||
static char _current_cmd;
|
|
||||||
static int _current_len;
|
|
||||||
|
|
||||||
static void _handle_request(int);
|
|
||||||
static void _handle_response(void);
|
|
||||||
|
|
||||||
public:
|
|
||||||
Comm(int addr);
|
|
||||||
int action(char, char* (*)(int, char*));
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //PROTOCOL_H
|
|
|
@ -1,39 +0,0 @@
|
||||||
class pushbutton : public CallBackInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int n_clicks;
|
|
||||||
uint8_t pin;
|
|
||||||
unsigned int interval;
|
|
||||||
unsigned long last;
|
|
||||||
|
|
||||||
pushbutton (uint8_t _pin, unsigned int _interval): pin(_pin) , interval(_interval) {
|
|
||||||
dir = 0;
|
|
||||||
n_clicks = 0;
|
|
||||||
last = 0;
|
|
||||||
init();
|
|
||||||
};
|
|
||||||
void cbmethod() {
|
|
||||||
last = millis();
|
|
||||||
};
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
if (last != 0 && (millis() - last) > interval) {
|
|
||||||
n_clicks += dir;
|
|
||||||
last = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDir(int d) {
|
|
||||||
dir = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int dir;
|
|
||||||
|
|
||||||
void init () {
|
|
||||||
pinMode(pin, INPUT);
|
|
||||||
digitalWrite(pin, HIGH);
|
|
||||||
PCintPort::attachInterrupt(pin, this, CHANGE);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
Ładowanie…
Reference in New Issue