Samstag, 8. Dezember 2012

Aktueller Code...

Hier der Code und gleich der Link zu COSM:
https://cosm.com/users/heizduino

#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Ethernet.h>
#include <LCD.h>
#include <Keypad.h>
#include <Keypad_I2C.h>
#include <SPI.h>


// fuer den LCD

#define I2C_ADDR 0x27 // Define I2C Address where the PCF8574A is
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

// fuer COSM

#define APIKEY "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // your cosm api key
#define FEEDID 90041 // your feed ID
#define USERAGENT "Heizduino (90041)" // user agent is the project name

// für das Keypad

#define ROWS 4
#define COLS 4 // sollte 4 sein!
#define PCF8574_ADDR 0x23 // Keypad Adresse

#define expander_keypad 0x23 //EXPANDER address, hier mit A0 und A1 auf HIGH, Adresse des Keypads
#define expander_relais 0x20 //EXPANDER address with 3 address pins grounded, Adresse der Relaiskarte

byte rowPins[4] = {0,1,2,3}; //connect to the row pinouts of the keypad
byte colPins[4] = {4,5,6,7}; //connect to the column pinouts of the keypad
char keys[4][4]={
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};

/*
// Der PCF8574 hat die Adresse 0x20
// einer ist für das Keyboard (Adresse: 0x20)
// einer ist für das Relaismodul (Adresse: 0x21, dazu A0 kurzschliessem; wofür INT steht ist unklar)

// Pins 0-5 sind an die Temp-Fühler (Erdungsfarbe) angeschlossen, braun an +, blau an -

// Update: Pin 0 und 1 sind beim Ethernet-Shield für die Nutzung von SD Card gedacht und liefern daher falsche Werte, daher Umlegung auf 8-13
// 8 = 300l-Boiler oben
// 9 = 300l-Boiler unten
// 10 = 500l-Boiler oben
// 11 = 500l-Boiler unten
// 12 = Vorlauf
// 13 = Rücklauf
*/
/*
// Relaisbyte
// ACHTUNG: Relais mit +/- nicht über Arduino versorgen, sondern ext. Stromquelle anzapfen!
// Achtung: Das Relaisboard ist so konstruiert, dass die einzelnen Relais imer unter Strom sind,
// Wird das Kanal auf LOW geschaltet (GND), dann fließt Strom und das Relais schließt.
// Folge: bei 11111110 schaltet das erste Relais, die anderen bleiben aus.
//
// Bit 0 - Zusatzpumpe für die Heizungsunterstützung, falls der Vorlauf z.B. über 95 Grad steigt
// Bit 1 - Pumpe UND Zwangsventil für die Aufheizung der Warmwasser-Boiler durch die Heizung ("befüllen")
// Bit 2 - für später
// Bit 3 - 3-Wege-Ventil für die Aufheizung: in kleinen oder großen Boiler
// Bit 4 - Umwälzpumpe UND Ventil für die Umwälzung der Wärme vom 500l-Solarboiler in den kleinen 300l-Boiler ("umwälzen")
// Bit 5 - für später
// Bit 6 - 3-Wege-Ventil für das Brauchwasser: 300l- vs. 500l-Boiler
// Bit 7 -

// dementsprechend werden die Relais zugeordnet!
*/

byte relais_byte;
byte relais_vorschlag_byte;
char test[4];
char tmp[10];

boolean arbeitsmodus=0; // Setzen des Arbeitsmodus: entweder Manuell (=1) oder Autopilot (=0)
boolean neue_temp_da=0;

unsigned long time; // wird nach 50 Tagen oder so wieder auf Null gestezt
unsigned long time_z1; // Zwischenstand für temp_erfassung_ausgabe()
unsigned long time_z2; // Zwischenstände für regelmäßigen lcd_reset
unsigned long time_z3; // Zwischenstände
unsigned long time_z4; // Zwischenstände
unsigned long time_d; // Zwischenstände

unsigned int Heizung_3WV=0;

const unsigned int TEMP_SENSOR_PIN[6]={8, 9, 10, 11, 12, 13}; // Pinnummern zu Temp-Sensoren zuweisen, s.o.
const int Anzahl_Temp_Messungen=50; // Zahl der pro Durchgang gemachten Messungen an den Fühlern, je mehr, desto besser
// const int large_archiv_groesse=10; // Zahl der gespeicherten alten Temp-Werte, kommt später!

float TEMP_SENSOR[6]={0,1,2,3,4,5};
int TEMP_SENSOR_Reading[6][Anzahl_Temp_Messungen];
//float TEMP_SENSOR_L[6][large_archiv_groesse];
// und gleich die sechs passenden Zeiger
// int temp_pointer[6]; , kommt päter


const float max_B_temp=50; // Temperatur, die ein Boiler maximal erreichen darf, um keine Kalkablagerungen abzukriegen
const float max_temp_vorlauf=80; // ab hier schaltet die Zusatzpumpe
const float zusatzpumpen_hysteresis=5; // unterschreitet die temp die max_temp_vorlauf-Temp um diesen Wert, schaltet die Zusatzpumpe aus
const float sommer_temp_solarboiler=50; // angenommene Temp im gr. Boiler unten, wenn Sommer ist

