#include #include #include #include #include #include #include "RTClib.h" #include #include const uint8_t days_in_month [12] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const int chipSelect = 10; const char string_0[] PROGMEM = "1=0-Fallend 1-Steigend 2-Beide"; const char string_1[] PROGMEM = "2=Abtast Intervall"; const char string_2[] PROGMEM = "3=0-Datum+Uhrzeit,1-Timestamp,2-Timestamp+Millis,3-Systemmillis,4-Systemmillis+Differenz"; const char string_3[] PROGMEM = "4=Ausgabe 0-Serial 1-SD 2-Beides"; const char string_4[] PROGMEM = "5=Minimale Pulslaenge in Ms"; const char string_5[] PROGMEM = "6=Entprellung in Ms"; const char string_6[] PROGMEM = "7=Channel Aktivieren 1=Ein 0=Aus"; const char string_7[] PROGMEM = "8=Channel wechseln(1-4)"; const char string_8[] PROGMEM = "9=Speichern!"; const char string_9[] PROGMEM = "10=RTC setzen unixtime UTC!"; const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7, string_8, string_9}; //Beispielconfig int configs[40] = {1, 5, 2, 0, 50, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //RTC&Zeit RTC_DS3231 RTC; String filename = ""; void setup() { loadconfigs(); Serial.begin(115200); if (! RTC.begin()) {} setSyncProvider(syncProvider); setSyncInterval(1000); if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); // don't do anything more: return; } filename += String(now() / 60 / 60); filename += ".csv"; } #define SECONDS_FROM_1970_TO_2000 946684800 int pins[4] = {2, 3, 4, 5}; //Pinconfig char buffer2[100]; //Serial Buffer String inputString = ""; //Serial Buffer boolean stringComplete = false; //Serial Helper int channel = 1; //Menuhelper boolean menuactive = false; //Menuhelper int menuchoice = 0; //Menuhelper int choicevalue = 0; //Menuhelper int laststate[4] = {HIGH, HIGH, HIGH, HIGH}; //Statehelper int state[4] = {HIGH, HIGH, HIGH, HIGH}; //Statehelper //Testtrash //int channelorder; //int chswitch = 1; //int chswitchbackup; void loop() { if (!menuactive) intervallset(); serialmenu(); } //Call between Loops by Serial Input void serialEvent() { while (Serial.available()) { // get the new byte: char inChar = (char)Serial.read(); if (!menuactive) { inputString += inChar; if (inChar == '\n') { stringComplete = true; } } else { if (isDigit(inChar)) { inputString += (char)inChar; } if (inChar == '\n') { stringComplete = true; } } } } //MenuPrintout void menu() { Serial.print(hour()); Serial.print(":"); Serial.print(minute()); Serial.print(":"); Serial.print(second()); Serial.print("-"); Serial.print(day()); Serial.print("."); Serial.print(month()); Serial.print("."); Serial.println(year()); Serial.print("Aktiver Kanal: "); Serial.println(channel); for (int i = 0; i <= 9; i++) { int test = ((channel - 1) * 10) + i; int tempwert = configs[((((channel - 1) * 10) + i))]; if (tempwert != -1) Serial.print(tempwert); spaces(String(tempwert).length()); strcpy_P(buffer2, (char*)pgm_read_word(&(string_table[i]))); Serial.println(buffer2); delay( 100 ); } } //Menucontrol void serialmenu() { // Serial.println(menuchoice); if (stringComplete) if (!menuactive && inputString == "menu\n") { menuactive = true; stringComplete = false; inputString = ""; // menuchoice=0; menu(); } else if (menuactive && menuchoice == 0) { menuchoice = inputString.toInt(); strcpy_P(buffer2, (PGM_P)pgm_read_word(&(string_table[menuchoice - 1]))); Serial.println(buffer2); Serial.println("Neuen Wert eingeben!"); stringComplete = false; inputString = ""; } else if (menuactive && menuchoice == 8) { choicevalue = inputString.toInt(); if (choicevalue < 4) { channel = choicevalue; } else { Serial.println("Falsche Eingabe"); } stringComplete = false; inputString = ""; menuchoice = 0; menu(); } else if (menuactive && menuchoice == 9) { saveconfigs((channel - 1)); menuchoice = 0; menuactive = false; stringComplete = false; inputString = ""; menu(); } else if (menuactive && menuchoice == 10) { static time_t tLast; time_t t = inputString.toInt() + 3600; RTC.adjust(t); stringComplete = false; inputString = ""; menuchoice = 0; menuactive = false; menu(); //dump any extraneous input } else if (menuactive && menuchoice != 0) { choicevalue = inputString.toInt(); configs[((channel - 1) * 10) + (menuchoice - 1)] = choicevalue; stringComplete = false; inputString = ""; menuchoice = 0; menu(); } } //Menuhelper für Zeilen void spaces(int sizechars) { for (int z = 8; z != sizechars; z--) { Serial.print(" "); } } boolean debouncing[4] = {false, false, false, false}; //Entprellt? boolean mininterval[4] = {true, true, true, true}; //Minimale Impulslänge für Aktion unsigned long lastintervallmillis[4] = {millis(), millis(), millis(), millis()}; unsigned long changestate[4] = {millis(), millis(), millis(), millis()}; unsigned long lastdebounce[4] = {millis(), millis(), millis(), millis()}; unsigned long lastminpulse[4] = {millis(), millis(), millis(), millis()}; //ControlUnit void intervallset() { unsigned long tempmillis = millis(); for (int i = 0; i <= 3; i++) { if (tempmillis >= lastintervallmillis[i] + configs[(i * 10) + 1] && configs[(i * 10) + 6] == 1) { // Serial.println("check state"); lastintervallmillis[i] = tempmillis; int tempstate = digitalRead(pins[i]); if (tempstate != laststate[i]) { debouncing[i] = true; lastminpulse[i] = true; laststate[i] = tempstate; changestate[i] = tempmillis; mininterval[i] = true; //Serial.println("Statechange"); } if (debouncing[i]) { // Serial.println("debouncing"); if (tempmillis >= changestate[i] + configs[((i * 10) + 5)] && debouncing[i]) { debouncing[i] = false; mininterval[i] = false; } } if (tempmillis >= changestate[i] + configs[((i * 10) + 5)] + configs[((i * 10) + 4)] && !debouncing[i] && !mininterval[i]) { //Serial.println("check mininterval"); state[i] = laststate[i]; debouncing[i] = false; lastminpulse[i] = false; mininterval[i] = true; int Flanke = configs[(i * 10)]; if (Flanke == 2) { Flanke = tempstate; } if (state[i] == Flanke) { if (configs[((i * 10) + 3)] == 0 || configs[((i * 10) + 3)] == 2) { Serial.println( createlogtext(state[i], i, now(), millis())); } if (configs[((i * 10) + 3)] == 1 || configs[((i * 10) + 3)] == 2) { File dataFile = SD.open(filename, FILE_WRITE); if (dataFile) { dataFile.println( createlogtext(state[i], i, now(), millis() % 1000)); dataFile.close(); } } } } } } } //Generate Unixtime for RTC Setup uint32_t get_unixtime(tmElements_t t) { uint8_t i; uint16_t d; int16_t y; uint32_t rv; int tmpYear = t.Year + 1970; if (tmpYear >= 2000) { y = tmpYear - 2000; } else { return 0; } d = t.Day - 1; for (i = 1; i < (int)t.Month; i++) { d += pgm_read_byte(days_in_month + i - 1); } if ((int)t.Month > 2 && y % 4 == 0) { d++; } // count leap days d += (365 * y + (y + 3) / 4); rv = ((d * 24UL + (int)t.Hour) * 60 + (int)t.Minute) * 60 + (int)t.Second + SECONDS_FROM_1970_TO_2000; return rv; } //print date and time to Serial void printDateTime(time_t t) { printDate(t); Serial << ' '; printTime(t); } //print time to Serial void printTime(time_t t) { printI00(hour(t), ':'); printI00(minute(t), ':'); printI00(second(t), ' '); } //print date to Serial void printDate(time_t t) { printI00(day(t), 0); Serial << monthShortStr(month(t)) << _DEC(year(t)); } //Print an integer in "00" format (with leading zero), //followed by a delimiter character to Serial. //Input value assumed to be between 0 and 99. void printI00(int val, char delim) { if (val < 10) Serial << '0'; Serial << _DEC(val); if (delim > 0) Serial << delim; return; } void saveconfigs(int channel) { for (int i = channel * 10; i <= channel * 10 + 10; i++) eepromWriteInt(i * 2, configs[i]); } void loadconfigs() { for (int i = 0; i <= 39; i++) configs[i] = eepromReadInt(i * 2); } void eepromWriteInt(int adr, int wert) { byte low, high; low = wert & 0xFF; high = (wert >> 8) & 0xFF; EEPROM.write(adr, low); // dauert 3,3ms EEPROM.write(adr + 1, high); return; } //eepromWriteInt int eepromReadInt(int adr) { byte low, high; low = EEPROM.read(adr); high = EEPROM.read(adr + 1); return low + ((high << 8) & 0xFF00); } //eepromReadInt unsigned long laststatemillis1[4]; unsigned long laststatemillis0[4]; String createlogtext(int state, int channel, unsigned long newunixtime, unsigned long newmillis) { //"3=0-Datum+Uhrzeit,1-Timestamp,2-TimestampMillis,3-Systemtime"; String tempstring = "'"; int checkconfig = configs[(channel * 10) + 2]; switch (checkconfig) { case 0: tempstring += day(); tempstring += "."; tempstring += month(); tempstring += "."; tempstring += year(); tempstring += "-"; tempstring += hour(); tempstring += ":"; tempstring += minute(); tempstring += ":"; tempstring += second(); tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += channel; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += state; tempstring += "'"; return tempstring; break; //do something when var equals 1 case 1: tempstring += newunixtime; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += channel; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += state; tempstring += "'"; return tempstring; case 2: tempstring += newunixtime; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += newmillis; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += channel; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += state; tempstring += "'"; return tempstring; break; case 3: tempstring += newmillis; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += channel; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += state; tempstring += "'"; return tempstring; break; case 4: tempstring += newmillis; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += channel; tempstring += "'"; tempstring += ","; tempstring += "'"; tempstring += state; tempstring += "'"; tempstring += ","; tempstring += "'"; if (state == 0) { tempstring += newmillis - laststatemillis0[channel]; laststatemillis0[channel] = newmillis; } else { tempstring += newmillis - laststatemillis1[channel]; laststatemillis1[channel] = newmillis; } tempstring += "'"; return tempstring; break; } } time_t syncProvider() { return RTC.now().unixtime(); }