Mal als Anregung eine andere Variante
Ich habe einen etwas anderen Weg beschritten,
wenn schon ein Prozessor dazwischen, dann soll er auch dem IPS ein wenig Arbeit abnehmen.
Ich lasse über einen Interrupt einen Zähler hochlaufen, der genau alle 1/4 Std abgefragt wird.
Das reicht für Statistiken.
Eingebuat ist dafür eine RTC, die ich seriell über IPS setzen kann. Es wird zusätzlich ein
4 zeiliges LCD Display verwendet, das alle nötigen Werte anzeigt.
Zusätzlich wird über ein I/O Expander die Waschmaschine und der Trockner abgefragt.
Da ich den ARD im Keller neben dem Zählerkasten installiert habe, werden alle seriellen Daten über einen
XBEE zum IPS gesendet.
In IPS werden nur ein paar Zeilen Code für die Auswertung benötigt.
Somit kommen nur alle 1/4 Std ein paar Zeilen Daten angeflattert, die das system so gut wie überhaupt nicht belasten.
Läuft seit einem 3/4 Jahr Problemlos und genau.
Hier der Arduino Scetch
/*
LiquidCrystal Library - Hello World
Demonstrates the use a 16x2 LCD display. The LiquidCrystal
library works with all LCD displays that are compatible with the
Hitachi HD44780 driver. There are many of them out there, and you
can usually tell them by the 16-pin interface.
This sketch prints "Hello World!" to the LCD
and shows the time.
The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
Library originally added 18 Apr 2008
by David A. Mellis
library modified 5 Jul 2009
by Limor Fried (http://www.ladyada.net)
example added 9 Jul 2009
by Tom Igoe
modified 22 Nov 2010
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/
// include the library code:
#include <LiquidCrystal.h>
#include <Wire.h> // For some strange reasons, Wire.h must be included here
#include <IOexp.h>
#include <DS1307new.h>
#define IO_ADDR (0x4 << 3 | 0x0)
IOexp myIOexpander(IO_ADDR);
bool bool1, bool2, bool3, bool4, bool5, bool6, bool7, bool8; // the bool vars bool1 and bool2 are to store the status of the Inputs we wish to read.
uint16_t startAddr = 0x0000; // Start address to store in the NV-RAM
uint16_t lastAddr; // new address for storing in NV-RAM
uint16_t TimeIsSet = 0xaa55;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
const int buttonPin = 2; // the number of the pushbutton pin
const int ledpin = 13;
int data;
int pbIn = 0; // Interrupt 0 is on DIGITAL PIN 2
int zaehler = 0;
int leer = 20; // Zeichenlänge LCD Zeile
int zehn_sekunden = 0;
String var1 ="Imp./15 Min ";
// Zähler für die Begrenzung des sendens der ext Pins
int count1_bool1_true = 0;
int count2_bool2_true = 0;
int count3_bool3_true = 0;
int count4_bool4_true = 0;
int count5_bool5_true = 0;
int count6_bool6_true = 0;
int count1_bool1_false = 0;
int count2_bool2_false = 0;
int count3_bool3_false = 0;
int count4_bool4_false = 0;
int count5_bool5_false = 0;
int count6_bool6_false = 0;
int count_ende = 3;
// Variablen setzen für 2 Analog Eingänge
const int analogInPin0 = A0;
const int analogInPin1 = A1;
int sensorValue0 = 0;
int sensorValue1 = 0;
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(20, 4);
Wire.begin(); // join i2c bus (address optional for master)
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
pinMode(ledpin,OUTPUT);
digitalWrite(buttonPin,HIGH);
digitalWrite(13, HIGH);
// start serial port at 9600 bps and wait for port to open:
Serial.begin(19200);
//Attach the interrupt to the input pin and monitor for ANY Change
attachInterrupt(pbIn, stateChange, CHANGE);
lcd.setCursor(0,0);
lcd.print("Strom Impulszaehler");
/*
PLEASE NOTICE: WE HAVE MADE AN ADDRESS SHIFT FOR THE NV-RAM!!!
NV-RAM ADDRESS 0x08 HAS TO ADDRESSED WITH ADDRESS 0x00=0
TO AVOID OVERWRITING THE CLOCK REGISTERS IN CASE OF
ERRORS IN YOUR CODE. SO THE LAST ADDRESS IS 0x38=56!
*/
RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));// Store startAddr in NV-RAM address 0x08
RTC.getTime();
RTC.ctrl = 0x00; // 0x00=disable SQW pin, 0x10=1Hz,
// 0x11=4096Hz, 0x12=8192Hz, 0x13=32768Hz
RTC.setCTRL();
}
void loop() {
if(Serial.available() > 0){ // Set RTC after receiving serial characters:
set_RTC();
}
lcd.setCursor(12, 2);
// 3. Zeile löschen, da sich manchmal die Stellen verschieben
for (int i = 12; i < leer; i++) {
lcd.print(" ");
}
//RTC aufbereiten
RTC.getTime();
if (RTC.hour < 10) // correct hour if necessary
{
//Serial.print("0");
//Serial.print(RTC.hour, DEC);
//std = RTC.hour, DEC;
lcd.setCursor(12, 2);
lcd.print("0");
lcd.print(RTC.hour, DEC);
}
else
{
//Serial.print(RTC.hour, DEC);
//String std = RTC.hour, DEC;
lcd.setCursor(12, 2);
lcd.print(RTC.hour, DEC);
}
//Serial.print(":");
lcd.print(":");
if (RTC.minute < 10) // correct minute if necessary
{
//Serial.print("0");
//Serial.print(RTC.minute, DEC);
//int minu = RTC.minute, DEC;
lcd.print("0");
lcd.print(RTC.minute, DEC);
}
else
{
//Serial.print(RTC.minute, DEC);
//int minu = RTC.minute, DEC;
lcd.print(RTC.minute, DEC);
}
//Serial.print(":");
lcd.print(":");
if (RTC.second < 10) // correct second if necessary
{
//Serial.print("0");
//Serial.print(RTC.second, DEC);
lcd.print("0");
lcd.print(RTC.second, DEC);
}
else
{
//Serial.print(RTC.second, DEC);
lcd.print(RTC.second, DEC);
}
//Abfrage ext. Ports
bool1 = myIOexpander.read(P0);
bool2 = myIOexpander.read(P1);
bool3 = myIOexpander.read(P2);
bool4 = myIOexpander.read(P3);
bool5 = myIOexpander.read(P4);
bool6 = myIOexpander.read(P5);
// Nur wenn ein bit aktiv Low, wird auf der ersten Zeile
// im LCD umgeschaltet auf ext. Port Anzeige
data = myIOexpander.fullread();
if (data < 255)
{
lcd.setCursor(0, 0);
// 1. Zeile löschen
for (int i = 0; i < leer; i++) {
lcd.print(" ");
}
lcd.setCursor(0, 0);
//Watt Zahl errechnen . 10 Imp =1W/h
lcd.print("ext. Ports ");
lcd.print(data, BIN);
zehn_sekunden = 0; //10sec Warte Zeit für das Umschalten der ersten
//LCD Zeile auf null setzen
}
if (data == 255 and zehn_sekunden < 11)
{
lcd.setCursor(0, 0);
// 1. Zeile löschen
for (int i = 0; i < leer; i++) {
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Strom Impulszaehler");
zehn_sekunden++;
}
}
// Nur 3 mal übertragen
//bool1 false = 'Waschmasch. ein'
if (bool1 == false and count1_bool1_false < count_ende)
{
Serial.print("bool1");
Serial.print(bool1);
Serial.print("
");
count1_bool1_true = 0;
count1_bool1_false++;
}
///bool1 true = 'Waschmasch. aus'
else if (bool1 == true and count1_bool1_true < count_ende)
{
Serial.print("bool1");
Serial.print(bool1);
Serial.print("
");
count1_bool1_false = 0;
count1_bool1_true++;
}
//Nur wenn bool1 false (Waschm. ein) darf abgerfragt werden
if (bool2 == false and bool1 == false and count2_bool2_false < count_ende)
//bool2 false = 'Waschmasch. läuft'
{
Serial.print("bool2");
Serial.print(bool2);
Serial.print("
");
count2_bool2_true = 0;
count2_bool2_false++;
}
//bool2 true = Waschmasch. 'ein'
else if (bool2 == true and bool1 == false and count2_bool2_true < count_ende)
{
Serial.print("bool2");
Serial.print(bool2);
Serial.print("
");
count2_bool2_false = 0;
count2_bool2_true++;
}
//bool3 false = Waschmasch. 'Störung'
if (bool3 == false and bool1 == false and count3_bool3_false < count_ende)
{
Serial.print("bool3");
Serial.print(bool3);
Serial.print("
");
count3_bool3_true = 0;
count3_bool3_false++;
}
//bool3 true = Waschmasch. 'ein' oder 'läuft'
else if (bool3 == true and bool1 == false and count3_bool3_true < count_ende)
{
//Serial.print("bool3");
//Serial.print(bool3);
//Serial.print("
");
count3_bool3_false = 0;
count3_bool3_true++;
// je nach aktiven Zustand 'an' oder 'läuft' wird nach
// dem Fehler der alte Zustand wieder angezeigt
if (bool1 == false and bool2 == false)
{
count2_bool2_false = 0;
}
else if (bool1 == false)
{
count1_bool1_false = 0;
}
}
//bool4 false = 'Trockner ein'
if (bool4 == false and count4_bool4_false < count_ende)
{
Serial.print("bool4");
Serial.print(bool4);
Serial.print("
");
count4_bool4_true = 0;
count4_bool4_false++;
}
//bool4 true = 'Trockner aus'
else if (bool4 == true and count4_bool4_true < count_ende)
{
Serial.print("bool4");
Serial.print(bool4);
Serial.print("
");
count4_bool4_false = 0;
count4_bool4_true++;
}
//bool5 false = 'Trockner läuft'
if (bool5 == false and bool4 == false and count5_bool5_false < count_ende)
{
Serial.print("bool5");
Serial.print(bool5);
Serial.print("
");
count5_bool5_true = 0;
count5_bool5_false++;
}
//bool5 true = 'Trockner an oder beendet'
else if (bool5 == true and bool4 == false and count5_bool5_true < count_ende)
{
Serial.print("bool5");
Serial.print(bool5);
Serial.print("
");
count5_bool5_false = 0;
count5_bool5_true++;
}
//bool6 false = 'Trockner Störung'
if (bool6 == false and bool4 == false and count6_bool6_false < count_ende)
{
Serial.print("bool6");
Serial.print(bool6);
Serial.print("
");
count6_bool6_true = 0;
count6_bool6_false++;
}
//bool6 true = Trocker Störung wieder aufgehoben, je nach vorherigen
//Zustand danach 'Trocker an' oder 'Trockner läuft'
else if (bool6 == true and bool4 == false and count6_bool6_true < count_ende)
{
//Serial.print("bool6");
//Serial.print(bool6);
//Serial.print("
");
count6_bool6_false = 0;
count6_bool6_true++;
// je nach aktiven Zustand 'an' oder 'läuft' wird nach
// dem Fehler der alte Zustand wieder angezeigt
if (bool4 == false and bool5 == false)
{
count5_bool5_false = 0;
}
else if (bool4 == false)
{
count4_bool4_false = 0;
}
}
//Serial.println(zaehler);
if (RTC.second ==0) //immer wenn sec auf null , eine Abfrage alle 15 Min
{
switch (RTC.minute)
{
case 0:
lcd.setCursor(0, 1);
// 2. Zeile löschen, da sie immer eine andere Länge hat
for (int i = 0; i < leer; i++) {
lcd.print(" ");
}
lcd.setCursor(0, 1);
//Watt Zahl errechnen . 10 Imp =1W/h
lcd.print(RTC.minute);
lcd.print(" Min-");
lcd.print(zaehler);
lcd.print("Imp/");
lcd.print(zaehler/2,5);
lcd.print("W");
lcd.setCursor(0, 2);
lcd.print(var1);
Serial.print("Impulse");
// damit die Länger des Minuten Wertes immer gleich ist
//unter 10 mit '0' auffüllen
Serial.print("0");
Serial.print(RTC.minute);
Serial.print(zaehler);
zaehler = 0;
//Zusätzlich Analogwerte abfragen
sensorValue0 = analogRead(analogInPin0);
sensorValue1 = analogRead(analogInPin1);
lcd.setCursor(0, 3);
lcd.print("An0-");
lcd.print(sensorValue0*(5.0/1023.0));
lcd.print("V ");
lcd.print("An1-");
lcd.print(sensorValue1*(5.0/1023.0));
lcd.print("V");
Serial.print("Analogwert A0");
Serial.print(sensorValue0);
Serial.print("Analogwert A1");
Serial.println(sensorValue1);
break;
case 15:
lcd.setCursor(0, 1);
// 2. Zeile löschen, da sie immer eine andere Länge hat
for (int i = 0; i < leer; i++) {
lcd.print(" ");
}
lcd.setCursor(0, 1);
//Watt Zahl errechnen . 10 Imp =1W/h
lcd.print(RTC.minute);
lcd.print("Min-");
lcd.print(zaehler);
lcd.print("Imp/");
lcd.print(zaehler/2,5);
lcd.print("W");
lcd.setCursor(0, 2);
lcd.print(var1);
Serial.print("Impulse");
Serial.print(RTC.minute);
Serial.print(zaehler);
zaehler = 0;
//Zusätzlich Analogwerte abfragen
sensorValue0 = analogRead(analogInPin0);
sensorValue1 = analogRead(analogInPin1);
lcd.setCursor(0, 3);
lcd.print("An0-");
lcd.print(sensorValue0*(5.0/1023.0));
lcd.print("V ");
lcd.print("An1-");
lcd.print(sensorValue1*(5.0/1023.0));
lcd.print("V");
Serial.print("Analogwert A0");
Serial.print(sensorValue0);
Serial.print("Analogwert A1");
Serial.println(sensorValue1);
break;
case 30:
lcd.setCursor(0, 1);
// 2. Zeile löschen, da sie immer eine andere Länge hat
for (int i = 0; i < leer; i++) {
lcd.print(" ");
}
lcd.setCursor(0, 1);
//Watt Zahl errechnen . 10 Imp =1W/h
lcd.print(RTC.minute);
lcd.print("Min-");
lcd.print(zaehler);
lcd.print("Imp/");
lcd.print(zaehler/2,5);
lcd.print("W");
lcd.setCursor(0, 2);
lcd.print(var1);
Serial.print("Impulse");
Serial.print(RTC.minute);
Serial.print(zaehler);
zaehler = 0;
//Zusätzlich Analogwerte abfragen
sensorValue0 = analogRead(analogInPin0);
sensorValue1 = analogRead(analogInPin1);
lcd.setCursor(0, 3);
lcd.print("An0-");
lcd.print(sensorValue0*(5.0/1023.0));
lcd.print("V ");
lcd.print("An1-");
lcd.print(sensorValue1*(5.0/1023.0));
lcd.print("V");
Serial.print("Analogwert A0");
Serial.print(sensorValue0);
Serial.print("Analogwert A1");
Serial.println(sensorValue1);
break;
case 45:
lcd.setCursor(0, 1);
// 2. Zeile löschen, da sie immer eine andere Länge hat
for (int i = 0; i < leer; i++) {
lcd.print(" ");
}
lcd.setCursor(0, 1);
//Watt Zahl errechnen . 10 Imp =1W/h
lcd.print(RTC.minute);
lcd.print("Min-");
lcd.print(zaehler);
lcd.print("Imp/");
lcd.print(zaehler/2,5);
lcd.print("W");
lcd.setCursor(0, 2);
lcd.print(var1);
Serial.print("Impulse");
Serial.print(RTC.minute);
Serial.print(zaehler);
zaehler = 0;
//Zusätzlich Analogwerte abfragen
sensorValue0 = analogRead(analogInPin0);
sensorValue1 = analogRead(analogInPin1);
lcd.setCursor(0, 3);
lcd.print("An0-");
lcd.print(sensorValue0*(5.0/1023.0));
lcd.print("V ");
lcd.print("An1-");
lcd.print(sensorValue1*(5.0/1023.0));
lcd.print("V");
Serial.print("Analogwert A0");
Serial.print(sensorValue0);
Serial.print("Analogwert A1");
Serial.println(sensorValue1);
break;
}
}
delay(1000);
}
void stateChange()
{
//Serial.println("Button gedrueckt");
zaehler++;
digitalWrite(13, LOW); // Port 13 wird high geschaltet
delay(250); // eine Sekunde warten
digitalWrite(13, HIGH); // Port 13 wird low geschaltet
delay(250); // eine Sekunde warten
}
/*
Funktion set_RTC() abgearbeitet wird. Dir über die serielle
Schnittstelle (XBEE)zu sendende Zeichensequenz hat den Aufbau WDDMMYYHHMMSS
•W = Day of Week (1=Monday, 2= Tuesday,..., 7=Sunday)
•DD= Tag (00...31)
•MM=Monat (01...12)
•YY=Jahr (00...99)
•HH=Stunde (00...23)
•MM=Minute (00...59)
•SS=Sekunde (00...59)
z.B 4070213131900
Donnerstag den 07.02.13 13:19:00
*/
void set_RTC(){
// Read received characters, build values and set RTC:
int year, month, day, wday;
int hour, minute, second;
RTC.stopClock();
delay(10);
wday= (Serial.read() - 48);
//rtc.setDOW(wday);
day = (Serial.read() - 48) *10 + (Serial.read() - 48);
month = (Serial.read() - 48) *10 + (Serial.read() - 48);
year = (Serial.read() - 48) *10 + (Serial.read() - 48) + 2000;
RTC.fillByYMD(year, month, day );
hour = (Serial.read() - 48) *10 + (Serial.read() - 48);
minute = (Serial.read() - 48) *10 + (Serial.read() - 48);
second = (Serial.read() - 48) * 10 + (Serial.read() - 48);
RTC.fillByHMS(hour, minute, second);
RTC.setTime();
RTC.startClock();
}