char key;
byte key2;
byte key_i;

const float SUPPLY_VOLTAGE = 1.1; // Voltage für die interne Vergleichsspannung
const unsigned int BOUD_RATE = 38400; // Übetragungsrate zum ser. Monitor, warum nicht 9600 oder mehr?

// assign a MAC address for the ethernet controller.
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
IPAddress ip(192,168,178,47);
// initialize the library instance:
EthernetClient client;
char server[] = "api.cosm.com";
//IPAddress server(216,52,233,121);


byte gateway[] = {
192,168,178,1};
byte subnet[] = {
255, 255, 255, 0};

// Beschreibung der String-Lib: http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html
// und http://www.robotc.net/wiki/ARDUINO_328_Functions_Strings

char temp_string[200];

unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const int postingInterval = 10000; //delay between updates to Pachube.com, in ms

/* Ende der Sachen für Pachube */

/* alt:
//The link:http://www.dfrobot.com/image/data/DFR0154/LiquidCrystal_I2Cv1-1.rar
//DFRobot.com
//Compatible with the Arduino IDE 1.0
//Library version:1.1

neu:
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
*/

// keine Ahnung wofür
#if defined(ARDUINO) && ARDUINO >= 100 // k.A.
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif;

// LCD Sonderzeichen definieren

uint8_t boilerwand[8] = {
0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4};
uint8_t arrow_left[8] = {
0x4,0x4,0xc,0x1f,0xc,0x4,0x4,0x4};
uint8_t arrow_right[8] = {
0x4,0x4,0x6,0x1f,0x6,0x4,0x4,0x4};
uint8_t ecke_re[8] = {
0x4,0x4,0x4,0x7,0x0,0x0,0x0,0x0};
uint8_t ecke_li[8] = {
0x4,0x4,0x4,0x1c,0x0,0x0,0x0,0x0};
uint8_t linie[8] = {
0x0,0x0,0x0,0x1f,0x0,0x0,0x0,0x0};

uint8_t arrow_up[8] = {
0x4,0xe,0x1f,0x4,0x4,0x4,0x4};
uint8_t arrow_down[8] = {
0x4,0x4,0x4,0x4,0x1f,0xa,0x4};

