#include #include #include #include #include "util.h" #include "register_map_pm8000.h" // #include #include #include #define SD_CS_PIN 10 // Chip Select for SD Card // RS485 pins #define DE_RE_PIN 4 #define RX_PIN 8 // SoftwareSerial RX pin #define TX_PIN 7 // SoftwareSerial TX pin #define SLAVE_ID 101 #define SERIAL_BAUDRATE 9600 // Try to select the best SD card configuration. #define SPI_CLOCK SD_SCK_MHZ(50) #if HAS_SDIO_CLASS #define SD_CONFIG SdioConfig(FIFO_SDIO) #elif ENABLE_DEDICATED_SPI #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK) #else // HAS_SDIO_CLASS #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) #endif // HAS_SDIO_CLASS RTC_DS3231 rtc; // Create an RTC object SdFat32 sd; // SdExFat sd; File dataFile; NeoSWSerial modbusSerial(RX_PIN, TX_PIN); // Create a software serial instance ModbusMaster node; unsigned long lastRefreshTime = 0; bool headerWritten = false; void setup() { Serial.begin(SERIAL_BAUDRATE); // For debugging Serial.println(F("Startup \n")); // Initialize RTC if (!rtc.begin()) { Serial.println(F("Couldn't find RTC\n")); } if (rtc.lostPower()) { Serial.println(F("RTC lost power, let's set the time!\n")); // Comment out the following line once the time is set to avoid resetting on every start rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } Serial.print(F("Time: ")); Serial.print(rtc.now().timestamp()); Serial.println(F("\n")); // Initialize SD card Serial.println(F("SD card initializing...")); pinMode(SD_CS_PIN, OUTPUT); // if (!SD.begin(SPI_HALF_SPEED, SD_CS_PIN )) // { // Serial.println(F("SD card initialization failed!\n")); // return; // } // Initialize the SD. if (!sd.begin(SD_CONFIG)) { sd.initErrorHalt(&Serial); return; } Serial.println(F("SD card initialized.\n")); Serial.println(F("Initialize RS485 module / Modbus \n")); pinMode(DE_RE_PIN, OUTPUT); digitalWrite(DE_RE_PIN, LOW); // Set to LOW for receiving mode initially modbusSerial.begin(SERIAL_BAUDRATE); node.begin(SLAVE_ID, modbusSerial); node.preTransmission(preTransmission); node.postTransmission(postTransmission); } void preTransmission() { // Serial.println(F("Transmitting Start")); digitalWrite(DE_RE_PIN, HIGH); // Enable RS485 transmit } void postTransmission() { digitalWrite(DE_RE_PIN, LOW); // Disable RS485 transmit // Serial.println(F("Transmitting End")); } void primeFileDate() { if (!dataFile) { Serial.println(F("Error opening file")); return; } DateTime now = rtc.now(); // Log the current date and time dataFile.print("\n"); dataFile.print(now.year(), DEC); dataFile.print('-'); dataFile.print(now.month(), DEC); dataFile.print('-'); dataFile.print(now.day(), DEC); dataFile.print(" "); dataFile.print(now.hour(), DEC); dataFile.print(':'); dataFile.print(now.minute(), DEC); dataFile.print(':'); dataFile.print(now.second(), DEC); dataFile.print(F(",")); } String getFilename() { DateTime now = rtc.now(); String mb = F(""); mb += now.year(); mb += now.month(); mb += now.day(); mb += F(".csv"); return mb; } // const char[20] filename = "20240523.csv"; void loop() { delay(100); String writebuffer; if (millis() - lastRefreshTime >= 1000) { lastRefreshTime += 1000; Serial.print(F("\nTime: ")); Serial.print(rtc.now().timestamp()); // Serial.print("\nHeep:"); // Serial.print(ESP.getFreeHeap()); const uint16_t totalReg = sizeof(registers) / sizeof(registers[0]); // Open File String filename = getFilename(); Serial.print(F("Open Card ")); Serial.print(filename.c_str()); Serial.print("\n"); if (!dataFile.open(filename.c_str(), FILE_WRITE)) { Serial.println(F("Failed to Open Card ")); } if (!headerWritten) { dataFile.print("\nDate Time,"); for (int i = 0; i < totalReg; i++) { const uint16_t regaddr = pgm_read_word(®isters[i].regaddr); dataFile.print("Addr @ "); dataFile.print(regaddr); dataFile.print(","); } headerWritten = true; } primeFileDate(); Serial.print("\n"); Serial.println(totalReg); // Modbus Data Loop for (int i = 0; i < totalReg; i++) { const uint16_t regaddr = pgm_read_word(®isters[i].regaddr); const uint8_t regtype = pgm_read_word(®isters[i].regtype); Serial.print(F("Reg Read: ")); Serial.println(regtype); Serial.println(regaddr); if (regaddr > 0) { delay(50); //Gives the pending communication a little delay uint8_t result = node.readHoldingRegisters(regaddr - 1, 2); delay(50); //Delay the read for a little bit so that the buffer can be read if (result == node.ku8MBSuccess) { if (regtype == 2) { dataFile.print(getRegisterFloat(node.getResponseBuffer(0), node.getResponseBuffer(1))); } else if (regtype == 1) { dataFile.print(node.getResponseBuffer(0)); } // else if (regtype == 3) // { // dataFile.print(getRegisterInt64(node.getResponseBuffer(0), node.getResponseBuffer(1), node.getResponseBuffer(2), node.getResponseBuffer(3))); // } else if (regtype == 0) { dataFile.print(getRegisterInt32(node.getResponseBuffer(0), node.getResponseBuffer(1))); } else { dataFile.print(F("null")); } } else { Serial.print(F("Reg Error: ")); Serial.print(result, HEX); Serial.print("\n"); dataFile.print(F("E")); dataFile.print(result, HEX); } dataFile.print(","); } } Serial.print(F("\nRead buffer: ")); delay(10); if (dataFile) { dataFile.close(); // Close the file Serial.print(F("Data written to SD card: ")); Serial.print(filename.c_str()); Serial.print(F("\n")); } Serial.print(F("\n\n")); delay(100); } // // Check if the read was successful }