#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;
}
Comments