#include <EEPROM.h>
//-----------------------------------------------
// Définition des Entrée Sorties
//-----------------------------------------------
#define iPinEncClk 2
#define iPinEncDt 3
#define iPinEncSw 7
#define iPinBtnH 6
#define iPinBtnB 8
#define iPinNtcChauffe A0
#define iPinNtcProduit A1
#define oPinChauffe 5
//-----------------------------------------------
// Bibliothèque
//-----------------------------------------------
#include <Encoder.h> //--------------------------
Encoder myEnc(iPinEncClk, iPinEncDt);
//-----------------------------------------------
#include <SmoothThermistor.h> //-----------------
SmoothThermistor smoothThermistorChauffe(A0,ADC_SIZE_10_BIT, 20000, 22000, 3950, 25, 1);
SmoothThermistor smoothThermistorProduit(A1,ADC_SIZE_10_BIT, 100000, 100000, 3950, 25, 1);
//-----------------------------------------------
#include <PID_v1.h> //--------------------------
double Setpoint, Input, Output;
double Kp=0.1, Ki=0.1, Kd=0;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
float coefPid = 10000;
//----------------------------------------------
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // QT-PY / XIAO
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Valeurs en EEPROM
// 0-1 = int 19369 si initialisé
// 2-3 = int Température de chauffe High
// 4-5 = int Temperature produit High
// 6-7 = int Température de chauffe Low
// 8-9 = int temperature produit Low
// 10 = shortint deltaTempLow;
// 11 = shortint deltaTempHigh;
// 12 = temperature selectionnee 0 ==> Low / 1 ==> High
// 13 = int Pid
// 15 = int pId
// 17 = int piD
// 19 = temperature exact
// 21 = coef de correction
int consTempChauffeLow, consTempProduitLow;
int consTempChauffeHigh, consTempProduitHigh;
int valTempChauffe, valTempProduit;
byte deltaTempLow;
byte deltaTempHigh;
int mesTempChauffe;
int mesTempProduit;
int temp;
int isInit;
bool tempSelec;
unsigned long dimmerTime,oldDimmerTime;
float multiplicateurTempCoef = 100;
#define tempsAppuiCourt 50
#define tempsAppuiLong 500
#define tempsAppuiTresLong 2000
unsigned long currentTime,timeBtnH,timeBtnB,timeBtnSw;
bool flagBtnH, flagHcourt, flagHlong;
bool flagBtnB, flagBcourt, flagBlong, flagBtreslong;
bool flagBtnSw, flagSwcourt, flagSwlong, flagSwtreslong;
bool flagReglageChauffe, flagReglageProduit, flagReglagePid, flagReglageTemp;
bool etatBtnB, etatBtnH, etatBtnSw;
long oldPosition;
byte reglageKpid,reglageTemp;
int nbMesure;
int inputChauffe, inputProduit, moyenneChauffe;
int Pid, pId, piD;
int tempExact,tempCoef;
float tempCoefReel;
//--------------------------------------------------
// Setup
//--------------------------------------------------
void setup(){
//Serial.println("debut");
smoothThermistorChauffe.useAREF(true);
smoothThermistorProduit.useAREF(true);
EEPROM.get(0, isInit); // Chargement des dernieres valeurs utilisées
if (isInit == 19369) {
EEPROM.get(2, consTempChauffeHigh);
EEPROM.get(4, consTempProduitHigh);
EEPROM.get(6, consTempChauffeLow);
EEPROM.get(8, consTempProduitLow);
EEPROM.get(10,deltaTempLow);
EEPROM.get(11,deltaTempHigh);
EEPROM.get(12,tempSelec);
EEPROM.get(13,Pid);
Kp=Pid/coefPid;
EEPROM.get(15,pId);
Ki = pId/coefPid;
EEPROM.get(17,piD);
Kd = piD/coefPid;
EEPROM.get(19,tempExact);
EEPROM.get(21,tempCoef);
tempCoefReel = tempCoef/multiplicateurTempCoef;
}
else { // Séquence d'initialisation pour la premiere mise en route
for (int i = 0 ; i < EEPROM.length() ; i++) { // RAZ EEPROM
EEPROM.write(i, 255);
}
consTempChauffeLow = 510;
consTempProduitLow = 320;
EEPROM.put(6, consTempChauffeLow);
EEPROM.put(8, consTempProduitLow);
EEPROM.put(10,deltaTempLow);
EEPROM.put(11,deltaTempHigh);
consTempChauffeHigh = 750;
consTempProduitHigh = 550;
EEPROM.put(2, consTempChauffeHigh);
EEPROM.put(4, consTempProduitHigh);
tempSelec = true;
EEPROM.put(12,tempSelec);
Pid = 1000;
Kp=Pid/coefPid;
EEPROM.put(13,Pid);
pId = 40;
Ki = pId/coefPid;
EEPROM.put(15,pId);
piD = 0;
Kd = piD/coefPid;
EEPROM.put(17,piD);
tempExact = 10;
EEPROM.put(19,tempExact);
tempCoef = 1.1*multiplicateurTempCoef;
EEPROM.put(21,tempCoef);
tempCoefReel = tempCoef/multiplicateurTempCoef;
isInit = 19369; // Validation de l'initialisation
EEPROM.put(0, isInit);
}
if (tempSelec){
valTempChauffe = consTempChauffeHigh;
valTempProduit = consTempProduitHigh;
}
else {
valTempChauffe = consTempChauffeLow;
valTempProduit = consTempProduitLow;
}
display.begin(i2c_Address, true); // Address 0x3C default
display.clearDisplay();
delay(200);
Input = smoothThermistorProduit.temperature() * 10;
Setpoint = valTempProduit;
myPID.SetMode(AUTOMATIC);
delay(200);
myPID.SetTunings(Kp, Ki, Kd);
//TriacDimmer::begin();
pinMode(oPinChauffe, OUTPUT);
flagBtnH = false;
flagBtnB = false;
flagBtnSw = false;
inputChauffe = 0;
inputProduit = 0;
nbMesure = 0;
reglageKpid = 0;
//Serial.begin(57600);
}
long newPosition = 0;
unsigned long oldTime300 = 0, oldTime100 = 0, oldTime1000 = 0, oldTime10000 = 0;
//-----------------------------------------------------
// Loop
//-----------------------------------------------------
void loop() {
if (millis() > (oldTime1000 + 1000)){
oldTime1000 = millis();
inputProduit = inputProduit/nbMesure;
inputProduit = (inputProduit - 100) * 1.07 + 100;
inputChauffe = inputChauffe/nbMesure;
inputChauffe = (inputChauffe - 100) * 1.07 + 100;
nbMesure = 0;
Input = inputProduit;
moyenneChauffe = inputChauffe;
myPID.Compute();
if (!flagReglagePid and !flagReglageTemp) afficheTemp(inputProduit, inputChauffe);
inputProduit = 0;
inputChauffe = 0;
//Serial.println(Input);
}
if (millis() > (oldTime100 + 100)){
oldTime100 = millis();
inputProduit = inputProduit + (smoothThermistorProduit.temperature() * 10);
inputChauffe = inputChauffe + (smoothThermistorChauffe.temperature() * 10);
nbMesure =nbMesure+1;
if (!flagReglagePid and !flagReglageTemp) afficheConsigne(valTempChauffe, valTempProduit);
if (flagReglagePid) affichePid();
if (flagReglageTemp) afficheReglageTemp();
}
dimmerTherm();
gestionBouton();
gestionEncodeur();
}
//-------------------------------------------------------
// Sous Programmes
//-------------------------------------------------------
void afficheDebug(byte val){
display.setTextSize(1);
display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(64, 55);
display.print(val);
display.print(" ");
display.display();
}
void gestionEncodeur(){
if (flagReglageProduit){
newPosition = myEnc.read();
valTempProduit = valTempProduit + ((newPosition - oldPosition)/2);
oldPosition = newPosition;
}
if (flagReglageChauffe){
newPosition = myEnc.read();
valTempChauffe = valTempChauffe + ((newPosition - oldPosition)/2);
oldPosition = newPosition;
}
if (flagReglagePid){
newPosition = myEnc.read();
if (reglageKpid ==0){
Pid = Pid + ((newPosition - oldPosition)/4);
if (Pid < 0) Pid=0;
}
if (reglageKpid ==1){
pId = pId + ((newPosition - oldPosition)/4);
if (pId < 0) pId=0;
}
if (reglageKpid ==2){
piD = piD + ((newPosition - oldPosition)/4);
if (piD < 0) piD=0;
}
}
if (flagReglageTemp){
newPosition = myEnc.read();
if (reglageTemp == 0){
tempExact = tempExact + ((newPosition - oldPosition)/4);
}
if (reglageTemp == 1){
tempCoef = tempCoef + ((newPosition - oldPosition)/4);
}
}
oldPosition = newPosition;
}
void dimmerTherm() {
int inputEnt;
int inputVir;
dimmerTime=millis();
display.setTextSize(1);
if ((dimmerTime-oldDimmerTime)>=5120) oldDimmerTime=dimmerTime;
display.setCursor(0, 57);
if ((dimmerTime-oldDimmerTime) >= (Output*20)){
digitalWrite(oPinChauffe,false);
display.print(" ");
}
else{
if (moyenneChauffe < valTempChauffe){
digitalWrite(oPinChauffe,true);
display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.print("* ");
myPID.SetMode(1);
}
else{
digitalWrite(oPinChauffe,false);
display.setTextColor(SH110X_BLACK,SH110X_WHITE);
display.print("* ");
myPID.SetMode(0);
}
}
inputEnt = (Output/2.55);
inputVir = (Output/2.55*10)-(inputEnt*10);
if (inputEnt < 10) display.print(" ");
else if (inputEnt < 100) display.print(" ");
display.print(inputEnt);
display.print(".");
display.print(inputVir);
display.print("%");
display.display();
}
void afficheTemp (double tempProduit, double tempChauffe) {
int inputEnt;
int inputVir;
//display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 0);
inputEnt = (tempProduit)/10;
inputVir = (tempProduit)-(inputEnt*10);
display.print(inputEnt);
display.print(".");
display.print(inputVir);
display.setCursor(0, 32);
inputEnt = tempChauffe/10;
inputVir = (tempChauffe)-(inputEnt*10);
display.print(inputEnt);
display.print(".");
display.print(inputVir);
display.display();
}
void afficheConsigne(double valTempChauffe, double valTempProduit) {// bool adjChauffe,bool adjProduit) {
int inputEnt;
int inputVir;
//display.clearDisplay();
display.setTextSize(2);
if (!flagReglageProduit) display.setTextColor(SH110X_WHITE,SH110X_BLACK);
else display.setTextColor(SH110X_BLACK,SH110X_WHITE);
display.setCursor(64, 0);
inputEnt = (valTempProduit+0.5)/10; //
inputVir = (valTempProduit+.5)-(inputEnt*10);
display.print(inputEnt);
display.print(".");
display.print(inputVir);
display.setCursor(64, 32);
if (!flagReglageChauffe) display.setTextColor(SH110X_WHITE,SH110X_BLACK);
else display.setTextColor(SH110X_BLACK,SH110X_WHITE);
inputEnt = (valTempChauffe+.5)/10;
inputVir = (valTempChauffe+.5)-(inputEnt*10);
display.print(inputEnt);
display.print(".");
display.print(inputVir);
display.display();
}
void affichePid(){
display.setTextSize(2);
if (reglageKpid == 0) display.setTextColor(SH110X_BLACK,SH110X_WHITE);
else display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 0);
display.print("Kp = ");
display.print(Pid);
display.print(" ");
if (reglageKpid == 1) display.setTextColor(SH110X_BLACK,SH110X_WHITE);
else display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 20);
display.print("Ki = ");
display.print(pId);
display.print(" ");
if (reglageKpid == 2) display.setTextColor(SH110X_BLACK,SH110X_WHITE);
else display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 40);
display.print("Kd = ");
display.print(piD);
display.print(" ");
display.display();
}
void afficheReglageTemp(){
display.setTextSize(2);
display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 0);
display.print("Temp Adj");
if (reglageTemp == 0) display.setTextColor(SH110X_BLACK,SH110X_WHITE);
else display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 20);
display.print("T = ");
display.print(tempExact);
display.print(" ");
if (reglageTemp == 1) display.setTextColor(SH110X_BLACK,SH110X_WHITE);
else display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(0, 40);
display.print("Coef= ");
display.print(tempCoef/100);
if (tempCoef -(tempCoef/100*100)<10){
display.print(".0");
display.print(tempCoef -(tempCoef/100*100));
}
else {
display.print(".");
display.print(tempCoef -(tempCoef/100*100));
}
display.print(" ");
display.display();
}
void afficheTempsBouton(byte val){
display.setTextSize(1);
display.setTextColor(SH110X_WHITE,SH110X_BLACK);
display.setCursor(110, 57);
if (val==0) display.print(" ");
else display.print(val);
display.display();
}
void gestionBouton() {
currentTime = millis();
etatBtnH = digitalRead(iPinBtnH);
etatBtnB = digitalRead(iPinBtnB);
etatBtnSw = digitalRead(iPinEncSw);
if (etatBtnSw and etatBtnB and etatBtnH) afficheTempsBouton(0);
if (!etatBtnSw) { //Appui bouton Encodeur
if (flagBtnSw) {
if ((currentTime - timeBtnSw > tempsAppuiCourt) and !flagSwcourt and !flagSwlong and !flagSwtreslong){
flagSwcourt = true;
afficheTempsBouton(1);
}
if ((currentTime - timeBtnSw > tempsAppuiLong) and !flagSwlong and !flagSwtreslong){
flagSwcourt = false;
flagSwlong = true;
afficheTempsBouton(2);
}
if ((currentTime - timeBtnSw > tempsAppuiTresLong) and !flagSwtreslong){
flagSwlong = false;
flagSwtreslong = true;
afficheTempsBouton(3);
}
}
else{
flagBtnSw = true;
timeBtnSw = currentTime;
}
} else {
flagBtnSw = false;
if (flagSwcourt and !flagSwlong) {
flagSwcourt = false;
flagSwlong = false;
boutonSwcourt();
}
if (flagSwlong) {
flagSwlong = false;
flagSwcourt = false;
boutonSwlong();
}
if (flagSwtreslong) {
flagSwlong = false;
flagSwcourt = false;
flagSwtreslong = false;
boutonSwtreslong();
}
}
if (!etatBtnH) { //Appui bouton Haut
if (flagBtnH) {
if ((currentTime - timeBtnH > tempsAppuiCourt) and !flagHcourt and !flagHlong) {
flagHcourt = true;
afficheTempsBouton(1);
}
if ((currentTime - timeBtnH > tempsAppuiLong) and !flagHlong) {
flagHcourt = false;
flagHlong = true;
afficheTempsBouton(2);
}
} else {
flagBtnH = true;
timeBtnH = currentTime;
afficheTempsBouton(3);
}
} else {
flagBtnH = false;
if (flagHcourt and !flagHlong) {
flagHcourt = false;
flagHlong = false;
boutonHcourt();
}
if (flagHlong) {
flagHlong = false;
flagHcourt = false;
boutonHlong();
}
}
if (!etatBtnB) { //Appui bouton Bas
if (flagBtnB) {
if ((currentTime - timeBtnB > tempsAppuiCourt) and !flagBcourt and !flagBlong and !flagBtreslong) {
flagBcourt = true;
afficheTempsBouton(1);
}
if ((currentTime - timeBtnB > tempsAppuiLong) and !flagBlong and !flagBtreslong) {
flagBcourt = false;
flagBlong = true;
afficheTempsBouton(2);
}
if ((currentTime - timeBtnB > tempsAppuiTresLong) and !flagBtreslong){
flagBlong = false;
flagBtreslong = true;
afficheTempsBouton(3);
}
} else {
flagBtnB = true;
timeBtnB = currentTime;
}
} else {
if (flagBcourt) {
flagBcourt = false;
flagBlong = false;
flagBtreslong =false;
boutonBcourt();
}
if (flagBlong) {
flagBlong = false;
flagBcourt = false;
flagBtreslong = false;
boutonBlong();
}
if (flagBtreslong) {
flagBlong = false;
flagBcourt = false;
flagBtreslong = false;
boutonBtreslong();
}
flagBtnB = false;
}
}
void boutonHcourt() {
if (!flagReglagePid and !flagReglageTemp){
valTempChauffe = consTempChauffeHigh;
valTempProduit = consTempProduitHigh;
Setpoint = valTempProduit;
}
if (flagReglagePid){
reglageKpid = reglageKpid + 1;
if (reglageKpid > 2) reglageKpid = 0;
}
if (flagReglageTemp){
reglageTemp = reglageTemp + 1;
if (reglageTemp > 1) reglageTemp=0;
}
}
void boutonHlong() {
if (!flagReglageProduit and !flagReglageChauffe){
flagReglageProduit= true;
oldPosition = myEnc.read();
}
}
void boutonBcourt() {
valTempChauffe = consTempChauffeLow;
valTempProduit = consTempProduitLow;
Setpoint = valTempProduit;
}
void boutonBlong() {
if (!flagReglageProduit and !flagReglageChauffe){
flagReglageChauffe = true;
oldPosition = myEnc.read();
}
}
void boutonBtreslong() {
flagReglageTemp = true;
display.clearDisplay();
}
void boutonSwcourt() {
if (flagReglageProduit){
if (tempSelec){
EEPROM.put(4, valTempProduit);
Setpoint = valTempProduit;
consTempProduitHigh = valTempProduit;
}
else{
EEPROM.put(8, valTempProduit);
Setpoint = valTempProduit;
consTempProduitLow = valTempProduit;
}
}
if (flagReglageChauffe){
if (tempSelec) {
EEPROM.put(2, valTempChauffe);
consTempChauffeHigh = valTempChauffe;
}
else{
EEPROM.put(6, valTempChauffe);
consTempChauffeLow = valTempChauffe;
}
if (flagReglageTemp){
EEPROM.put(19,tempExact);
EEPROM.put(21,tempCoef);
tempCoefReel = tempCoef/multiplicateurTempCoef;
}
}
flagReglageChauffe = false;
flagReglageProduit = false;
flagReglageTemp = false;
display.clearDisplay();
if (flagReglagePid){
flagReglagePid = false;
display.clearDisplay();
EEPROM.put(13,Pid);
EEPROM.put(15,pId);
EEPROM.put(17,piD);
Kp = Pid/coefPid;
Ki = pId/coefPid;
Kd = piD/coefPid;
myPID.SetTunings(Kp, Ki, Kd);
}
}
void boutonSwlong() {
boutonSwcourt();
}
void boutonSwtreslong() {
flagReglagePid = true;
display.clearDisplay();
}