//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);
}
Loading
ssd1306
ssd1306