Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "SPI.h"
- #include "Wire.h"
- #include "ZUNO_OneWire.h"
- #define SPI_CS 8
- SPISettings spi_settings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
- #define oneWirePin 12
- // MAX31820 uses default 12 bit for 0.05 °C resolution, requires > 750ms conversion time
- OneWire oneWire(oneWirePin);
- uint8_t MAX31820addr[8][4]; //2-d array for 4 MAX31820 ROM addresses
- uint16_t RTCaddress = 0xA2; //PCF85263A I2C target write address; read target address is 0xA3
- //ZUNO_SETUP_CHANNELS(ZUNO_SENSOR_BINARY())
- ZUNO_SETUP_ISR_INT0(ofenSetError);
- ZUNO_SETUP_ISR_INT1(RTCseconds);
- #define FET1 16
- #define FET2 15
- #define FET3 14
- #define FET4 3
- #define INT_RTC 18
- #define INT_OFEN 17
- #define INT_LFTG 19
- #define LED_OFEN 21
- #define LED_LFTG 20
- //variables
- float v_resistorLadder = 4.7; //Spannung der Resistor Ladder Op-Amp
- uint8_t ofenDefault = 7; //Standardheizleistung Ofen in kW
- uint8_t lueftungDefault = 2; //Standardstufe Lüftung
- uint8_t ofenHeizleistung = ofenDefault; //Aktuelle Heizleistung Ofen in kW
- uint8_t lueftungStufe = lueftungDefault; //Aktuelle Stufe Lüftung
- float tempAussen;
- float tempZuluft;
- float tempFortluft;
- float tempAbluft;
- //bypass settings
- float tMax = 20; //default 24
- float tMin = 13; //default 13
- uint8_t incrementLueftung = 0;
- uint8_t incrementOfen = 0;
- uint8_t retryCounter = 0;
- uint8_t deviceCount = 0; //number of discovered OneWire-Devices on the bus
- uint16_t borDetectionInterval = 300; //seconds between Brownout-Checks
- uint16_t temperaturePollingIntervall = 300;
- uint16_t RTCintCounter = 0; //counter variable for periodic (1s) RTC interrupts, reset after 300s
- boolean FET1_on = false; //Koppelrelais Ofen
- boolean FET2_on = true; //Koppelrelais Lüftung
- boolean FET3_on = false;
- boolean FET4_on = true;
- boolean ofenOn = false;
- boolean lueftungOn = true;
- boolean ofenError = false; //Störmeldung Ofen D1
- boolean lueftungError = false; //Störmeldung Lüftung D2
- boolean lueftungBypassOffen = false;
- boolean RTCalarm1 = false; //mm:dd:hh:mm:ss
- boolean RTCalarm2 = false; //hh:mm and weekday
- //void DACpowerState(int channel = 0, char* state = "off"); (SDCC compiler error, optional args werden nicht kompiliert?)
- //void lueftungSetState(char* state, int duration = 0);
- void RTCseconds() {
- RTCintCounter++;
- }
- void ofenSetError() {
- ofenError = true;
- digitalWrite(LED_OFEN, LOW);
- }
- void setup() {
- Serial.begin(115200);
- SPI.begin();
- pinMode(SPI_CS, OUTPUT);
- digitalWrite(SPI_CS, HIGH);
- delay(1);
- Wire.begin();
- //Wire.setWireTimeout(3000, true); //abort transmission after 3000 us and reset communication module
- zunoExtIntMode(ZUNO_EXT_INT0, RISING);
- zunoExtIntMode(ZUNO_EXT_INT1, RISING);
- // set up inputs
- pinMode(INT_LFTG, INPUT);
- pinMode(INT_OFEN, INPUT);
- pinMode(INT_RTC, INPUT);
- // set up outputs
- pinMode(FET1, OUTPUT);
- pinMode(FET2, OUTPUT);
- pinMode(FET3, OUTPUT);
- pinMode(FET4, OUTPUT);
- pinMode(LED_LFTG, OUTPUT);
- pinMode(LED_OFEN, OUTPUT);
- digitalWrite(FET1, LOW);
- digitalWrite(FET2, LOW);
- digitalWrite(FET3, LOW);
- digitalWrite(FET4, LOW);
- digitalWrite(LED_LFTG, LOW);
- digitalWrite(LED_OFEN, LOW);
- delay(100);
- Serial.println("Opened serial connection.");
- //Set up DAC registers
- DACinit();
- //Set up RTC registers
- RTCinit();
- Serial.println("Probing OneWire bus...");
- oneWire.reset_search();
- deviceCount = 0;
- uint8_t newAddr[8];
- while (oneWire.search(newAddr)) {
- deviceCount++;
- Serial.print("New device found:");
- for (int i = 0; i < 8; i++) {
- MAX31820addr[deviceCount][i] = newAddr[i];
- Serial.print(newAddr[i], HEX);
- Serial.print(" ");
- }
- Serial.println();
- }
- Serial.println("No more devices found.");
- }
- void loop() {
- //testing
- if (incrementOfen > 13) incrementOfen = 0;
- if (incrementLueftung > 3) incrementLueftung = 0;
- if (RTCintCounter == 20) {
- DACsetVoltage(1, ofenCalcVoltage(ofenHeizleistung));
- DACsetVoltage(2, lueftungCalcVoltage(ofenHeizleistung));
- ofenHeizleistung = incrementOfen;
- lueftungStufe = incrementLueftung;
- }
- //end testing
- if (RTCintCounter == 60) {
- Serial.println("60s elapsed.");
- delay(16); //maximum time for periodic interrupt flag clearance is 2* 1/128 = 16 ms
- RTCgetFlags();
- }
- if (RTCintCounter == 300) {
- Serial.println("300s elapsed.");
- RTCintCounter = 0;
- MAX31820getAllTemperatures();
- DACborDetection();
- }
- }
- void DACinit() {
- Serial.println("Initializing DAC...");
- DACread(0x0A); //clear POR Bit by reading status register
- DACwrite(0x0A, 0x03, 0x00); //set gain B9:B8 of 1x for both channels
- DACwrite(0x08, 0x00, 0x00); //set VREF to VDD for both channels
- DACsetVoltage(1, ofenCalcVoltage(ofenHeizleistung));
- DACsetVoltage(2, lueftungCalcVoltage(lueftungStufe));
- if (ofenOn) ofenSetState("on");
- if (!ofenOn) ofenSetState("off");
- if (lueftungOn) lueftungSetState("on");
- if (!lueftungOn) lueftungSetState("off");
- Serial.println("Done initzializing DAC.");
- }
- void DACborDetection() {
- Serial.print("Checking for BOR-related memory corruption on DAC...");
- word borWord = DACread(0x0A);
- boolean borBitSet = bitRead(borWord, 8);
- if (borBitSet == true) {
- Serial.println("FAILED! Reinitizialing DAC.");
- DACinit(); //reinitialize DAC with current values
- } else {
- Serial.println("PASS.");
- }
- }
- void DACsetVoltage(int channel = 0, float voltage = 0) { //writes register 0x00 or 0x01 respectively
- Serial.print("Setting wiper value of ");
- if (voltage > 2 * v_resistorLadder) voltage = 2 * v_resistorLadder;
- if (voltage < 0) voltage = 0;
- byte wiperPosition = (int)(((voltage / 2) / v_resistorLadder) * 256);
- Serial.print(wiperPosition);
- if (channel == 1) {
- Serial.println(" for oven...");
- DACwrite(0x00, 0x00, wiperPosition);
- }
- if (channel == 2) {
- Serial.println(" for lueftung...");
- DACwrite(0x01, 0x00, wiperPosition);
- }
- //confirm correct output voltage is set in DAC register
- }
- void DACpowerState(int channel = 0, char *state = "off") { //writes register 0x09, if channel 0 is used, both channels are switched
- if (channel == 0) {
- if (!strcmp(state, "on")) {
- DACwrite(0x09, 0x00, 0x00);
- ofenOn = true;
- lueftungOn = true;
- }
- if (!strcmp(state, "off")) {
- DACwrite(0x09, 0x00, 0x03);
- ofenOn = false;
- lueftungOn = false;
- }
- } else if (channel == 1) {
- if (!strcmp(state, "on")) {
- byte cmd = 0x00;
- bitWrite(cmd, 1, lueftungOn);
- DACwrite(0x09, 0x00, cmd);
- ofenOn = true;
- }
- if (!strcmp(state, "off")) {
- byte cmd = 0x01;
- bitWrite(cmd, 1, lueftungOn);
- DACwrite(0x09, 0x00, cmd);
- ofenOn = false;
- }
- } else if (channel == 2) {
- if (!strcmp(state, "on")) {
- byte cmd = 0x00;
- bitWrite(cmd, 0, ofenOn);
- DACwrite(0x09, 0x00, cmd);
- lueftungOn = true;
- }
- if (!strcmp(state, "off")) {
- byte cmd = 0x02;
- bitWrite(cmd, 0, ofenOn);
- DACwrite(0x09, 0x00, cmd);
- lueftungOn = false;
- }
- }
- }
- void DACwrite(byte writeAddr, byte data2, byte data1) {
- if (retryCounter < 3) {
- Serial.print("Writing ");
- Serial.print(data2, HEX);
- Serial.print(data1, HEX);
- Serial.print(" at DAC address ");
- Serial.print(writeAddr, HEX);
- Serial.print(" ...");
- byte cmdReturn;
- writeAddr = writeAddr << 3;
- byte cmdByte = writeAddr; // 00 write 0 error bit, so nothing has to be added
- SPI.beginTransaction(&spi_settings);
- digitalWrite(SPI_CS, LOW);
- delay(1);
- SPI.transfer(cmdByte);
- cmdReturn = SPI.transfer(data2);
- SPI.transfer(data1);
- delay(1);
- digitalWrite(SPI_CS, HIGH);
- SPI.endTransaction();
- if (cmdReturn != 0xFF) {
- retryCounter++;
- Serial.println("FAILED! Retrying.");
- DACwrite(writeAddr, data2, data1);
- } else
- retryCounter = 0;
- Serial.println("Done.");
- } else {
- Serial.println("FAILED 3 times. Abort.");
- retryCounter = 0;
- }
- }
- word DACread(byte readAddr) {
- if (retryCounter < 3) {
- Serial.print("Reading 1 byte at DAC address ");
- Serial.print(readAddr, HEX);
- Serial.print(" ...");
- byte cmdReturn;
- readAddr = readAddr << 3;
- byte cmdByte = readAddr + 6;
- SPI.beginTransaction(&spi_settings);
- digitalWrite(SPI_CS, LOW);
- delay(1);
- SPI.transfer(cmdByte);
- cmdReturn = SPI.transfer(0);
- word DACreply = SPI.transfer16(0);
- delay(1);
- digitalWrite(SPI_CS, HIGH);
- SPI.endTransaction();
- Serial.print("DAC returned ");
- Serial.println(cmdReturn, HEX);
- if (cmdReturn != 0xFF) {
- retryCounter++;
- DACread(readAddr);
- } else {
- retryCounter = 0;
- Serial.println("Done.");
- return DACreply;
- }
- } else {
- word error = 0;
- Serial.println("FAILED 3 times. Abort.");
- return error;
- }
- }
- float ofenCalcVoltage(uint8_t leistung) { //geforderte Leistung zwischen 3 und 13 kW
- Serial.print("Calculating analog value for ");
- Serial.print(leistung);
- Serial.println("kW thermal power...");
- if (leistung < 3) leistung = 3;
- if (leistung > 13) leistung = 13;
- ofenHeizleistung = leistung; //bad programming (eventuell unterscheiden sich dann Zustand und simulierte Variable, wenn der write-Befehl dreimal scheitert)
- float voltage = ((13 - 3) / 10) * (leistung - 3);
- Serial.print(voltage);
- Serial.println("V");
- return voltage;
- }
- float lueftungCalcVoltage(uint8_t stufe) { //LUT-artig für Lüftungsstufen
- Serial.print("Calculating analog value for fan level");
- Serial.print(stufe);
- Serial.println("...");
- if (stufe < 1) lueftungSetState("off");
- if (stufe > 3) stufe = 3;
- lueftungStufe = stufe; //bad programming (eventuell unterscheiden sich dann Zustand und simulierte Variable, wenn der write-Befehl dreimal scheitert)
- float voltage[3] = { 3, 6, 9 };
- Serial.print(voltage[stufe - 1]);
- Serial.println("V");
- return voltage[stufe - 1];
- }
- void ofenSetState(char *state) {
- if (!strcmp(state, "on")) {
- Serial.println("Setting ofen state to on...");
- digitalWrite(FET1, HIGH);
- FET1_on = true;
- DACpowerState(1, "on");
- DACsetVoltage(1, ofenCalcVoltage(ofenHeizleistung)); //Ofen schaltet auf letztem bekannten Wert ein
- ofenOn = true;
- Serial.println("Ofen state set to on.");
- }
- if (!strcmp(state, "off")) {
- Serial.println("Setting ofen state to off...");
- digitalWrite(FET1, LOW);
- FET1_on = false;
- DACpowerState(1, "off");
- ofenOn = false;
- Serial.println("Ofen state set to off.");
- }
- }
- void lueftungSetState(char *state) { //argument duration missing
- if (!strcmp(state, "on")) {
- Serial.println("Setting lueftung state to on...");
- digitalWrite(FET2, HIGH);
- FET2_on = true;
- DACpowerState(2, "on");
- DACsetVoltage(2, lueftungCalcVoltage(lueftungStufe)); //Lueftung schaltet auf letztem bekannten Wert ein
- lueftungOn = true;
- Serial.println("Lueftung state set to on.");
- }
- if (!strcmp(state, "off")) {
- Serial.println("Setting lueftung state to off...");
- digitalWrite(FET2, LOW);
- FET2_on = false;
- DACpowerState(2, "off");
- lueftungOn = false;
- Serial.println("Lueftung state set to off.");
- }
- }
- void MAX31820getAllTemperatures() {
- Serial.println("Getting temperature data from all known MAX31820 sensors...");
- oneWire.reset();
- oneWire.skip(); //simulataneously start temperature conversion on all devices
- oneWire.write(0x44);
- delay(1000); //wait 1000 ms, because read time slot allocation is not possible in multi-slaves queries
- for (int i = 0; i < deviceCount; i++) {
- uint8_t rom[8];
- for (int j = 0; i < 8; i++) {
- rom[j] = MAX31820addr[i][j];
- }
- oneWire.reset();
- oneWire.select(rom);
- oneWire.write(0xBE); //read scratchpad register
- byte scratchpad[9]; //9 bit scratchpad
- for (int i = 0; i < 9; i++) {
- scratchpad[i] = oneWire.read();
- }
- if (oneWire.crc8(scratchpad, 8) == rom[7]) {
- Serial.println("CRC match for ROM ");
- for (int i = 0; i < 8; i++) {
- Serial.println(rom[i]);
- }
- int16_t raw = (scratchpad[1] << 8) | scratchpad[0];
- if (bitRead(raw, 15)) {
- raw = (raw ^ 0xFFFF) - 0x01; //two's complement for negative numbers
- }
- float celsius = (float)raw / 0xF; //last nibble 1111b = 15d = 0xF
- if (bitRead(raw, 15)) celsius = -celsius;
- switch (i) {
- case 0:
- tempAussen = celsius;
- Serial.print("tempAussen ");
- Serial.println(tempAussen);
- break;
- case 1:
- tempZuluft = celsius;
- Serial.print("tempZuluft ");
- Serial.println(tempZuluft);
- break;
- case 2:
- tempFortluft = celsius;
- Serial.print("tempFortluft ");
- Serial.println(tempFortluft);
- break;
- case 3:
- tempAbluft = celsius;
- Serial.print("tempAbluft ");
- Serial.println(tempAbluft);
- break;
- case 4: break;
- }
- }
- }
- Serial.println("Done.");
- }
- void lueftungTemperatureControl() {
- float hysterese = 0.7; // Hysterese von 1 K
- if ((tempAussen < tempFortluft - 2) && tempFortluft > tMax && tempZuluft > tMin) {
- if (abs(tempAussen - tempZuluft) < 1.5) lueftungBypassOffen = true;
- } else {
- lueftungBypassOffen = false;
- }
- if (((tempZuluft + hysterese / 2) > tempFortluft) && (lueftungBypassOffen == true)) {
- lueftungSetState("off");
- }
- if (((tempZuluft - hysterese / 2) < tempFortluft) && (lueftungBypassOffen == true)) {
- lueftungSetState("on");
- }
- if ((((tempZuluft - hysterese / 2) - tempFortluft) < -5) && (lueftungBypassOffen = false)) {
- lueftungSetState("off");
- }
- if ((((tempZuluft + hysterese / 2) - tempFortluft) > -5) && (lueftungBypassOffen = false)) {
- lueftungSetState("on");
- }
- }
- void checkInputs() {
- if (!digitalRead(INT_LFTG)) {
- lueftungError = true;
- digitalWrite(LED_LFTG, HIGH);
- }
- }
- void RTCinit() {
- Serial.print("Initializing RTC...");
- Wire.beginTransmission(RTCaddress);
- Wire.write((uint8_t)0x23); // Start register (timestamp_mode)
- Wire.write((uint8_t)0x6); // TSR Register 3 First time switch to batt, TSR Register 2 Last time switch to batt
- Wire.write((uint8_t)0x00); // 0x24 Two's complement offset value
- Wire.write((uint8_t)0x15); // 0x25 no INV, normal offset correction mode, 24h,low-jitter mode, 6pF load caps
- Wire.write((uint8_t)0x00); // 0x26 battery switch enabled, switch at Vth (internal ref)
- Wire.write((uint8_t)0x00); // 0x27 Enable periodic interupt pin on INTA
- Wire.write((uint8_t)0x47); // 0x28 INTA Clock pulse every 1 minute, RTC Mode, STOP ctl default, no CLK output
- Wire.write((uint8_t)0x40); // 0x29 pulsed periodic interrupt
- Wire.write((uint8_t)0x00); // 0x2a no INTB, so no interrupts configured
- Wire.endTransmission();
- Serial.println("Done initializing RTC.");
- }
- void RTCgetFlags() {
- Serial.print("Getting current RTC flag status...");
- Wire.beginTransmission(RTCaddress);
- Wire.write((uint8_t)0x02); //stopwatch minutes register contains EMON bit
- Wire.endTransmission(false); //RTC accepts I2C restart conditions, so the bus is not released
- Wire.requestFrom(RTCaddress, 1);
- byte emonRegister = Wire.read();
- if (bitRead(emonRegister, 7)) { //read flags if EMON shows that flags are set
- Wire.endTransmission(false);
- Wire.beginTransmission(RTCaddress);
- Wire.write((uint8_t)0x2B);
- Wire.endTransmission(false);
- Wire.requestFrom(RTCaddress, 1);
- byte flags = Wire.read();
- Wire.endTransmission();
- Serial.println("Done");
- if (flags != 0x00) {
- if (bitRead(flags, 5)) {
- RTCalarm1 = true;
- Serial.println("Alarm1 RTC asserted - not implemented.");
- }
- if (bitRead(flags, 6)) {
- RTCalarm2 = true;
- Serial.println("Alarm2 RTC asserted - not implemented.");
- }
- }
- } else {
- Wire.endTransmission();
- Serial.println("No flags set.");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement