Prof. J. Walter - Informationstechnik, Mikrocomputertechnik, Digitale Medien Quellcode
Hochschule Karlsruhe Logo Informationstechnik
Beheizung Keramik 3D Drucker
Wintersemester 2017/18
Tobias Bruder
Lena Jablonsky

Quellcode

/* Programname: ESP32_DataLogger_Duesenbeheizung
* Author: Lena Jablonsky, Tobias Bruder, Jonas Messerschmid, Florian Proß
* Date: 09.11.2017
*
*
* The circuit:
*
* 5V - VCC // NOT 3V3
*
* SD card attached to SPI bus as follows:
** GPIO 23 - MOSI
** GPIO 19 - MISO
** GPIO 18 - CLK
** GPIO 5 - CS
*
* I/O attached to ESP32
** GPIO 16 - DS18B20 analog input
** GPIO 04 - Cerabar PMC21/SKU237545 analog input
** GPIO 17 - Proximity sensor digital input
** GPIO 00 - Poti analog input
*
* OLED display attached to I2C bus as follow
** GPIO 22 - SCL
** GPIO 21 - SDA
*/

// ******************** DECLARATIONS ****************************************************************

/////////////////////////////////////////////////////////////////
// DECLARATION OLED display
/////////////////////////////////////////////////////////////////
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // not used
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };

#if (SSD1306_LCDHEIGHT != 64)
//#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

/////////////////////////////////////////////////////////////////
// DECLARATION temperature sensor DS18B20
/////////////////////////////////////////////////////////////////
#include <OneWire.h>

// Data wire is plugged into pin
OneWire ds(15);

byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;

int SolltemperaturGlobal;
int Isttemperatur;
int Solltemperatur; // Solltemperatur lokal
int Temp;

/////////////////////////////////////////////////////////////////
// DECLARATIONEN Poti
/////////////////////////////////////////////////////////////////
const int S = 0; // analog
int Spannung; // für Poti

/////////////////////////////////////////////////////////////////
// DECLARATION control relay
/////////////////////////////////////////////////////////////////
int Relais = 13; // Low Aktiv

/////////////////////////////////////////////////////////////////
// DECLARATIONEN Cerabar PMC21/SKU237545
/////////////////////////////////////////////////////////////////
//here we use analog pin GIO04 of ESP32 to read data
#define analogPin 4

// *** Cerabar PMC21 ***
//here we need variables to put in and calculate the value
int inputVariable0 = 0;
int inputVariable1 = 0;

// *** SKU237545 ***
int SensorVal; // AD converter value
float Voltage; // Current voltage
float Pressure; // Current pressure

/////////////////////////////////////////////////////////////////
// DECLARATION SD card
/////////////////////////////////////////////////////////////////
#include "FS.h"
#include "SD.h"
#include "SPI.h" // SPI bus

File dataFile;
#define LOGDATEI "/Log" // SLASH WICHTIG für Verzeichnis der SD Karte

/////////////////////////////////////////////////////////////////
// DECLARATION Stopwatch
/////////////////////////////////////////////////////////////////
unsigned long startzeit;
unsigned long vergangeneZeit;
int zaehlvariable = 0;

/////////////////////////////////////////////////////////////////
// DECLARATION Proximity sensor
/////////////////////////////////////////////////////////////////
//here we use digital pin GIO17 of ESP32 to read data
#define proximitySensor 17


//// ********************** METHODS ******************************************************************

///////////////////////////////////////////////////////////////////
//
// impSD()
// implement SD card
//
///////////////////////////////////////////////////////////////////
void impSD()
{
if(!SD.begin()){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();

if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}

Serial.println("SD card detected");
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}

uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
Serial.println("Set-up SD card");

const uint8_t NAMENSLAENGE= sizeof(LOGDATEI) - 1;
String dateiName = LOGDATEI "00.csv"; // Z.B. DHT11.csv

while (SD.exists(dateiName))
{
if (dateiName[NAMENSLAENGE + 1] != '9') {
dateiName[NAMENSLAENGE + 1]++;
}
else if (dateiName[NAMENSLAENGE] != '9') {
dateiName[NAMENSLAENGE + 1] = '0';
dateiName[NAMENSLAENGE]++;
}
else {
Serial.println("Kann Datei nicht erzeugen");
}
}

// Jetzt file öffnen:
dataFile = SD.open(dateiName, FILE_WRITE);
}

/////////////////////////////////////////////////////////////////
//
// impHeader()
// implement header
//
/////////////////////////////////////////////////////////////////
void impHeader()
{
dataFile.println(F("Temperaturmessungen mit DS18B20 und Druckmessung mit Cerabar PMC21/SKU237545 mit Nutzung eines Dataloggers"));
dataFile.print(F("Zeit [m]"));
dataFile.print(';');
dataFile.print(F("Druck [bar]"));
dataFile.print(';');
dataFile.print(F("Temperatur [*C]"));
dataFile.print(';');
dataFile.println();
Serial.println("Set-up header");
}

