#include <AccelStepper.h>
#include <GyverOLED.h>
#include <EncButton.h>
#include <EEPROM.h>
#define PinBtn1 7
#define PinBtn2 10
#define PinBtn3 11
#define CLK 9
#define DT 8
#define SW 12
#define EN 2
#define STEP 3
#define DIR 4
#define TermPin 0
#define HeaterPin 5
#define FanPin 6
#define c1 -0.9039915889e-3
#define c2 4.217766123e-4
#define c3 -4.048954741e-7
enum DeviceEnum
{
Temp,
Step,
Fan
};
struct SettingsDeviceDiapasonStruct
{
int AddingSelect;
int MinSelect;
int MaxSelect;
int SelectAfterMin;
int SelectAfterMax;
};
struct MemorizedDeviceDataStruct
{
int MemoTemp = 0;
int MemoStepperSpeed = 0;
int MemoFanSpeed = 0;
};
unsigned long MillisTime = 0;
unsigned long PrevMillisTime = 0;
EncButton<EB_TICK, VIRT_BTN> Btn1;
EncButton<EB_TICK, VIRT_BTN> Btn2;
EncButton<EB_TICK, VIRT_BTN> Btn3;
EncButton<EB_TICK, CLK, DT, SW> Encoder1;
GyverOLED<SSD1306_128x64, OLED_BUFFER> Oled;
AccelStepper StepEngine(AccelStepper::DRIVER, STEP, DIR);
bool bHeater = false;
bool bStepper = false;
bool bFan = false;
int Max_Temp = 0;
int StepperSpeed = 0;
int FanSpeed = 0;
int ChangeTemp = 0;
int ChangeStep = 0;
int ChangeFan = 0;
bool bSetOrChoose = false;
int SelectionPos = 0;
SettingsDeviceDiapasonStruct HetSet {10,0,220,0,220};
SettingsDeviceDiapasonStruct StpSet {50,0,1000,0,1000};
SettingsDeviceDiapasonStruct FanSet {15,0,255,0,255};
SettingsDeviceDiapasonStruct DeviceSet {1,0,2,2,0};
MemorizedDeviceDataStruct MemorizedDeviceData;
String NameOff = "OFF";
String TemperatureName = "Temp";
String StepperName = "Step";
String FanName = "Fan";
void CalculateHeater(float Temperature)
{
float PWM_Value = 0;
float CurTempDiffRange = Max_Temp * 0.1; //Temp_Percentage = 0.1;
float Temp_Delta = Max_Temp - CurTempDiffRange;
if(Max_Temp > 0)
{
if(Temperature > Temp_Delta)
{
PWM_Value = map(Temperature - Temp_Delta, 0, CurTempDiffRange, 255, 0);
if(PWM_Value < 0)
{
PWM_Value = 0;
}
}
else
{
PWM_Value = 255;
}
}
analogWrite(HeaterPin, PWM_Value);
}
float CalculateTermistor()
{
float logR2 = log(4700 / (1023.0 / (float)analogRead(TermPin) - 1.0)); //#define R1 4700
return (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2)) - 273.15;
}
void SetStepperSpeed()
{
if(StepperSpeed == 0)
{
digitalWrite(EN, HIGH);
}
else
{
digitalWrite(EN, LOW);
}
StepEngine.setSpeed(StepperSpeed);
}
void SetFanSpeed()
{
analogWrite(FanPin, FanSpeed);
}
void SetCursorNameTextToPos(int x0, int y0, int xN, int yN, String Text, bool bSelected)
{
Oled.clear(x0, y0, xN, yN);
Oled.setCursorXY(x0,y0);
Oled.invertText(bSelected);
Oled.print(Text);
Oled.invertText(false);
Oled.update(x0, y0, xN, yN);
}
void SetCursorNameTextToPosByDevice(int UsingInt, DeviceEnum Device, String Text, bool bSelected)
{
switch (Device)
{
case Temp:
switch (UsingInt)
{
case 0:
SetCursorNameTextToPos(15,4,41,11,Text,bSelected);
break;
case 1:
SetCursorNameTextToPos(2,18,41,25,Text,bSelected);
break;
case 2:
SetCursorNameTextToPos(2,33,41,40,Text,bSelected);
break;
}
break;
case Step:
switch (UsingInt)
{
case 0:
SetCursorNameTextToPos(55,4,81,11,Text,bSelected);
break;
case 1:
SetCursorNameTextToPos(42,18,81,25,Text,bSelected);
break;
case 2:
SetCursorNameTextToPos(42,33,81,40,Text,bSelected);
break;
}
break;
case Fan:
switch (UsingInt)
{
case 0:
SetCursorNameTextToPos(95,4,126,11,Text,bSelected);
break;
case 1:
SetCursorNameTextToPos(82,18,126,25,Text,bSelected);
break;
case 2:
SetCursorNameTextToPos(82,33,126,40,Text,bSelected);
break;
}
break;
}
}
void InitDisplayMenu()
{
Oled.init();
Oled.clear();
Oled.setCursorXY(2,4);
Oled.print("T:");
Oled.setCursorXY(42,4);
Oled.print("S:");
Oled.setCursorXY(82,4);
Oled.print("F:");
SetCursorNameTextToPosByDevice(0, Temp, NameOff, false);
SetCursorNameTextToPosByDevice(0, Step, NameOff, false);
SetCursorNameTextToPosByDevice(0, Fan, NameOff, false);
SetCursorNameTextToPosByDevice(1, Temp, TemperatureName, true);
SetCursorNameTextToPosByDevice(1, Step, StepperName, false);
SetCursorNameTextToPosByDevice(1, Fan, FanName, false);
SetCursorNameTextToPosByDevice(2, Temp, String(ChangeTemp), false);
SetCursorNameTextToPosByDevice(2, Step, String(ChangeStep), false);
SetCursorNameTextToPosByDevice(2, Fan, String(ChangeFan), false);
SetCursorNameTextToPos(2, 50, 126, 57, "Hold enc to save", false);
Oled.update();
}
void setup()
{
//Serial.begin(9600);
EEPROM.get(0, MemorizedDeviceData);
if(MemorizedDeviceData.MemoTemp != -1)
{
ChangeTemp = MemorizedDeviceData.MemoTemp;
}
if(MemorizedDeviceData.MemoStepperSpeed != -1)
{
ChangeStep = MemorizedDeviceData.MemoStepperSpeed;
}
if(MemorizedDeviceData.MemoFanSpeed != -1)
{
ChangeFan = MemorizedDeviceData.MemoFanSpeed;
}
SetAllData();
//Serial.println(MemorizedDeviceData.MemoTemp);
//Serial.println(MemorizedDeviceData.MemoStepperSpeed);
//Serial.println(MemorizedDeviceData.MemoFanSpeed);
pinMode(PinBtn1, INPUT_PULLUP);
pinMode(PinBtn2, INPUT_PULLUP);
pinMode(PinBtn3, INPUT_PULLUP);
pinMode(EN, OUTPUT);
digitalWrite(EN, HIGH); //Stepper driver is disbled
StepEngine.setMaxSpeed(1000);
StepEngine.setSpeed(0);
pinMode(HeaterPin, OUTPUT);
pinMode(FanPin, OUTPUT);
PrevMillisTime = millis();
InitDisplayMenu();
}
int CalculateSelectableInt(bool bRight, int& ChangableInt, SettingsDeviceDiapasonStruct SettingsStruct)
{
int AddingSelect = SettingsStruct.AddingSelect;
int MinSelect = SettingsStruct.MinSelect;
int MaxSelect = SettingsStruct.MaxSelect;
int SelectAfterMin = SettingsStruct.SelectAfterMin;
int SelectAfterMax = SettingsStruct.SelectAfterMax;
if(bRight)
{
ChangableInt -= AddingSelect;
}
else
{
ChangableInt += AddingSelect;
}
if(ChangableInt < MinSelect)
{
ChangableInt = SelectAfterMin;
}
if(ChangableInt > MaxSelect)
{
ChangableInt = SelectAfterMax;
}
return ChangableInt;
}
void SetPosSelection(bool bRight)
{
if(bSetOrChoose)
{
if(SelectionPos == 0)
{
ChangeTemp = CalculateSelectableInt(bRight, ChangeTemp, HetSet);
}
else if(SelectionPos == 1)
{
ChangeStep = CalculateSelectableInt(bRight, ChangeStep, StpSet);
}
else if(SelectionPos == 2)
{
ChangeFan = CalculateSelectableInt(bRight, ChangeFan, FanSet);
}
}
else
{
SelectionPos = CalculateSelectableInt(bRight,SelectionPos, DeviceSet);
}
}
void SetSelection()
{
if(SelectionPos == 0)
{
SetCursorNameTextToPosByDevice(1, Temp, TemperatureName, true);
SetCursorNameTextToPosByDevice(1, Step, StepperName, false);
SetCursorNameTextToPosByDevice(1, Fan, FanName, false);
if(bSetOrChoose)
{
SetCursorNameTextToPosByDevice(2, Temp, String(ChangeTemp), true);
SetCursorNameTextToPosByDevice(2, Step, String(ChangeStep), false);
SetCursorNameTextToPosByDevice(2, Fan, String(ChangeFan), false);
}
}
else if (SelectionPos == 1)
{
SetCursorNameTextToPosByDevice(1, Temp, TemperatureName, false);
SetCursorNameTextToPosByDevice(1, Step, StepperName, true);
SetCursorNameTextToPosByDevice(1, Fan, FanName, false);
if(bSetOrChoose)
{
SetCursorNameTextToPosByDevice(2, Temp, String(ChangeTemp), false);
SetCursorNameTextToPosByDevice(2, Step, String(ChangeStep), true);
SetCursorNameTextToPosByDevice(2, Fan, String(ChangeFan), false);
}
}
else if (SelectionPos == 2)
{
SetCursorNameTextToPosByDevice(1, Temp, TemperatureName, false);
SetCursorNameTextToPosByDevice(1, Step, StepperName, false);
SetCursorNameTextToPosByDevice(1, Fan, FanName, true);
if(bSetOrChoose)
{
SetCursorNameTextToPosByDevice(2, Temp, String(ChangeTemp), false);
SetCursorNameTextToPosByDevice(2, Step, String(ChangeStep), false);
SetCursorNameTextToPosByDevice(2, Fan, String(ChangeFan), true);
}
}
if(!bSetOrChoose)
{
SetCursorNameTextToPosByDevice(2, Temp, String(ChangeTemp), false);
SetCursorNameTextToPosByDevice(2, Step, String(ChangeStep), false);
SetCursorNameTextToPosByDevice(2, Fan, String(ChangeFan), false);
}
}
void SetAllData()
{
FanSpeed = bFan ? ChangeFan : 0;
StepperSpeed = bStepper ? ChangeStep : 0;
Max_Temp = bHeater ? ChangeTemp : 0;
}
void loop()
{
Encoder1.tick();
Btn1.tick(!digitalRead(PinBtn1));
Btn2.tick(!digitalRead(PinBtn2));
Btn3.tick(!digitalRead(PinBtn3));
float Temperature = CalculateTermistor();
if(Encoder1.held())
{
MemorizedDeviceData.MemoTemp = ChangeTemp;
MemorizedDeviceData.MemoStepperSpeed = ChangeStep;
MemorizedDeviceData.MemoFanSpeed = ChangeFan;
EEPROM.put(0, MemorizedDeviceData);
SetCursorNameTextToPos(2, 50, 126, 57, ">>>>> SAVED <<<<<", true);
}
else if(Encoder1.release())
{
SetCursorNameTextToPos(2, 50, 126, 57, "Hold enc to save", false);
}
if(Encoder1.click())
{
bSetOrChoose = !bSetOrChoose;
SetSelection();
}
if(Encoder1.right())
{
SetPosSelection(true);
SetSelection();
SetAllData();
}
else if(Encoder1.left())
{
SetPosSelection(false);
SetSelection();
SetAllData();
}
if(Btn1.click())
{
bFan = !bFan;
SetCursorNameTextToPosByDevice(0, Fan, bFan ? String(FanSpeed) : NameOff, false);
FanSpeed = bFan ? ChangeFan : 0;
}
if(Btn2.click())
{
bStepper = !bStepper;
SetCursorNameTextToPosByDevice(0, Step, bStepper ? String(StepperSpeed) : NameOff, false);
StepperSpeed = bStepper ? ChangeStep : 0;
SetStepperSpeed();
}
if(Btn3.click())
{
bHeater = !bHeater;
SetCursorNameTextToPosByDevice(0, Temp, bHeater ? String(Temperature,1) : NameOff, false);
Max_Temp = bHeater ? ChangeTemp : 0;
}
CalculateHeater(Temperature);
SetStepperSpeed();
SetFanSpeed();
StepEngine.runSpeed();
MillisTime = millis();
if(MillisTime - PrevMillisTime > 500)
{
SetCursorNameTextToPosByDevice(0, Temp, bHeater ? String(Temperature,1) : NameOff, false);
SetCursorNameTextToPosByDevice(0, Step, bStepper ? String(StepperSpeed) : NameOff, false);
SetCursorNameTextToPosByDevice(0, Fan, bFan ? String(FanSpeed) : NameOff, false);
PrevMillisTime = millis();
}
}