uint8_t clock[8] = {
0x0,0xe,0x15,0x17,0x11,0xe,0x0};
uint8_t check[8] = {
0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
uint8_t retarrow[8] = {
0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
uint8_t bell[8] = {
0x4,0xe,0xe,0xe,0x1f,0x0,0x4};

// LCD Instanz
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

// Keypad Instanz

Keypad_I2C kpd = Keypad_I2C(makeKeymap(keys),rowPins,colPins,ROWS,COLS,PCF8574_ADDR); // für das Keypad


void lcd_init()
{lcd.setCursor(5,0); lcd.print(F("a"));
lcd.begin(20, 4);
// lcd.init(); // initialize the lcd
// lcd.backlight();
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home (); // go home
lcd.createChar(0, boilerwand);
lcd.createChar(1, arrow_left);
lcd.createChar(2, arrow_right);
lcd.createChar(3, ecke_re);
lcd.createChar(4, ecke_li);

lcd.createChar(5, check);
lcd.createChar(6, linie);
lcd.createChar(7, retarrow);
lcd.home();
lcd.setCursor(5,0); lcd.print(F("A"));
}


void get_temperature()
{lcd.setCursor(5,0); lcd.print(F("b"));
long vol=0;
for (int i=0; i<Anzahl_Temp_Messungen; i++)
{
for (int j=0; j<=5; j++)
{
TEMP_SENSOR_Reading[j][i]=analogRead(TEMP_SENSOR_PIN[(j)]);
}
}

// nun die Mittelwert-Berechnung!
for (int i=0; i<=5; i++)
{
vol=0;
for (int j=0; j<Anzahl_Temp_Messungen; j++)
{
vol=vol+TEMP_SENSOR_Reading[i][j];
}
TEMP_SENSOR[i]=SUPPLY_VOLTAGE*vol/10.24/Anzahl_Temp_Messungen;
if (TEMP_SENSOR[i]>=99) TEMP_SENSOR[i]=99; // Absicherung gegen unerwünschte und unrealistische Readings
if (TEMP_SENSOR[i]<=0) TEMP_SENSOR[i]=0; // Absicherung gegen unerwünschte und unrealistische Readings
}
lcd.setCursor(5,0); lcd.print(F("B"));
}


void lcd_ausgabe()
{lcd.setCursor(5,0); lcd.print(F("c"));
byte bitmask;
Serial.println(F("lcd_ausgabe!"));
lcd.clear();
//ZEICHNUNG
for (int i=0;i<=3;i++) {
lcd.setCursor(0, i);
lcd.write(uint8_t(0));
}
for (int i=0;i<=3;i++) {
lcd.setCursor(3, i);
lcd.write(uint8_t(0));
}
for (int i=0;i<=3;i++) {
lcd.setCursor(14, i);
lcd.write(uint8_t(0));
}
for (int i=0;i<=3;i++) {
lcd.setCursor(19, i);
lcd.write(uint8_t(0));
}
// kleiner Boiler-Temperatur
lcd.setCursor(1, 0);
lcd.print(TEMP_SENSOR[0],0);
lcd.setCursor(1, 3);
lcd.print(TEMP_SENSOR[1],0);
// großer Boiler-Temperatur
lcd.setCursor(15, 0);
lcd.print(TEMP_SENSOR[2],1);
lcd.setCursor(15, 3);
lcd.print(TEMP_SENSOR[3],1);
// Vorlauf- und Rücklauf-Temperatur
lcd.setCursor(6, 2);
lcd.print(F("V:"));
lcd.print(TEMP_SENSOR[4],1);
lcd.setCursor(6, 3);
lcd.print(F("R:"));
lcd.print(TEMP_SENSOR[5],1);

// Relaisfunktionen: vgl. byte relais_byte
bitmask=1<<0; //Zusatzpumpe: "+"
if ((bitmask & relais_byte)>0) {
lcd.setCursor(5, 2);
lcd.print(F("+"));
}
else {
lcd.setCursor(5, 2);
lcd.print(F(" "));
}

bitmask=1<<4; //Umwälzung zwischen den beiden Boilern
// Umwälzen und Aufheizen findet niemals zusammen statt, daher diese Abfrage zuerst
if ((bitmask & relais_byte)>0)
{
lcd.setCursor(3, 1);
lcd.printByte(1);
for (int i=0;i<=9;i++) {lcd.printByte(6);}
lcd.printByte(2);
}
else
{
lcd.setCursor(3, 1);
lcd.write(uint8_t(0));
lcd.print(F(" "));
lcd.write(uint8_t(0));
}

bitmask=1<<1; //Aufheizung: "|"
if ((bitmask&relais_byte)>0)
{
lcd.setCursor(9, 0);
lcd.write(uint8_t(0));

bitmask=1<<3; //Aufheizung des kl. (0) o. gr. (1) Boilers

if ((bitmask&relais_byte)==0)
{
lcd.setCursor(3, 1);
lcd.write(uint8_t(0));
lcd.print(F(" "));
lcd.printByte(3);
for (int i=0;i<=3;i++) {
lcd.printByte(6);
}
lcd.printByte(2);
}
else
{
lcd.setCursor(3, 1);
lcd.printByte(1);
for (int i=0;i<=4;i++) {
lcd.printByte(6);
}
lcd.printByte(4);
lcd.print(F(" "));
lcd.write(uint8_t(0));
}
}
else
{
lcd.setCursor(9, 0);
lcd.print(F(" "));
}

bitmask=1<<6; //Entnahme aus kleinen (1) bzw. großen Boiler (0)
if ((bitmask & relais_byte)>0) {
lcd.setCursor(3, 0);
lcd.printByte(2);
lcd.print(F("WW"));
lcd.setCursor(12, 0);
lcd.print(F(" "));
lcd.write(uint8_t(0));
}
else {
lcd.setCursor(3, 0);
lcd.write(uint8_t(0));
lcd.print(F(" "));
lcd.setCursor(12, 0);
lcd.print(F("WW"));
lcd.printByte(1);
}

// und zum Schluss das Relais der Auffüllung zeigen, falls es auf 300 zeigt und damit umsonst arbeitet
bitmask=1<<3; //Entnahme aus kleinen (1) bzw. großen Boiler (0)
if ((bitmask&relais_byte)>0)
{
lcd.setCursor(9, 1);
lcd.printByte(4);
}

if (arbeitsmodus == 0)
{
lcd.setCursor(19, 3);
lcd.print(F("A"));
}
else
{
lcd.setCursor(19, 3);
lcd.print(F("M"));
}

lcd.setCursor(5,0); lcd.print(F("C"));
}


// Ansteuerung der Expander-Karte
void expanderWrite(byte data)
{lcd.setCursor(5,0); lcd.print(F("d"));
Wire.beginTransmission(expander_relais);
Wire.write(data);
delay(500); // um evtl. Stromstösse o.ä. durch Relais ? abzuwarteb
Wire.endTransmission();
delay(3000); // um evtl. Stromstösse o.ä. durch Relais ? abzuwarteb
lcd_init(); // um das Kaulderwelsch zu beseitigen
lcd.setCursor(5,0); lcd.print(F("D"));
}

void expanderWrite_o_delay(byte data)
{lcd.setCursor(5,0); lcd.print(F("d"));
Wire.beginTransmission(expander_relais);
Wire.write(data);
Wire.endTransmission();
lcd.setCursor(5,0); lcd.print(F("D"));
}

/* alt:
void expanderWrite(byte _data ) {
Wire.beginTransmission(expander);
Wire.send(_data);
Wire.endTransmission();
} */

byte expanderRead(int i2caddr)
{lcd.setCursor(5,0); lcd.print(F("e"));
int _data = -1; // Returnwert bei Fehlern ist "-1"!! // wäre abzufangen!
Wire.requestFrom(i2caddr, 1);
if (Wire.available())
{
_data = Wire.read();
}
return _data;
lcd.setCursor(5,0); lcd.print(F("E"));
}


int byte_bit_abfragen(byte by, int stelle)
{lcd.setCursor(5,0); lcd.print(F("f"));
int bitmaske = 1 << stelle;
if ((bitmaske&by)>0)
return 1;
else return 0;
lcd.setCursor(5,0); lcd.print(F("F"));
}


byte relais_bit_setzen(byte rel_byte, unsigned int Position, boolean wert)
{ lcd.setCursor(5,0); lcd.print(F("g"));
unsigned int bitmaske = 1 << Position;
byte vb=0;

if (wert==0)
{
vb=((~bitmaske)&rel_byte);
}
else
{
vb=(rel_byte|bitmaske);
}
return vb;
lcd.setCursor(5,0); lcd.print(F("G"));
}


void relais_byte_senden_o_delay (byte vb)
{ lcd.setCursor(5,0); lcd.print(F("h"));
vb=~vb; // Das Relaisbyte muss vor dem Senden invertiert werden, da nur bei bit=low das Relais schaltet!!
expanderWrite_o_delay(vb); //... und rüberschieben zur Relaiskarte
lcd.setCursor(5,0); lcd.print(F("H"));
}

void relais_byte_senden (byte vb)
{ lcd.setCursor(5,0); lcd.print(F("h"));
vb=~vb; // Das Relaisbyte muss vor dem Senden invertiert werden, da nur bei bit=low das Relais schaltet!!
expanderWrite(vb); //... und rüberschieben zur Relaiskarte
lcd.setCursor(5,0); lcd.print(F("H"));
}


void temp_archivieren(int fuehler, float temp)
{lcd.setCursor(5,0); lcd.print(F("i"));
/*Serial.println("temp_archivieren!");
TEMP_SENSOR_L[fuehler][temp_pointer[fuehler]]=temp;
if ((temp_pointer[fuehler]+1)==large_archiv_groesse)
{
temp_pointer[fuehler]=0;
}
else
{
temp_pointer[fuehler]=temp_pointer[fuehler]+1;
}
*/
lcd.setCursor(5,0); lcd.print(F("I"));
}


void temp_erfassung_ausgabe()
{lcd.setCursor(5,0); lcd.print(F("j"));
time=millis();
if (time>=time_z1)
{//lcd.setCursor(6,0); lcd.print(F("1"));
time_d=time-time_z1;
}
else
{//lcd.setCursor(6,0); lcd.print(F("2"));
time_d=4294967295-time_z1;
time_d=time_d+time;
}

if ((time_d>10000)) // wurde vor mehr als x Sek gemessen? Dann führe erneute Messung durch!
{//lcd.setCursor(6,0); lcd.print(F("3"));
get_temperature();
//temp_archivieren(k,TEMP_SENSOR[k]);
time_z1=millis();
// lcd.setCursor(6,0); lcd.print(F("4"));
lcd_ausgabe();
neue_temp_da=1;
// lcd.setCursor(6,0); lcd.print(F("5"));
daten_zu_cosm(); // zusammenstoepseln passiert in derdem unterprg.; Daten zu Cosm schaffen
}
else
{//lcd.setCursor(6,0); lcd.print(F("6"));
neue_temp_da=0;
}
lcd.setCursor(5,0); lcd.print(F("J"));
}


float mittelwert_L_berechnen(int fuehler)
{//lcd.setCursor(4,0); lcd.print(F(""L"));
/* Serial.println("mittelwert_berechnen!");
float mittelwert=0;
for (int a=0;a<large_archiv_groesse; a++)
{
mittelwert=mittelwert+TEMP_SENSOR_L[fuehler][a];
}
return (mittelwert/large_archiv_groesse);
*/
}


char keypad_ergebnis() // Abfrage des Keypads; evtl. unnötig, wird z.Z. nicht benutzt
{lcd.setCursor(5,0); lcd.print(F("k"));
char k = kpd.getKey();
if (k != 0) {
return k;
}
lcd.setCursor(5,0); lcd.print(F("K"));
}


void temp_ausgabe_serial()
{ lcd.setCursor(5,0); lcd.print(F("l"));
for (int i=0; i<=5; i++)
{
Serial.print(TEMP_SENSOR[i],1);
Serial.print(F(" ("));
// Serial.print(mittelwert_L_berechnen(i),2);
Serial.print(F(")"));
Serial.print(F(" - "));
}
Serial.print(F(" --- "));
Serial.write(itoa(relais_byte,test,10));
Serial.print(F(" --- "));
Serial.write(itoa(relais_vorschlag_byte,test,10));
Serial.println();
lcd.setCursor(5,0); lcd.print(F("L"));
}


byte relais_bit_wechseln(byte vb, byte pos)
{lcd.setCursor(5,0); lcd.print(F("m"));
// Serial.println("relais_bit_wechseln!");
byte bitmask2=1<<pos;
vb=vb^bitmask2;
return vb;
lcd.setCursor(5,0); lcd.print(F("M"));
}


boolean sommer_feststellen()
{lcd.setCursor(5,0); lcd.print(F("n"));
if (TEMP_SENSOR[3]>sommer_temp_solarboiler) return 1;
else return 0;
lcd.setCursor(5,0); lcd.print(F("N"));
}


/* int getLength(int someValue) //obsolet
{lcd.setCursor(4,0); lcd.print(F("q"));

// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
lcd.setCursor(4,0); lcd.print(F("Q"));
}
*/


void sendData() // zu COSM
{lcd.setCursor(5,0); lcd.print(F("p"));
// this method makes a HTTP connection to the server:
// if there's a successful connection:
if (client.connect(server, 80))
{lcd.setCursor(6,0); lcd.print(F("1"));

Serial.println(F("connecting..."));
// send the HTTP PUT request:
client.print(F("PUT /v2/feeds/"));
client.print(FEEDID);
client.println(F(".csv HTTP/1.1"));
client.println(F("Host: api.pachube.com"));
client.print(F("X-PachubeApiKey: "));
client.println(APIKEY);
client.print(F("User-Agent: "));
client.println(USERAGENT);

client.print(F("Content-Length: "));
client.println(strlen(temp_string), DEC);
// war client.println(temp_string.length(), DEC);
// last pieces of the HTTP PUT request:
client.print(F("Content-Type: text/csv\n"));
client.println(F("Connection: close\n"));

// here's the actual content of the PUT request:
Serial.println(temp_string);
client.println(temp_string);

// note the time that the connection was made:
lastConnectionTime = millis();
}
else
{
// if you couldn't make a connection:
lcd.setCursor(6,0); lcd.print(F("2"));
Serial.println(F("connection failed"));
Serial.println();
Serial.println(F("disconnecting."));
client.stop();
}
lcd.setCursor(5,0); lcd.print(F("P"));
}


void daten_zu_cosm()
{lcd.setCursor(5,0); lcd.print(F("q"));
lcd.setCursor(6,0); lcd.print(F("3"));
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
while (client.available())
{
char c = client.read();
Serial.print(c);
// lcd.setCursor(6,0); lcd.print(F("4"));
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected)
{
Serial.println();
Serial.println(F("disconnecting.."));
client.stop();
lcd.setCursor(6,0); lcd.print(F("5"));
}

// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if (!client.connected() && (millis() - lastConnectionTime > postingInterval))
{
cosm_daten_zusammenstoepseln();
sendData(); // temp_string wird verschickt
lcd.setCursor(6,0); lcd.print(F("6"));
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
lcd.setCursor(5,0); lcd.print(F("Q"));
}


void cosm_daten_zusammenstoepseln()
{lcd.setCursor(5,0); lcd.print(F("r"));
// Serial.println("daten_zusammenstoepseln!");

strcpy (temp_string,"sensor0"); strcat(temp_string,",");
strcat(temp_string,(dtostrf(TEMP_SENSOR[0],3,2,tmp)));
strcat(temp_string,"\n");

strcat (temp_string,"sensor1"); strcat(temp_string,",");
strcat(temp_string,(dtostrf(TEMP_SENSOR[1],3,2,tmp)));
strcat(temp_string,"\n");

strcat (temp_string,"sensor2"); strcat(temp_string,",");
strcat(temp_string,(dtostrf(TEMP_SENSOR[2],3,2,tmp)));
strcat(temp_string,"\n");

strcat (temp_string,"sensor3"); strcat(temp_string,",");
strcat(temp_string,(dtostrf(TEMP_SENSOR[3],3,2,tmp)));
strcat(temp_string,"\n");

strcat (temp_string,"sensor4"); strcat(temp_string,",");
strcat(temp_string,(dtostrf(TEMP_SENSOR[4],3,2,tmp)));
strcat(temp_string,"\n");

strcat (temp_string,"sensor5"); strcat(temp_string,",");
strcat(temp_string,(dtostrf(TEMP_SENSOR[5],3,2,tmp)));
strcat(temp_string,"\n");


strcat(temp_string,"relais0"); strcat(temp_string,",");
strcat(temp_string,(itoa(byte_bit_abfragen(relais_byte,0),test,10)));
strcat(temp_string,"\n");

strcat(temp_string,"relais1"); strcat(temp_string,",");
strcat(temp_string,(itoa(byte_bit_abfragen(relais_byte,1),test,10)));
strcat(temp_string,"\n");

strcat(temp_string,"relais3"); strcat(temp_string,",");
strcat(temp_string,(itoa(byte_bit_abfragen(relais_byte,3),test,10)));
strcat(temp_string,"\n");

strcat(temp_string,"relais4"); strcat(temp_string,",");
strcat(temp_string,(itoa(byte_bit_abfragen(relais_byte,4),test,10)));
strcat(temp_string,"\n");

strcat(temp_string,"relais6"); strcat(temp_string,",");
strcat(temp_string,(itoa(byte_bit_abfragen(relais_byte,5),test,10)));
strcat(temp_string,"\n");

strcat(temp_string,"manuell"); strcat(temp_string,",");
strcat(temp_string,(itoa(arbeitsmodus,test,10)));
strcat(temp_string,"\n");

lcd.setCursor(5,0); lcd.print(F("R"));
}

void lcd_reset()
{// jede 600 Sek. = 10 Min
lcd.setCursor(5,0); lcd.print(F("s"));
time=millis();
if (time>=time_z2)
{
time_d=time-time_z2;
}
else
{
time_d=4294967295-time_z2+time;
}

if (time_d>600000) // wurde vor mehr als XXX Sek gemessen? Dann führe erneute Messung durch!
{
lcd_init();
lcd_ausgabe();
time_z2=millis();
}
else
{
}
lcd.setCursor(5,0); lcd.print(F("S"));
}

int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

// SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*SETUP*
void setup()
{ lcd.setCursor(4,0); lcd.println(F("a"));
analogReference(INTERNAL1V1);

pinMode(8, INPUT); // NEU!
pinMode(9, INPUT); // NEU!
pinMode(10, INPUT); // NEU!
pinMode(11, INPUT); // NEU!
pinMode(12, INPUT); // NEU!
pinMode(13, INPUT); // NEU!

// -----------------------------------------
// Open serial communications and wait for port to open:
Serial.begin(BOUD_RATE);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}


// start the Ethernet connection:
if (Ethernet.begin(mac) == 0)
{
Serial.println(F("Failed to configure Ethernet using DHCP"));
// DHCP failed, so use a fixed IP address:
Ethernet.begin(mac, ip);
}

// -----------------------------------------

Wire.begin(); // für den Anschluss der Expander-Karte
delay(1000);

kpd.begin(); // Keypad initialisieren

//Ansteuerungs-Byte der Relaiskarte auf null setzen
relais_byte=0;
relais_byte_senden(byte(0)); // für ein Reset alles auf 0!

key=0;

time_z1=time_z2=time_z3=time_z4=time_d=time=millis(); // alle Zwischenstände beim Start auf praktisch Null setzen

lcd_init(); // initialize the lcd


// for (int i=0; i<=5; i++)
{ //TEMP_SENSOR[i]=0; // aktuelle Werte auf Null setzen

// temp_pointer[i]=0; // Pointer setzen!
// for (int j=0;j<=large_archiv_groesse;j++)
// {
// TEMP_SENSOR_L[i][j]=0; // auch alle Archivwerte auf 0 setzen
// }
}

/* // damit wird die clock speed verändert!
// TWBR = 152;
TWBR = 158;
TWSR |= _BV (TWPS0); // inkl. prescaler! macht eine Freq von 12,5 kHz
*/

lcd_ausgabe();
lcd.setCursor(4,0); lcd.println(F("A"));
}


void loop()
{
// LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP // LOOP
// Serial.print(F("--------------->FREIER RAM: ------------------------> ")); Serial.println(freeRam()); // mal aschauen, was mit dem RAM passiert
relais_vorschlag_byte=relais_byte;
temp_erfassung_ausgabe(); // wird nur jede X Sek wirklich durchgeführt
lcd_reset(); // wird nur jede X Sek wirklich durchgeführt

key=0;
//lcd.setCursor(4,0); lcd.print(F("b"));
key=kpd.getKey(); // neu, war: key=keypad_ergebnis();
//lcd.setCursor(4,0); lcd.print(F("c"));
if (key==0 && neue_temp_da==0)
{
// leeren Key und keine Temp-Veränderung da nicht neu gelesen, abfangen!!
}
else
{
if (key=='A') { arbeitsmodus=0; lcd_ausgabe(); }
if (key=='B') { arbeitsmodus=1; lcd_ausgabe(); }
if (key=='D') // RESET des LCD und der Relaislarte
{
lcd_init();
lcd_ausgabe(); // vorläufig; hier detailliertere Infos ausgeben
lcd.setCursor(4,0); lcd.print(F("c"));
relais_byte_senden(relais_byte);
// Serial.print(F("--------------->FREIER RAM: ------------------------> ")); Serial.println(freeRam()); // mal aschauen, was mit dem RAM passiert
lcd.setCursor(4,1); lcd.print(freeRam());

}

if (arbeitsmodus==1) // MANUELL
{
if (key=='0' || key=='1' || key=='3' || key=='4' || key=='6')
{
key2=key-48;
relais_vorschlag_byte=relais_bit_wechseln(relais_vorschlag_byte, key2);
lcd.setCursor(4,0); lcd.print(F("e"));
}
else
{
if (key=='A' || key=='B' || key=='D' || key==0 )
{
// zulässige Eingaben ausschliessen
}
else
{
lcd.clear(); // Fehlermeldung("Falsche Taste")
lcd.setCursor(0, 2);
lcd.print(F("Nur [0,1,3,4,6,A,B]"));
delay(1000); // obwohl es ein delay ist, ist es gerade hier richtig
lcd_ausgabe(); // aktuellen Zustand am LCD erneut anzeigen
lcd.setCursor(4,0); lcd.print(F("f"));
}
}
}

if (arbeitsmodus==0) // AUTOPILOT
{
if ((relais_byte&B00001000)==0) {Heizung_3WV=0;} else {Heizung_3WV=1;} // Heizung_3WV auf 1 bei 300l-, auf 0 bei 500l-Boiler
// Serial.print("Stellung des 3WV ist ermittelt: ");Serial.println(Heizung_3WV);
lcd.setCursor(4,0); lcd.print(F("g"));
relais_vorschlag_byte=relais_byte; // sicherheitshalber
// Serial.print("gesetzt auf autopilot\n"); // gesetzt auf manuell
if (key=='D') // Reset des LCD und der Relaiskarte
{
lcd_init();
lcd_ausgabe(); // vorläufig; hier detailliertere Infos ausgeben
relais_byte_senden(relais_byte);
}

// Prüfung der Vorlauftemperatur, um evtl. die Zusatzpumpe anzuwerfen

if (TEMP_SENSOR[4]>=max_temp_vorlauf) // falls Temp Vorlauf zu hoch, schon mal die Zusatzpumpe einschlaten!
{
// Serial.print("Temp Vorlauf >= Temp B o !!");
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,0,1);
lcd.setCursor(4,0); lcd.print(F("h"));
}
else
{
// Serial.print("Temp Vorlauf <= Temp B o !!");
if (TEMP_SENSOR[4]<=(max_temp_vorlauf-zusatzpumpen_hysteresis))
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,0,0);
}
lcd.setCursor(4,0); lcd.print(F("i"));
}

// Boilerauswahl

if (TEMP_SENSOR[2]-TEMP_SENSOR[0]>0) // Temp des großen Boilers größer als die des Kleinen...
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,6,0); //... großen Boiler als WW-Quelle auswählen
lcd.setCursor(4,0); lcd.print(F("j"));
}
else
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,6,1); // ... kleinen Boiler als WW-Quelle auswählen
}