/////////////////////////////////////////////////////////////////
//
// impDS18B20()
// implement DS18B20 temperature sensor
//
/////////////////////////////////////////////////////////////////
void impDS18B20()
{
Serial.println("Set-up DS18B20");
}

/////////////////////////////////////////////////////////////////
//
// impStoppuhr()
// implement Stopwatch
//
/////////////////////////////////////////////////////////////////
void impStoppuhr()
{
startzeit = millis();
startzeit = startzeit/60000;
Serial.print("Set-up stopwatch");
Serial.print(" Starttime of meassurement: ");
Serial.print(startzeit);
Serial.print(" min");
Serial.println();
}

/////////////////////////////////////////////////////////////////
//
// impOLED()
// implement OLED display
//
/////////////////////////////////////////////////////////////////
void impOLED()
{
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
// init done

// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.display();
delay(2000);

// Clear the buffer.
display.clearDisplay();

// text display tests
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Informationstechnik-");
display.println("Labor:");
display.println();
display.println("3D Keramik Druck");
display.display();
delay(3000);
display.clearDisplay();

Serial.println("Set-up OLED display");
}

/////////////////////////////////////////////////////////////////
//
// impRelay()
// implement relay
//
/////////////////////////////////////////////////////////////////
void impRelay()
{
pinMode(Relais, OUTPUT);
digitalWrite(Relais, HIGH);

Serial.println("Set-up relays");
}

/////////////////////////////////////////////////////////////////
//
// impDrehschalter()
// implement Drehschalter/Poti
//
/////////////////////////////////////////////////////////////////
void impDrehschalter()
{
    // evtl. falls Tausch auf Joystick
}

/////////////////////////////////////////////////////////////////
//
// impProximity()
// implement proximity sensor
//
/////////////////////////////////////////////////////////////////
void impProximity()
{
pinMode(proximitySensor, INPUT_PULLUP);

Serial.println("Set-up proximity sensor");
}

/////////////////////////////////////////////////////////////////
//
// setup()
// initialize SD card reader, header, stopwatch, display,
// relay, Drehschalter/Poti and sensors
//
/////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200); // serial communication on
impSD(); // initialize sd card
impHeader(); // initialize header for .csv file
impStoppuhr(); // initialize stopwatch
impOLED(); // initialize OLED display
impRelay(); // initialize relay
impDrehschalter(); // initialize poti
impProximity(); // initialize proximity sensor
impDS18B20(); // initialize temperature sensor

Serial.println();
Serial.println("SET-UP DONE.");
Serial.println();
}

/////////////////////////////////////////////////////////////////
//
// Loop:
// Reading sensors, print to sd, control relay
//
/////////////////////////////////////////////////////////////////

void loop()
{
if(digitalRead(proximitySensor) == LOW)
{
Serial.println("New print starts -> impSD, impHeader, impStoppuhr");

dataFile.close();
Serial.println();
Serial.println("File closed");
delay(1000);

impSD(); // initialize sd card
impHeader(); // initialize header for .csv file
impStoppuhr(); // initialize stopwatch



while(digitalRead(proximitySensor) != LOW)
{
Serial.print("Loop for new meassurement");

// Delay between every meassurement because of slow sensor
delay(2000);

// Get time
unsigned long zeit = getTime();

// Get pressure value from Cerabar PMC21/SKU237545
int pressure = getPressure();

// Get temperatur value form DS18B20
Isttemperatur = getTemperature();

// Control temperature relay
SolltemperaturGlobal = regelung();

// Print to seriell monitor
seriellAusgabe();

// Print to OLED display
OLED();

// Write data to sd card depends how modulo is set
if(zaehlvariable%2)
{
schreibeMessung(zeit, pressure, Isttemperatur);
}

// // Anzahl der Durchläufe bis file closed
// if(i >= 10)
// {
// dataFile.close();
// Serial.println();
// Serial.println("File closed");
// while(1);
// }
// i++;

// varible to count every loop -> is needed to write not every messurement to sd card
zaehlvariable++;
}
}
else
{
Serial.println("Waiting for new meassurement");
delay(500); // As short as possible
}
}

/////////////////////////////////////////////////////////////////
//
// schreibeMessung()
// Write messurement values to SD card
//
/////////////////////////////////////////////////////////////////
void schreibeMessung(unsigned long vergZeit, float Pressure, int temperature)
{
dataFile.print(vergZeit);
dataFile.print(';');
dataFile.print(Pressure);
dataFile.print(';');
dataFile.print(temperature);
dataFile.println();
}

