#include <Wire.h> //Arduino Nano; SDA = A4, SCL = A5
#include <SPI.h>
//Variables for the PT100 boards
double resistance;
uint8_t reg1, reg2; //reg1 holds MSB, reg2 holds LSB for RTD
uint16_t fullreg; //fullreg holds the combined reg1 and reg2
double temperature;
//Variables and parameters for the R - T conversion
double Z1, Z2, Z3, Z4, Rt;
double RTDa = 3.9083e-3;
double RTDb = -5.775e-7;
double rpoly = 0;
//--Display---------------------------------------------
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_ADDRESS 0x3C
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Adafruit_MAX31865 chip select
//SCK => SCK //Arduino 13
//MISO => SDO //Arduino 12
//MOSI => SDI //Arduino 11
//CS => CS //Arduino 10
const int chipSelectPin = 10;
//--MOSFET---------------------------------------------
// Pins für PWM-Ausgang und MOSFET
#define PWM_PIN 3
#define MOSFET_PIN 2
//--PID-Regler---------------------------------------------
#include <PID_v1.h>
// Variablen für PID-Regler
double Kp = 10; // Proportionaler Faktor
double Ki = 0.1; // Integraler Faktor
double Kd = 0; // Differenzierender Faktor
double setpoint = 20; // Sollwert der Temperatur in Grad Celsius
double temp = 0; // Istwert der Temperatur in Grad Celsius
double output = 0; // Ausgangswert für den PWM-Ausgang
bool enabled = true; // Status des PID-Reglers (ein oder aus)
//bool sendToPlotter = true; // Status des Plotter (ein oder aus)
// Objekt für PID-Regler mit den Variablen als Parameter
PID pid(&temp, &output, &setpoint, Kp, Ki, Kd, DIRECT);
void setup()
{
SPI.begin();
Serial.begin(115200); //Serielle Kommunikation starten
pinMode(chipSelectPin, OUTPUT); //weil CS manuell geschaltet wird
display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
display.setTextColor(SSD1306_WHITE);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(5, 15); // Start in der linken oberen Ecke
display.print("temp.");
display.setCursor(5, 40); // Start in der linken oberen Ecke
display.print("controller");
display.display();
delay(3000);
}
void loop()
{
readRegister();
convertToTemperature();
printDisplay();
pidCompute();
readSerialCommand();
delay(200);
}
void printDisplay()
{
display.clearDisplay(); // Löschung der Anzeige
display.setTextColor(SSD1306_WHITE);
display.setCursor(5, 0);
display.setTextSize(1);
display.print("temperature: ");
display.setTextSize(2);
display.setCursor(10, 10);
display.print(temperature);
display.setCursor(115, 10);
//display.print(" ");
display.cp437(true);
display.setTextSize(1);
display.write(167);
display.setTextSize(2);
display.print("C");
display.setTextSize(1);
display.setCursor(0, 35);
display.print("setpoint: ");
display.setTextSize(2);
display.setCursor(10, 45);
display.print(setpoint);
display.setCursor(110, 45);
//display.print(" ");
display.cp437(true);
display.setTextSize(1);
display.write(167);
display.setTextSize(2);
display.print("C");
display.display();
}
void convertToTemperature()
{
Rt = resistance;
Rt /= 32768;
Rt *= 430; //Dies ist nun der tatsächliche Widerstand in Ohm
Z1 = -RTDa;
Z2 = RTDa * RTDa - (4 * RTDb);
Z3 = (4 * RTDb) / 100;
Z4 = 2 * RTDb;
temperature = Z2 + (Z3 * Rt);
temperature = (sqrt(temperature) + Z1) / Z4;
if (temperature >= 0)
{
Serial.print("Temperature_of_PT100:");
Serial.println(temperature); //Temperatur in Grad Celsius
return; //exit
}
else
{
Rt /= 100;
Rt *= 100; // auf 100 Ohm normalisieren
rpoly = Rt;
temperature = -242.02;
temperature += 2.2228 * rpoly;
rpoly *= Rt; // square
temperature += 2.5859e-3 * rpoly;
rpoly *= Rt; // ^3
temperature -= 4.8260e-6 * rpoly;
rpoly *= Rt; // ^4
temperature -= 2.8183e-8 * rpoly;
rpoly *= Rt; // ^5
temperature += 1.5243e-10 * rpoly;
Serial.print("Temperature_of_PT100:");
Serial.println(temperature); //Temperatur in Grad Celsius
}
//Anmerkung: alle Formeln sind in der AN-709 Application Note von Analog Devices zu finden
// https://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
}
void readRegister()
{
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE1));
digitalWrite(chipSelectPin, LOW);
SPI.transfer(0x80); //80h = 128 - config register
SPI.transfer(0xB0); //B0h = 176 - 10110000: bias ON, 1-shot, start 1-shot, 3-wire, rest are 0
digitalWrite(chipSelectPin, HIGH);
digitalWrite(chipSelectPin, LOW);
SPI.transfer(1);
reg1 = SPI.transfer(0xFF);
reg2 = SPI.transfer(0xFF);
digitalWrite(chipSelectPin, HIGH);
fullreg = reg1; //MSB lesen
fullreg <<= 8; //Verschiebung zum MSB-Teil
fullreg |= reg2; //LSB lesen und mit MSB kombinieren
fullreg >>= 1; //D0 herausschieben.
resistance = fullreg; //Übertrage diesen Wert an die Widerstandsvariable
//Hinweis: Dies ist noch nicht der Widerstand des RTD!
digitalWrite(chipSelectPin, LOW);
SPI.transfer(0x80); //80h = 128
SPI.transfer(144); //144 = 10010000
SPI.endTransaction();
digitalWrite(chipSelectPin, HIGH);
}
void pidCompute()
{
// PID-Regelung durchführen, wenn eingeschaltet
if (enabled)
{
// PID-Berechnung aufrufen (automatisch)
pid.Compute();
// Ausgang begrenzen zwischen 0 und 300
output = constrain(output, 0, 300);
// PWM-Ausgang und MOSFET ansteuern
analogWrite(PWM_PIN, output);
digitalWrite(MOSFET_PIN, output > 0);
}
else
{
// Ausgang auf 0 setzen, wenn ausgeschaltet
output = 0;
// PWM-Ausgang und MOSFET ausschalten
analogWrite(PWM_PIN, output);
digitalWrite(MOSFET_PIN, output > 0);
// Display löschen
display.clearDisplay();
// Text anzeigen
display.setTextSize(1);
display.setCursor(0,10); // Position festlegen
display.println("PID controller disabled");
// Display aktualisieren
display.display();
delay(5000);
}
// Eine Sekunde warten
delay(1000);
}
void readSerialCommand()
{
unsigned long startTime = millis(); // Startzeit speichern
while (Serial.available() == 0)
{
// Warten auf serielle Daten
if (millis() - startTime > 5000) // Timeout nach 5 Sekunden
{
Serial.println("Timeout: Keine seriellen Daten empfangen.");
return; // Schleife verlassen
}
}
String command = Serial.readStringUntil('\n');
command.trim(); // Leerzeichen und Zeilenumbrüche entfernen
// Befehl auswerten...
if (command.startsWith("set:"))
{
// Sollwert der Temperatur ändern
double newSetpoint = command.substring(4).toDouble();
if (newSetpoint >= 0 && newSetpoint <= 300)
{
setpoint = newSetpoint;
Serial.print("Setpoint geändert auf ");
Serial.println(setpoint);
}
else
{
Serial.println("Fehler: Setpoint außerhalb des gültigen Bereichs (0-300)");
}
}
/*
else if (command.startsWith("pid:"))
{
// PID-Regler ein- oder ausschalten
String pidCommand = command.substring(4);
if (pidCommand.equals("on"))
{
enabled = true;
pid.SetMode(AUTOMATIC);
Serial.println("PID-Regler aktiviert");
}
else if (pidCommand.equals("off"))
{
enabled = false;
pid.SetMode(MANUAL);
Serial.println("PID-Regler deaktiviert");
}
else
{
Serial.println("Ungültiger PID-Befehl");
}
}
else
{
Serial.println("Ungültiger Befehl");
}
// Hier den Rest des Codes ausführen (ohne rekursiven Aufruf) */
}
/*
void readSerialCommand()
{
// Serielle Kommunikation überprüfen
if (Serial.available() > 7)
{
// Befehl von der seriellen Schnittstelle lesen
String command;
command = Serial.readStringUntil('\n');
command.trim(); // Leerzeichen und Zeilenumbrüche entfernen
// Befehl auswerten
if (command.startsWith("set:"))
{
// Sollwert der Temperatur ändern
double newSetpoint = command.substring(4).toDouble();
if (newSetpoint >= 0 && newSetpoint <= 300)
{
//setpoint = newSetpoint;
Serial.print("Setpoint geändert auf ");
Serial.println(setpoint);
}
else
{
Serial.println("Fehler: Setpoint außerhalb des gültigen Bereichs (0-300)");
}
}
else if (command.startsWith("pid:"))
{
// PID-Regler einschalten oder ausschalten
String pidCommand = command.substring(4);
if (pidCommand.equals("on"))
{
enabled = true;
pid.SetMode(AUTOMATIC);
Serial.println("PID-Regler aktiviert");
}
else if (pidCommand.equals("off"))
{
enabled = false;
pid.SetMode(MANUAL);
Serial.println("PID-Regler deaktiviert");
}
else
{
Serial.println("Ungültiger PID-Befehl");
}
}
else
{
// Ungültiger Befehl
Serial.println("Ungültiger Befehl");
}
}
else
{
loop();
}
delay(1000);
}
*/
Loading
ssd1306
ssd1306