Changes for the Arduino Mega setups
This commit is contained in:
356
firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.ino
Normal file
356
firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.ino
Normal 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(®isters[i].regaddr);
|
||||
dataFile.print("@");
|
||||
dataFile.print(regaddr);
|
||||
dataFile.print(",");
|
||||
}
|
||||
headerWritten = true;
|
||||
flicker(LED_A_PIN, 50, 10); // Success pattern: 50 quick blinks
|
||||
}
|
||||
}
|
||||
|
||||
// ==== MAIN PROGRAM LOOP ====
|
||||
void loop() {
|
||||
// If setup failed, wait and try again
|
||||
if (!booted) {
|
||||
delay(10000); // Wait 10 seconds
|
||||
digitalWrite(LED_A_PIN, LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's time for next reading (every 1000ms)
|
||||
if (millis() - lastRefreshTime >= 1000) {
|
||||
lastRefreshTime += 1000;
|
||||
|
||||
// Create new file for today's date
|
||||
char filename[20];
|
||||
getFilename(filename);
|
||||
|
||||
// Try to open the data file
|
||||
if (!dataFile.open(filename, FILE_WRITE)) {
|
||||
flicker(LED_B_PIN, 6, 500); // Error pattern: 6 medium blinks
|
||||
return;
|
||||
}
|
||||
|
||||
// Write header if needed and timestamp
|
||||
writeHeader();
|
||||
writeDateTime(dataFile);
|
||||
|
||||
// Initialize variables for reading registers
|
||||
const uint16_t totalReg = sizeof(registers) / sizeof(registers[0]);
|
||||
float baseValues[4] = {ERROR_VALUE, ERROR_VALUE, ERROR_VALUE, ERROR_VALUE};
|
||||
uint8_t errorCount = 0;
|
||||
|
||||
// Read and process all registers
|
||||
for (uint16_t i = 0; i < totalReg; i++) {
|
||||
// Get register information
|
||||
const uint16_t regaddr = pgm_read_word(®isters[i].regaddr);
|
||||
const uint8_t regtype = pgm_read_word(®isters[i].regtype);
|
||||
const float scale = pgm_read_float(®isters[i].scale);
|
||||
float value = ERROR_VALUE;
|
||||
|
||||
// Read basic register types
|
||||
if (regtype <= 3 && regaddr > 0) {
|
||||
value = readRegisterWithRetry(regaddr, regtype);
|
||||
if (value == ERROR_VALUE) {
|
||||
errorCount++;
|
||||
if (errorCount > 5) { // Too many errors, abort
|
||||
dataFile.close();
|
||||
flicker(LED_B_PIN, 10, 100); // Error pattern: 10 quick blinks
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (i < 4) baseValues[i] = value; // Store first 4 values for calculations
|
||||
} else {
|
||||
// Check if we have valid base values for calculations
|
||||
bool validBase = true;
|
||||
for(uint8_t j = 0; j < 4; j++) {
|
||||
if (baseValues[j] == ERROR_VALUE) {
|
||||
validBase = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate derived values if base values are valid
|
||||
if (validBase) {
|
||||
switch(regtype) {
|
||||
case 4:
|
||||
value = calculateStatusWord(baseValues);
|
||||
break;
|
||||
case 5:
|
||||
value = calculateThermal(baseValues);
|
||||
break;
|
||||
case 6:
|
||||
value = calculatePower(baseValues);
|
||||
break;
|
||||
case 7:
|
||||
value = calculateRPM(baseValues);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply scaling factor if value is valid
|
||||
if (value != ERROR_VALUE) {
|
||||
value *= scale;
|
||||
}
|
||||
// Write value to file
|
||||
dataFile.print(value);
|
||||
dataFile.print(',');
|
||||
}
|
||||
|
||||
// Close file after writing
|
||||
dataFile.close();
|
||||
|
||||
// Report status
|
||||
if (errorCount > 0) {
|
||||
Serial.print(F("Cycle completed with "));
|
||||
Serial.print(errorCount);
|
||||
Serial.println(F(" errors"));
|
||||
flicker(LED_B_PIN, errorCount, 200); // Error pattern: blink count = error count
|
||||
} else {
|
||||
Serial.println(F("Cycle completed successfully"));
|
||||
flicker(LED_A_PIN, 4, 100); // Success pattern: 4 quick blinks
|
||||
}
|
||||
|
||||
// Abort if too many errors
|
||||
if (errorCount > 5) {
|
||||
Serial.println(F("Too many errors, aborting cycle"));
|
||||
dataFile.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
135
firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.md
Normal file
135
firmware/mega/mega-sd-mb-vsd-generic/mega-sd-mb-vsd-generic.md
Normal 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
|
||||
|
||||
63
firmware/mega/mega-sd-mb-vsd-generic/register_map.h
Normal file
63
firmware/mega/mega-sd-mb-vsd-generic/register_map.h
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#ifndef REGISTER_MAP_VSD_H
|
||||
#define REGISTER_MAP_VSD_H
|
||||
struct RegisterMap {
|
||||
uint16_t regaddr;
|
||||
uint8_t regtype; // 1=UINT16, 2=FLOAT32, 3=INT64, 4=Status, 5=Thermal, 6=Power, 7=RPM
|
||||
float scale;
|
||||
};
|
||||
|
||||
const PROGMEM RegisterMap registers[] = {
|
||||
{2910, 4, 1.0}, // Status Word
|
||||
{2911, 6, 1.0}, // Min Active Value
|
||||
{2912, 5, 1.0}, // Thermal Sense
|
||||
{2913, 2, 10.0}, // Frequency
|
||||
{2914, 1, 1.0}, // Running Hours
|
||||
{2916, 1, 1.0}, // Operating Hours
|
||||
{2918, 2, 1.0}, // kWh Counter
|
||||
{2920, 2, 100.0}, // Input Power kW
|
||||
{2922, 6, 134.102}, // Input Power HP
|
||||
{2924, 2, 100.0}, // Motor Current
|
||||
{2926, 2, 100.0}, // Phase I1
|
||||
{2928, 2, 100.0}, // Phase I2
|
||||
{2930, 2, 100.0}, // Phase I3
|
||||
{2932, 7, 60.0}, // Motor RPM
|
||||
{2934, 2, 10.0}, // Motor Voltage
|
||||
{2935, 6, 1.0}, // Torque Nm
|
||||
{2936, 5, 1.0}, // Motor Thermal
|
||||
{2937, 5, 1.0}, // Heatsink Temp
|
||||
{2938, 5, 1.0}, // Card Temp
|
||||
{2939, 5, 1.0}, // Inverter Thermal
|
||||
{2940, 2, 1.0}, // DC Link Voltage
|
||||
{2941, 6, 1.0}, // Motor Torque %
|
||||
{2942, 2, 100.0}, // Inverter Nominal Current
|
||||
{2944, 2, 100.0}, // Inverter Max Current
|
||||
{2946, 4, 1.0}, // Alarm Word 1
|
||||
{2948, 4, 1.0}, // Alarm Word 2
|
||||
{2950, 4, 1.0}, // Warning Word 1
|
||||
{2952, 4, 1.0}, // Warning Word 2
|
||||
{2954, 4, 1.0}, // Power Ups
|
||||
{3000, 5, 1.0} // Over Temp Counter
|
||||
};
|
||||
|
||||
float calculateStatusWord(float* values) {
|
||||
uint16_t status = 0;
|
||||
if(values[0] > 0) status |= 0x0001; // Running
|
||||
if(values[1] > 100) status |= 0x0002; // Overload
|
||||
return status;
|
||||
}
|
||||
|
||||
float calculateThermal(float* values) {
|
||||
return (values[0] / 100.0) * 100.0;
|
||||
}
|
||||
|
||||
float calculatePower(float* values) {
|
||||
return values[0] * 0.746; // kW to HP conversion
|
||||
}
|
||||
|
||||
float calculateRPM(float* values) {
|
||||
return values[0] * 60.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
27
firmware/mega/mega-sd-mb-vsd-generic/util.h
Normal file
27
firmware/mega/mega-sd-mb-vsd-generic/util.h
Normal 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user