//Teplotní regulace PID - CASE FAN PC ventilátory a jejich řízení.
// Teplotní čidlo DS18B20
// připojení knihoven
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PID_v2.h>
#include <EEPROM.h>
#include "U8glib.h"
// inicializace displeje
U8GLIB_SSD1306_128X64 oled_1(U8G_I2C_OPT_NONE); // Display which does not send AC
//promene
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)
//double teplotapoz=10; //požadovaná teplotA
//double teplotapoz=EEPROM.read(1); //uložení teploty v integrované paměti
double teplotapoz;
int cykl=0; //cyklus pro uložení teploty
double regulace; //regulační proměnná - výstup PID
double teplota; //teplota čtená
double teplotaPID; //teplota převedená z floatu do double pro vstup do PID
//vyhlazování průběhu teplot
int INDEX = 0;
int VALUE = 0;
int SUM = 0;
int READINGS[10];
int AVERAGED = 18;
//PWM piny pro FAN regulaci
int PWM_pin = 10; //pwm,
int PWM_pin2 = 9; //pwm,
// nastavení čísla vstupního pinu
const int pinCidlaDS = 2;
// vytvoření instance oneWireDS z knihovny OneWire
OneWire oneWireDS(pinCidlaDS);
// vytvoření instance senzoryDS z knihovny DallasTemperature
DallasTemperature senzoryDS(&oneWireDS);
PID myPID(&teplotaPID,®ulace,&teplotapoz,100,10,10,REVERSE); //PID Regulátor - měřená teplota, regulační výstup, poždovaná teplota, Kp, Ki, Kd, směr regulace
void setup(void) {
// Configure Timer 1 for PWM @ 25 kHz.
TCCR1A = 0; // undo the configuration done by...
TCCR1B = 0; // ...the Arduino core library
TCNT1 = 0; // reset timer
TCCR1A = _BV(COM1A1) // non-inverted PWM on ch. A
| _BV(COM1B1) // same on ch; B
| _BV(WGM11); // mode 10: ph. correct PWM, TOP = ICR1
TCCR1B = _BV(WGM13) // ditto
| _BV(CS10); // prescaler = 1
ICR1 = 320; // TOP = 320
// Set the PWM pins as output.
pinMode(PWM_pin, OUTPUT); // sets the pin as output
pinMode(PWM_pin2, OUTPUT); // sets the pin as output
// komunikace přes sériovou linku rychlostí 9600 baud
Serial.begin(9600);
// zapnutí komunikace knihovny s teplotním čidlem
senzoryDS.begin();
EEPROM.write(1,20);
teplotapoz=EEPROM.read(1);
//něco co souvisí s PID
myPID.SetMode(AUTOMATIC);
}
void loop(void) {
// smyčka, která obnovuje displej
oled_1.firstPage();
do
{
// rovná čára
oled_1.drawLine(0,1,128,1);
// nastavení fontu, odkaz v článku
oled_1.setFont(u8g_font_7x14);
// nastevení pozice kurzoru
oled_1.setPrintPos(0, 20);
// výpis informace
oled_1.print(teplotapoz);
// nastevení pozice kurzoru
oled_1.setPrintPos(40, 20);
// výpis informace
oled_1.print(teplotaPID);
// nastavení pozice
oled_1.setPrintPos(10,50);
// výpis informace
oled_1.print(regulace);
// rovná čára (od souřadnic -> do souřadnic)
oled_1.drawLine(0,61,128,61);
}
while(oled_1.nextPage());
// "obnovovací frekvence displeje"
float teplotaokamzita;
// načtení informací ze všech připojených čidel na daném pinu
senzoryDS.requestTemperatures();
// výpis teploty na sériovou linku, při připojení více čidel
// na jeden pin můžeme postupně načíst všechny teploty
// pomocí změny čísla v závorce (0) - pořadí dle unikátní adresy čidel
teplotaokamzita = senzoryDS.getTempCByIndex(0);
teplotaokamzita = teplotaokamzita*10;
//Serial.print("Teplota cidla DS18B20: ");
//Serial.print(teplotaokamzita);
//Serial.println(" stupnu Celsia");
// pauza pro přehlednější výpis
//delay(1000);
//průměrování teploty
SUM = SUM - READINGS[INDEX]; // Remove the oldest entry from the sum
VALUE = teplotaokamzita; // Read the next sensor value
READINGS[INDEX] = VALUE; // Add the newest reading to the window
SUM = SUM + VALUE; // Add the newest reading to the sum
INDEX = (INDEX+1) % 10; // Increment the index, and wrap to 0 if it exceeds the window size
AVERAGED = SUM / 10; // Divide the sum of the window by the window size for the result
float AVERAGEDdesetinne = AVERAGED;
AVERAGEDdesetinne = AVERAGEDdesetinne/10;
teplotaPID=AVERAGEDdesetinne;
teplota=AVERAGEDdesetinne;
//Serial.print("Teplota okamzita: ");
//Serial.println(teplotaokamzita/10);
//Serial.print("Teplota průměrná: ");
//Serial.println(AVERAGEDdesetinne);
//cyklus, který ukládá teplotu do integrované paměti - čeká vždy 100 cyklů než se přepíše v integrované paměti, aby se zbytečně neopotřebovávala
if (teplotapoz!=EEPROM.read(1)) {
if (cykl!=100) {
cykl=cykl+1; }
if (cykl==100) {
EEPROM.write(1,teplotapoz);
cykl=0;}
}
//načtení PWM
myPID.Compute();
// read the analog in value:
sensorValue = analogRead(analogInPin); //cteni z analogpinu - hodnota z potenciometru
// map it to the range of the analog out:
teplotapoz = map(sensorValue, 0, 1023, 0, 100); //premapovani - normalizace hodnot a prevod na rozsah teploty 0-100.
//PWM - 0-320
outputValue = 150;
OCR1A = outputValue;
//Serial.println("SensortValue , OutputValue , Teplotapoz , TeplotaPID , Regulace ");
//Serial.print(sensorValue);
//Serial.print(" , ");
//Serial.print(outputValue);
//Serial.print(" , ");
Serial.print(teplotapoz);
Serial.print(" , ");
Serial.print(teplotaPID);
Serial.print(" , ");
Serial.println(regulace);
}