Changes for the Arduino Mega setups

This commit is contained in:
2024-12-07 10:20:29 +02:00
parent dc2b3429a6
commit 4c77b98388
45 changed files with 1705 additions and 0 deletions

View File

@@ -0,0 +1,271 @@
#include <Wire.h> // Library for I2C communication
#include <RTClib.h> // Library for Real Time Clock
#include <ModbusMaster.h> // Library for Modbus communication
#include "util.h" // Custom utility functions
#include "register_map.h" // Map of Modbus registers to read
#include <SPI.h> // Library for SPI communication
#include <SdFat.h> // 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(&registers[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(&registers[i].regaddr);
const uint8_t regtype = pgm_read_word(&registers[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);
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,356 @@
#include <Wire.h> // Library for I2C communication (used by RTC)
#include <RTClib.h> // Library for Real Time Clock
#include <ModbusMaster.h> // Library for Modbus communication
#include "util.h" // Custom utility functions
#include "register_map.h" // Map of Modbus registers to read
#include <SPI.h> // Library for SPI communication (used by SD card)
#include <SdFat.h> // 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(&registers[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(&registers[i].regaddr);
const uint8_t regtype = pgm_read_word(&registers[i].regtype);
const float scale = pgm_read_float(&registers[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;
}
}
}

View File

@@ -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

52
firmware/mega/pinout.md Normal file
View File

@@ -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

View File

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

View File