/////////////////////////////////////////////////////////////////
//
// seriellAusgabe()
// Print to serial monitor
//
/////////////////////////////////////////////////////////////////
int seriellAusgabe()
{
Serial.println("");
Serial.print("Isttemperatur: ");
Serial.print(Isttemperatur); // Why "byIndex"?
// You can have more than one DS18B20 on the same bus.
// 0 refers to the first IC on the wire
Serial.println(" Grad C");
Serial.println("");
Serial.print("Solltemperatur: ");
Serial.print(SolltemperaturGlobal); // Why "byIndex"?
Serial.println(" Grad C");
Serial.println("");
// // print out the values Drehschalter
//
// /*Serial.print("vertical: ");
// Serial.print(vertical,DEC);
// //Serial.print(" horizontal: ");
// //Serial.print(horizontal,DEC);
// //Serial.print(" select: ");
// //if(select == HIGH)
// // Serial.println("not pressed");
// //else
// // Serial.println("PRESSED!");*/
// Serial.print("Analoger Wert: "); // für Poti
// Serial.print(Spannung);
// Serial.println("");
// Serial.print("Relais aktiv ");
// Serial.print(Relais);
// Serial.println("");
}

/////////////////////////////////////////////////////////////////
//
// OLED()
// Print to OLED display
//
/////////////////////////////////////////////////////////////////
int OLED()
{
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Isttemperatur: ");
display.println();
display.print(Isttemperatur);
display.println(" \tC");
display.print("Solltemperatur: ");
display.println();
display.print(SolltemperaturGlobal);
display.println(" \tC");
display.display();
delay(2000);
display.clearDisplay();
}

/////////////////////////////////////////////////////////////////
//
// Zeit()
// get the time
//
/////////////////////////////////////////////////////////////////
unsigned long getTime()
{
vergangeneZeit = millis() - startzeit;
vergangeneZeit = vergangeneZeit/60000;
Serial.println();
Serial.print("Messung nach: ");
Serial.print(vergangeneZeit);
Serial.print(" min");
Serial.println();
return vergangeneZeit;
}

/////////////////////////////////////////////////////////////////
//
// pressure()
// Read pressure from Cerabar PMC21/SKU237545 via analog in
//
/////////////////////////////////////////////////////////////////
int getPressure()
{
// *** Cerabar PMC21 ***
// inputVariable0 = 0; // This value must be cleared before next reading
//
// // Lesen
// inputVariable1 = analogRead(analogPin);
// inputVariable0 = inputVariable0 + inputVariable1;
// inputVariable0 = (inputVariable0 - 2048) / 818 ;
//
// // Ausgabe auf Konsole
// Serial.print("Pressure: ");
// Serial.print(inputVariable0);
// Serial.println(" bar");
//
// return inputVariable0;

// *** SKU237545 ***

// Reading pressure sensor via analog input -> 12 bit AD converter (4096)
int SensorVal = analogRead(analogPin);

// Calcaulate the value of AD converter to voltage
float Voltage = (SensorVal/4096.0)*3.3; // 0 bar = 215 (sensorVal)
// 6 bar = 2048 (sensorVal)
// 12 bar = 4096 (sensorVal)

// Calculate the value of the voltage to bar
float Pressure = (Voltage-0.18)*4.65;

return Pressure;
}

/////////////////////////////////////////////////////////////////
//
// temperature()
// Read temperature from DS18B20 via analog in
//
/////////////////////////////////////////////////////////////////
int getTemperature()
{
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
// return;
}

// Serial.print("ROM =");
for( i = 0; i < 8; i++) {
// Serial.write(' ');
// Serial.print(addr[i], HEX);
}

if (OneWire::crc8(addr, 7) != addr[7]) {
// Serial.println("CRC is not valid!");
// return;
}
// Serial.println();

// the first ROM byte indicates which chip
switch (addr[0])
{
case 0x10:
// Serial.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
// Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
// Serial.println(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
// return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end

delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

// Serial.print(" Data = ");
// Serial.print(present, HEX);
// Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
// Serial.print(data[i], HEX);
// Serial.print(" ");
}
// Serial.print(" CRC=");
// Serial.print(OneWire::crc8(data, 8), HEX);
// Serial.println();

// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}

Temp = (float)raw / 16.0;

return Temp;
}

/////////////////////////////////////////////////////////////////
//
// Regelung()
// control the temperature
//
/////////////////////////////////////////////////////////////////
int regelung()
{
        Spannung = analogRead(S); // will be 0-1023

        Solltemperatur = Spannung / 58; // in Grad °C

        if (Solltemperatur > Isttemperatur )
        {
            digitalWrite(Relais, LOW); // Laufen lassen bis Temperatur IST / SOLL gleich
        }


        if (Solltemperatur <= Isttemperatur + 2) // heizen erfolgreich
        {
            digitalWrite(Relais, HIGH); // Heizung aus
        }

        return Solltemperatur;
}

  Mit Unterstützung von Prof. J. Walter Wintersemester 2017/18