I'm working on making a coffee machine, I have implemented the following code, and it seems to work. Keep in mind I'm not a coder so I'm sure a lot of what I'm doing is not necessarily the best way to do it. here's the schematic.
currently everything works from a hardware perspective, and I can get all the systems to work on there own, and I can get the code I have now to work. However now I want to add the OLED display, and when I do ( see the commented out portions) the code just gets locked up and nothing happens, I know I'm using a bunch of If statements for logic in state 2, which I'm guessing is causing some errors, not really sure how to change that logic. Again I can get the OLED to work if I run the SH1106 example sketch, but I'm not a coder so I don't really know what I'm doing. Any help would be appreciated.
for reference, I'm using a ds1820 temp sensor, simple push buttons for the switches, and the water tank sw is just a water level probe, the SSR goes through a opto Isolator. The motorOn header goes to a separate motor controller.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define i2c_Address 0x3c ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Pin Definitions
#define ONE_WIRE_BUS 6
#define FAULT_PIN 2
#define POWER_ON_PIN 3
#define TEMP_UP_PIN 5
#define TEMP_DOWN_PIN 4
#define BREW_SW_PIN 7
#define MOTOR_PIN 8
#define WATER_TANK_PIN A2
#define SSR_PIN A3
// Constants
double setTemp = 200; // Set temperature
// Initialize OneWire and DallasTemperature objects
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Initialize PID variables
double Input, Output;
double Kp = 22, Ki = 1.5, Kd = 20;
PID myPID(&Input, &Output, &setTemp, Kp, Ki, Kd, DIRECT);
// Define state enumeration
enum State {
STATE_1,
STATE_2,
STATE_3,
STATE_4,
STATE_5,
STATE_6
};
// Global variable for current state
State currentState = STATE_1;
// Function prototypes
void handleState1();
void handleState2();
void handleState3();
void handleState4();
void handleState5();
void handleState6();
void setup() {
Serial.begin(9600);
delay(2000); // wait for the OLED to power up
display.begin(i2c_Address, true);
display.display();
pinMode(FAULT_PIN, INPUT);
pinMode(POWER_ON_PIN, INPUT);
pinMode(TEMP_UP_PIN, INPUT);
pinMode(TEMP_DOWN_PIN, INPUT);
pinMode(BREW_SW_PIN, INPUT);
pinMode(MOTOR_PIN, OUTPUT);
pinMode(WATER_TANK_PIN, INPUT_PULLUP);
pinMode(SSR_PIN, OUTPUT);
digitalWrite(MOTOR_PIN, LOW);
digitalWrite(SSR_PIN, LOW);
myPID.SetMode(AUTOMATIC); // Set PID to automatic mode
sensors.begin();
}
void loop() {
switch (currentState) {
case STATE_1:
handleState1();
break;
case STATE_2:
handleState2();
break;
case STATE_3:
handleState3();
break;
case STATE_4:
handleState4();
break;
case STATE_5:
handleState5();
break;
case STATE_6:
handleState6();
break;
}
}
void handleState1() {
// check to make sure there is water in the boiler.
Serial.println("State: STATE_1");
if (digitalRead(WATER_TANK_PIN) == LOW) {
currentState = STATE_2;
} else {
currentState = STATE_5;
}
}
void handleState2() {
Serial.println("State: STATE_2");
sensors.requestTemperatures();
float temp = sensors.getTempFByIndex(0); // get the temp of the water
Input = temp; // send the temp to the pid
Serial.print("Temperature: ");
Serial.println(temp);
Serial.println(setTemp);
// because of the delay in the temp reading, if the temp is not within 10 deg of the set temp turn on the SSR
if (temp + 10 < setTemp) {
digitalWrite(SSR_PIN, HIGH);
// display.clearDisplay();
// display.setTextSize(2); // Normal 1:1 pixel scale
// display.setTextColor(SH110X_WHITE); // Draw white text
// display.setCursor(10, 10);
// display.print("HEATING...");
// display.display();
} else if (temp + 10 > setTemp) { // if the temp is within 10 deg use PID
myPID.Compute(); // calculate the PID
sendPWM(Output); // send the PWM to the
Serial.println("sendmess");
sendMess(setTemp);// send the set temp to the screen
}
if (digitalRead(TEMP_UP_PIN) == HIGH) { // if the temp up sw is pressed increase the temp
currentState = STATE_3;
} else if (digitalRead(TEMP_DOWN_PIN) == HIGH) { // vise versa for the temp down switch.
currentState = STATE_4;
} else if (digitalRead(BREW_SW_PIN) == HIGH) { // check if the brew sw is pressed
currentState = STATE_6;
}
if (digitalRead(WATER_TANK_PIN) == HIGH) { // check if theres water in the tank
currentState = STATE_5;
}
}
void handleState3() {
Serial.println("State: STATE_3");
// logic for increasing temperature
// dont let the temp go above 209 deg
if (setTemp < 209) {
setTemp++;
// sendMess(setTemp);
sendMess(setTemp); // send the new set temp to the screen
currentState = STATE_2;
}
delay(100);
currentState = STATE_2;
}
void handleState4() {
Serial.println("State: STATE_4");
// Add logic for decreasing temperature
// dont let the set temp go below 195 deg
if (setTemp > 195) {
setTemp--;
//sendMess(setTemp);
sendMess(setTemp);
Serial.println(setTemp);
currentState = STATE_2;
}
delay(100);
currentState = STATE_2;
}
void handleState5() {
Serial.println("State: STATE_5");
// logic for handling water tank being filled
while (digitalRead(WATER_TANK_PIN) == HIGH) { // Check if WATER_TANK_PIN is HIGH
digitalWrite(MOTOR_PIN, HIGH);// Turn on the motor until tank is full
digitalWrite(SSR_PIN, LOW); // dont let the SSR turn on while the motot is on
}
digitalWrite(MOTOR_PIN, LOW); // Turn off the motor
currentState = STATE_2; // Transition to STATE_2
}
void handleState6() {
Serial.println("State: STATE_6");
// logic for handling brew switch state
while (digitalRead(WATER_TANK_PIN) == LOW && digitalRead(BREW_SW_PIN) == HIGH) { // the brew switch needs to be high and the water tank needs to be filled.
digitalWrite(MOTOR_PIN, HIGH);// Turn on the motor until brew switch is low.
digitalWrite(SSR_PIN, LOW);// dont let the SSR turn on while the motot is on
}
digitalWrite(MOTOR_PIN, LOW);// Turn off the motor
currentState = STATE_2;
}
///////////////////// other functions
/* send the pwm out to the SSR
the PID sends an output of 0-255 however the SSR needs to have PWM with a period of around
250-300 to work, so to do this the Duty cycle of the PWM is defined by the PID
*/
void sendPWM(int duty) {
// because the PWM logic makes the SSR turn on even for a mS this code is added so if the Duty cycle is 0 the SSR is off.
if (duty >= 0) {
Serial.print("send pwm");
Serial.println(duty);
analogWrite(A3, 255); // turn on the SSR
delay(duty); // wait for the duty cycle
analogWrite(A3, 0); // tunr off the SSR
delay(255 - duty); // wait for the rest of the duty cycle.
} else if (duty = 0) {
analogWrite(A3, 0);
}
}
void sendMess(float temp) {
// send the set temp on the screen.
// display.display();
// display.clearDisplay();
// display.setTextSize(1); // Normal 1:1 pixel scale
// display.setTextColor(SH110X_WHITE); // Draw white text
// display.setCursor(10, 1);
// display.print("Set Temp :");
// display.setTextSize(2); // Normal 1:1 pixel scale
// display.setTextColor(SH110X_WHITE); // Draw white text
// display.setCursor(10, 10);
// display.println(temp);
// display.setCursor(90, 10);
// display.print("F");
// display.display();
}