@@ -1,120 +0,0 @@
# Modbus Reading for Generic VSD Device
This is a specification and implementation of the Arduino-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 to connect to Modbus devices, read information, and log it onto an SD card with timestamps.
### Hardware needed:
1. Arduino Board
Recommended: Arduino MEGA 2560 (for more memory and I/O pins) or Arduino UNO (for simpler projects).
- [Arduino MEGA @ R377.20](https://www.robotics.org.za/MEGA-16U2?search=Arduino%20MEGA%202560)
- [UNO R3 with 16U2 USB Interface @ R151.00](https://www.robotics.org.za/UNOR3-16U2?search=%20Arduino%20UNO)
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
#### RS485 Module to Arduino:
1. RO (Receiver Output) to Arduino RX (pin 8)
2. DI (Driver Input) to Arduino TX (pin 7)
3. DE (Driver Enable) & RE (Receiver Enable) to Arduino digital pin 4
4. VCC to 5V on Arduino
5. GND to GND on Arduino
6. A & B (RS485 differential pair) to Modbus device
#### SD Card Module to Arduino:
1. VCC to 5V on Arduino
2. GND to GND on Arduino
3. MOSI to MOSI (pin 51 on MEGA, pin 11 on UNO)
4. MISO to MISO (pin 50 on MEGA, pin 12 on UNO)
5. SCK to SCK (pin 52 on MEGA, pin 13 on UNO)
6. CS (Chip Select) to digital pin 10
#### RTC Module to Arduino:
1. VCC to 5V on the Arduino
2. GND to GND on the Arduino
3. SDA to SDA (pin 20 on MEGA, pin A4 on UNO)
4. SCL to SCL (pin 21 on MEGA, pin A5 on UNO)
#### 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
- NeoSWSerial: For better latency on software serial communication
### Implementation Details
1. Modbus Configuration:
- Slave ID: 101
- Baud Rate: 9600
- Register map: Defined in separate "register_map_pm8000.h" file
2. Data Logging:
- Frequency: Readings taken every second
- File Format: CSV (Comma-Separated Values)
- Filename: "pm8k_YYYYMMDD.csv" (generated daily based on current date)
- Data Structure: Timestamp, followed by register values
- Header Row: Includes register addresses for easy identification
3. Register Types Supported:
- Float (32-bit)
- Integer (32-bit)
- Long (64-bit)
- String (up to 20 characters)
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 (9600 baud)
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
### Programming Workflow
1. Initialize hardware (RTC, SD card, RS485 module)
2. Set up Modbus communication parameters
3. Enter main loop:
- Read current time from RTC
- Read data from Modbus registers
- Write timestamped data to SD card
- Handle any errors and provide status indication via LEDs
- Delay for 1 second before next reading
## Best Practices
- Start by commenting out registers you don't need before adding new ones.
- If you're using an Arduino UNO, you may need to be more selective about which registers to include due to memory constraints.
- Test your modifications incrementally to ensure the Arduino can handle the memory load.
- If you need to read a large number of registers, consider using an Arduino MEGA or a more powerful microcontroller.
By carefully managing the registers in the `register_map_vsd.h` file, you can customize this Modbus reader to suit your specific requirements while staying within the memory limitations of your Arduino board.

View File

@@ -1,199 +0,0 @@
#include <Wire.h>
#include <RTClib.h>
#include <NeoSWSerial.h>
#include <ModbusMaster.h>
#include "PM8000_Modbus_Map_ad.h"
//#include <SD.h>
#include <SPI.h>
#include <SdFat.h>
#define SD_CS_PIN 10 // Chip Select for SD Card
//RS485 pins
#define DE_RE_PIN 4
#define RX_PIN 8 // SoftwareSerial RX pin
#define TX_PIN 7 // SoftwareSerial TX pin
#define SLAVE_ID 101
#define SERIAL_BAUDRATE 9600
// Try to select the best SD card configuration.
#define SPI_CLOCK SD_SCK_MHZ(50)
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
RTC_DS3231 rtc; // Create an RTC object
SdFat32 sd;
//SdExFat sd;
File dataFile;
NeoSWSerial modbusSerial(RX_PIN, TX_PIN); // Create a software serial instance
ModbusMaster node;
void setup()
{
Serial.begin(SERIAL_BAUDRATE); // For debugging
Serial.println(F("Startup \n"));
// Initialize RTC
if (!rtc.begin())
{
Serial.println(F("Couldn't find RTC\n"));
}
if (rtc.lostPower())
{
Serial.println(F("RTC lost power, let's set the time!\n"));
// Comment out the following line once the time is set to avoid resetting on every start
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
Serial.print(F("Time: "));
Serial.print(rtc.now().timestamp());
Serial.println(F("\n"));
// Initialize SD card
Serial.println(F("SD card initializing..."));
pinMode(SD_CS_PIN, OUTPUT);
// if (!SD.begin(SPI_HALF_SPEED, SD_CS_PIN ))
// {
// Serial.println(F("SD card initialization failed!\n"));
// return;
// }
// Initialize the SD.
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
return;
}
Serial.println(F("SD card initialized.\n"));
Serial.println(F("Initialize RS485 module / Modbus \n"));
pinMode(DE_RE_PIN, OUTPUT);
digitalWrite(DE_RE_PIN, LOW); // Set to LOW for receiving mode initially
modbusSerial.begin(SERIAL_BAUDRATE);
node.begin(SLAVE_ID, modbusSerial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void preTransmission()
{
digitalWrite(DE_RE_PIN, HIGH); // Enable RS485 transmit
}
void postTransmission()
{
digitalWrite(DE_RE_PIN, LOW); // Disable RS485 transmit
}
void writeFile(char *str)
{
if (!dataFile)
{
Serial.println(F("Error opening file"));
return;
}
DateTime now = rtc.now();
// Log the current date and time
dataFile.print(now.year(), DEC);
dataFile.print('-');
dataFile.print(now.month(), DEC);
dataFile.print('-');
dataFile.print(now.day(), DEC);
dataFile.print(" ");
dataFile.print(now.hour(), DEC);
dataFile.print(':');
dataFile.print(now.minute(), DEC);
dataFile.print(':');
dataFile.print(now.second(), DEC);
dataFile.print(F(","));
dataFile.print(str);
dataFile.println();
}
String getFilename()
{
DateTime now = rtc.now();
String mb = F("");
mb += now.year();
mb += now.month();
mb += now.day();
mb += F(".csv");
return mb;
}
unsigned long lastRefreshTime = 0;
void loop()
{
delay(100);
if(millis() - lastRefreshTime >= 1000)
{
lastRefreshTime += 1000;
Serial.print(F("\nTime: "));
Serial.print(rtc.now().timestamp());
// Serial.print("\nHeep:");
// Serial.print(ESP.getFreeHeap());
Serial.print("\n");
// Open file for writing
String filename = getFilename();
dataFile.open(filename.c_str(), FILE_WRITE);
Serial.print(F("Open Card "));
Serial.print(filename.c_str());
Serial.print("\n");
String mb = "modbus,";
writeFile(mb.c_str());
if (dataFile)
{
dataFile.close(); // Close the file
Serial.print(F("Data written to SD card: "));
Serial.print(filename.c_str());
Serial.print(F("\n"));
}
Serial.print(F("\n\n"));
}
for (int i = 0; i < 10; i++) {
Serial.print(F("\naddress: "));
Serial.print(registers[i].regaddr);
Serial.print(F("\ntype: "));
Serial.print(registers[i].regtype);
Serial.print(F("\n "));
if (registers[i].regaddr > 0) {
uint8_t result = node.readHoldingRegisters(registers[i].regaddr , 2);
if (result == node.ku8MBSuccess)
{
Serial.print(F("Modbus Read successful:"));
} else {
Serial.print(F("Modbus Read error: "));
Serial.println(result, HEX);
}
}
}
// // Check if the read was successful
delay(100);
}

View File

@@ -1,99 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define the pins for SoftwareSerial communication
#define RX_PIN 7 // RX pin for SoftwareSerial
#define TX_PIN 6 // TX pin for SoftwareSerial
#define TX_ENABLE_PIN 4 // Pin to control RS485 direction
#define DE_ENABLE_PIN 5
// Create a SoftwareSerial object
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);
// Create an instance of the ModbusMaster class
ModbusMaster node;
// Function to control RS485 transmit enable
void preTransmission()
{
digitalWrite(TX_ENABLE_PIN, HIGH); // Enable RS485 transmit
}
void postTransmission()
{
digitalWrite(TX_ENABLE_PIN, LOW); // Disable RS485 transmit
}
void setup()
{
// Initialize the built-in serial port for debugging
Serial.begin(9600);
// Initialize SoftwareSerial for Modbus communication
modbusSerial.begin(9600);
pinMode(DE_ENABLE_PIN, OUTPUT);
digitalWrite(DE_ENABLE_PIN, HIGH);
// Set the pin mode for the RS485 control pin
pinMode(TX_ENABLE_PIN, OUTPUT);
digitalWrite(TX_ENABLE_PIN, LOW);
// Modbus communication setup
node.begin(1, modbusSerial); // Slave ID = 1, use modbusSerial for RS485 communication
// Set callbacks to handle RS485 flow control
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop()
{
static uint16_t count = 0;
uint8_t result;
uint16_t data[6];
// Read 6 holding registers starting at address 0x0000
result = node.readHoldingRegisters(0x0000, 6);
// Check if the read was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Read successful: ");
for (uint8_t j = 0; j < 6; j++)
{
data[j] = node.getResponseBuffer(j);
Serial.print(data[j], HEX);
Serial.print(" ");
}
Serial.println();
}
else
{
Serial.print("Read error: ");
Serial.println(result, HEX);
}
// Write the count value to the holding register at address 0x0001
result = node.writeSingleRegister(0x0001, count);
// Check if the write was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Write successful: ");
Serial.println(count);
}
else
{
Serial.print("Write error: ");
Serial.println(result, HEX);
}
// Increment the count value
count++;
// Delay before the next read cycle
delay(1000);
}

View File

@@ -1,67 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define software serial pins (use any digital pins if not using hardware serial)
#define RX_PIN 13
#define TX_PIN 12
#define DE_PIN 3
#define RE_PIN 4
SoftwareSerial s1(RX_PIN, TX_PIN);
void setup() {
// Start the software serial port
s1.begin(9600 );
//pinMode(RX_PIN, INPUT);
//pinMode(TX_PIN, OUTPUT);
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
//node.setTimeout(2000);
// Optionally, start the Serial monitor for debugging
Serial.begin(9600);
while (!s1) {
}
Serial.println("Setup done B");
}
int byteReceived;
static unsigned long lastRefreshTime = 0;
static unsigned long cnt = 0;
void loop() {
cnt++;
if (s1.available()) //Look for data from other Arduino
{
int inByte = s1.read();
Serial.write(inByte);
}
//delay(100); // Wait a second before the next loop
if(millis() - lastRefreshTime >= 1000)
{
digitalWrite(RE_PIN, HIGH);
digitalWrite(DE_PIN, HIGH);
s1.print("Its working.....");
s1.println(cnt);
s1.flush();
//delay(1000);
digitalWrite(RE_PIN, LOW);
digitalWrite(DE_PIN, LOW);
lastRefreshTime += 1000;
Serial.println("Cycle2\n\n");
}
}

View File

@@ -1,70 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define software serial pins (use any digital pins if not using hardware serial)
#define RX_PIN 13
#define TX_PIN 12
#define DE_PIN 3
#define RE_PIN 4
SoftwareSerial s1(RX_PIN, TX_PIN);
void setup() {
// Start the software serial port
s1.begin(9600 );
//pinMode(RX_PIN, INPUT);
//pinMode(TX_PIN, OUTPUT);
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
//node.setTimeout(2000);
// Optionally, start the Serial monitor for debugging
Serial.begin(9600);
while (!s1) {
}
Serial.println("Setup done A");
}
void loop() {
static unsigned long lastRefreshTime = 0;
s1.listen();
while (s1.available() > 0) {
int inByte = s1.read();
Serial.write(inByte);
}
//delay(10); // Wait a second before the next loop
// digitalWrite(RE_PIN, HIGH);
// s1.print("Hello");
// digitalWrite(RE_PIN, LOW);
if(millis() - lastRefreshTime >= 1000)
{
lastRefreshTime += 1000;
Serial.println("Cycle\n\n");
digitalWrite(RE_PIN, HIGH);
digitalWrite(DE_PIN, HIGH);
s1.print("Ping..");
s1.flush();
//delay(1000);
digitalWrite(RE_PIN, LOW);
digitalWrite(DE_PIN, LOW);
}
}

View File

@@ -1,108 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define software serial pins (use any digital pins if not using hardware serial)
#define RX_PIN 13
#define TX_PIN 12
#define DE_PIN 3
#define RE_PIN 4
SoftwareSerial s1(RX_PIN, TX_PIN);
ModbusMaster node;
uint16_t holdingRegisters[20];
void setup() {
// Start the software serial port
s1.begin(9600 );
//pinMode(RX_PIN, INPUT);
//pinMode(TX_PIN, OUTPUT);
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
//node.setTimeout(2000);
// Optionally, start the Serial monitor for debugging
Serial.begin(9600);
while (!s1) {
}
node.begin(101, s1);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void preTransmission()
{
digitalWrite(DE_PIN, HIGH); // Enable RS485 transmit
digitalWrite(RE_PIN, HIGH);
}
void postTransmission()
{
digitalWrite(DE_PIN, LOW); // Disable RS485 transmit
digitalWrite(RE_PIN, LOW);
}
static unsigned long lastRefreshTime = 0;
#define ReadSize 4
void loop() {
static uint16_t count = 0;
uint8_t result;
int16_t data[ReadSize];
//delay(100); // Wait a second before the next loop
// digitalWrite(RE_PIN, HIGH);
// s1.print("Hello");
// digitalWrite(RE_PIN, LOW);
if(millis() - lastRefreshTime >= 1000)
{
lastRefreshTime += 1000;
Serial.print("Cycle\n\n");
result = node.readHoldingRegisters(1836 , 8);
// Check if the read was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Meter Date Time Read successful: ");
Serial.print("Y : ");
Serial.println(node.getResponseBuffer(0));
Serial.print("M : ");
Serial.println(node.getResponseBuffer(1));
Serial.print("D : ");
Serial.println(node.getResponseBuffer(2));
Serial.print("H : ");
Serial.println(node.getResponseBuffer(3));
Serial.print("M : ");
Serial.println(node.getResponseBuffer(4));
// for (uint8_t j = 0; j < ReadSize; j++)
// {
// int recv = node.getResponseBuffer(j);
// data[j] = recv;
// Serial.print(recv );
// }
// Serial.print("\nHEX:");
// for (uint8_t j = 0; j < ReadSize; j++)
// {
// Serial.print(data[j],"HEX");
// }
// Serial.println();
} else {
Serial.print("Read error: ");
Serial.println(result, HEX);
}
}
}

View File

@@ -1,109 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define software serial pins (use any digital pins if not using hardware serial)
#define RX_PIN 13
#define TX_PIN 12
#define DE_PIN 3
#define RE_PIN 4
SoftwareSerial s1(RX_PIN, TX_PIN);
ModbusMaster node;
uint16_t holdingRegisters[20];
void setup() {
// Start the software serial port
s1.begin(9600 );
//pinMode(RX_PIN, INPUT);
//pinMode(TX_PIN, OUTPUT);
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
//node.setTimeout(2000);
// Optionally, start the Serial monitor for debugging
Serial.begin(9600);
while (!s1) {
}
node.begin(101, s1);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void preTransmission()
{
digitalWrite(DE_PIN, HIGH); // Enable RS485 transmit
digitalWrite(RE_PIN, HIGH);
}
void postTransmission()
{
digitalWrite(DE_PIN, LOW); // Disable RS485 transmit
digitalWrite(RE_PIN, LOW);
}
static unsigned long lastRefreshTime = 0;
#define ReadSize 4
void loop() {
static uint16_t count = 0;
uint8_t result;
int16_t data[ReadSize];
//delay(100); // Wait a second before the next loop
// digitalWrite(RE_PIN, HIGH);
// s1.print("Hello");
// digitalWrite(RE_PIN, LOW);
if(millis() - lastRefreshTime >= 1000)
{
lastRefreshTime += 1000;
Serial.print("Cycle\n\n");
result = node.readHoldingRegisters(2705 , 2);
// Check if the read was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Read successful: ");
uint16_t highWord = node.getResponseBuffer(0);
uint16_t lowWord = node.getResponseBuffer(1);
uint32_t floatRaw = ((uint32_t)highWord << 16) | lowWord; // Combine registers
float floatValue;
// Convert raw 32-bit value to float
memcpy(&floatValue, &floatRaw, sizeof(float));
Serial.print("Float value: ");
Serial.println(floatValue);
// for (uint8_t j = 0; j < ReadSize; j++)
// {
// int recv = node.getResponseBuffer(j);
// data[j] = recv;
// Serial.print(recv );
// }
// Serial.print("\nHEX:");
// for (uint8_t j = 0; j < ReadSize; j++)
// {
// Serial.print(data[j],"HEX");
// }
// Serial.println();
} else {
Serial.print("Read error: ");
Serial.println(result, HEX);
}
}
}

View File

@@ -1,99 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define software serial pins (use any digital pins if not using hardware serial)
#define RX_PIN 13
#define TX_PIN 12
#define DE_PIN 3
#define RE_PIN 4
SoftwareSerial s1(RX_PIN, TX_PIN);
ModbusMaster node;
uint16_t holdingRegisters[20];
void setup() {
// Start the software serial port
s1.begin(9600 );
//pinMode(RX_PIN, INPUT);
//pinMode(TX_PIN, OUTPUT);
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
digitalWrite(DE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
//node.setTimeout(2000);
// Optionally, start the Serial monitor for debugging
Serial.begin(9600);
while (!s1) {
}
node.begin(101, s1);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void preTransmission()
{
digitalWrite(DE_PIN, HIGH); // Enable RS485 transmit
digitalWrite(RE_PIN, HIGH);
}
void postTransmission()
{
digitalWrite(DE_PIN, LOW); // Disable RS485 transmit
digitalWrite(RE_PIN, LOW);
}
static unsigned long lastRefreshTime = 0;
#define ReadSize 4
void loop() {
static uint16_t count = 0;
uint8_t result;
int16_t data[ReadSize];
//delay(100); // Wait a second before the next loop
// digitalWrite(RE_PIN, HIGH);
// s1.print("Hello");
// digitalWrite(RE_PIN, LOW);
if(millis() - lastRefreshTime >= 1000)
{
lastRefreshTime += 1000;
Serial.print("Cycle\n\n");
result = node.readHoldingRegisters(29 , 70);
// Check if the read was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Read successful: ");
for (uint8_t j = 0; j < 70; j++)
{
uint8_t v = node.getResponseBuffer(j);
char a = v;
if (v == 0) {
continue;
}
Serial.print(a);
}
} else {
Serial.print("Read error: ");
Serial.println(result, HEX);
}
}
}

View File

@@ -1,81 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define the pins for SoftwareSerial communication
#define RX_PIN 13 // RX pin for SoftwareSerial
#define TX_PIN 12 // TX pin for SoftwareSerial
#define TX_ENABLE_PIN 4 // Pin to control RS485 direction
#define DE_ENABLE_PIN 5
// Create a SoftwareSerial object
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);
// Create an instance of the ModbusMaster class
ModbusMaster node;
// Function to control RS485 transmit enable
void preTransmission()
{
digitalWrite(TX_ENABLE_PIN, HIGH); // Enable RS485 transmit
digitalWrite(DE_ENABLE_PIN, HIGH);
}
void postTransmission()
{
digitalWrite(TX_ENABLE_PIN, LOW); // Disable RS485 transmit
digitalWrite(DE_ENABLE_PIN, LOW);
}
void setup()
{
// Initialize the built-in serial port for debugging
Serial.begin(9600);
// Initialize SoftwareSerial for Modbus communication
modbusSerial.begin(9600);
pinMode(DE_ENABLE_PIN, OUTPUT);
digitalWrite(DE_ENABLE_PIN, HIGH);
// Set the pin mode for the RS485 control pin
pinMode(TX_ENABLE_PIN, OUTPUT);
digitalWrite(TX_ENABLE_PIN, LOW);
// Modbus communication setup
node.begin(1, modbusSerial); // Slave ID = 1, use modbusSerial for RS485 communication
// Set callbacks to handle RS485 flow control
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop()
{
static uint16_t count = 0;
uint8_t result;
uint16_t data[6];
Serial.print("Loop:");
Serial.println(count);
// Write the count value to the holding register at address 0x0001
result = node.writeSingleRegister(0x0001, count);
// Check if the write was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Write successful: ");
Serial.println(count);
}
else
{
Serial.print("Write error: ");
Serial.println(result, HEX);
}
// Increment the count value
count++;
// Delay before the next read cycle
delay(1000);
}

View File

@@ -1,81 +0,0 @@
#include <ModbusMaster.h>
#include <SoftwareSerial.h>
// Define the pins for SoftwareSerial communication
#define RX_PIN 3 // RX pin for SoftwareSerial
#define TX_PIN 4 // TX pin for SoftwareSerial
#define TX_ENABLE_PIN 2 // Pin to control RS485 direction
#define DE_ENABLE_PIN 5
// Create a SoftwareSerial object
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);
// Create an instance of the ModbusMaster class
ModbusMaster node;
// Function to control RS485 transmit enable
void preTransmission()
{
digitalWrite(TX_ENABLE_PIN, HIGH); // Enable RS485 transmit
digitalWrite(DE_ENABLE_PIN, HIGH);
}
void postTransmission()
{
digitalWrite(TX_ENABLE_PIN, LOW); // Disable RS485 transmit
digitalWrite(DE_ENABLE_PIN, LOW);
}
void setup()
{
// Initialize the built-in serial port for debugging
Serial.begin(9600);
// Initialize SoftwareSerial for Modbus communication
modbusSerial.begin(9600);
pinMode(DE_ENABLE_PIN, OUTPUT);
digitalWrite(DE_ENABLE_PIN, HIGH);
// Set the pin mode for the RS485 control pin
pinMode(TX_ENABLE_PIN, OUTPUT);
digitalWrite(TX_ENABLE_PIN, LOW);
// Modbus communication setup
node.begin(1, modbusSerial); // Slave ID = 1, use modbusSerial for RS485 communication
// Set callbacks to handle RS485 flow control
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop()
{
static uint16_t count = 0;
uint8_t result;
uint16_t data[6];
Serial.print("Loop:");
Serial.println(count);
// Write the count value to the holding register at address 0x0001
result = node.writeSingleRegister(0x0001, count);
// Check if the write was successful
if (result == node.ku8MBSuccess)
{
Serial.print("Write successful: ");
Serial.println(count);
}
else
{
Serial.print("Write error: ");
Serial.println(result, HEX);
}
// Increment the count value
count++;
// Delay before the next read cycle
delay(1000);
}

View File

@@ -1,57 +0,0 @@
/*-----( Import needed libraries )-----*/
#include <SoftwareSerial.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define SSerialRX 13 //Serial Receive pin
#define SSerialTX 12 //Serial Transmit pin
#define SSerialTxControl 4 //RS485 Direction control
#define RS485Transmit HIGH
#define RS485Receive LOW
#define Pin13LED 9
/*-----( Declare objects )-----*/
SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
/*-----( Declare Variables )-----*/
int byteReceived;
int byteSend;
void setup() /****** SETUP: RUNS ONCE ******/
{
// Start the built-in serial port, probably to Serial Monitor
Serial.begin(9600);
Serial.println("Remote connector"); // Can be ignored
pinMode(Pin13LED, OUTPUT);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Receive); // Init Transceiver
// Start the software serial port, to another device
RS485Serial.begin(9600); // set the data rate
}//--(end setup )---
void loop() /****** LOOP: RUNS CONSTANTLY ******/
{
//Copy input data to output
if (RS485Serial.available())
{
byteSend = RS485Serial.read(); // Read the byte
digitalWrite(Pin13LED, HIGH); // Show activity
delay(1);
digitalWrite(Pin13LED, LOW);
digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit
RS485Serial.write(byteSend); // Send the byte back
//delay(10);
digitalWrite(SSerialTxControl, RS485Receive); // Disable RS485 Transmit
Serial.println("Bounce");
Serial.println(byteSend);
// delay(100);
}// End If RS485SerialAvailable
}//--(end main loop )---

View File

@@ -1,72 +0,0 @@
/*-----( Import needed libraries )-----*/
#include <SoftwareSerial.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define SSerialRX 13 //Serial Receive pin
#define SSerialTX 12 //Serial Transmit pin
#define SSerialTxControl 4 //RS485 Direction control
#define RS485Transmit HIGH
#define RS485Receive LOW
#define Pin13LED 9
/*-----( Declare objects )-----*/
SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
/*-----( Declare Variables )-----*/
int byteReceived;
int byteSend;
void setup() /****** SETUP: RUNS ONCE ******/
{
// Start the built-in serial port, probably to Serial Monitor
Serial.begin(9600);
Serial.println("Master connector");
pinMode(Pin13LED, OUTPUT);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Receive); // Init Transceiver
// Start the software serial port, to another device
RS485Serial.begin(9600); // set the data rate
}//--(end setup )---
void loop() /****** LOOP: RUNS CONSTANTLY ******/
{
digitalWrite(Pin13LED, HIGH); // Show activity
if (Serial.available())
{
byteReceived = Serial.read();
digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit
RS485Serial.write(byteReceived); // Send byte to Remote Arduino
digitalWrite(Pin13LED, LOW); // Show activity
//Serial.println("\nRead Local");
delay(10);
digitalWrite(SSerialTxControl, RS485Receive); // Disable RS485 Transmit
}
if (RS485Serial.available()) //Look for data from other Arduino
{
digitalWrite(Pin13LED, HIGH); // Show activity
byteReceived = RS485Serial.read(); // Read received byte
Serial.println("Received ");
Serial.write(byteReceived); // Show on Serial Monitor
delay(10);
digitalWrite(Pin13LED, LOW); // Show activity
}
}//--(end main loop )---
/*-----( Declare User-written Functions )-----*/
//NONE
//*********( THE END )***********

View File

@@ -0,0 +1,602 @@
#include <stdint.h>
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
}
;

View File

@@ -0,0 +1,27 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
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;
}

37
firmware/uno/pinout.md Normal file
View File

@@ -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