MetaView
Published © GPL3+

Energy Consumption Logger

Counting the energy consumption from the (Ferraris) meter using a reflex optocoupler. The impulses are counted by a Arduino Uno.

IntermediateShowcase (no instructions)2 hours5,862
Energy Consumption Logger

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
SparkFun Bluetooth Modem - BlueSMiRF Silver
SparkFun Bluetooth Modem - BlueSMiRF Silver
×1
RTC Shield
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Prinzip.png

Code

EnergieZaehler

Arduino
#include <AltSoftSerial.h>
#include <LowPower.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
#include <string.h>
#include <stdlib.h>

// logging intervall in minutes
#define INTERVALL     15
// CS pin for SD card
#define CHIPSELECT    10

/* PINS: */
#define PIN_SOFT_RX  8 // soft serial
#define PIN_SOFT_TX  9
#define PIN_CNTR_IN  2 // counter (opto-coupler)
#define PIN_CNTR_OUT 4 // GND for counter opto-coupler
#define PIN_BUTTON   3 // button
#define PIN_LED      7 // LED on card adapter
#define PIN_BT_POWER 6 // power for BT adapter

RTC_DS1307 rtc;
AltSoftSerial mySerial(PIN_SOFT_RX, PIN_SOFT_TX); // RX, TX


volatile unsigned long counterRisingMillis = 0;
volatile int counter = 0;
volatile unsigned long wakeupRisingMillis = 0;
volatile long startUpSeconds = 0;

void handleRTC();
void counterPinRising();
void counterPinFalling();
void wakeupPinRising();
void wakeupPinFalling();
void doDebugOutput(char line, int row, int col);

void setup()
{
	Serial.begin(115200);

	// set the data rate for the SoftwareSerial port
	mySerial.begin(9600);
	mySerial.print("AT");
	delay(1000);
	while (mySerial.available())
		Serial.write(mySerial.read());
	Serial.println();
	mySerial.print("AT+NAMEenergie1");
	delay(1000);
	while (mySerial.available())
		Serial.write(mySerial.read());
	Serial.println();
	mySerial.print("AT+PIN1134");
	delay(1000);
	while (mySerial.available())
		Serial.write(mySerial.read());
	Serial.println();

	Serial.println("Hello from EnergieZaehler. (Send 's')");
	mySerial.println("Hello from EnergieZaehler. (Send 's')");

	if (!rtc.begin())
	{
		doDebugOutput("Couldn't find RTC.", 0, 1);
	}

	if (!rtc.isrunning())
	{
		doDebugOutput("RTC is NOT running.", 0, 1);
	}

	// make sure that the default chip select pin is set to
	// output, even if you don't use it:
	pinMode(CHIPSELECT, OUTPUT);
	// see if the card is present and can be initialized:
	if (!SD.begin(CHIPSELECT))
	{
		doDebugOutput("Card failed.", 0, 1);
	}

	// raise an interrupt whenever PIN 2 sees an L/H change
	// set PIN 2 as INPUT with pull-up
	pinMode(PIN_CNTR_IN, INPUT); //counter
	digitalWrite(PIN_CNTR_IN, HIGH);
	pinMode(PIN_CNTR_OUT, OUTPUT); // GND connection for opto-coupler in ferraris-sensor module
	digitalWrite(PIN_CNTR_OUT, LOW);
	pinMode(PIN_BUTTON, INPUT); // wakeup button
	digitalWrite(PIN_BUTTON, HIGH);
	attachInterrupt(digitalPinToInterrupt(PIN_CNTR_IN), counterPinRising, RISING);
	attachInterrupt(digitalPinToInterrupt(PIN_CNTR_IN), counterPinFalling, FALLING);
	attachInterrupt(digitalPinToInterrupt(PIN_BUTTON), wakeupPinRising, RISING);
	attachInterrupt(digitalPinToInterrupt(PIN_BUTTON), wakeupPinFalling, FALLING);

	pinMode(PIN_BT_POWER, OUTPUT); // BT power
	digitalWrite(PIN_BT_POWER, HIGH);
	pinMode(PIN_LED, OUTPUT); // live led
	digitalWrite(PIN_LED, LOW);

	startUpSeconds = 0;
}