// Umwälzung der Boiler im Sommer

if ((relais_byte&B00010000)==0)
{
lcd.setCursor(4,0); lcd.print(F("k"));
if ((sommer_feststellen()==1) &&
((TEMP_SENSOR[2]-TEMP_SENSOR[0])>10) &&
(TEMP_SENSOR[2]>max_B_temp) &&
(TEMP_SENSOR[0]<=max_B_temp)) // Festlegung, wann es zur Umwälzung kommen soll!
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,1,0); // Befüllung stoppen (falls sowoeso nicht gestoppt!)
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,4,1); // Umwälzung zw den Boilern beginnen
}
}

if ((relais_byte&B00010000)>0)
{
if (((TEMP_SENSOR[2]-TEMP_SENSOR[0])<5) ||
(TEMP_SENSOR[2]<=45) ||
TEMP_SENSOR[0]>max_B_temp) // Festlegung, wann die Umwälzung aufhören soll! Sommer_feststellen wohl nicht erforderlich :-)
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,4,0); // Umwälzung zw den Boilern stoppen
}
}

// Aufheizung der Boiler im Winter

if ((relais_byte&B00000010)>0)
{
// Serial.print("Die Aufheizung des Boilers laeuft.\n"); // Eine Meldung ausgeben
if (key=='#') // wenn Heizung als Ziel ausgewählt wird
{
lcd.setCursor(4,0); lcd.print(F("l"));
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,1,0); // Auffüllen des Boilers beenden, Relais schließen
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,3,0); // dazu das 3WV-Relais in den Ruhezustand schalten
// Serial.print("Sie haben # ausgewaehlt, Boiler wird geschlossen, das 3WV in Ruhezustand versetzt\n"); // Eine Meldung ausgeben
// temp_ausgabe_serial();
}

