diff --git a/firmware/mega/mega-sd-mb-pm8000/mega-sd-mb-pm8000.ino b/firmware/mega/mega-sd-mb-pm8000/mega-sd-mb-pm8000.ino new file mode 100644 index 0000000..e8f141b --- /dev/null +++ b/firmware/mega/mega-sd-mb-pm8000/mega-sd-mb-pm8000.ino @@ -0,0 +1,271 @@ +#include // Library for I2C communication +#include // Library for Real Time Clock +#include // Library for Modbus communication +#include "util.h" // Custom utility functions +#include "register_map.h" // Map of Modbus registers to read +#include // Library for SPI communication +#include // Enhanced SD card library + +// ==== PIN CONNECTIONS AND SETTINGS ==== +/* +Physical Connections Guide: + +SD CARD MODULE: +- CS -> Arduino MEGA pin 53 (Hardware SS) +- MOSI -> Arduino MEGA pin 51 +- MISO -> Arduino MEGA pin 50 +- SCK -> Arduino MEGA pin 52 +- VCC -> 5V +- GND -> GND + +RS485 MODULE: +- DI -> Arduino MEGA TX1 (Pin 18) +- RO -> Arduino MEGA RX1 (Pin 19) +- DE & RE -> Arduino MEGA Pin 4 +- VCC -> 5V +- GND -> GND + +RTC MODULE (DS3231): +- SDA -> Arduino MEGA Pin 20 +- SCL -> Arduino MEGA Pin 21 +- VCC -> 5V +- GND -> GND + +STATUS LEDs: +- LED A -> Arduino MEGA Pin 3 +- LED B -> Arduino MEGA Pin 5 +*/ + +// ==== CONFIGURATION SETTINGS ==== +#define SD_CS_PIN 53 // SD card chip select pin (MEGA's SS pin) +#define DE_RE_PIN 4 // RS485 direction control +#define SLAVE_ID 101 // Modbus device address +#define SERIAL_BAUDRATE 115200 // Debug communication speed +#define MODBUS_BAUDRATE 9600 // Modbus communication speed +#define LED_A_PIN 3 // Activity LED +#define LED_B_PIN 5 // Error LED +#define MAX_RETRIES 3 // Maximum read attempts +#define ERROR_VALUE -999.99 // Error indicator value + +// ==== SD CARD CONFIGURATION ==== +#define SPI_CLOCK SD_SCK_MHZ(16) // SD card speed (16MHz for stability) +#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 +#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) +#endif + +// ==== GLOBAL OBJECTS ==== +RTC_DS3231 rtc; // RTC object +SdFat32 sd; // SD card object +File dataFile; // File object +ModbusMaster node; // Modbus object + +// ==== GLOBAL VARIABLES ==== +unsigned long lastRefreshTime = 0; +bool headerWritten = false; +bool booted = false; + +// ==== UTILITY FUNCTIONS ==== +void flicker(uint8_t pin, uint8_t times, uint16_t speed) { + for (uint8_t i = 0; i < times; i++) { + digitalWrite(pin, HIGH); + delay(speed); + digitalWrite(pin, LOW); + delay(speed); + } +} + +// ==== SETUP FUNCTION ==== +void setup() { + booted = false; + + // Initialize status LEDs + pinMode(LED_A_PIN, OUTPUT); + pinMode(LED_B_PIN, OUTPUT); + digitalWrite(LED_A_PIN, LOW); + digitalWrite(LED_B_PIN, HIGH); // Error LED on until setup complete + + // Start debug serial communication + Serial.begin(SERIAL_BAUDRATE); + Serial.println(F("Startup")); + + // Start Modbus serial communication (Hardware Serial1) + Serial1.begin(MODBUS_BAUDRATE); + + // Initialize RTC + if (!rtc.begin()) { + Serial.println(F("RTC initialization failed")); + flicker(LED_B_PIN, 4, 1000); + return; + } + + if (rtc.lostPower()) { + Serial.println(F("RTC lost power, setting time")); + rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); + flicker(LED_B_PIN, 4, 500); + } + + // Initialize SD card + pinMode(SD_CS_PIN, OUTPUT); + digitalWrite(SD_CS_PIN, HIGH); // Ensure SS pin is high initially + + if (!sd.begin(SD_CONFIG)) { + Serial.println(F("SD card initialization failed")); + flicker(LED_B_PIN, 2, 1000); + return; + } + + // Initialize Modbus + pinMode(DE_RE_PIN, OUTPUT); + digitalWrite(DE_RE_PIN, LOW); // Start in receive mode + + node.begin(SLAVE_ID, Serial1); + node.preTransmission(preTransmission); + node.postTransmission(postTransmission); + + flicker(LED_B_PIN, 10, 100); // Setup success indicator + digitalWrite(LED_B_PIN, LOW); + booted = true; +} + +// ==== RS485 CONTROL FUNCTIONS ==== +void preTransmission() { + digitalWrite(DE_RE_PIN, HIGH); + digitalWrite(LED_A_PIN, HIGH); + delayMicroseconds(50); // Give RS485 time to switch +} + +void postTransmission() { + delayMicroseconds(50); // Give RS485 time to switch + digitalWrite(DE_RE_PIN, LOW); + digitalWrite(LED_A_PIN, LOW); +} + +// ==== FILE OPERATIONS ==== +String getFilename() { + DateTime now = rtc.now(); + char buffer[20]; + sprintf(buffer, "pm8k_%d%02d%02d.csv", now.year(), now.month(), now.day()); + return String(buffer); +} + +void writeDateTime() { + DateTime now = rtc.now(); + 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(','); +} + +// ==== MODBUS OPERATIONS ==== +float readRegisterWithRetry(uint16_t addr, uint8_t regtype) { + for (uint8_t retry = 0; retry < MAX_RETRIES; retry++) { + delay(5); // Short delay between attempts + uint8_t result = node.readHoldingRegisters(addr - 1, 2); + + if (result == node.ku8MBSuccess) { + switch(regtype) { + case 1: // Integer + return node.getResponseBuffer(0); + case 2: // Float + return getRegisterFloat(node.getResponseBuffer(0), node.getResponseBuffer(1)); + case 0: // 32-bit Integer + return getRegisterInt32(node.getResponseBuffer(0), node.getResponseBuffer(1)); + case 5: // String + String str; + for (uint8_t j = 0; j < 20; j++) { + uint8_t v = node.getResponseBuffer(j); + if (v == 0) break; + str += (char)v; + } + return str.toFloat(); + } + } + + Serial.print(F("Read error at register ")); + Serial.print(addr); + Serial.print(F(", attempt ")); + Serial.println(retry + 1); + + delay(50 * (retry + 1)); // Increasing delay between retries + flicker(LED_B_PIN, 1, 50); + } + return ERROR_VALUE; +} + +// ==== MAIN LOOP ==== +void loop() { + if (!booted) { + Serial.println(F("Boot failed, retrying in 10 seconds")); + delay(10000); + return; + } + + if (millis() - lastRefreshTime >= 1000) { + lastRefreshTime += 1000; + String filename = getFilename(); + uint8_t errorCount = 0; + + if (!dataFile.open(filename.c_str(), FILE_WRITE)) { + Serial.println(F("Failed to open file")); + flicker(LED_B_PIN, 6, 500); + return; + } + + if (!headerWritten) { + dataFile.print(F("\nDate Time,")); + const uint16_t totalReg = sizeof(registers) / sizeof(registers[0]); + for (uint16_t i = 0; i < totalReg; i++) { + const uint16_t regaddr = pgm_read_word(®isters[i].regaddr); + dataFile.print(F("@")); + dataFile.print(regaddr); + dataFile.print(F(",")); + } + headerWritten = true; + flicker(LED_A_PIN, 3, 100); + } + + writeDateTime(); + + // Read all registers + const uint16_t totalReg = sizeof(registers) / sizeof(registers[0]); + for (uint16_t 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); + + if (regaddr > 0) { + float value = readRegisterWithRetry(regaddr, regtype); + if (value == ERROR_VALUE) { + errorCount++; + if (errorCount > 5) { + Serial.println(F("Too many errors, aborting cycle")); + dataFile.close(); + return; + } + } + dataFile.print(value); + dataFile.print(F(",")); + } + } + + dataFile.close(); + + if (errorCount > 0) { + flicker(LED_B_PIN, errorCount, 200); + } else { + flicker(LED_A_PIN, 1, 100); + } + } +} \ No newline at end of file diff --git a/firmware/mega/mega-sd-mb-pm8000/mega-sd-mb-pm8000.md b/firmware/mega/mega-sd-mb-pm8000/mega-sd-mb-pm8000.md new file mode 100644 index 0000000..a1fe715 --- /dev/null +++ b/firmware/mega/mega-sd-mb-pm8000/mega-sd-mb-pm8000.md @@ -0,0 +1,135 @@ +# Modbus Reading for Schneider PowerLogic PM8000 + +This is a specification and implementation of the Arduino-based Modbus data logger for the Schneider PowerLogic PM8000. +This software is designed for Vivarox EMS and only Vivarox has right to use and modify this software. + +## Arduino Implementation: + +This project uses an Arduino MEGA 2560 to connect to Modbus devices, read information, and log it onto an SD card with timestamps. The MEGA 2560 is particularly well-suited for this project due to its increased memory capacity and multiple hardware serial ports. + +### Hardware needed: + +1. Arduino Board + Required: Arduino MEGA 2560 (selected for its 256KB flash memory, 8KB SRAM, and multiple hardware serial ports) + - [Arduino MEGA @ R377.20](https://www.robotics.org.za/MEGA-16U2?search=Arduino%20MEGA%202560) + +2. RS485 to TTL Module + Allows communication between the Arduino and Modbus devices using the RS485 protocol. + - [RS485 Module (TTL -> RS485) @ R25.30](https://www.robotics.org.za/RS485-MOD) + - [MAX485 Bus Transceiver (4 Pack) @ R16.00](https://www.robotics.org.za/MAX485-DIP?search=MAX485) + +3. SD Card Module + Allows the Arduino to read from and write data to an SD card. + - [Micro SD Card Module @ R25.00](https://www.diyelectronics.co.za/store/memory/512-micro-sd-card-module.html?srsltid=AfmBOoptww8c6kx53xbZWiP2_C_qOE3r9xinyoCO-AZHrZkNQiyxU17c) + +4. RTC Module + To keep track of the current date and time, even when the Arduino is powered off. + - [DS3231 Real Time Clock Module @ R55.20](https://www.robotics.org.za/DS3231-MOD?search=DS3231) + +5. Power Supply + To power the Arduino and connected peripherals. + - [AC Adapter 9V with barrel jack @ R60](https://www.robotics.org.za/AC-9V-2A-2155?search=%20Power%20Supply) + +6. LED Indicators + Two LEDs for status indication (not included in original cost estimate). + +### Wiring for MEGA 2560 + +#### RS485 Module to Arduino MEGA: +1. RO (Receiver Output) to MEGA RX1 (pin 19) - Using Hardware Serial1 +2. DI (Driver Input) to MEGA TX1 (pin 18) - Using Hardware Serial1 +3. DE (Driver Enable) & RE (Receiver Enable) to MEGA digital pin 4 +4. VCC to 5V on MEGA +5. GND to GND on MEGA +6. A & B (RS485 differential pair) to Modbus device + +#### SD Card Module to Arduino MEGA: +1. VCC to 5V on MEGA +2. GND to GND on MEGA +3. MOSI to MOSI (pin 51) +4. MISO to MISO (pin 50) +5. SCK to SCK (pin 52) +6. CS (Chip Select) to digital pin 53 + +#### RTC Module to Arduino MEGA: +1. VCC to 5V on the MEGA +2. GND to GND on the MEGA +3. SDA to SDA (pin 20) +4. SCL to SCL (pin 21) + +#### LED Indicators: +1. LED A to digital pin 3 +2. LED B to digital pin 5 + +### Software + +- Modbus Library: ModbusMaster +- SD Library: SdFat (more advanced than the standard SD library) +- RTC Library: RTClib by Adafruit + + +### Implementation Details + +1. Modbus Configuration: + - Slave ID: 1 + - Baud Rate: 9600 + - Register map: Defined in separate "register_map.h" file + - Using Hardware Serial1 for improved reliability + +2. Data Logging: + - Frequency: Readings taken every second + - File Format: CSV (Comma-Separated Values) + - Filename: "log_YYYYMMDD.csv" (generated daily based on current date) + - Data Structure: Timestamp, followed by register values + - Header Row: Includes register addresses for easy identification + - Larger buffer sizes possible due to MEGA's increased memory + +3. Register Types Supported: + - Float (32-bit) + - Integer (32-bit) + - Long (64-bit) + - String (up to 20 characters) + - Multiple register reads supported simultaneously due to larger memory + +4. Error Handling and Status Indication: + - LED A: Indicates successful data writing and transmission + - LED B: Indicates errors (e.g., SD card issues, RTC problems, Modbus communication errors) + - Serial output for debugging (115200 baud possible due to hardware serial) + +5. Special Features: + - Automatic creation of new log file on date change + - Header row written only once per file + - Robust error handling for SD card, RTC, and Modbus communication + - Support for larger register maps due to increased memory + - Possibility to implement multiple Modbus device communication using additional hardware serial ports + +### Programming Workflow + +1. Initialize hardware (RTC, SD card, RS485 module) +2. Set up Modbus communication parameters using Hardware Serial1 +3. Enter main loop: + - Read current time from RTC + - Read data from Modbus registers (larger batches possible) + - Write timestamped data to SD card + - Handle any errors and provide status indication via LEDs + - Delay for 1 second before next reading + +## MEGA-Specific Advantages + +- More memory allows reading more registers simultaneously +- Hardware serial ports provide more reliable communication +- Additional I/O pins available for expansion +- Possibility to monitor multiple Modbus devices using different serial ports +- Larger program space allows for more complex error handling and data processing +- No need to be selective about registers due to memory constraints +- Can implement additional features like local display or network connectivity + +## Best Practices + +- Use Hardware Serial1 (pins 18/19) for primary Modbus communication +- Additional Modbus devices can use Serial2 (pins 16/17) or Serial3 (pins 14/15) +- Take advantage of the extra memory to implement robust error checking +- Consider using the additional I/O pins for status displays or control interfaces +- You can include all registers from your register map without memory concerns +- Consider implementing a circular buffer for temporary data storage + diff --git a/firmware/modbus-SIM808-pm8000/register_map_pm8000.h b/firmware/mega/mega-sd-mb-pm8000/register_map.h similarity index 100% rename from firmware/modbus-SIM808-pm8000/register_map_pm8000.h rename to firmware/mega/mega-sd-mb-pm8000/register_map.h diff --git a/firmware/modbus-SIM808-pm8000/util.h b/firmware/mega/mega-sd-mb-pm8000/util.h similarity index 100% rename from firmware/modbus-SIM808-pm8000/util.h rename to firmware/mega/mega-sd-mb-pm8000/util.h diff --git a/firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.ino b/firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.ino new file mode 100644 index 0000000..e63c30a --- /dev/null +++ b/firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.ino @@ -0,0 +1,356 @@ +#include // Library for I2C communication (used by RTC) +#include // Library for Real Time Clock +#include // Library for Modbus communication +#include "util.h" // Custom utility functions +#include "register_map.h" // Map of Modbus registers to read +#include // Library for SPI communication (used by SD card) +#include // Enhanced SD card library + +// ==== PIN CONNECTIONS AND SETTINGS ==== +/* +Physical Connections Guide: + +SD CARD MODULE: +- CS (Chip Select) -> Arduino MEGA pin 53 +- MOSI -> Arduino MEGA pin 51 +- MISO -> Arduino MEGA pin 50 +- SCK -> Arduino MEGA pin 52 +- VCC -> 5V +- GND -> GND + +RS485 MODULE: +- DI (Data In) -> Arduino MEGA TX1 (Pin 18) +- RO (Receive Out) -> Arduino MEGA RX1 (Pin 19) +- DE & RE (Data/Receive Enable) -> Arduino MEGA Pin 4 +- VCC -> 5V +- GND -> GND +- A & B -> To Modbus device (polarity sensitive) + +RTC MODULE (DS3231): +- SDA -> Arduino MEGA Pin 20 +- SCL -> Arduino MEGA Pin 21 +- VCC -> 5V +- GND -> GND + +STATUS LEDs: +- LED A (Activity) -> Arduino MEGA Pin 3 (blinks during normal operation) +- LED B (Error) -> Arduino MEGA Pin 5 (blinks during errors) +*/ + +// ==== CONFIGURATION SETTINGS ==== +#define SD_CS_PIN 53 // SD card chip select pin (uses MEGA's default SS pin) +#define DE_RE_PIN 4 // Controls RS485 direction (transmit/receive switching) +#define SLAVE_ID 1 // Modbus device address (change to match your device) +#define SERIAL_BAUDRATE 115200 // Speed for debug messages via USB + +#define MODBUS_SERIAL_BAUDRATE 9600 // Speed for Modbus communication +#define LED_A_PIN 3 // Activity LED (blinks during normal operation) +#define LED_B_PIN 5 // Error LED (blinks when problems occur) +#define MAX_RETRIES 1 // Number of times to retry failed readings +#define ERROR_VALUE -999.99 // Value used to indicate reading errors + +// ==== SD CARD CONFIGURATION ==== +// Sets up the SD card for optimal performance with MEGA +#define SPI_CLOCK SD_SCK_MHZ(16) // //50 (fast) //16 (half) //4 (slow) SD card speed (50MHz) +// Choose the best SD card mode based on hardware capabilities +#if HAS_SDIO_CLASS +#define SD_CONFIG SdioConfig(FIFO_SDIO) // Use SDIO if available (faster) +#elif ENABLE_DEDICATED_SPI +#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK) // Dedicated SPI bus +#else +#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK) // Shared SPI bus +#endif + +// ==== GLOBAL OBJECTS ==== +RTC_DS3231 rtc; // Real Time Clock object for timekeeping +SdFat32 sd; // SD card object for file operations +File dataFile; // File object for data logging +ModbusMaster node; // Modbus communication object + +// ==== GLOBAL VARIABLES ==== +unsigned long lastRefreshTime = 0; // Tracks time between readings +bool headerWritten = false; // Tracks if CSV header has been written +bool booted = false; // Tracks if setup completed successfully + +// ==== UTILITY FUNCTIONS ==== +// Makes an LED blink a specified number of times +// pin: which LED to blink +// times: how many blinks +// speed: how fast to blink (in milliseconds) +void flicker(uint8_t pin, uint8_t times, uint16_t speed) { + while(times--) { + delay(speed); + digitalWrite(pin, HIGH); // Turn LED on + delay(speed); + digitalWrite(pin, LOW); // Turn LED off + } +} + +// ==== SETUP FUNCTION ==== +// Runs once when the Arduino starts or resets +// Initializes all hardware and prepares for operation +void setup() { + booted = false; // Mark as not ready + + // Setup status LEDs + pinMode(LED_A_PIN, OUTPUT); + pinMode(LED_B_PIN, OUTPUT); + digitalWrite(LED_A_PIN, LOW); // Activity LED off + digitalWrite(LED_B_PIN, HIGH); // Error LED on until setup complete + + // Start serial communication for debugging via USB + Serial.begin(SERIAL_BAUDRATE); + Serial.println(F("Startup \n")); + + // Start serial communication for Modbus (using hardware Serial1) + Serial1.begin(MODBUS_SERIAL_BAUDRATE); + + // Initialize Real Time Clock + if (!rtc.begin()) { + Serial.println(F("Couldn't find RTC\n")); + flicker(LED_B_PIN, 4, 1000); // Error pattern: 4 slow blinks + digitalWrite(LED_B_PIN, HIGH); + digitalWrite(LED_A_PIN, HIGH); + return; // Stop if RTC fails + } + + // Check if RTC lost power and reset time if needed + if (rtc.lostPower()) { + Serial.println(F("RTC lost power, let's set the time!\n")); + rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Set to compile time + flicker(LED_B_PIN, 4, 500); // Warning pattern: 4 medium blinks + } + + // Initialize SD card + pinMode(SD_CS_PIN, OUTPUT); + // Set pin to high, hopefully fix Mega issue + digitalWrite(SD_CS_PIN, HIGH); + + if (!sd.begin(SD_CONFIG)) { + flicker(LED_B_PIN, 2, 1000); // Error pattern: 2 slow blinks + digitalWrite(LED_B_PIN, HIGH); + sd.initErrorHalt(&Serial); + return; // Stop if SD card fails + } + + // Setup RS485 communication direction control + pinMode(DE_RE_PIN, OUTPUT); + digitalWrite(DE_RE_PIN, LOW); // Start in receive mode + + // Initialize Modbus communication + node.begin(SLAVE_ID, Serial1); // Using Hardware Serial1 for Modbus + node.preTransmission(preTransmission); // Set callbacks for RS485 direction control + node.postTransmission(postTransmission); + + flicker(LED_B_PIN, 10, 100); // Success pattern: 10 quick blinks + digitalWrite(LED_B_PIN, LOW); // Turn off error LED + booted = true; // Mark setup as complete +} + +// ==== RS485 CONTROL FUNCTIONS ==== +// Called before Modbus transmission begins +void preTransmission() { + digitalWrite(DE_RE_PIN, HIGH); // Enable transmitter + digitalWrite(LED_A_PIN, HIGH); // Turn on activity LED +} + +// Called after Modbus transmission completes +void postTransmission() { + digitalWrite(DE_RE_PIN, LOW); // Enable receiver + digitalWrite(LED_A_PIN, LOW); // Turn off activity LED +} + +// ==== FILE OPERATIONS ==== +// Writes the current date and time to the CSV file +void writeDateTime(File &file) { + DateTime now = rtc.now(); // Get current time from RTC + file.print('\n'); // Start new line + // Write date and time in format: YYYY-MM-DD HH:MM:SS, + file.print(now.year(), DEC); + file.print('-'); + file.print(now.month(), DEC); + file.print('-'); + file.print(now.day(), DEC); + file.print(' '); + file.print(now.hour(), DEC); + file.print(':'); + file.print(now.minute(), DEC); + file.print(':'); + file.print(now.second(), DEC); + file.print(','); +} + +// Generates filename based on current date (format: pm8k_YYYYMMDD.csv) +void getFilename(char* buffer) { + DateTime now = rtc.now(); + sprintf(buffer, "log_%d%02d%02d.csv", now.year(), now.month(), now.day()); +} + +// ==== MODBUS OPERATIONS ==== +// Reads a Modbus register with retry capability +// addr: register address to read +// regtype: type of register (1=int, 2=float, 3=long) +// Returns: register value or ERROR_VALUE if failed +float readRegisterWithRetry(uint16_t addr, uint8_t regtype) { + for(uint8_t retry = 0; retry < MAX_RETRIES; retry++) { + delay(5); // Short delay between attempts + uint8_t result = node.readHoldingRegisters(addr - 1, 2); // Read register + + if(result == node.ku8MBSuccess) { + // Convert register value based on type + switch(regtype) { + case 1: // Integer + return node.getResponseBuffer(0); + case 2: // Float + return getRegisterFloat(node.getResponseBuffer(0), node.getResponseBuffer(1)); + case 3: // Long + return getRegisterInt64(node.getResponseBuffer(0), node.getResponseBuffer(1), + node.getResponseBuffer(2), node.getResponseBuffer(3)); + } + } + + // Log error if read failed + Serial.print(F("Read error at register ")); + Serial.print(addr); + Serial.print(F(", attempt ")); + Serial.print(retry + 1); + Serial.print(F(" of ")); + Serial.print(MAX_RETRIES); + Serial.print(F(", error code: ")); + Serial.println(result); + + delay(5 * (retry + 1)); // Increasing delay between retries + flicker(LED_B_PIN, 1, 50); // Quick error blink + } + return ERROR_VALUE; // Return error value if all retries failed +} + +// Writes the CSV header row if it hasn't been written yet +void writeHeader() { + if (!headerWritten) { + dataFile.print("\nDate Time,"); + // Write register addresses as column headers + const uint16_t totalReg = sizeof(registers) / sizeof(registers[0]); + for (uint16_t i = 0; i < totalReg; i++) { + const uint16_t regaddr = pgm_read_word(®isters[i].regaddr); + dataFile.print("@"); + dataFile.print(regaddr); + dataFile.print(","); + } + headerWritten = true; + flicker(LED_A_PIN, 50, 10); // Success pattern: 50 quick blinks + } +} + +// ==== MAIN PROGRAM LOOP ==== +void loop() { + // If setup failed, wait and try again + if (!booted) { + delay(10000); // Wait 10 seconds + digitalWrite(LED_A_PIN, LOW); + return; + } + + // Check if it's time for next reading (every 1000ms) + if (millis() - lastRefreshTime >= 1000) { + lastRefreshTime += 1000; + + // Create new file for today's date + char filename[20]; + getFilename(filename); + + // Try to open the data file + if (!dataFile.open(filename, FILE_WRITE)) { + flicker(LED_B_PIN, 6, 500); // Error pattern: 6 medium blinks + return; + } + + // Write header if needed and timestamp + writeHeader(); + writeDateTime(dataFile); + + // Initialize variables for reading registers + const uint16_t totalReg = sizeof(registers) / sizeof(registers[0]); + float baseValues[4] = {ERROR_VALUE, ERROR_VALUE, ERROR_VALUE, ERROR_VALUE}; + uint8_t errorCount = 0; + + // Read and process all registers + for (uint16_t i = 0; i < totalReg; i++) { + // Get register information + const uint16_t regaddr = pgm_read_word(®isters[i].regaddr); + const uint8_t regtype = pgm_read_word(®isters[i].regtype); + const float scale = pgm_read_float(®isters[i].scale); + float value = ERROR_VALUE; + + // Read basic register types + if (regtype <= 3 && regaddr > 0) { + value = readRegisterWithRetry(regaddr, regtype); + if (value == ERROR_VALUE) { + errorCount++; + if (errorCount > 5) { // Too many errors, abort + dataFile.close(); + flicker(LED_B_PIN, 10, 100); // Error pattern: 10 quick blinks + return; + } + } + if (i < 4) baseValues[i] = value; // Store first 4 values for calculations + } else { + // Check if we have valid base values for calculations + bool validBase = true; + for(uint8_t j = 0; j < 4; j++) { + if (baseValues[j] == ERROR_VALUE) { + validBase = false; + break; + } + } + + // Calculate derived values if base values are valid + if (validBase) { + switch(regtype) { + case 4: + value = calculateStatusWord(baseValues); + break; + case 5: + value = calculateThermal(baseValues); + break; + case 6: + value = calculatePower(baseValues); + break; + case 7: + value = calculateRPM(baseValues); + break; + } + } + } + + // Apply scaling factor if value is valid + if (value != ERROR_VALUE) { + value *= scale; + } + // Write value to file + dataFile.print(value); + dataFile.print(','); + } + + // Close file after writing + dataFile.close(); + + // Report status + if (errorCount > 0) { + Serial.print(F("Cycle completed with ")); + Serial.print(errorCount); + Serial.println(F(" errors")); + flicker(LED_B_PIN, errorCount, 200); // Error pattern: blink count = error count + } else { + Serial.println(F("Cycle completed successfully")); + flicker(LED_A_PIN, 4, 100); // Success pattern: 4 quick blinks + } + + // Abort if too many errors + if (errorCount > 5) { + Serial.println(F("Too many errors, aborting cycle")); + dataFile.close(); + return; + } + } +} \ No newline at end of file diff --git a/firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.md b/firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.md new file mode 100644 index 0000000..89ff4fb --- /dev/null +++ b/firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.md @@ -0,0 +1,135 @@ +# Modbus Reading for Generic VSD Device - MEGA Implementation + +This is a specification and implementation of the Arduino MEGA 2560-based Modbus data logger for a Generic VSD Device. +This software is designed for Vivarox EMS and only Vivarox has right to use and modify this software. + +## Arduino Implementation: + +This project uses an Arduino MEGA 2560 to connect to Modbus devices, read information, and log it onto an SD card with timestamps. The MEGA 2560 is particularly well-suited for this project due to its increased memory capacity and multiple hardware serial ports. + +### Hardware needed: + +1. Arduino Board + Required: Arduino MEGA 2560 (selected for its 256KB flash memory, 8KB SRAM, and multiple hardware serial ports) + - [Arduino MEGA @ R377.20](https://www.robotics.org.za/MEGA-16U2?search=Arduino%20MEGA%202560) + +2. RS485 to TTL Module + Allows communication between the Arduino and Modbus devices using the RS485 protocol. + - [RS485 Module (TTL -> RS485) @ R25.30](https://www.robotics.org.za/RS485-MOD) + - [MAX485 Bus Transceiver (4 Pack) @ R16.00](https://www.robotics.org.za/MAX485-DIP?search=MAX485) + +3. SD Card Module + Allows the Arduino to read from and write data to an SD card. + - [Micro SD Card Module @ R25.00](https://www.diyelectronics.co.za/store/memory/512-micro-sd-card-module.html?srsltid=AfmBOoptww8c6kx53xbZWiP2_C_qOE3r9xinyoCO-AZHrZkNQiyxU17c) + +4. RTC Module + To keep track of the current date and time, even when the Arduino is powered off. + - [DS3231 Real Time Clock Module @ R55.20](https://www.robotics.org.za/DS3231-MOD?search=DS3231) + +5. Power Supply + To power the Arduino and connected peripherals. + - [AC Adapter 9V with barrel jack @ R60](https://www.robotics.org.za/AC-9V-2A-2155?search=%20Power%20Supply) + +6. LED Indicators + Two LEDs for status indication (not included in original cost estimate). + +### Wiring for MEGA 2560 + +#### RS485 Module to Arduino MEGA: +1. RO (Receiver Output) to MEGA RX1 (pin 19) - Using Hardware Serial1 +2. DI (Driver Input) to MEGA TX1 (pin 18) - Using Hardware Serial1 +3. DE (Driver Enable) & RE (Receiver Enable) to MEGA digital pin 4 +4. VCC to 5V on MEGA +5. GND to GND on MEGA +6. A & B (RS485 differential pair) to Modbus device + +#### SD Card Module to Arduino MEGA: +1. VCC to 5V on MEGA +2. GND to GND on MEGA +3. MOSI to MOSI (pin 51) +4. MISO to MISO (pin 50) +5. SCK to SCK (pin 52) +6. CS (Chip Select) to digital pin 53 + +#### RTC Module to Arduino MEGA: +1. VCC to 5V on the MEGA +2. GND to GND on the MEGA +3. SDA to SDA (pin 20) +4. SCL to SCL (pin 21) + +#### LED Indicators: +1. LED A to digital pin 3 +2. LED B to digital pin 5 + +### Software + +- Modbus Library: ModbusMaster +- SD Library: SdFat (more advanced than the standard SD library) +- RTC Library: RTClib by Adafruit + + +### Implementation Details + +1. Modbus Configuration: + - Slave ID: 1 + - Baud Rate: 9600 + - Register map: Defined in separate "register_map.h" file + - Using Hardware Serial1 for improved reliability + +2. Data Logging: + - Frequency: Readings taken every second + - File Format: CSV (Comma-Separated Values) + - Filename: "log_YYYYMMDD.csv" (generated daily based on current date) + - Data Structure: Timestamp, followed by register values + - Header Row: Includes register addresses for easy identification + - Larger buffer sizes possible due to MEGA's increased memory + +3. Register Types Supported: + - Float (32-bit) + - Integer (32-bit) + - Long (64-bit) + - String (up to 20 characters) + - Multiple register reads supported simultaneously due to larger memory + +4. Error Handling and Status Indication: + - LED A: Indicates successful data writing and transmission + - LED B: Indicates errors (e.g., SD card issues, RTC problems, Modbus communication errors) + - Serial output for debugging (115200 baud possible due to hardware serial) + +5. Special Features: + - Automatic creation of new log file on date change + - Header row written only once per file + - Robust error handling for SD card, RTC, and Modbus communication + - Support for larger register maps due to increased memory + - Possibility to implement multiple Modbus device communication using additional hardware serial ports + +### Programming Workflow + +1. Initialize hardware (RTC, SD card, RS485 module) +2. Set up Modbus communication parameters using Hardware Serial1 +3. Enter main loop: + - Read current time from RTC + - Read data from Modbus registers (larger batches possible) + - Write timestamped data to SD card + - Handle any errors and provide status indication via LEDs + - Delay for 1 second before next reading + +## MEGA-Specific Advantages + +- More memory allows reading more registers simultaneously +- Hardware serial ports provide more reliable communication +- Additional I/O pins available for expansion +- Possibility to monitor multiple Modbus devices using different serial ports +- Larger program space allows for more complex error handling and data processing +- No need to be selective about registers due to memory constraints +- Can implement additional features like local display or network connectivity + +## Best Practices + +- Use Hardware Serial1 (pins 18/19) for primary Modbus communication +- Additional Modbus devices can use Serial2 (pins 16/17) or Serial3 (pins 14/15) +- Take advantage of the extra memory to implement robust error checking +- Consider using the additional I/O pins for status displays or control interfaces +- You can include all registers from your register map without memory concerns +- Consider implementing a circular buffer for temporary data storage + diff --git a/firmware/modbus-sd-VSD-generic-alt/register_map_vsd.h b/firmware/mega/mega-sd-mb-vsd-generic/register_map.h similarity index 100% rename from firmware/modbus-sd-VSD-generic-alt/register_map_vsd.h rename to firmware/mega/mega-sd-mb-vsd-generic/register_map.h diff --git a/firmware/modbus-sd-VSD-generic-alt/util.h b/firmware/mega/mega-sd-mb-vsd-generic/util.h similarity index 100% rename from firmware/modbus-sd-VSD-generic-alt/util.h rename to firmware/mega/mega-sd-mb-vsd-generic/util.h diff --git a/firmware/mega/pinout.md b/firmware/mega/pinout.md new file mode 100644 index 0000000..a1fb14a --- /dev/null +++ b/firmware/mega/pinout.md @@ -0,0 +1,52 @@ +ARDUINO MEGA PINOUT +================== + +DIGITAL PINS (Basic, D0-D13) +--------------------------- +D0 - RX0 (Serial) +D1 - TX0 (Serial) +D2 - Digital +D3 - PWM +D4 - Digital +D5 - PWM +D6 - PWM +D7 - Digital +D8 - Digital +D9 - PWM +D10 - PWM +D11 - PWM +D12 - Digital +D13 - Digital/LED + +COMMUNICATION PINS +---------------- +D14 - TX3 D15 - RX3 +D16 - TX2 D17 - RX2 +D18 - TX1 D19 - RX1 +D20 - SDA (I2C) D21 - SCL (I2C) + +ADDITIONAL DIGITAL PINS +--------------------- +D22-D53 - Digital I/O +PWM Pins: 2-13, 44-46 + +ANALOG PINS (A0-A15) +------------------- +A0-A15 - Analog Inputs +(All can be used as digital I/O) + +SPI PINS +-------- +50 - MISO +51 - MOSI +52 - SCK +53 - SS + +POWER +----- +VIN - Input Voltage (7-12V) +GND - Ground (multiple pins) +5V - 5V Output +3.3V - 3.3V Output +AREF - Analog Reference +RST - Reset \ No newline at end of file diff --git a/firmware/modbus-SIM808-pm8000/modbus-SIM808-pm8000.ino b/firmware/uno/modbus-SIM808-pm8000/modbus-SIM808-pm8000.ino similarity index 100% rename from firmware/modbus-SIM808-pm8000/modbus-SIM808-pm8000.ino rename to firmware/uno/modbus-SIM808-pm8000/modbus-SIM808-pm8000.ino diff --git a/firmware/modbus-SIM808-pm8000/modbus-SIM808-pm8000.md b/firmware/uno/modbus-SIM808-pm8000/modbus-SIM808-pm8000.md similarity index 100% rename from firmware/modbus-SIM808-pm8000/modbus-SIM808-pm8000.md rename to firmware/uno/modbus-SIM808-pm8000/modbus-SIM808-pm8000.md diff --git a/firmware/modbus-sd-pm8000/register_map_pm8000.h b/firmware/uno/modbus-SIM808-pm8000/register_map_pm8000.h similarity index 100% rename from firmware/modbus-sd-pm8000/register_map_pm8000.h rename to firmware/uno/modbus-SIM808-pm8000/register_map_pm8000.h diff --git a/firmware/modbus-sd-VSD-generic/util.h b/firmware/uno/modbus-SIM808-pm8000/util.h similarity index 100% rename from firmware/modbus-sd-VSD-generic/util.h rename to firmware/uno/modbus-SIM808-pm8000/util.h diff --git a/firmware/modbus-sd-VSD-generic/modbus-sd-VSD-generic.ino b/firmware/uno/modbus-sd-VSD-generic/modbus-sd-VSD-generic.ino similarity index 100% rename from firmware/modbus-sd-VSD-generic/modbus-sd-VSD-generic.ino rename to firmware/uno/modbus-sd-VSD-generic/modbus-sd-VSD-generic.ino diff --git a/firmware/modbus-sd-VSD-generic-alt/modbus-sd-vsd.md b/firmware/uno/modbus-sd-VSD-generic/modbus-sd-vsd.md similarity index 100% rename from firmware/modbus-sd-VSD-generic-alt/modbus-sd-vsd.md rename to firmware/uno/modbus-sd-VSD-generic/modbus-sd-vsd.md diff --git a/firmware/modbus-sd-VSD-generic/register_map_vsd.h b/firmware/uno/modbus-sd-VSD-generic/register_map_vsd.h similarity index 100% rename from firmware/modbus-sd-VSD-generic/register_map_vsd.h rename to firmware/uno/modbus-sd-VSD-generic/register_map_vsd.h diff --git a/firmware/modbus-sd-pm8000/util.h b/firmware/uno/modbus-sd-VSD-generic/util.h similarity index 100% rename from firmware/modbus-sd-pm8000/util.h rename to firmware/uno/modbus-sd-VSD-generic/util.h diff --git a/firmware/modbus-sd-pm8000/data/pm8k_2024923.csv b/firmware/uno/modbus-sd-pm8000/data/pm8k_2024923.csv similarity index 100% rename from firmware/modbus-sd-pm8000/data/pm8k_2024923.csv rename to firmware/uno/modbus-sd-pm8000/data/pm8k_2024923.csv diff --git a/firmware/modbus-sd-pm8000/manual.md b/firmware/uno/modbus-sd-pm8000/manual.md similarity index 100% rename from firmware/modbus-sd-pm8000/manual.md rename to firmware/uno/modbus-sd-pm8000/manual.md diff --git a/firmware/modbus-sd-pm8000/manual.pdf b/firmware/uno/modbus-sd-pm8000/manual.pdf similarity index 100% rename from firmware/modbus-sd-pm8000/manual.pdf rename to firmware/uno/modbus-sd-pm8000/manual.pdf diff --git a/firmware/modbus-sd-pm8000/modbus-sd-pm8000.ino b/firmware/uno/modbus-sd-pm8000/modbus-sd-pm8000.ino similarity index 100% rename from firmware/modbus-sd-pm8000/modbus-sd-pm8000.ino rename to firmware/uno/modbus-sd-pm8000/modbus-sd-pm8000.ino diff --git a/firmware/modbus-sd-pm8000/modbus-sd-pm8000.md b/firmware/uno/modbus-sd-pm8000/modbus-sd-pm8000.md similarity index 100% rename from firmware/modbus-sd-pm8000/modbus-sd-pm8000.md rename to firmware/uno/modbus-sd-pm8000/modbus-sd-pm8000.md diff --git a/firmware/modbus-sim800c-pm8000/register_map_pm8000.h b/firmware/uno/modbus-sd-pm8000/register_map_pm8000.h similarity index 100% rename from firmware/modbus-sim800c-pm8000/register_map_pm8000.h rename to firmware/uno/modbus-sd-pm8000/register_map_pm8000.h diff --git a/firmware/modbus-sim800c-pm8000/util.h b/firmware/uno/modbus-sd-pm8000/util.h similarity index 100% rename from firmware/modbus-sim800c-pm8000/util.h rename to firmware/uno/modbus-sd-pm8000/util.h diff --git a/firmware/modbus-sim800c-pm8000/modbus-sim800c-pm8000.ino b/firmware/uno/modbus-sim800c-pm8000/modbus-sim800c-pm8000.ino similarity index 100% rename from firmware/modbus-sim800c-pm8000/modbus-sim800c-pm8000.ino rename to firmware/uno/modbus-sim800c-pm8000/modbus-sim800c-pm8000.ino diff --git a/firmware/modbus-sim800c-pm8000/modbus-sim800c-pm8000.md b/firmware/uno/modbus-sim800c-pm8000/modbus-sim800c-pm8000.md similarity index 100% rename from firmware/modbus-sim800c-pm8000/modbus-sim800c-pm8000.md rename to firmware/uno/modbus-sim800c-pm8000/modbus-sim800c-pm8000.md diff --git a/firmware/uno/modbus-sim800c-pm8000/register_map_pm8000.h b/firmware/uno/modbus-sim800c-pm8000/register_map_pm8000.h new file mode 100644 index 0000000..82a214d --- /dev/null +++ b/firmware/uno/modbus-sim800c-pm8000/register_map_pm8000.h @@ -0,0 +1,602 @@ + +#include + +struct RegisterMap +{ + uint16_t regaddr; + uint8_t regtype; +}; + +const PROGMEM RegisterMap registers[] = { + //{ 30, 5} , // Name: Meter Name (DeviceName) - [30,20] as UTF8 + //{ 50, 5} , // Name: Meter Model (DeviceType) - [50,20] as UTF8 + { 1837, 1} , // Name: Year (Year) - [1837,1] as INT16U + { 1838, 1} , // Name: Month (Month) - [1838,1] as INT16U + { 1839, 1} , // Name: Day (Day) - [1839,1] as INT16U + { 1840, 1} , // Name: Hour (Hour) - [1840,1] as INT16U + { 1841, 1} , // Name: Minute (Minute) - [1841,1] as INT16U + { 2700, 2} , // Name: Active Energy Delivered (Into Load) (kWh del) - [2700,2] as FLOAT32 + { 2702, 2} , // Name: Active Energy Received (Out of Load) (kWh rec) - [2702,2] as FLOAT32 + { 2704, 2} , // Name: Active Energy Delivered + Received (kWh del+rec) - [2704,2] as FLOAT32 + { 2706, 2} , // Name: Active Energy Delivered- Received (kWh del-rec) - [2706,2] as FLOAT32 + { 2708, 2} , // Name: Reactive Energy Delivered (kVARh del) - [2708,2] as FLOAT32 + { 2710, 2} , // Name: Reactive Energy Received (kVARh rec) - [2710,2] as FLOAT32 + { 2712, 2} , // Name: Reactive Energy Delivered + Received (kVARh del+rec) - [2712,2] as FLOAT32 + { 2714, 2} , // Name: Reactive Energy Delivered - Received (kVARh del-rec) - [2714,2] as FLOAT32 + { 2716, 2} , // Name: Apparent Energy Delivered (kVAh del) - [2716,2] as FLOAT32 + { 2718, 2} , // Name: Apparent Energy Received (kVAh rec) - [2718,2] as FLOAT32 + { 2720, 2} , // Name: Apparent Energy Delivered + Received (kVAh del+rec) - [2720,2] as FLOAT32 + { 2722, 2} , // Name: Apparent Energy Delivered - Received (kVAh del-rec) - [2722,2] as FLOAT32 + { 2724, 2} , // Name: Active Energy in Quadrant I (kWh Q1) - [2724,2] as FLOAT32 + { 2726, 2} , // Name: Active Energy in Quadrant II (kWh Q2) - [2726,2] as FLOAT32 + { 2728, 2} , // Name: Active Energy in Quadrant III (kWh Q3) - [2728,2] as FLOAT32 + { 2730, 2} , // Name: Active Energy in Quadrant IV (kWh Q4) - [2730,2] as FLOAT32 + { 2732, 2} , // Name: Reactive Energy in Quadrant I (kVARh Q1) - [2732,2] as FLOAT32 + { 2734, 2} , // Name: Reactive Energy in Quadrant II (kVARh Q2) - [2734,2] as FLOAT32 + { 2736, 2} , // Name: Reactive Energy in Quadrant III (kVARh Q3) - [2736,2] as FLOAT32 + { 2738, 2} , // Name: Reactive Energy in Quadrant IV (kVARh Q4) - [2738,2] as FLOAT32 + { 2740, 2} , // Name: Apparent Energy in Quadrant I (kVAh Q1) - [2740,2] as FLOAT32 + { 2742, 2} , // Name: Apparent Energy in Quadrant II (kVAh Q2) - [2742,2] as FLOAT32 + { 2744, 2} , // Name: Apparent Energy in Quadrant III (kVAh Q3) - [2744,2] as FLOAT32 + { 2746, 2} , // Name: Apparent Energy in Quadrant IV (kVAh Q4) - [2746,2] as FLOAT32 + { 2748, 2} , // Name: Conditional Active Energy Delivered (Into Load) (Cnd kWh del) - [2748,2] as FLOAT32 + { 2750, 2} , // Name: Conditional Active Energy Received (Out of Load) (Cnd kWh rec) - [2750,2] as FLOAT32 + { 2754, 2} , // Name: Active Energy Delivered - Received, Conditional (Cnd kWh d-r) - [2754,2] as FLOAT32 + { 2756, 2} , // Name: Conditional Reactive Energy In (Delivered) (Cnd kVARh del) - [2756,2] as FLOAT32 + { 2758, 2} , // Name: Conditional Reactive Energy Out (Received) (Cnd kVARh rec) - [2758,2] as FLOAT32 + { 2762, 2} , // Name: Reactive Energy Delivered - Received, Conditional (Cnd kVARh d-r) - [2762,2] as FLOAT32 + { 2768, 2} , // Name: Apparent Energy Delivered + Received, Conditional (Cnd kVAh d+r) - [2768,2] as FLOAT32 + { 2772, 2} , // Name: Active Energy Delivered , Last Complete Interval (Inc kWh del C) - [2772,2] as FLOAT32 + { 2774, 2} , // Name: Active Energy Received , Last Complete Interval (Inc kWh rec C) - [2774,2] as FLOAT32 + { 2776, 2} , // Name: Active Energy Delivered - Received , Last Complete Interval (Inc kWh d-r C) - [2776,2] as FLOAT32 + { 2778, 2} , // Name: Reactive Energy Delivered , Last Complete Interval (Inc kVARh del C) - [2778,2] as FLOAT32 + { 2780, 2} , // Name: Reactive Energy Received , Last Complete Interval (Inc kVARh rec C) - [2780,2] as FLOAT32 + { 2782, 2} , // Name: Reactive Energy Delivered - Received , Last Complete Interval (Inc kVARh d-r C) - [2782,2] as FLOAT32 + { 2784, 2} , // Name: Apparent Energy Delivered + Received , Last Complete Interval (Inc kVAh d+r C) - [2784,2] as FLOAT32 + { 2786, 2} , // Name: Active Energy Delivered , Present Interval (Inc kWh del) - [2786,2] as FLOAT32 + { 2788, 2} , // Name: Active Energy Received , Present Interval (Inc kWh rec) - [2788,2] as FLOAT32 + { 2790, 2} , // Name: Active Energy Delivered - Received , Present Interval (Inc kWh d-r) - [2790,2] as FLOAT32 + { 2792, 2} , // Name: Reactive Energy Delivered , Present Interval (Inc kVARh del) - [2792,2] as FLOAT32 + { 2794, 2} , // Name: Reactive Energy Received , Present Interval (Inc kVARh rec) - [2794,2] as FLOAT32 + { 2796, 2} , // Name: Reactive Energy Delivered - Received , Present Interval (Inc kVARh d-r) - [2796,2] as FLOAT32 + { 2798, 2} , // Name: Apparent Energy Delivered + Received , Present Interval (Inc kVAh d+r) - [2798,2] as FLOAT32 + { 2800, 2} , // Name: Active Energy Delivered Interval (kWh del int) - [2800,2] as FLOAT32 + { 2802, 2} , // Name: Active Energy Received Interval (kWh rec int) - [2802,2] as FLOAT32 + { 2804, 2} , // Name: Reactive Energy Delivered Interval (kVARh del int) - [2804,2] as FLOAT32 + { 2806, 2} , // Name: Reactive Energy Received Interval (kVARh rec int) - [2806,2] as FLOAT32 + { 2808, 2} , // Name: Apparent Energy Delivered Interval (kVAh del int) - [2808,2] as FLOAT32 + { 2810, 2} , // Name: Apparent Energy Received Interval (kVAh rec int) - [2810,2] as FLOAT32 + { 3000, 2} , // Name: Current A (I a) - [3000,2] as FLOAT32 + { 3002, 2} , // Name: Current B (I b) - [3002,2] as FLOAT32 + { 3004, 2} , // Name: Current C (I c) - [3004,2] as FLOAT32 + { 3006, 2} , // Name: Current N (I 4) - [3006,2] as FLOAT32 + { 3008, 2} , // Name: Current G (I 5) - [3008,2] as FLOAT32 + //{ 3010, 2} , // Name: Current Avg (I avg) - [3010,2] as FLOAT32 + { 3020, 2} , // Name: Voltage A-B (Vll ab) - [3020,2] as FLOAT32 + { 3022, 2} , // Name: Voltage B-C (Vll bc) - [3022,2] as FLOAT32 + { 3024, 2} , // Name: Voltage C-A (Vll ca) - [3024,2] as FLOAT32 + //{ 3026, 2} , // Name: Voltage L-L Avg (Vll avg) - [3026,2] as FLOAT32 + { 3028, 2} , // Name: Voltage A-N (Vln a) - [3028,2] as FLOAT32 + { 3030, 2} , // Name: Voltage B-N (Vln b) - [3030,2] as FLOAT32 + { 3032, 2} , // Name: Voltage C-N (Vln c) - [3032,2] as FLOAT32 +// { 3036, 2} , // Name: Voltage L-N Avg (Vln avg) - [3036,2] as FLOAT32 + { 3054, 2} , // Name: Active Power A (kW a) - [3054,2] as FLOAT32 + { 3056, 2} , // Name: Active Power B (kW b) - [3056,2] as FLOAT32 + { 3058, 2} , // Name: Active Power C (kW c) - [3058,2] as FLOAT32 + { 3060, 2} , // Name: Active Power Total (kW tot) - [3060,2] as FLOAT32 + { 3062, 2} , // Name: Reactive Power A (kVAR a) - [3062,2] as FLOAT32 + { 3064, 2} , // Name: Reactive Power B (kVAR b) - [3064,2] as FLOAT32 + { 3066, 2} , // Name: Reactive Power C (kVAR c) - [3066,2] as FLOAT32 + { 3068, 2} , // Name: Reactive Power Total (kVAR tot) - [3068,2] as FLOAT32 + { 3070, 2} , // Name: Apparent Power A (kVA a) - [3070,2] as FLOAT32 + { 3072, 2} , // Name: Apparent Power B (kVA b) - [3072,2] as FLOAT32 + { 3074, 2} , // Name: Apparent Power C (kVA c) - [3074,2] as FLOAT32 + { 3076, 2} , // Name: Apparent Power Total (kVA tot) - [3076,2] as FLOAT32 + { 3110, 2} , // Name: Frequency (Freq) - [3110,2] as FLOAT32 +// { 3204, 3} , // Name: Active Energy Delivered (Into Load) (kWh del) - [3204,4] as INT64 +// { 3208, 3} , // Name: Active Energy Received (Out of Load) (kWh rec) - [3208,4] as INT64 +// { 3212, 3} , // Name: Active Energy Delivered + Received (kWh del+rec) - [3212,4] as INT64 +// { 3216, 3} , // Name: Active Energy Delivered- Received (kWh del-rec) - [3216,4] as INT64 +// { 3220, 3} , // Name: Reactive Energy Delivered (kVARh del) - [3220,4] as INT64 +// { 3224, 3} , // Name: Reactive Energy Received (kVARh rec) - [3224,4] as INT64 +// { 3228, 3} , // Name: Reactive Energy Delivered + Received (kVARh del+rec) - [3228,4] as INT64 +// { 3232, 3} , // Name: Reactive Energy Delivered - Received (kVARh del-rec) - [3232,4] as INT64 +// { 3236, 3} , // Name: Apparent Energy Delivered (kVAh del) - [3236,4] as INT64 +// { 3240, 3} , // Name: Apparent Energy Received (kVAh rec) - [3240,4] as INT64 +// { 3244, 3} , // Name: Apparent Energy Delivered + Received (kVAh del+rec) - [3244,4] as INT64 +// { 3248, 3} , // Name: Apparent Energy Delivered - Received (kVAh del-rec) - [3248,4] as INT64 +// { 3256, 3} , // Name: Active Energy in Quadrant I (kWh Q1) - [3256,4] as INT64 +// { 3260, 3} , // Name: Active Energy in Quadrant II (kWh Q2) - [3260,4] as INT64 +// { 3264, 3} , // Name: Active Energy in Quadrant III (kWh Q3) - [3264,4] as INT64 +// { 3268, 3} , // Name: Active Energy in Quadrant IV (kWh Q4) - [3268,4] as INT64 +// { 3272, 3} , // Name: Reactive Energy in Quadrant I (kVARh Q1) - [3272,4] as INT64 +// { 3276, 3} , // Name: Reactive Energy in Quadrant II (kVARh Q2) - [3276,4] as INT64 +// { 3280, 3} , // Name: Reactive Energy in Quadrant III (kVARh Q3) - [3280,4] as INT64 +// { 3284, 3} , // Name: Reactive Energy in Quadrant IV (kVARh Q4) - [3284,4] as INT64 +// { 3288, 3} , // Name: Apparent Energy in Quadrant I (kVAh Q1) - [3288,4] as INT64 +// { 3292, 3} , // Name: Apparent Energy in Quadrant II (kVAh Q2) - [3292,4] as INT64 +// { 3296, 3} , // Name: Apparent Energy in Quadrant III (kVAh Q3) - [3296,4] as INT64 +// { 3300, 3} , // Name: Apparent Energy in Quadrant IV (kVAh Q4) - [3300,4] as INT64 +// { 3358, 3} , // Name: Conditional Active Energy Delivered (Into Load) (Cnd kWh del) - [3358,4] as INT64 +// { 3362, 3} , // Name: Conditional Active Energy Received (Out of Load) (Cnd kWh rec) - [3362,4] as INT64 +// { 3370, 3} , // Name: Active Energy Delivered - Received, Conditional (Cnd kWh d-r) - [3370,4] as INT64 +// { 3374, 3} , // Name: Conditional Reactive Energy In (Delivered) (Cnd kVARh del) - [3374,4] as INT64 +// { 3378, 3} , // Name: Conditional Reactive Energy Out (Received) (Cnd kVARh rec) - [3378,4] as INT64 +// { 3386, 3} , // Name: Reactive Energy Delivered - Received, Conditional (Cnd kVARh d-r) - [3386,4] as INT64 +// { 3398, 3} , // Name: Apparent Energy Delivered + Received, Conditional (Cnd kVAh d+r) - [3398,4] as INT64 +// { 3414, 3} , // Name: Active Energy Delivered , Last Complete Interval (Inc kWh del C) - [3414,4] as INT64 +// { 3418, 3} , // Name: Active Energy Received , Last Complete Interval (Inc kWh rec C) - [3418,4] as INT64 +// { 3422, 3} , // Name: Active Energy Delivered - Received , Last Complete Interval (Inc kWh d-r C) - [3422,4] as INT64 +// { 3426, 3} , // Name: Reactive Energy Delivered , Last Complete Interval (Inc kVARh del C) - [3426,4] as INT64 +// { 3430, 3} , // Name: Reactive Energy Received , Last Complete Interval (Inc kVARh rec C) - [3430,4] as INT64 +// { 3434, 3} , // Name: Reactive Energy Delivered - Received , Last Complete Interval (Inc kVARh d-r C) - [3434,4] as INT64 +// { 3438, 3} , // Name: Apparent Energy Delivered + Received , Last Complete Interval (Inc kVAh d+r C) - [3438,4] as INT64 +// { 3442, 3} , // Name: Active Energy Delivered , Present Interval (Inc kWh del) - [3442,4] as INT64 +// { 3446, 3} , // Name: Active Energy Received , Present Interval (Inc kWh rec) - [3446,4] as INT64 +// { 3450, 3} , // Name: Active Energy Delivered - Received , Present Interval (Inc kWh d-r) - [3450,4] as INT64 +// { 3454, 3} , // Name: Reactive Energy Delivered , Present Interval (Inc kVARh del) - [3454,4] as INT64 +// { 3458, 3} , // Name: Reactive Energy Received , Present Interval (Inc kVARh rec) - [3458,4] as INT64 +// { 3462, 3} , // Name: Reactive Energy Delivered - Received , Present Interval (Inc kVARh d-r) - [3462,4] as INT64 +// { 3466, 3} , // Name: Apparent Energy Delivered + Received , Present Interval (Inc kVAh d+r) - [3466,4] as INT64 +// { 3470, 3} , // Name: Active Energy Delivered Interval (kWh del int) - [3470,4] as INT64 +// { 3474, 3} , // Name: Active Energy Received Interval (kWh rec int) - [3474,4] as INT64 +// { 3478, 3} , // Name: Reactive Energy Delivered Interval (kVARh del int) - [3478,4] as INT64 +// { 3482, 3} , // Name: Reactive Energy Received Interval (kVARh rec int) - [3482,4] as INT64 +// { 3486, 3} , // Name: Apparent Energy Delivered Interval (kVAh del int) - [3486,4] as INT64 +// { 3490, 3} , // Name: Apparent Energy Received Interval (kVAh rec int) - [3490,4] as INT64 +// { 3650, 2} , // Name: Current A Squared Hours (MU Ia^2h) - [3650,2] as FLOAT32 +// { 3652, 2} , // Name: Current B Square Hours (MU Ib^2h) - [3652,2] as FLOAT32 +// { 3654, 2} , // Name: Current C Square Hours (MU Ic^2h) - [3654,2] as FLOAT32 +// { 3656, 2} , // Name: Voltage A-B Square Hours (MU Vll ab^2h) - [3656,2] as FLOAT32 +// { 3658, 2} , // Name: Voltage B-C Square Hours (MU Vll bc^2h) - [3658,2] as FLOAT32 +// { 3660, 2} , // Name: Voltage C-A Square Hours (MU Vll ca^2h) - [3660,2] as FLOAT32 +// { 3668, 2} , // Name: Current A Squared Hours (MU Ia^2h int) - [3668,2] as FLOAT32 +// { 3670, 2} , // Name: Current B Square Hours (MU Ib^2h int) - [3670,2] as FLOAT32 +// { 3672, 2} , // Name: Current C Square Hours (MU Ic^2h int) - [3672,2] as FLOAT32 +// { 3674, 2} , // Name: Voltage A-B Square Hours (MU Vllab^2h int) - [3674,2] as FLOAT32 +// { 3676, 2} , // Name: Voltage B-C Square Hours (MU Vllbc^2h int) - [3676,2] as FLOAT32 +// { 3678, 2} , // Name: Voltage C-A Square Hours (MU Vllca^2h int) - [3678,2] as FLOAT32 +// { 3680, 2} , // Name: Voltage A-N Square Hours (MU Vlna^2h int) - [3680,2] as FLOAT32 +// { 3682, 2} , // Name: Voltage B-N Square Hours (MU Vlnb^2h int) - [3682,2] as FLOAT32 +// { 3684, 2} , // Name: Voltage C-N Square Hours (MU Vlnc^2h int) - [3684,2] as FLOAT32 +// { 4196, 3} , // Name: Active Energy Delivered Rate 1 (kWh del A) - [4196,4] as INT64 +// { 4200, 3} , // Name: Active Energy Delivered Rate 2 (kWh del B) - [4200,4] as INT64 +// { 4204, 3} , // Name: Active Energy Delivered Rate 3 (kWh del C) - [4204,4] as INT64 +// { 4208, 3} , // Name: Active Energy Delivered Rate 4 (kWh del D) - [4208,4] as INT64 +// { 4228, 3} , // Name: Active Energy Received Rate 1 (kWh rec A) - [4228,4] as INT64 +// { 4232, 3} , // Name: Active Energy Received Rate 2 (kWh rec B) - [4232,4] as INT64 +// { 4236, 3} , // Name: Active Energy Received Rate 3 (kWh rec C) - [4236,4] as INT64 +// { 4240, 3} , // Name: Active Energy Received Rate 4 (kWh rec D) - [4240,4] as INT64 +// { 4260, 3} , // Name: Reactive Energy Delivered Rate 1 (kVARh del A) - [4260,4] as INT64 +// { 4264, 3} , // Name: Reactive Energy Delivered Rate 2 (kVARh del B) - [4264,4] as INT64 +// { 4268, 3} , // Name: Reactive Energy Delivered Rate 3 (kVARh del C) - [4268,4] as INT64 +// { 4272, 3} , // Name: Reactive Energy Delivered Rate 4 (kVARh del D) - [4272,4] as INT64 +// { 4292, 3} , // Name: Reactive Energy Received Rate 1 (kVARh rec A) - [4292,4] as INT64 +// { 4296, 3} , // Name: Reactive Energy Received Rate 2 (kVARh rec B) - [4296,4] as INT64 +// { 4300, 3} , // Name: Reactive Energy Received Rate 3 (kVARh rec C) - [4300,4] as INT64 +// { 4304, 3} , // Name: Reactive Energy Received Rate 4 (kVARh rec D) - [4304,4] as INT64 +// { 4324, 3} , // Name: Apparent Energy Delivered Rate 1 (kVAh del A) - [4324,4] as INT64 +// { 4328, 3} , // Name: Apparent Energy Delivered Rate 2 (kVAh del B) - [4328,4] as INT64 +// { 4332, 3} , // Name: Apparent Energy Delivered Rate 3 (kVAh del C) - [4332,4] as INT64 +// { 4336, 3} , // Name: Apparent Energy Delivered Rate 4 (kVAh del D) - [4336,4] as INT64 +// { 4356, 3} , // Name: Apparent Energy Received Rate 1 (kVAh rec A) - [4356,4] as INT64 +// { 4360, 3} , // Name: Apparent Energy Received Rate 2 (kVAh rec B) - [4360,4] as INT64 +// { 4364, 3} , // Name: Apparent Energy Received Rate 3 (kVAh rec C) - [4364,4] as INT64 +// { 4368, 3} , // Name: Apparent Energy Received Rate 4 (kVAh rec D) - [4368,4] as INT64 +// { 4800, 2} , // Name: Active Energy Delivered Rate 1 (kWh del A) - [4800,2] as FLOAT32 +// { 4802, 2} , // Name: Active Energy Delivered Rate 2 (kWh del B) - [4802,2] as FLOAT32 +// { 4804, 2} , // Name: Active Energy Delivered Rate 3 (kWh del C) - [4804,2] as FLOAT32 +// { 4806, 2} , // Name: Active Energy Delivered Rate 4 (kWh del D) - [4806,2] as FLOAT32 +// { 4816, 2} , // Name: Active Energy Received Rate 1 (kWh rec A) - [4816,2] as FLOAT32 +// { 4818, 2} , // Name: Active Energy Received Rate 2 (kWh rec B) - [4818,2] as FLOAT32 +// { 4820, 2} , // Name: Active Energy Received Rate 3 (kWh rec C) - [4820,2] as FLOAT32 +// { 4822, 2} , // Name: Active Energy Received Rate 4 (kWh rec D) - [4822,2] as FLOAT32 +// { 4832, 2} , // Name: Reactive Energy Delivered Rate 1 (kVARh del A) - [4832,2] as FLOAT32 +// { 4834, 2} , // Name: Reactive Energy Delivered Rate 2 (kVARh del B) - [4834,2] as FLOAT32 +// { 4836, 2} , // Name: Reactive Energy Delivered Rate 3 (kVARh del C) - [4836,2] as FLOAT32 +// { 4838, 2} , // Name: Reactive Energy Delivered Rate 4 (kVARh del D) - [4838,2] as FLOAT32 +// { 4848, 2} , // Name: Reactive Energy Received Rate 1 (kVARh rec A) - [4848,2] as FLOAT32 +// { 4850, 2} , // Name: Reactive Energy Received Rate 2 (kVARh rec B) - [4850,2] as FLOAT32 +// { 4852, 2} , // Name: Reactive Energy Received Rate 3 (kVARh rec C) - [4852,2] as FLOAT32 +// { 4854, 2} , // Name: Reactive Energy Received Rate 4 (kVARh rec D) - [4854,2] as FLOAT32 +// { 4864, 2} , // Name: Apparent Energy Delivered Rate 1 (kVAh del A) - [4864,2] as FLOAT32 +// { 4866, 2} , // Name: Apparent Energy Delivered Rate 2 (kVAh del B) - [4866,2] as FLOAT32 +// { 4868, 2} , // Name: Apparent Energy Delivered Rate 3 (kVAh del C) - [4868,2] as FLOAT32 +// { 4870, 2} , // Name: Apparent Energy Delivered Rate 4 (kVAh del D) - [4870,2] as FLOAT32 +// { 4880, 2} , // Name: Apparent Energy Received Rate 1 (kVAh rec A) - [4880,2] as FLOAT32 +// { 4882, 2} , // Name: Apparent Energy Received Rate 2 (kVAh rec B) - [4882,2] as FLOAT32 +// { 4884, 2} , // Name: Apparent Energy Received Rate 3 (kVAh rec C) - [4884,2] as FLOAT32 +// { 4886, 2} , // Name: Apparent Energy Received Rate 4 (kVAh rec D) - [4886,2] as FLOAT32 +// { 14045, 2} , // Name: Pickup Setpoint (Over I 4 High Limit) - [14045,2] as FLOAT32 +// { 14049, 2} , // Name: Dropout Setpoint (Over I 4 Low Limit) - [14049,2] as FLOAT32 +// { 14325, 2} , // Name: Pickup Setpoint (Over kW sd High Limit) - [14325,2] as FLOAT32 +// { 14329, 2} , // Name: Dropout Setpoint (Over kW sd Low Limit) - [14329,2] as FLOAT32 +// { 14585, 2} , // Name: Pickup Setpoint (Over I a High Limit) - [14585,2] as FLOAT32 +// { 14589, 2} , // Name: Dropout Setpoint (Over I a Low Limit) - [14589,2] as FLOAT32 +// { 14605, 2} , // Name: Pickup Setpoint (Over I b High Limit) - [14605,2] as FLOAT32 +// { 14609, 2} , // Name: Dropout Setpoint (Over I b Low Limit) - [14609,2] as FLOAT32 +// { 14625, 2} , // Name: Pickup Setpoint (Over I c High Limit) - [14625,2] as FLOAT32 +// { 14629, 2} , // Name: Dropout Setpoint (Over I c Low Limit) - [14629,2] as FLOAT32 +// { 21000, 2} , // Name: HS Current A (HS I a) - [21000,2] as FLOAT32 +// { 21002, 2} , // Name: HS Current B (HS I b) - [21002,2] as FLOAT32 +// { 21004, 2} , // Name: HS Current C (HS I c) - [21004,2] as FLOAT32 +// { 21006, 2} , // Name: HS Current N (HS I 4) - [21006,2] as FLOAT32 +// { 21008, 2} , // Name: HS Current G (HS I 5) - [21008,2] as FLOAT32 +// { 21010, 2} , // Name: HS Current Avg (HS I avg) - [21010,2] as FLOAT32 +// { 21016, 2} , // Name: HS Frequency (HS Freq) - [21016,2] as FLOAT32 +// { 21018, 2} , // Name: HS Voltage, A-B (HS Vll ab) - [21018,2] as FLOAT32 +// { 21020, 2} , // Name: HS Voltage, B-C (HS Vll bc) - [21020,2] as FLOAT32 +// { 21022, 2} , // Name: HS Voltage, C-A (HS Vll ca) - [21022,2] as FLOAT32 +// { 21024, 2} , // Name: HS Voltage, L-L Average (HS Vll avg) - [21024,2] as FLOAT32 +// { 21026, 2} , // Name: HS Voltage, A-N (HS Vln a) - [21026,2] as FLOAT32 +// { 21028, 2} , // Name: HS Voltage, B-N (HS Vln b) - [21028,2] as FLOAT32 +// { 21030, 2} , // Name: HS Voltage, C-N (HS Vln c) - [21030,2] as FLOAT32 +// { 21034, 2} , // Name: HS Voltage, L-N Average (HS Vln avg) - [21034,2] as FLOAT32 +// { 21040, 2} , // Name: HS Active Power A (HS kW a) - [21040,2] as FLOAT32 +// { 21042, 2} , // Name: HS Active Power B (HS kW b) - [21042,2] as FLOAT32 +// { 21044, 2} , // Name: HS Active Power C (HS kW c) - [21044,2] as FLOAT32 +// { 21046, 2} , // Name: HS Active Power Total (HS kW tot) - [21046,2] as FLOAT32 +// { 21048, 2} , // Name: HS Reactive Power A (HS kVAR a) - [21048,2] as FLOAT32 +// { 21050, 2} , // Name: HS Reactive Power B (HS kVAR b) - [21050,2] as FLOAT32 +// { 21052, 2} , // Name: HS Reactive Power C (HS kVAR c) - [21052,2] as FLOAT32 +// { 21054, 2} , // Name: HS Reactive Power Total (HS kVAR tot) - [21054,2] as FLOAT32 +// { 21056, 2} , // Name: HS Apparent Power A (HS kVA a) - [21056,2] as FLOAT32 +// { 21058, 2} , // Name: HS Apparent Power B (HS kVA b) - [21058,2] as FLOAT32 +// { 21060, 2} , // Name: HS Apparent Power C (HS kVA c) - [21060,2] as FLOAT32 +// { 21062, 2} , // Name: HS Apparent Power Total (HS kVA tot) - [21062,2] as FLOAT32 +// { 21358, 2} , // Name: K-Factor A (I1 K Factor) - [21358,2] as FLOAT32 +// { 21360, 2} , // Name: K-Factor B (I2 K Factor) - [21360,2] as FLOAT32 +// { 21362, 2} , // Name: K-Factor C (I3 K Factor) - [21362,2] as FLOAT32 +// { 27218, 2} , // Name: Min Current A (I a mn) - [27218,2] as FLOAT32 +// { 27220, 2} , // Name: Min Current B (I b mn) - [27220,2] as FLOAT32 +// { 27222, 2} , // Name: Min Current C (I c mn) - [27222,2] as FLOAT32 +// { 27224, 2} , // Name: Min Current N (I4 mn) - [27224,2] as FLOAT32 +// { 27226, 2} , // Name: Min Current G (I5 mn) - [27226,2] as FLOAT32 +// { 27228, 2} , // Name: Min Current Avg (I avg mn) - [27228,2] as FLOAT32 +// { 27238, 2} , // Name: Min Voltage A-B (Vll ab mn) - [27238,2] as FLOAT32 +// { 27240, 2} , // Name: Min Voltage B-C (Vll bc mn) - [27240,2] as FLOAT32 +// { 27242, 2} , // Name: Min Voltage C-A (Vll ca mn) - [27242,2] as FLOAT32 +// { 27244, 2} , // Name: Min Voltage L-L Avg (Vll avg mn) - [27244,2] as FLOAT32 +// { 27246, 2} , // Name: Min Voltage A-N (Vln a mn) - [27246,2] as FLOAT32 +// { 27248, 2} , // Name: Min Voltage B-N (Vln b mn) - [27248,2] as FLOAT32 +// { 27250, 2} , // Name: Min Voltage C-N (Vln c mn) - [27250,2] as FLOAT32 +// { 27254, 2} , // Name: Min Voltage L-N Avg (Vln avg mn) - [27254,2] as FLOAT32 +// { 27278, 2} , // Name: Min Active Power Total (kW tot mn) - [27278,2] as FLOAT32 +// { 27286, 2} , // Name: Min Reactive Power Total (kVAR tot mn) - [27286,2] as FLOAT32 +// { 27294, 2} , // Name: Min Apparent Power Total (kVA tot mn) - [27294,2] as FLOAT32 +// { 27616, 2} , // Name: Min Frequency (Freq mn) - [27616,2] as FLOAT32 +// { 27644, 2} , // Name: Current A Low (I a low) - [27644,2] as FLOAT32 +// { 27646, 2} , // Name: Current B Low (I b low) - [27646,2] as FLOAT32 +// { 27648, 2} , // Name: Current C Low (I c low) - [27648,2] as FLOAT32 +// { 27650, 2} , // Name: Current N Low (I4 low) - [27650,2] as FLOAT32 +// { 27652, 2} , // Name: Current Avg Low (I avg low) - [27652,2] as FLOAT32 +// { 27654, 2} , // Name: Voltage A-B Low (Vll ab low) - [27654,2] as FLOAT32 +// { 27656, 2} , // Name: Voltage B-C Low (Vll bc low) - [27656,2] as FLOAT32 +// { 27658, 2} , // Name: Voltage C-A Low (Vll ca low) - [27658,2] as FLOAT32 +// { 27660, 2} , // Name: Voltage L-L Avg Low (Vll avg low) - [27660,2] as FLOAT32 +// { 27672, 2} , // Name: Active Power Low (kW tot low) - [27672,2] as FLOAT32 +// { 27674, 2} , // Name: Reactive Power Low (kVAR tot low) - [27674,2] as FLOAT32 +// { 27676, 2} , // Name: Apparent Power Low (kVA tot low) - [27676,2] as FLOAT32 +// { 27682, 2} , // Name: Frequency Low (Freq low) - [27682,2] as FLOAT32 +// { 27694, 2} , // Name: Max Current A (I a mx) - [27694,2] as FLOAT32 +// { 27696, 2} , // Name: Max Current B (I b mx) - [27696,2] as FLOAT32 +// { 27698, 2} , // Name: Max Current C (I c mx) - [27698,2] as FLOAT32 +// { 27700, 2} , // Name: Max Current N (I4 mx) - [27700,2] as FLOAT32 +// { 27702, 2} , // Name: Max Current G (I5 mx) - [27702,2] as FLOAT32 +// { 27704, 2} , // Name: Max Current Avg (I avg mx) - [27704,2] as FLOAT32 +// { 27714, 2} , // Name: Max Voltage A-B (Vll ab mx) - [27714,2] as FLOAT32 +// { 27716, 2} , // Name: Max Voltage B-C (Vll bc mx) - [27716,2] as FLOAT32 +// { 27718, 2} , // Name: Max Voltage C-A (Vll ca mx) - [27718,2] as FLOAT32 +// { 27720, 2} , // Name: Max Voltage L-L Avg (Vll avg mx) - [27720,2] as FLOAT32 +// { 27722, 2} , // Name: Max Voltage A-N (Vln a mx) - [27722,2] as FLOAT32 +// { 27724, 2} , // Name: Max Voltage B-N (Vln b mx) - [27724,2] as FLOAT32 +// { 27726, 2} , // Name: Max Voltage C-N (Vln c mx) - [27726,2] as FLOAT32 +// { 27730, 2} , // Name: Max Voltage L-N Avg (Vln avg mx) - [27730,2] as FLOAT32 +// { 27754, 2} , // Name: Max Active Power Total (kW tot mx) - [27754,2] as FLOAT32 +// { 27762, 2} , // Name: Max Reactive Power Total (kVAR tot mx) - [27762,2] as FLOAT32 +// { 27770, 2} , // Name: Max Apparent Power Total (kVA tot mx) - [27770,2] as FLOAT32 +// { 28092, 2} , // Name: Max Frequency (Freq mx) - [28092,2] as FLOAT32 +// { 28120, 2} , // Name: Current A High (I a high) - [28120,2] as FLOAT32 +// { 28122, 2} , // Name: Current B High (I b high) - [28122,2] as FLOAT32 +// { 28124, 2} , // Name: Current C High (I c high) - [28124,2] as FLOAT32 +// { 28126, 2} , // Name: Current N High (I 4 high) - [28126,2] as FLOAT32 +// { 28128, 2} , // Name: Current Avg High (I avg high) - [28128,2] as FLOAT32 +// { 28130, 2} , // Name: Voltage A-B High (Vll ab high) - [28130,2] as FLOAT32 +// { 28132, 2} , // Name: Voltage B-C High (Vll bc high) - [28132,2] as FLOAT32 +// { 28134, 2} , // Name: Voltage C-A High (Vll ca high) - [28134,2] as FLOAT32 +// { 28136, 2} , // Name: Voltage L-L Avg High (Vll avg high) - [28136,2] as FLOAT32 +// { 28162, 2} , // Name: Active Power High (kW tot high) - [28162,2] as FLOAT32 +// { 28164, 2} , // Name: Reactive Power High (kVAR tot high) - [28164,2] as FLOAT32 +// { 28166, 2} , // Name: Apparent Power High (kVA tot high) - [28166,2] as FLOAT32 +// { 28172, 2} , // Name: Frequency High (Freq high) - [28172,2] as FLOAT32 +// { 28180, 2} , // Name: Current A Mean (I a mean) - [28180,2] as FLOAT32 +// { 28182, 2} , // Name: Current B Mean (I b mean) - [28182,2] as FLOAT32 +// { 28184, 2} , // Name: Current C Mean (I c mean) - [28184,2] as FLOAT32 +// { 28186, 2} , // Name: Current N Mean (I 4 mean) - [28186,2] as FLOAT32 +// { 28188, 2} , // Name: Current Avg Mean (I avg mean) - [28188,2] as FLOAT32 +// { 28190, 2} , // Name: Voltage A-B Mean (Vll ab mean) - [28190,2] as FLOAT32 +// { 28192, 2} , // Name: Voltage B-C Mean (Vll bc mean) - [28192,2] as FLOAT32 +// { 28194, 2} , // Name: Voltage C-A Mean (Vll ca mean) - [28194,2] as FLOAT32 +// { 28196, 2} , // Name: Voltage L-L Avg Mean (Vll avg mean) - [28196,2] as FLOAT32 +// { 28208, 2} , // Name: Active Power Mean (kW tot mean) - [28208,2] as FLOAT32 +// { 28210, 2} , // Name: Reactive Power Mean (kVAR tot mean) - [28210,2] as FLOAT32 +// { 28212, 2} , // Name: Apparent Power Mean (kVA tot mean) - [28212,2] as FLOAT32 +// { 28218, 2} , // Name: Frequency Mean (Freq mean) - [28218,2] as FLOAT32 +// { 29884, 2} , // Name: Current A Last Demand (I a sd) - [29884,2] as FLOAT32 +// { 29886, 2} , // Name: Current A Predicted Demand (I a sd pred) - [29886,2] as FLOAT32 +// { 29888, 0} , // Name: Current A Peak Demand (I a sd mx) - [29888,6] as TIMESTAMPED_FLOAT32 +// { 29898, 2} , // Name: Current B Last Demand (I b sd) - [29898,2] as FLOAT32 +// { 29900, 2} , // Name: Current B Predicted Demand (I b sd pred) - [29900,2] as FLOAT32 +// { 29902, 0} , // Name: Current B Peak Demand (I b sd mx) - [29902,6] as TIMESTAMPED_FLOAT32 +// { 29912, 2} , // Name: Current C Last Demand (I c sd) - [29912,2] as FLOAT32 +// { 29914, 2} , // Name: Current C Predicted Demand (I c sd pred) - [29914,2] as FLOAT32 +// { 29916, 0} , // Name: Current C Peak Demand (I c sd mx) - [29916,6] as TIMESTAMPED_FLOAT32 +// { 29926, 2} , // Name: Current 4 Last Demand (I 4 sd) - [29926,2] as FLOAT32 +// { 29928, 2} , // Name: Current 4 Predicted Demand (I 4 sd pred) - [29928,2] as FLOAT32 +// { 29930, 0} , // Name: Current 4 Peak Demand (I 4 sd mx) - [29930,6] as TIMESTAMPED_FLOAT32 +// { 29940, 2} , // Name: Current Avg Last Demand (I avg sd) - [29940,2] as FLOAT32 +// { 29942, 2} , // Name: Current Avg Predicted Demand (I avg sd pred) - [29942,2] as FLOAT32 +// { 29944, 0} , // Name: Current Avg Peak Demand (I avg sd mx) - [29944,6] as TIMESTAMPED_FLOAT32 +// { 29954, 2} , // Name: Active Power Last Demand (kW sd del-rec) - [29954,2] as FLOAT32 +// { 29956, 2} , // Name: Active Power Predicted Demand (kW pr del-rec) - [29956,2] as FLOAT32 +// { 29958, 0} , // Name: Active Power Peak Demand (kW sd mx d-r) - [29958,6] as TIMESTAMPED_FLOAT32 +// { 29968, 2} , // Name: Active Power Del Last Demand (kW sd del) - [29968,2] as FLOAT32 +// { 29970, 2} , // Name: Active Power Del Predicted Demand (kW pr del) - [29970,2] as FLOAT32 +// { 29972, 0} , // Name: Active Power Del Peak Demand (kW sd mx del) - [29972,6] as TIMESTAMPED_FLOAT32 +// { 29982, 2} , // Name: Active Power Rec Last Demand (kW sd rec) - [29982,2] as FLOAT32 +// { 29984, 2} , // Name: Active Power Rec Predicted Demand (kW pr rec) - [29984,2] as FLOAT32 +// { 29986, 0} , // Name: Active Power Rec Peak Demand (kW sd mx rec) - [29986,6] as TIMESTAMPED_FLOAT32 +// { 29996, 2} , // Name: Active Power Total Last Demand (kW sd del+rec) - [29996,2] as FLOAT32 +// { 29998, 2} , // Name: Active Power Total Predicted Demand (kW pr del+rec) - [29998,2] as FLOAT32 +// { 30000, 0} , // Name: Active Power Total Peak Demand (kW sd mx d+r) - [30000,6] as TIMESTAMPED_FLOAT32 +// { 30010, 2} , // Name: Reactive Power Last Demand (kVAR sd del-rec) - [30010,2] as FLOAT32 +// { 30012, 2} , // Name: Reactive Power Predicted Demand (kVAR pr del-rec) - [30012,2] as FLOAT32 +// { 30014, 0} , // Name: Reactive Power Peak Demand (kVAR sd mx d-r) - [30014,6] as TIMESTAMPED_FLOAT32 +// { 30024, 2} , // Name: Reactive Power Del Last Demand (kVAR sd del) - [30024,2] as FLOAT32 +// { 30026, 2} , // Name: Reactive Power Del Predicted Demand (kVAR pr del) - [30026,2] as FLOAT32 +// { 30028, 0} , // Name: Reactive Power Del Peak Demand (kVAR sd mx del) - [30028,6] as TIMESTAMPED_FLOAT32 +// { 30038, 2} , // Name: Reactive Power Rec Last Demand (kVAR sd rec) - [30038,2] as FLOAT32 +// { 30040, 2} , // Name: Reactive Power Rec Predicted Demand (kVAR pr rec) - [30040,2] as FLOAT32 +// { 30042, 0} , // Name: Reactive Power Rec Peak Demand (kVAR sd mx rec) - [30042,6] as TIMESTAMPED_FLOAT32 +// { 30052, 2} , // Name: Reactive Power Total Last Demand (kVAR sd del+rec) - [30052,2] as FLOAT32 +// { 30054, 2} , // Name: Reactive Power Total Predicted Demand (kVAR pr del+rec) - [30054,2] as FLOAT32 +// { 30056, 0} , // Name: Reactive Power Total Peak Demand (kVAR sd mx d+r) - [30056,6] as TIMESTAMPED_FLOAT32 +// { 30066, 2} , // Name: Apparent Power Last Demand (kVA sd del-rec) - [30066,2] as FLOAT32 +// { 30068, 2} , // Name: Apparent Power Predicted Demand (kVA pr del-rec) - [30068,2] as FLOAT32 +// { 30070, 0} , // Name: Apparent Power Peak Demand (kVA sd mx d-r) - [30070,6] as TIMESTAMPED_FLOAT32 +// { 30080, 2} , // Name: Apparent Power Del Last Demand (kVA sd del) - [30080,2] as FLOAT32 +// { 30082, 2} , // Name: Apparent Power Del Predicted Demand (kVA pr del) - [30082,2] as FLOAT32 +// { 30084, 0} , // Name: Apparent Power Del Peak Demand (kVA sd mx del) - [30084,6] as TIMESTAMPED_FLOAT32 +// { 30094, 2} , // Name: Apparent Power Rec Last Demand (kVA sd rec) - [30094,2] as FLOAT32 +// { 30096, 2} , // Name: Apparent Power Rec Predicted Demand (kVA pr rec) - [30096,2] as FLOAT32 +// { 30098, 0} , // Name: Apparent Power Rec Peak Demand (kVA sd mx rec) - [30098,6] as TIMESTAMPED_FLOAT32 +// { 30108, 2} , // Name: Apparent Power Total Last Demand (kVA sd del+rec) - [30108,2] as FLOAT32 +// { 30110, 2} , // Name: Apparent Power Total Predicted Demand (kVA pr del+rec) - [30110,2] as FLOAT32 +// { 30112, 0} , // Name: Apparent Power Total Peak Demand (kVA sd mx d+r) - [30112,6] as TIMESTAMPED_FLOAT32 +// { 30222, 2} , // Name: Active Power Del A Last Demand (kW sd del A) - [30222,2] as FLOAT32 +// { 30224, 2} , // Name: Active Power Del A Predicted Demand (kW pr del A) - [30224,2] as FLOAT32 +// { 30226, 0} , // Name: Active Power Del A Peak Demand (kW sd mx del A) - [30226,6] as TIMESTAMPED_FLOAT32 +// { 30236, 2} , // Name: Active Power Del B Last Demand (kW sd del B) - [30236,2] as FLOAT32 +// { 30238, 2} , // Name: Active Power Del B Predicted Demand (kW pr del B) - [30238,2] as FLOAT32 +// { 30240, 0} , // Name: Active Power Del B Peak Demand (kW sd mx del B) - [30240,6] as TIMESTAMPED_FLOAT32 +// { 30250, 2} , // Name: Active Power Del C Last Demand (kW sd del C) - [30250,2] as FLOAT32 +// { 30252, 2} , // Name: Active Power Del C Predicted Demand (kW pr del C) - [30252,2] as FLOAT32 +// { 30254, 0} , // Name: Active Power Del C Peak Demand (kW sd mx del C) - [30254,6] as TIMESTAMPED_FLOAT32 +// { 30264, 2} , // Name: Active Power Del D Last Demand (kW sd del D) - [30264,2] as FLOAT32 +// { 30266, 2} , // Name: Active Power Del D Predicted Demand (kW pr del D) - [30266,2] as FLOAT32 +// { 30268, 0} , // Name: Active Power Del D Peak Demand (kW sd mx del D) - [30268,6] as TIMESTAMPED_FLOAT32 +// { 30278, 2} , // Name: Active Power Rec A Last Demand (kW sd rec A) - [30278,2] as FLOAT32 +// { 30280, 2} , // Name: Active Power Rec A Predicted Demand (kW pr rec A) - [30280,2] as FLOAT32 +// { 30282, 0} , // Name: Active Power Rec A Peak Demand (kW sd mx rec A) - [30282,6] as TIMESTAMPED_FLOAT32 +// { 30292, 2} , // Name: Active Power Rec B Last Demand (kW sd rec B) - [30292,2] as FLOAT32 +// { 30294, 2} , // Name: Active Power Rec B Predicted Demand (kW pr rec B) - [30294,2] as FLOAT32 +// { 30296, 0} , // Name: Active Power Rec B Peak Demand (kW sd mx rec B) - [30296,6] as TIMESTAMPED_FLOAT32 +// { 30306, 2} , // Name: Active Power Rec C Last Demand (kW sd rec C) - [30306,2] as FLOAT32 +// { 30308, 2} , // Name: Active Power Rec C Predicted Demand (kW pr rec C) - [30308,2] as FLOAT32 +// { 30310, 0} , // Name: Active Power Rec C Peak Demand (kW sd mx rec C) - [30310,6] as TIMESTAMPED_FLOAT32 +// { 30320, 2} , // Name: Active Power Rec D Last Demand (kW sd rec D) - [30320,2] as FLOAT32 +// { 30322, 2} , // Name: Active Power Rec D Predicted Demand (kW pr rec D) - [30322,2] as FLOAT32 +// { 30324, 0} , // Name: Active Power Rec D Peak Demand (kW sd mx rec D) - [30324,6] as TIMESTAMPED_FLOAT32 +// { 30334, 2} , // Name: Reactive Power Del A Last Demand (kVAR sd del A) - [30334,2] as FLOAT32 +// { 30336, 2} , // Name: Reactive Power Del A Predicted Demand (kVAR pr del A) - [30336,2] as FLOAT32 +// { 30338, 0} , // Name: Reactive Power Del A Peak Demand (kVAR sd mx d A) - [30338,6] as TIMESTAMPED_FLOAT32 +// { 30348, 2} , // Name: Reactive Power Del B Last Demand (kVAR sd del B) - [30348,2] as FLOAT32 +// { 30350, 2} , // Name: Reactive Power Del B Predicted Demand (kVAR pr del B) - [30350,2] as FLOAT32 +// { 30352, 0} , // Name: Reactive Power Del B Peak Demand (kVAR sd mx d B) - [30352,6] as TIMESTAMPED_FLOAT32 +// { 30362, 2} , // Name: Reactive Power Del C Last Demand (kVAR sd del C) - [30362,2] as FLOAT32 +// { 30364, 2} , // Name: Reactive Power Del C Predicted Demand (kVAR pr del C) - [30364,2] as FLOAT32 +// { 30366, 0} , // Name: Reactive Power Del C Peak Demand (kVAR sd mx d C) - [30366,6] as TIMESTAMPED_FLOAT32 +// { 30376, 2} , // Name: Reactive Power Del D Last Demand (kVAR sd del D) - [30376,2] as FLOAT32 +// { 30378, 2} , // Name: Reactive Power Del D Predicted Demand (kVAR pr del D) - [30378,2] as FLOAT32 +// { 30380, 0} , // Name: Reactive Power Del D Peak Demand (kVAR sd mx d D) - [30380,6] as TIMESTAMPED_FLOAT32 +// { 30390, 2} , // Name: Reactive Power Rec A Last Demand (kVAR sd rec A) - [30390,2] as FLOAT32 +// { 30392, 2} , // Name: Reactive Power Rec A Predicted Demand (kVAR pr rec A) - [30392,2] as FLOAT32 +// { 30394, 0} , // Name: Reactive Power Rec A Peak Demand (kVAR sd mx r A) - [30394,6] as TIMESTAMPED_FLOAT32 +// { 30404, 2} , // Name: Reactive Power Rec B Last Demand (kVAR sd rec B) - [30404,2] as FLOAT32 +// { 30406, 2} , // Name: Reactive Power Rec B Predicted Demand (kVAR pr rec B) - [30406,2] as FLOAT32 +// { 30408, 0} , // Name: Reactive Power Rec B Peak Demand (kVAR sd mx r B) - [30408,6] as TIMESTAMPED_FLOAT32 +// { 30418, 2} , // Name: Reactive Power Rec C Last Demand (kVAR sd rec C) - [30418,2] as FLOAT32 +// { 30420, 2} , // Name: Reactive Power Rec C Predicted Demand (kVAR pr rec C) - [30420,2] as FLOAT32 +// { 30422, 0} , // Name: Reactive Power Rec C Peak Demand (kVAR sd mx r C) - [30422,6] as TIMESTAMPED_FLOAT32 +// { 30432, 2} , // Name: Reactive Power Rec D Last Demand (kVAR sd rec D) - [30432,2] as FLOAT32 +// { 30434, 2} , // Name: Reactive Power Rec D Predicted Demand (kVAR pr rec D) - [30434,2] as FLOAT32 +// { 30436, 0} , // Name: Reactive Power Rec D Peak Demand (kVAR sd mx r D) - [30436,6] as TIMESTAMPED_FLOAT32 +// { 30446, 2} , // Name: Apparent Power Del A Last Demand (kVA sd del A) - [30446,2] as FLOAT32 +// { 30448, 2} , // Name: Apparent Power Del A Predicted Demand (kVA pr del A) - [30448,2] as FLOAT32 +// { 30450, 0} , // Name: Apparent Power Del A Peak Demand (kVA sd mx del A) - [30450,6] as TIMESTAMPED_FLOAT32 +// { 30460, 2} , // Name: Apparent Power Del B Last Demand (kVA sd del B) - [30460,2] as FLOAT32 +// { 30462, 2} , // Name: Apparent Power Del B Predicted Demand (kVA pr del B) - [30462,2] as FLOAT32 +// { 30464, 0} , // Name: Apparent Power Del B Peak Demand (kVA sd mx del B) - [30464,6] as TIMESTAMPED_FLOAT32 +// { 30474, 2} , // Name: Apparent Power Del C Last Demand (kVA sd del C) - [30474,2] as FLOAT32 +// { 30476, 2} , // Name: Apparent Power Del C Predicted Demand (kVA pr del C) - [30476,2] as FLOAT32 +// { 30478, 0} , // Name: Apparent Power Del C Peak Demand (kVA sd mx del C) - [30478,6] as TIMESTAMPED_FLOAT32 +// { 30488, 2} , // Name: Apparent Power Del D Last Demand (kVA sd del D) - [30488,2] as FLOAT32 +// { 30490, 2} , // Name: Apparent Power Del D Predicted Demand (kVA pr del D) - [30490,2] as FLOAT32 +// { 30492, 0} , // Name: Apparent Power Del D Peak Demand (kVA sd mx del D) - [30492,6] as TIMESTAMPED_FLOAT32 +// { 30502, 2} , // Name: Apparent Power Rec A Last Demand (kVA sd rec A) - [30502,2] as FLOAT32 +// { 30504, 2} , // Name: Apparent Power Rec A Predicted Demand (kVA pr rec A) - [30504,2] as FLOAT32 +// { 30506, 0} , // Name: Apparent Power Rec A Peak Demand (kVA sd mx rec A) - [30506,6] as TIMESTAMPED_FLOAT32 +// { 30516, 2} , // Name: Apparent Power Rec B Last Demand (kVA sd rec B) - [30516,2] as FLOAT32 +// { 30518, 2} , // Name: Apparent Power Rec B Predicted Demand (kVA pr rec B) - [30518,2] as FLOAT32 +// { 30520, 0} , // Name: Apparent Power Rec B Peak Demand (kVA sd mx rec B) - [30520,6] as TIMESTAMPED_FLOAT32 +// { 30530, 2} , // Name: Apparent Power Rec C Last Demand (kVA sd rec C) - [30530,2] as FLOAT32 +// { 30532, 2} , // Name: Apparent Power Rec C Predicted Demand (kVA pr rec C) - [30532,2] as FLOAT32 +// { 30534, 0} , // Name: Apparent Power Rec C Peak Demand (kVA sd mx rec C) - [30534,6] as TIMESTAMPED_FLOAT32 +// { 30544, 2} , // Name: Apparent Power Rec D Last Demand (kVA sd rec D) - [30544,2] as FLOAT32 +// { 30546, 2} , // Name: Apparent Power Rec D Predicted Demand (kVA pr rec D) - [30546,2] as FLOAT32 +// { 30548, 0} , // Name: Apparent Power Rec D Peak Demand (kVA sd mx rec D) - [30548,6] as TIMESTAMPED_FLOAT32 +// { 30558, 2} , // Name: Active Power Q1 Last Demand (kW sd Q1) - [30558,2] as FLOAT32 +// { 30560, 2} , // Name: Active Power Q1 Predicted Demand (kW pr Q1) - [30560,2] as FLOAT32 +// { 30562, 0} , // Name: Active Power Q1 Peak Demand (kW sd mx Q1) - [30562,6] as TIMESTAMPED_FLOAT32 +// { 30572, 2} , // Name: Active Power Q2 Last Demand (kW sd Q2) - [30572,2] as FLOAT32 +// { 30574, 2} , // Name: Active Power Q2 Predicted Demand (kW pr Q2) - [30574,2] as FLOAT32 +// { 30576, 0} , // Name: Active Power Q2 Peak Demand (kW sd mx Q2) - [30576,6] as TIMESTAMPED_FLOAT32 +// { 30586, 2} , // Name: Active Power Q3 Last Demand (kW sd Q3) - [30586,2] as FLOAT32 +// { 30588, 2} , // Name: Active Power Q3 Predicted Demand (kW pr Q3) - [30588,2] as FLOAT32 +// { 30590, 0} , // Name: Active Power Q3 Peak Demand (kW sd mx Q3) - [30590,6] as TIMESTAMPED_FLOAT32 +// { 30600, 2} , // Name: Active Power Q4 Last Demand (kW sd Q4) - [30600,2] as FLOAT32 +// { 30602, 2} , // Name: Active Power Q4 Predicted Demand (kW pr Q4) - [30602,2] as FLOAT32 +// { 30604, 0} , // Name: Active Power Q4 Peak Demand (kW sd mx Q4) - [30604,6] as TIMESTAMPED_FLOAT32 +// { 30614, 2} , // Name: Reactive Power Q1 Last Demand (kVAR sd Q1) - [30614,2] as FLOAT32 +// { 30616, 2} , // Name: Reactive Power Q1 Predicted Demand (kVAR pr Q1) - [30616,2] as FLOAT32 +// { 30618, 0} , // Name: Reactive Power Q1 Peak Demand (kVAR sd mx Q1) - [30618,6] as TIMESTAMPED_FLOAT32 +// { 30628, 2} , // Name: Reactive Power Q2 Last Demand (kVAR sd Q2) - [30628,2] as FLOAT32 +// { 30630, 2} , // Name: Reactive Power Q2 Predicted Demand (kVAR pr Q2) - [30630,2] as FLOAT32 +// { 30632, 0} , // Name: Reactive Power Q2 Peak Demand (kVAR sd mx Q2) - [30632,6] as TIMESTAMPED_FLOAT32 +// { 30642, 2} , // Name: Reactive Power Q3 Last Demand (kVAR sd Q3) - [30642,2] as FLOAT32 +// { 30644, 2} , // Name: Reactive Power Q3 Predicted Demand (kVAR pr Q3) - [30644,2] as FLOAT32 +// { 30646, 0} , // Name: Reactive Power Q3 Peak Demand (kVAR sd mx Q3) - [30646,6] as TIMESTAMPED_FLOAT32 +// { 30656, 2} , // Name: Reactive Power Q4 Last Demand (kVAR sd Q4) - [30656,2] as FLOAT32 +// { 30658, 2} , // Name: Reactive Power Q4 Predicted Demand (kVAR pr Q4) - [30658,2] as FLOAT32 +// { 30660, 0} , // Name: Reactive Power Q4 Peak Demand (kVAR sd mx Q4) - [30660,6] as TIMESTAMPED_FLOAT32 +// { 30670, 2} , // Name: Apparent Power Q1 Last Demand (kVA sd Q1) - [30670,2] as FLOAT32 +// { 30672, 2} , // Name: Apparent Power Q1 Predicted Demand (kVA pr Q1) - [30672,2] as FLOAT32 +// { 30674, 0} , // Name: Apparent Power Q1 Peak Demand (kVA sd mx Q1) - [30674,6] as TIMESTAMPED_FLOAT32 +// { 30684, 2} , // Name: Apparent Power Q2 Last Demand (kVA sd Q2) - [30684,2] as FLOAT32 +// { 30686, 2} , // Name: Apparent Power Q2 Predicted Demand (kVA pr Q2) - [30686,2] as FLOAT32 +// { 30688, 0} , // Name: Apparent Power Q2 Peak Demand (kVA sd mx Q2) - [30688,6] as TIMESTAMPED_FLOAT32 +// { 30698, 2} , // Name: Apparent Power Q3 Last Demand (kVA sd Q3) - [30698,2] as FLOAT32 +// { 30700, 2} , // Name: Apparent Power Q3 Predicted Demand (kVA pr Q3) - [30700,2] as FLOAT32 +// { 30702, 0} , // Name: Apparent Power Q3 Peak Demand (kVA sd mx Q3) - [30702,6] as TIMESTAMPED_FLOAT32 +// { 30712, 2} , // Name: Apparent Power Q4 Last Demand (kVA sd Q4) - [30712,2] as FLOAT32 +// { 30714, 2} , // Name: Apparent Power Q4 Predicted Demand (kVA pr Q4) - [30714,2] as FLOAT32 +// { 30716, 0} , // Name: Apparent Power Q4 Peak Demand (kVA sd mx Q4) - [30716,6] as TIMESTAMPED_FLOAT32 +// { 30822, 2} , // Name: Block Demand Active Power (kVA co kW d-r) - [30822,2] as FLOAT32 +// { 30824, 2} , // Name: Block Demand Active Power Into the Load (kVA co kW del) - [30824,2] as FLOAT32 +// { 30826, 2} , // Name: Block Demand Active Power Out of the Load (kVA co kW rec) - [30826,2] as FLOAT32 +// { 30828, 2} , // Name: Block Demand Active Power Total (kVA co kW d+r) - [30828,2] as FLOAT32 +// { 30830, 2} , // Name: Block Demand Reactive Power (kVA co kVAR d-r) - [30830,2] as FLOAT32 +// { 30832, 2} , // Name: Block Demand Reactive Power Into the Load (kVA co kVAR del) - [30832,2] as FLOAT32 +// { 30834, 2} , // Name: Block Demand Reactive Power Out of the Load (kVA co kVAR rec) - [30834,2] as FLOAT32 +// { 30836, 2} , // Name: Block Demand Reactive Power Total (kVA co kVAR d+r) - [30836,2] as FLOAT32 +// { 30838, 2} , // Name: Block Demand Active Power (kVAR co kW d-r) - [30838,2] as FLOAT32 +// { 30840, 2} , // Name: Block Demand Active Power Into the Load (kVAR co kW del) - [30840,2] as FLOAT32 +// { 30842, 2} , // Name: Block Demand Active Power Out of the Load (kVAR co kW rec) - [30842,2] as FLOAT32 +// { 30844, 2} , // Name: Block Demand Active Power Total (kVAR co kW d+r) - [30844,2] as FLOAT32 +// { 30846, 2} , // Name: Block Demand Apparent Power (kVAR co kVA d-r) - [30846,2] as FLOAT32 +// { 30848, 2} , // Name: Block Demand Apparent Power Into the Load (kVAR co kVA del) - [30848,2] as FLOAT32 +// { 30850, 2} , // Name: Block Demand Apparent Power Out of the Load (kVAR co kVA rec) - [30850,2] as FLOAT32 +// { 30852, 2} , // Name: Block Demand Apparent Power Total (kVAR co kVA d+r) - [30852,2] as FLOAT32 +// { 30854, 2} , // Name: Block Demand Reactive Power (kW co kVAR d-r) - [30854,2] as FLOAT32 +// { 30856, 2} , // Name: Block Demand Reactive Power Into the Load (kW co kVAR del) - [30856,2] as FLOAT32 +// { 30858, 2} , // Name: Block Demand Reactive Power Out of the Load (kW co kVAR rec) - [30858,2] as FLOAT32 +// { 30860, 2} , // Name: Block Demand Reactive Power Total (kW co kVAR d+r) - [30860,2] as FLOAT32 +// { 30862, 2} , // Name: Block Demand Apparent Power (kW co kVA d-r) - [30862,2] as FLOAT32 +// { 30864, 2} , // Name: Block Demand Apparent Power Into the Load (kW co kVA del) - [30864,2] as FLOAT32 +// { 30866, 2} , // Name: Block Demand Apparent Power Out of the Load (kW co kVA rec) - [30866,2] as FLOAT32 +// { 30868, 2} , // Name: Block Demand Apparent Power Total (kW co kVA d+r) - [30868,2] as FLOAT32 +// { 30870, 3} , // Name: Active Energy Delivered Rate 1 (PB kWh del A) - [30870,4] as INT64 +// { 30874, 3} , // Name: Active Energy Delivered Rate 2 (PB kWh del B) - [30874,4] as INT64 +// { 30878, 3} , // Name: Active Energy Delivered Rate 3 (PB kWh del C) - [30878,4] as INT64 +// { 30882, 3} , // Name: Active Energy Delivered Rate 4 (PB kWh del D) - [30882,4] as INT64 +// { 30886, 3} , // Name: Active Energy Delivered (PB kWh del) - [30886,4] as INT64 +// { 30890, 3} , // Name: Active Energy Received (PB kWh rec) - [30890,4] as INT64 +// { 30894, 3} , // Name: Reactive Energy Delivered (PB kVARh del) - [30894,4] as INT64 +// { 30898, 3} , // Name: Reactive Energy Received (PB kVARh rec) - [30898,4] as INT64 +// { 30902, 3} , // Name: Apparent Energy Delivered (PB kVAh del) - [30902,4] as INT64 +// { 30906, 3} , // Name: Apparent Energy Received (PB kVAh rec) - [30906,4] as INT64 +// { 30910, 2} , // Name: Peak Block Demand Active Power Delived Rate 1 (PB kW sd mx d A) - [30910,2] as FLOAT32 +// { 30912, 2} , // Name: Peak Block Demand Active Power Delived Rate 2 (PB kW sd mx d B) - [30912,2] as FLOAT32 +// { 30914, 2} , // Name: Peak Block Demand Active Power Delived Rate 3 (PB kW sd mx d C) - [30914,2] as FLOAT32 +// { 30916, 2} , // Name: Peak Block Demand Active Power Delived Rate 4 (PB kW sd mx d D) - [30916,2] as FLOAT32 +// { 30918, 2} , // Name: Peak Block Demand Active Power Received (PB kW sd mx rec) - [30918,2] as FLOAT32 +// { 30920, 2} , // Name: Peak Block Demand Reactive Power Delivered (PB kVAR sd mx d) - [30920,2] as FLOAT32 +// { 30922, 2} , // Name: Peak Block Demand Reactive Power Received (PB kVAR sd mx r) - [30922,2] as FLOAT32 +// { 30924, 2} , // Name: Peak Block Demand Apparent Power Delivered (PB kVA sd mx d) - [30924,2] as FLOAT32 +// { 30926, 2} , // Name: Peak Block Demand Apparent Power Received (PB kVA sd mx r) - [30926,2] as FLOAT32 +// { 30928, 3} , // Name: Active Energy Delivered Rate 1 (PS kWh del A) - [30928,4] as INT64 +// { 30932, 3} , // Name: Active Energy Delivered Rate 2 (PS kWh del B) - [30932,4] as INT64 +// { 30936, 3} , // Name: Active Energy Delivered Rate 3 (PS kWh del C) - [30936,4] as INT64 +// { 30940, 3} , // Name: Active Energy Delivered Rate 4 (PS kWh del D) - [30940,4] as INT64 +// { 30944, 3} , // Name: Active Energy Delivered (PS kWh del) - [30944,4] as INT64 +// { 30948, 3} , // Name: Active Energy Received (PS kWh rec) - [30948,4] as INT64 +// { 30952, 3} , // Name: Reactive Energy Delivered (PS kVARh del) - [30952,4] as INT64 +// { 30956, 3} , // Name: Reactive Energy Received (PS kVARh rec) - [30956,4] as INT64 +// { 30960, 3} , // Name: Apparent Energy Delivered (PS kVAh del) - [30960,4] as INT64 +// { 30964, 3} , // Name: Apparent Energy Received (PS kVAh rec) - [30964,4] as INT64 +// { 30968, 2} , // Name: Peak Block Demand Active Power Delived Rate 1 (PS kW sd mx d A) - [30968,2] as FLOAT32 +// { 30970, 2} , // Name: Peak Block Demand Active Power Delived Rate 2 (PS kW sd mx d B) - [30970,2] as FLOAT32 +// { 30972, 2} , // Name: Peak Block Demand Active Power Delived Rate 3 (PS kW sd mx d C) - [30972,2] as FLOAT32 +// { 30974, 2} , // Name: Peak Block Demand Active Power Delived Rate 4 (PS kW sd mx d D) - [30974,2] as FLOAT32 +// { 30976, 2} , // Name: Peak Block Demand Active Power Received (PS kW sd mx rec) - [30976,2] as FLOAT32 +// { 30978, 2} , // Name: Peak Block Demand Reactive Power Delivered (PS kVAR sd mx d) - [30978,2] as FLOAT32 +// { 30980, 2} , // Name: Peak Block Demand Reactive Power Received (PS kVAR sd mx r) - [30980,2] as FLOAT32 +// { 30982, 2} , // Name: Peak Block Demand Apparent Power Delivered (PS kVA sd mx d) - [30982,2] as FLOAT32 +// { 30984, 2} , // Name: Peak Block Demand Apparent Power Received (PS kVA sd mx r) - [30984,2] as FLOAT32 +// { 30986, 2} , // Name: Active Energy Delivered Rate 1 (PB kWh del A) - [30986,2] as FLOAT32 +// { 30988, 2} , // Name: Active Energy Delivered Rate 2 (PB kWh del B) - [30988,2] as FLOAT32 +// { 30990, 2} , // Name: Active Energy Delivered Rate 3 (PB kWh del C) - [30990,2] as FLOAT32 +// { 30992, 2} , // Name: Active Energy Delivered Rate 4 (PB kWh del D) - [30992,2] as FLOAT32 +// { 30994, 2} , // Name: Active Energy Delivered (PB kWh del) - [30994,2] as FLOAT32 +// { 30996, 2} , // Name: Active Energy Received (PB kWh rec) - [30996,2] as FLOAT32 +// { 30998, 2} , // Name: Reactive Energy Delivered (PB kVARh del) - [30998,2] as FLOAT32 +// { 31000, 2} , // Name: Reactive Energy Received (PB kVARh rec) - [31000,2] as FLOAT32 +// { 31002, 2} , // Name: Apparent Energy Delivered (PB kVAh del) - [31002,2] as FLOAT32 +// { 31004, 2} , // Name: Apparent Energy Received (PB kVAh rec) - [31004,2] as FLOAT32 +// { 31006, 2} , // Name: Active Energy Delivered Rate 1 (PS kWh del A) - [31006,2] as FLOAT32 +// { 31008, 2} , // Name: Active Energy Delivered Rate 2 (PS kWh del B) - [31008,2] as FLOAT32 +// { 31010, 2} , // Name: Active Energy Delivered Rate 3 (PS kWh del C) - [31010,2] as FLOAT32 +// { 31012, 2} , // Name: Active Energy Delivered Rate 4 (PS kWh del D) - [31012,2] as FLOAT32 +// { 31014, 2} , // Name: Active Energy Delivered (PS kWh del) - [31014,2] as FLOAT32 +// { 31016, 2} , // Name: Active Energy Received (PS kWh rec) - [31016,2] as FLOAT32 +// { 31018, 2} , // Name: Reactive Energy Delivered (PS kVARh del) - [31018,2] as FLOAT32 +// { 31020, 2} , // Name: Reactive Energy Received (PS kVARh rec) - [31020,2] as FLOAT32 +// { 31022, 2} , // Name: Apparent Energy Delivered (PS kVAh del) - [31022,2] as FLOAT32 +// { 31024, 2} , // Name: Apparent Energy Received (PS kVAh rec) - [31024,2] as FLOAT32 +// { 34352, 2} , // Name: Current, Phase A 3 Second (150/180 Cycles) (I1 3s) - [34352,2] as FLOAT32 +// { 34354, 2} , // Name: Current, Phase A 10 Minute (I1 10m) - [34354,2] as FLOAT32 +// { 34358, 2} , // Name: Current, Phase B 3 Second (150/180 Cycles) (I2 3s) - [34358,2] as FLOAT32 +// { 34360, 2} , // Name: Current, Phase B 10 Minute (I2 10m) - [34360,2] as FLOAT32 +// { 34364, 2} , // Name: Current, Phase C 3 Second (150/180 Cycles) (I3 3s) - [34364,2] as FLOAT32 +// { 34366, 2} , // Name: Current, Phase C 10 Minute (I3 10m) - [34366,2] as FLOAT32 +// { 34400, 2} , // Name: Voltage, A-N 3 Second (150/180 Cycles) (V1 3s) - [34400,2] as FLOAT32 +// { 34402, 2} , // Name: Voltage, A-N 10 Minute (V1 10m) - [34402,2] as FLOAT32 +// { 34404, 2} , // Name: Voltage, A-N 2 Hour (V1 2hr) - [34404,2] as FLOAT32 +// { 34406, 2} , // Name: Voltage, B-N 3 Second (150/180 Cycles) (V2 3s) - [34406,2] as FLOAT32 +// { 34408, 2} , // Name: Voltage, B-N 10 Minute (V2 10m) - [34408,2] as FLOAT32 +// { 34410, 2} , // Name: Voltage, B-N 2 Hour (V2 2hr) - [34410,2] as FLOAT32 +// { 34412, 2} , // Name: Voltage, C-N 3 Second (150/180 Cycles) (V3 3s) - [34412,2] as FLOAT32 +// { 34414, 2} , // Name: Voltage, C-N 10 Minute (V3 10m) - [34414,2] as FLOAT32 +// { 34416, 2} , // Name: Voltage, C-N 2 Hour (V3 2hr) - [34416,2] as FLOAT32 +// { 34472, 2} , // Name: Power Frequency 3 Second (150/180 Cycles) (Power Frequency) - [34472,2] as FLOAT32 +// { 34474, 2} , // Name: Power Frequency 10 Minute (Power Freq 10m) - [34474,2] as FLOAT32 +// { 34476, 2} , // Name: Power Frequency 2 Hour (Power Freq 2hr) - [34476,2] as FLOAT32 +// { 40000, 2} , // Name: Frequency 10m Mean (PQ Freq mean) - [40000,2] as FLOAT32 +// { 40002, 2} , // Name: Frequency 10m Low (PQ Freq low) - [40002,2] as FLOAT32 +// { 40004, 2} , // Name: Frequency 10m High (PQ Freq high) - [40004,2] as FLOAT32 +// { 40006, 2} , // Name: Frequency Minimum (PQ Freq mn-op) - [40006,2] as FLOAT32 +// { 40008, 2} , // Name: Frequency Maximum (PQ Freq mx-op) - [40008,2] as FLOAT32 +// { 40010, 2} , // Name: V1 10m Mean (PQ V1 mean) - [40010,2] as FLOAT32 +// { 40012, 2} , // Name: V1 10m Low (PQ V1 low) - [40012,2] as FLOAT32 +// { 40014, 2} , // Name: V1 10m High (PQ V1 high) - [40014,2] as FLOAT32 +// { 40016, 2} , // Name: V2 10m Mean (PQ V2 mean) - [40016,2] as FLOAT32 +// { 40018, 2} , // Name: V2 10m Low (PQ V2 low) - [40018,2] as FLOAT32 +// { 40020, 2} , // Name: V2 10m High (PQ V2 high) - [40020,2] as FLOAT32 +// { 40022, 2} , // Name: V3 10m Mean (PQ V3 mean) - [40022,2] as FLOAT32 +// { 40024, 2} , // Name: V3 10m Low (PQ V3 low) - [40024,2] as FLOAT32 +// { 40026, 2} , // Name: V3 10m High (PQ V3 high) - [40026,2] as FLOAT32 +// { 54396, 1} , // Name: FAC1 Nominal Frequency (N/A) - [54396,1] as INT16U +// { 56977, 0} , // Name: COM1 RTS Delay (N/A) - [56977,2] as INT32 + +} +; diff --git a/firmware/uno/modbus-sim800c-pm8000/util.h b/firmware/uno/modbus-sim800c-pm8000/util.h new file mode 100644 index 0000000..fc150b3 --- /dev/null +++ b/firmware/uno/modbus-sim800c-pm8000/util.h @@ -0,0 +1,27 @@ +#include +#include +#include + +uint32_t getRegisterUInt32(uint16_t highWord, uint16_t lowWord) { + uint32_t val = (highWord << 16) + lowWord; + return val; +} + +int32_t getRegisterInt32(uint16_t highWord, uint16_t lowWord) { + int32_t val = (highWord << 16) + lowWord; + return val; +} + +int64_t getRegisterInt64(uint16_t word1, uint16_t word2, uint16_t word3, uint16_t word4) { + uint64_t val = ((uint64_t)word1 << 48) + ((uint64_t)word2 << 32) + (word3 << 16) + word4; + return val; +} + +float getRegisterFloat(uint16_t highWord, uint16_t lowWord) { + uint32_t floatRaw = ((uint32_t)highWord << 16) | lowWord; + float floatValue; + + memcpy(&floatValue, &floatRaw, sizeof(float)); + return floatValue; +} + diff --git a/firmware/uno/pinout.md b/firmware/uno/pinout.md new file mode 100644 index 0000000..03d2f42 --- /dev/null +++ b/firmware/uno/pinout.md @@ -0,0 +1,37 @@ +ARDUINO UNO PINOUT +================= + +DIGITAL PINS (D0-D13) +-------------------- +D0 - RX (Serial) +D1 - TX (Serial) +D2 - Digital +D3 - PWM +D4 - Digital +D5 - PWM +D6 - PWM +D7 - Digital +D8 - Digital +D9 - PWM +D10 - PWM/SS (SPI) +D11 - PWM/MOSI (SPI) +D12 - MISO (SPI) +D13 - SCK (SPI) + +ANALOG PINS (A0-A5) +------------------ +A0 - Analog Input +A1 - Analog Input +A2 - Analog Input +A3 - Analog Input +A4 - SDA (I2C) +A5 - SCL (I2C) + +POWER +----- +VIN - Input Voltage (7-12V) +GND - Ground (multiple pins) +5V - 5V Output +3.3V - 3.3V Output +AREF - Analog Reference +RST - Reset \ No newline at end of file diff --git a/firmware/modbus-sd-VSD-generic-alt/modbus-sd-VSD-generic-alt.ino b/testing/modbus-sd-VSD-generic-alt/modbus-sd-VSD-generic-alt.ino similarity index 100% rename from firmware/modbus-sd-VSD-generic-alt/modbus-sd-VSD-generic-alt.ino rename to testing/modbus-sd-VSD-generic-alt/modbus-sd-VSD-generic-alt.ino diff --git a/firmware/modbus-sd-VSD-generic/modbus-sd-vsd.md b/testing/modbus-sd-VSD-generic-alt/modbus-sd-vsd.md similarity index 100% rename from firmware/modbus-sd-VSD-generic/modbus-sd-vsd.md rename to testing/modbus-sd-VSD-generic-alt/modbus-sd-vsd.md diff --git a/testing/modbus-sd-VSD-generic-alt/register_map_vsd.h b/testing/modbus-sd-VSD-generic-alt/register_map_vsd.h new file mode 100644 index 0000000..706d792 --- /dev/null +++ b/testing/modbus-sd-VSD-generic-alt/register_map_vsd.h @@ -0,0 +1,63 @@ + +#include +#ifndef REGISTER_MAP_VSD_H +#define REGISTER_MAP_VSD_H +struct RegisterMap { + uint16_t regaddr; + uint8_t regtype; // 1=UINT16, 2=FLOAT32, 3=INT64, 4=Status, 5=Thermal, 6=Power, 7=RPM + float scale; +}; + +const PROGMEM RegisterMap registers[] = { + {2910, 4, 1.0}, // Status Word + {2911, 6, 1.0}, // Min Active Value + {2912, 5, 1.0}, // Thermal Sense + {2913, 2, 10.0}, // Frequency + {2914, 1, 1.0}, // Running Hours + {2916, 1, 1.0}, // Operating Hours + {2918, 2, 1.0}, // kWh Counter + {2920, 2, 100.0}, // Input Power kW + {2922, 6, 134.102}, // Input Power HP + {2924, 2, 100.0}, // Motor Current + {2926, 2, 100.0}, // Phase I1 + {2928, 2, 100.0}, // Phase I2 + {2930, 2, 100.0}, // Phase I3 + {2932, 7, 60.0}, // Motor RPM + {2934, 2, 10.0}, // Motor Voltage + {2935, 6, 1.0}, // Torque Nm + {2936, 5, 1.0}, // Motor Thermal + {2937, 5, 1.0}, // Heatsink Temp + {2938, 5, 1.0}, // Card Temp + {2939, 5, 1.0}, // Inverter Thermal + {2940, 2, 1.0}, // DC Link Voltage + {2941, 6, 1.0}, // Motor Torque % + {2942, 2, 100.0}, // Inverter Nominal Current + {2944, 2, 100.0}, // Inverter Max Current + {2946, 4, 1.0}, // Alarm Word 1 + {2948, 4, 1.0}, // Alarm Word 2 + {2950, 4, 1.0}, // Warning Word 1 + {2952, 4, 1.0}, // Warning Word 2 + {2954, 4, 1.0}, // Power Ups + {3000, 5, 1.0} // Over Temp Counter +}; + +float calculateStatusWord(float* values) { + uint16_t status = 0; + if(values[0] > 0) status |= 0x0001; // Running + if(values[1] > 100) status |= 0x0002; // Overload + return status; +} + +float calculateThermal(float* values) { + return (values[0] / 100.0) * 100.0; +} + +float calculatePower(float* values) { + return values[0] * 0.746; // kW to HP conversion +} + +float calculateRPM(float* values) { + return values[0] * 60.0; +} + +#endif \ No newline at end of file diff --git a/testing/modbus-sd-VSD-generic-alt/util.h b/testing/modbus-sd-VSD-generic-alt/util.h new file mode 100644 index 0000000..fc150b3 --- /dev/null +++ b/testing/modbus-sd-VSD-generic-alt/util.h @@ -0,0 +1,27 @@ +#include +#include +#include + +uint32_t getRegisterUInt32(uint16_t highWord, uint16_t lowWord) { + uint32_t val = (highWord << 16) + lowWord; + return val; +} + +int32_t getRegisterInt32(uint16_t highWord, uint16_t lowWord) { + int32_t val = (highWord << 16) + lowWord; + return val; +} + +int64_t getRegisterInt64(uint16_t word1, uint16_t word2, uint16_t word3, uint16_t word4) { + uint64_t val = ((uint64_t)word1 << 48) + ((uint64_t)word2 << 32) + (word3 << 16) + word4; + return val; +} + +float getRegisterFloat(uint16_t highWord, uint16_t lowWord) { + uint32_t floatRaw = ((uint32_t)highWord << 16) | lowWord; + float floatValue; + + memcpy(&floatValue, &floatRaw, sizeof(float)); + return floatValue; +} + diff --git a/firmware/testing/modbus-sd-01.ino b/testing/other/modbus-sd-01.ino similarity index 100% rename from firmware/testing/modbus-sd-01.ino rename to testing/other/modbus-sd-01.ino diff --git a/firmware/testing/modbus_sender.ino b/testing/other/modbus_sender.ino similarity index 100% rename from firmware/testing/modbus_sender.ino rename to testing/other/modbus_sender.ino diff --git a/firmware/testing/send1.ino b/testing/other/send1.ino similarity index 100% rename from firmware/testing/send1.ino rename to testing/other/send1.ino diff --git a/firmware/testing/send2.ino b/testing/other/send2.ino similarity index 100% rename from firmware/testing/send2.ino rename to testing/other/send2.ino diff --git a/firmware/testing/serial1.ino b/testing/other/serial1.ino similarity index 100% rename from firmware/testing/serial1.ino rename to testing/other/serial1.ino diff --git a/firmware/testing/serial2.ino b/testing/other/serial2.ino similarity index 100% rename from firmware/testing/serial2.ino rename to testing/other/serial2.ino diff --git a/firmware/testing/rs485/dev_a.ino b/testing/rs485/dev_a.ino similarity index 100% rename from firmware/testing/rs485/dev_a.ino rename to testing/rs485/dev_a.ino diff --git a/firmware/testing/rs485/dev_b.ino b/testing/rs485/dev_b.ino similarity index 100% rename from firmware/testing/rs485/dev_b.ino rename to testing/rs485/dev_b.ino diff --git a/firmware/testing/rs485/pm8000.reg.h b/testing/rs485/pm8000.reg.h similarity index 100% rename from firmware/testing/rs485/pm8000.reg.h rename to testing/rs485/pm8000.reg.h diff --git a/firmware/testing/rs485/working_reader_datetime.ino b/testing/rs485/working_reader_datetime.ino similarity index 100% rename from firmware/testing/rs485/working_reader_datetime.ino rename to testing/rs485/working_reader_datetime.ino diff --git a/firmware/testing/rs485/working_reader_kwh_del_rec.ino b/testing/rs485/working_reader_kwh_del_rec.ino similarity index 100% rename from firmware/testing/rs485/working_reader_kwh_del_rec.ino rename to testing/rs485/working_reader_kwh_del_rec.ino diff --git a/firmware/testing/rs485/working_reader_string.ino b/testing/rs485/working_reader_string.ino similarity index 100% rename from firmware/testing/rs485/working_reader_string.ino rename to testing/rs485/working_reader_string.ino