void loop()
{
	static long lastWriteSeconds = 0;
	DateTime now = rtc.now();

	handleRTC(now);

	digitalWrite(PIN_LED, HIGH);
	delayMicroseconds(50);
	digitalWrite(PIN_LED, LOW);

	if (((now.minute() % INTERVALL) == 0) && (now.secondstime() - lastWriteSeconds) > ((INTERVALL - 1) * 60))
	{
		// skip the first write attempt (don't write incomplete data)
		if (lastWriteSeconds == 0)
		{
			doDebugOutput("Skip first write attempt.", 0, 1);
		}
		else
		{
			// open the file. note that only one file can be open at a time,
			// so you have to close this one before opening another.
			File dataFile = SD.open("datalog.txt", FILE_WRITE);
			if (dataFile)
			{
				// if the file is available, write to it:
				char dataString[32];
				sprintf(dataString, "%02d.%02d.%04d %02d:%02d:%02d\t%d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), counter);
				dataFile.println(dataString);
				dataFile.close();
				doDebugOutput("Wrote datalog.txt.", 0, 1);
			}
			else
			{
				// if the file isn't open, pop up an error:
				doDebugOutput("Error opening datalog.txt", 0, 1);
			}
		}
		lastWriteSeconds = now.secondstime();
		counter = 0;
	}

	if (Serial.available())
	{
		if (Serial.read() == 's')
		{
			char buffer[32];
			sprintf(buffer, "%02d.%02d.%04d %02d:%02d:%02d\t%d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), counter);
			Serial.println("Current Date/Time, current counter:");
			Serial.println(buffer);
			memset(buffer, 0, sizeof(buffer));
			Serial.readBytesUntil('\n', buffer, sizeof(buffer));
			Serial.print(strlen(buffer), DEC);
			Serial.print(": ");
			Serial.println(buffer);
			if (strlen(buffer) >= 20)
			{
				int DD = atoi(buffer + 1);
				int MM = atoi(buffer + 4);
				int YY = atoi(buffer + 7);
				int hh = atoi(buffer + 12);
				int mm = atoi(buffer + 15);
				int ss = atoi(buffer + 18);
				rtc.adjust(DateTime(YY, MM, DD, hh, mm, ss));
				now = rtc.now();
				sprintf(buffer, "%02d.%02d.%04d %02d:%02d:%02d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second());
				Serial.println("New Date/Time:");
				Serial.println(buffer);
			}
			else
			{
				Serial.println("To set Date/Time: s DD.MM.YYYY HH:MM:SS");
			}
		}
	}

	if (mySerial.available())
	{
		char chr = mySerial.read();
		if (chr == 's')
		{
			char buffer[32];
			sprintf(buffer, "%02d.%02d.%04d %02d:%02d:%02d\t%d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), counter);
			mySerial.println("Current Date/Time, current counter:");
			mySerial.println(buffer);
			memset(buffer, 0, sizeof(buffer));
			mySerial.readBytesUntil('\n', buffer, sizeof(buffer));
			mySerial.print(strlen(buffer), DEC);
			mySerial.print(": ");
			mySerial.println(buffer);
			if (strlen(buffer) >= 20)
			{
				int DD = atoi(buffer + 1);
				int MM = atoi(buffer + 4);
				int YY = atoi(buffer + 7);
				int hh = atoi(buffer + 12);
				int mm = atoi(buffer + 15);
				int ss = atoi(buffer + 18);
				rtc.adjust(DateTime(YY, MM, DD, hh, mm, ss));
				now = rtc.now();
				sprintf(buffer, "%02d.%02d.%04d %02d:%02d:%02d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second());
				mySerial.println("New Date/Time:");
				mySerial.println(buffer);
			}
			else
			{
				mySerial.println("To set Date/Time: s DD.MM.YYYY HH:MM:SS");
			}
		}
	}
}

void doDebugOutput(const char *line, int row, int col)
{
	Serial.println(line);
	mySerial.println(line);
}

void handleRTC(DateTime now)
{
	if (startUpSeconds == 0)
	{
		startUpSeconds = now.secondstime();
	}

	// use low power sleep after 5 minutes up-time (to allow serial communication during the first 5 minutes)
	if ((now.secondstime() - startUpSeconds) > (5 * 60))
	{
		// disable BT module
		digitalWrite(PIN_BT_POWER, LOW);
		LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
	}
	else
	{
		// enable BT module
		digitalWrite(PIN_BT_POWER, HIGH);
		delay(500);
	}
}

// Interrupt Service Routine (ISR)
void counterPinRising()
{
	counterRisingMillis = millis();
}

void counterPinFalling()
{
	// we need a signal of at least 20 ms length
	if ((millis() - counterRisingMillis) > 20)
		counter++;
}

void wakeupPinRising()
{
	wakeupRisingMillis = millis();
}

void wakeupPinFalling()
{
	// we need a signal of at least 20 ms length
	if ((millis() - wakeupRisingMillis) > 20)
		startUpSeconds = 0;
}

Credits

MetaView

MetaView

8 projects • 15 followers

Comments