if (TEMP_SENSOR[(2-Heizung_3WV*2)]>max_B_temp) // falls die Temp des geschalteten Boilers oben größer als erlaubte Temp: ...
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,1,0); // ... die Befüllung des entsprechenden Boilers beenden
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,3,0); // auch das 3WV-Relais in den Ruhezustand schalten
// Serial.print("Aufheizung des Boilers wird gleich unterbrochen werden, da die Temperatur des Boilers inzwischen groesser als erlaubt ist!\n");Serial.print(TEMP_SENSOR[(2-Heizung_3WV*2),2]); // Eine Meldung ausgeben
// evtl. später eine entsprechende LCD-Meldung einbauen
// temp_ausgabe_serial();
}
if ((TEMP_SENSOR[4]-TEMP_SENSOR[2-2*Heizung_3WV])-2<0) // Vorlauf um 2 Grad kleiner als Temperatur des geschalteten Boilers oben?
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,1,0); // ... die Befüllung des entsprechenden Boilers beenden
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,3,0); // auch das 3WV-Relais in den Ruhezustand schalten
// Serial.print("Aufheizung des Boilers wird gleich unterbrochen werden, da der Vorlauf inzwischen nicht mehr ausreicht!\n"); // Eine Meldung ausgeben
// evtl. später eine entsprechende LCD-Meldung einbauen
// temp_ausgabe_serial();
}
}
else
{
lcd.setCursor(4,0); lcd.print(F("m"));
// Serial.print("Die Aufheizung des Boilers findet nicht statt\n"); // Eine Meldung ausgeben
if (key=='#') // wenn Heizung als Ziel ausgewählt wird
{
// Serial.print("Sie haben # ausgewaehlt, Heizung ist jedoch bereits als Ziel ausgewaehlt\n"); // Eine Meldung ausgeben
// temp_ausgabe_serial();
}
if (key=='*') // wenn Boiler als Ziel ausgewählt wird
{
if ((TEMP_SENSOR[2]<=max_B_temp)&&((TEMP_SENSOR[2]+2)<TEMP_SENSOR[4])) // 500l-Boiler-Temp kleiner als max.Temp und kleiner als Vorlauf-Temp
{
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,3,0); // auch das 3WV-Relais in den Ruhezustand = 500l-Richtung schalten
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,1,1); // ... die Befüllung des entsprechenden Boilers beginnen
// Serial.print("Sie haben * ausgewaehlt, max. Temp des gr. Boilers ist noch nicht erreicht und der Vorlauf ist fuer den gr. Boiler warm genug, also wird der gr. Boiler aufgeladen\n"); // Eine Meldung ausgeben
// temp_ausgabe_serial();
}
else
{
// Serial.print("Sie haben * ausgewaehlt, max. Temp des gr. Boilers ist bereits erreicht oder der Vorlauf ist fuer den gr. Boiler nicht warm genug (evtl. aber fuer den 300l-Boiler)\n"); // Eine Meldung ausgeben
if ((TEMP_SENSOR[0]<=max_B_temp)&&((TEMP_SENSOR[0]+2)<TEMP_SENSOR[4])) // 300l-Boiler-Temp kleiner als max.Temp und kleiner als Vorlauf-Temp
{
lcd.setCursor(4,0); lcd.print(F("n"));
// Serial.print("Sie haben * ausgewaehlt, max. Temp des kl. Boilers ist noch nicht erreicht und der Vorlauf ist fuer den kl. Boiler warm genug, also wird der kl. Boiler aufgeladen\n"); // Eine Meldung ausgeben
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,3,1); // auch das 3WV-Relais in den Ruhezustand = 500l-Richtung schalten
relais_vorschlag_byte=relais_bit_setzen(relais_vorschlag_byte,1,1); // ... die Befüllung des entsprechenden Boilers beginnen
// temp_ausgabe_serial();
}
else
{
// Serial.print("Sie haben * ausgewaehlt, max. Temp auch des kl. Boilers ist bereits erreicht oder der Vorlauf ist fuer den kl. Boiler nicht warm genug, also wird auch er nicht aufgeladen\n"); // Eine Meldung ausgeben
// temp_ausgabe_serial();
}
}
}
}


} // Hier endet der Anweisungsblock für den Arbeitsmodus = 0

