Replies: 2 comments
-
Sorry, no code reviews here. TC4 is a different project that Artisan simply has compatibility with - you might get someone over there to look over your code, but nobody here is likely an expert in TC4 nor your esp32 code. TBH there isn't much to the serial stream, from what I have seen (since I implemented a "lite" version running on .Net MF over 10 years ago). There is a 4 year old minimal emulator that might be of help https://github.com/FilePhil/TC4-Emulator that is referred to in https://artisan-scope.org/docs/documents/ as well as https://github.com/greencardigan/TC4-shield/tree/master/applications/Artisan/aArtisan_PID/branches the aArtisanQ_PID that might also be of assistance, but ultimately you'll be a test-base of 1 unless you can find some others to assist your testing... |
Beta Was this translation helpful? Give feedback.
-
Sorry about that. I'm no coder with a lot of my work experience involving
animal surgeries or music.
Was getting desperate and hoping to be able to automate roasts.
Richard
…On Mon, Dec 4, 2023, 06:00 poundy ***@***.***> wrote:
Sorry, no code reviews here.
TC4 is a different project that Artisan simply has compatibility with -
you might get someone over there to look over your code, but nobody here is
likely an expert in TC4 nor your esp32 code.
TBH there isn't much to the serial stream, from what I have seen (since I
implemented a "lite" version running on .Net MF over 10 years ago). There
is a 4 year old minimal emulator that might be of help
https://github.com/FilePhil/TC4-Emulator that is referred to in
https://artisan-scope.org/docs/documents/ as well as
https://github.com/greencardigan/TC4-shield/tree/master/applications/Artisan/aArtisan_PID/branches
the aArtisanQ_PID that might also be of assistance, but ultimately you'll
be a test-base of 1 unless you can find some others to assist your
testing...
—
Reply to this email directly, view it on GitHub
<#1322 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BBRRMXHR3IL5W76KPJUPJTDYHTZAJAVCNFSM6AAAAAA74G4MHGVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM3TONBXGAYDA>
.
You are receiving this because you authored the thread.Message ID:
<artisan-roaster-scope/artisan/repo-discussions/1322/comments/7747000@
github.com>
|
Beta Was this translation helpful? Give feedback.
-
I've used the PID feature before with an Arduino / TC4+ but they're both spoiled now so I've gone to using an ESP32 with MAX6675 boards, I've taken code for temperature monitoring and then from another sketch for the serial commands to put together. Someone helped me with that and it compiles fine but he's not a coffee roaster and hasn't used Artisan Scope before. Can someone please take a look at the sketch for me and see whether I've missed out something because it doesn't work?
Also, can someone point me to a site or tell me what to do to get the heater control slider working. As said before, I've used it before but with the aArtisan sketch, it was pretty easy to set up.
`/**************
*
*/
#include "user.h"
#include <SerialCommands.h> // https://github.com/ppedro74/Arduino-SerialCommands
#include <BluetoothSerial.h> // Classic Bluetooth
#include <DHT.h> // DHT22
#include <SPI.h> // MAX6675 over hardware SPI
// Bluetooth
#define ROAST_ESP32_BLUETOOTH_NAME "U.A.F. Mk. 2" //Bluetooth device name
BluetoothSerial SerialBT;
// DHT22
#define DHTPIN 22 // GPIO22 -> DHT22 Output
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
double humidity;
double ambientc;
double ambientf;
// MAX6675
#define TC1_CS 32 // GPIO32 -> CS MAX6675[TC1]
#define TC2_CS 33 // GPIO33 -> CS MAX6675[TC2]
#define TC3_CS 25 // GPIO25 -> CS MAX6675[TC3]
#define TC4_CS 26 // GPIO26 -> CS MAX6675[TC4]
/* Note: All MAX6675
*/
bool unit_F = false;
#define SMA 5
int sma_idx = 0;
bool sma_filled = false;
double tc1s[SMA], tc2s[SMA], tc3s[SMA], tc4s[SMA];
double tc1, tc2, tc3, tc4;
// DHT22
void readDHT() {
float h = dht.readHumidity();
float c = dht.readTemperature();
float f = dht.readTemperature(true);
if (!isnan(h)) {
humidity = h;
}
if (!isnan(c)) {
ambientc = c;
}
if (!isnan(f)) {
ambientf = f;
}
}
// MAX6675
double readCelsius(uint8_t cs) {
uint16_t v;
digitalWrite(cs, LOW);
v = SPI.transfer(0x00);
v <<= 8;
v |= SPI.transfer(0x00);
digitalWrite(cs, HIGH);
if (v & 0x4) {
// uh oh, no thermocouple attached!
return NAN;
}
v >>= 3;
return v * 0.25;
}
double readFahrenheit(uint8_t cs) {
return readCelsius(cs) * 1.8 + 32;
}
bool readTCs() {
tc1s[sma_idx] = readCelsius(TC1_CS);
tc2s[sma_idx] = readCelsius(TC2_CS);
tc3s[sma_idx] = readCelsius(TC3_CS);
tc4s[sma_idx] = readCelsius(TC4_CS);
if (!isnan(tc1s[sma_idx]) && !isnan(tc1s[sma_idx]) && !isnan(tc1s[sma_idx]) && !isnan(tc1s[sma_idx])) {
sma_idx++;
if (sma_idx >= SMA) {
sma_filled = true;
sma_idx = 0;
}
tc1 = 0;
tc2 = 0;
tc3 = 0;
tc4 = 0;
if (sma_filled) {
for (int i = 0; i < SMA; i++) {
tc1 += tc1s[i];
tc2 += tc2s[i];
tc3 += tc3s[i];
tc4 += tc4s[i];
}
tc1 /= SMA;
tc2 /= SMA;
tc3 /= SMA;
tc4 /= SMA;
}
return true;
}
return false;
}
// USB & Bluetooth SerialCommands
char serialbt_cmds_buffer[32];
char serial_cmds_buffer[32];
SerialCommands serialbt_cmds(&SerialBT, serialbt_cmds_buffer, sizeof(serialbt_cmds_buffer), "\n", ";");
SerialCommands serial_cmds(&Serial, serial_cmds_buffer, sizeof(serial_cmds_buffer), "\n", ";");
//This is the default handler, and gets called when no other command matches.
void cmd_unrecognized(SerialCommands* sender, const char* cmd) {
sender->GetSerial()->print("Unrecognized command [");
sender->GetSerial()->print(cmd);
sender->GetSerial()->println("]");
}
void cmdSetChannel(SerialCommands* sender) {
sender->GetSerial()->println("#OK");
}
SerialCommand serialCmdSetChannel("CHAN", cmdSetChannel);
void cmdSetUnits(SerialCommands* sender) {
char* units = sender->Next();
if (units[0] == 'F') {
unit_F = true;
sender->GetSerial()->println("#OK Farenheit");
} else if (units[0] == 'C') {
unit_F = false;
sender->GetSerial()->println("#OK Celsius");
}
}
SerialCommand serialCmdSetUnits("UNITS", cmdSetUnits);
void cmdSetFilter(SerialCommands* sender) {
sender->GetSerial()->println("#OK");
}
SerialCommand serialCmdSetFilter("FILT", cmdSetFilter);
void cmdRead(SerialCommands* sender) {
readDHT();
if (unit_F) {
sender->GetSerial()->print(ambientf);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc1 * 1.8 + 32);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc2 * 1.8 + 32);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc3 * 1.8 + 32);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc4 * 1.8 + 32);
sender->GetSerial()->print(",0.00,0.00,0.00"); // Heater, Fan, PID set value
} else {
sender->GetSerial()->print(ambientc);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc1);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc2);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc3);
sender->GetSerial()->print(",");
sender->GetSerial()->print(tc4);
sender->GetSerial()->print(",0.00,0.00,0.00"); // Heater, Fan, PID set value
}
sender->GetSerial()->println("");
}
SerialCommand serialCmdRead("READ", cmdRead);
void setup() {
// DHT22 for ambient and humidity
pinMode(DHTPIN, INPUT);
dht.begin();
// Thermocouple (MAX6675 x4 over hardware SPI)
pinMode(TC1_CS, OUTPUT);
pinMode(TC2_CS, OUTPUT);
pinMode(TC3_CS, OUTPUT);
pinMode(TC4_CS, OUTPUT);
digitalWrite(TC1_CS, HIGH);
digitalWrite(TC2_CS, HIGH);
digitalWrite(TC3_CS, HIGH);
digitalWrite(TC4_CS, HIGH);
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
// USB Serial
Serial.begin(115200);
serial_cmds.SetDefaultHandler(cmd_unrecognized);
serial_cmds.AddCommand(&serialCmdSetChannel);
serial_cmds.AddCommand(&serialCmdSetUnits);
serial_cmds.AddCommand(&serialCmdSetFilter);
serial_cmds.AddCommand(&serialCmdRead);
// Bluetooth Serial
SerialBT.begin(ROAST_ESP32_BLUETOOTH_NAME);
serialbt_cmds.SetDefaultHandler(cmd_unrecognized);
serialbt_cmds.AddCommand(&serialCmdSetChannel);
serialbt_cmds.AddCommand(&serialCmdSetUnits);
serialbt_cmds.AddCommand(&serialCmdSetFilter);
serialbt_cmds.AddCommand(&serialCmdRead);
sma_idx = 0;
sma_filled = true;
tc1 = 0;
tc2 = 0;
tc3 = 0;
tc4 = 0;
}
void loop() {
serialbt_cmds.ReadSerial();
serial_cmds.ReadSerial();
if (readTCs()) {
delay(200);
}
}
//Parsing Serial Commands
void handleSerialCommand() {
if (SerialBT.available() > 0) {
String msg = SerialBT.readStringUntil('\n');
// if (Serial.available()>0){
// String msg = Serial.readStringUntil('\n'); //Serial.println(msg); //use for debug
}
}
`
And here's the contents of the user.h file.
`// user.h
// This file contains user definable compiler directives
// *************************************************************************************
// NOTE TO USERS: the following parameters should be
// be reviewed to suit your preferences and hardware setup.
// First, load and edit this sketch in the Arduino IDE.
// Next compile the sketch and upload it to the Arduino.
////////////////////
// Roasting software
// Comment out all if using TC4 stand alone
//#define ROASTLOGGER
#define ARTISAN
//#define ANDROID
//define output pins
#define HeatPin 27 //gpio pin for pwm to heater SSR
//This was used in the sketch and needs a definition
#define FanPin 25 //gpio pin to output analog value to set fan power
//These are not declared in the sketch - some of them probably need values set here
int dutyCycle, ManDutyCycle, PWMDutyCycle, fanPwr, FanDutyCycle;
bool ManualMode = false;
// set Heater PWM properties
const int freq = 1;
const int HeatChannel = 1; //use PWM channel 0 for heater
const int resolution = 10; // changing resolution changes max duty cycle
const int MaxDutyCycle = 1023; //max duty cycle for resolution = 10, 2exp10-1 = 1024-1 = 1023
////////////////////
// Temperature Unit
#define CELSIUS // controls only the initial conditions. Comment out for F.
////////////////////
// BAUD Rate for serial communications
#define BAUD 115200
#define BT_FILTER 10 // filtering level (percent) for displayed BT
#define ET_FILTER 10 // filtering level (percent) for displayed ET
// Thermocouple inputs
#define NC 4 // maximum number of physical channels on the TC4
// ambient sensor should be stable, so quick variations are probably noise -- filter heavily
//#define AMB_FILTER 70 // 70% filtering on ambient sensor readings
// *************************************************************************************
////////////////////
// Heater and Fan Limits/Options
//#define MIN_OT1 0 // Set output % for lower limit for OT1. 0% power will always be available
//#define MAX_OT1 100 // Set output % for upper limit for OT1
//#define MIN_OT2 0 // Set output % for lower limit for OT2. 0% power will always be available
//#define MAX_OT2 100 // Set output % for upper limit for OT2
//#define MIN_IO3 0 // Set output % for lower limit for IO3. 0% power will always be available
//#define MAX_IO3 100 // Set output % for upper limit for IO3
// cut power to Heater if fan duty is less than HTR_CUTOFF_FAN_VAL (to protect heater in air roaster). Set to 0 for no cutoff
//#define HTR_CUTOFF_FAN_VAL 0
//#define FAN_AUTO_COOL 100 // Set fan output duty for auto cool when using PID;STOP command
`
Beta Was this translation helpful? Give feedback.
All reactions