// Prüfung ob sich Daten geändert haben, wenn ja -> LCD neu zeichnen UND Byte setzen und schalten

if (relais_byte==relais_vorschlag_byte)
{
relais_byte_senden_o_delay(relais_byte); // ... und senden
// Serial.print("Keine Aenderng des Vorschlagsbytes eingetreten\n"); // gesetzt auf manuell, keine Änderung nötig
// temp_ausgabe_serial();
}
else // Relais_byte und Vorschlagsbyte sind ungleich
{
// Serial.print("Aenderng des Vorschlagsbytes eingetreten\n"); // gesetzt auf manuell
if (((relais_vorschlag_byte&B00000010)>0 && (relais_vorschlag_byte&B00010000))>0) // Kollision zwischen Auffüllen und Umwälzen abfangen, dann nichts machen!
{
relais_vorschlag_byte=relais_byte; // das manipulierte Vorschlag-Byte zurücksetzen auf den Ursprungswert
// Serial.print("Achtung: KOLLISION\n");
}
else
{ // wenn es aber keine Kollision gibt, Vorschlagsbyte als Relaisbyte übernehmen ...
// Serial.print("Keine KOLLISION\n");
relais_byte=relais_vorschlag_byte;
lcd.setCursor(4,0); lcd.print(F("o"));
relais_byte_senden(relais_byte); // ... und senden
lcd.setCursor(4,0); lcd.print(F("p"));
lcd_ausgabe();
lcd.setCursor(4,0); lcd.print(F("q"));
}
} // Ende der Ausgabe
} // Ende der Verarbeitungsschleife, wenn key != 0
} // Ende der loop-Funktion


Keine Kommentare:

Kommentar veröffentlichen