├── LICENSE.txt ├── README.md ├── examples └── ReadVEDirect │ └── ReadVEDirect.ino ├── keywords.txt ├── library.properties └── src ├── VEDirect.cpp └── VEDirect.h /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Brendan McLearie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VictronVEDirectArduino 2 | Lightweight Arduino library to read data using the VE.Direct protocol from Victron Energy devices 3 | 4 | Built as part of a larger project, now making it available separately in case others find it useful. 5 | 6 | Setup: 7 | - An Arduino(ish) board 8 | - A Victron Energy device that sends serial data using the text version of the VE.Direct protocol 9 | - A 5v to 3.3v serial converter (BMV is 3.3v - don't plug it directly into a 5v Arduino!) 10 | - Plugged into the Arduino on a serial port (eg Serial1, Serial2, Serial3 etc) 11 | - See also: https://www.victronenergy.com/live/vedirect_protocol:faq 12 | - Developed and tested with a BMV-700 battery monitor, should work with any that talk VE.Direct 13 | - Distributed under an MIT license - see LICENCE.txt 14 | 15 | Provides: 16 | - Read access to VE.Direct statistics and settings 17 | - Defaults set to read Volts, Power, Current, State of Charge (SOC), Alarm 18 | - Easily extendible by adding labels for any other stats and settings of interest 19 | - A diagnostic "full dump" of everything coming from the device 20 | 21 | This branch implements SoftwareSerial primarily for ESP8266 boards that need their native USB port for debug purposes. 22 | 23 | ### Usage: 24 | ```C 25 | #include "VEDirect.h" 26 | 27 | // Serial pins 28 | #define rxPin D7 29 | #define txPin D8 30 | 31 | VEDirect my_bmv(rxPin, txPin); 32 | my_int32 = my_bmv.read(VE_SOC); 33 | 34 | // VE_SOC, VE_VOLTAGE, VE_CURRENT, VE_POWER, VE_ALARM 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /examples/ReadVEDirect/ReadVEDirect.ino: -------------------------------------------------------------------------------- 1 | /****************************************************************** 2 | VEDirect Arduino 3 | 4 | Copyright 2018, 2019, Brendan McLearie 5 | Distributed under MIT license - see LICENSE.txt 6 | 7 | See README.md 8 | 9 | File: ReadVEDirect.ino / ReadVEDirect.cpp 10 | - Provides example use of the VEDirect library 11 | 12 | 2020.04.10 - convert to SoftwareSerial 13 | ******************************************************************/ 14 | 15 | #include "Arduino.h" 16 | #include "VEDirect.h" 17 | 18 | // Serial pins 19 | #define rxPin D7 20 | #define txPin D8 21 | 22 | // 32 bit ints to collect the data from the device 23 | int32_t VE_soc, VE_power, VE_voltage, VE_current; 24 | // Boolean to collect an ON/OFF value 25 | uint8_t VE_alarm; 26 | 27 | // VEDirect instantiated with relevant serial object 28 | VEDirect myve(rxPin, txPin); 29 | 30 | void setup() { 31 | Serial.begin(19200); // Adjust as needed - DEBUG serial port 32 | } 33 | 34 | void loop() { 35 | Serial.println("Reading values from Victron Energy device using VE.Direct text mode"); 36 | Serial.println(); 37 | 38 | // Read the data 39 | if(myve.begin()) { // test connection 40 | VE_soc = myve.read(VE_SOC); 41 | VE_power = myve.read(VE_POWER); 42 | VE_voltage = myve.read(VE_VOLTAGE); 43 | VE_current = myve.read(VE_CURRENT); 44 | VE_alarm = myve.read(VE_ALARM); 45 | } else { 46 | Serial.println("Could not open serial port to VE device"); 47 | while (1); 48 | } 49 | 50 | // Print each of the values 51 | Serial.print("State of Charge (SOC): "); 52 | Serial.println(VE_soc, DEC); 53 | Serial.print("Power: "); 54 | Serial.println(VE_power, DEC); 55 | Serial.print("Voltage "); 56 | Serial.println(VE_voltage, DEC); 57 | Serial.print("Current "); 58 | Serial.println(VE_current, DEC); 59 | Serial.print("Alarm "); 60 | Serial.println(VE_alarm, DEC); 61 | Serial.println(); 62 | 63 | // Copy the raw data stream (minus the \r) to Serial0 64 | // Call read() with a token that won't match any VE.Direct labels 65 | Serial.println("All data from device:"); 66 | myve.read(VE_DUMP); 67 | Serial.println(); 68 | delay(10000); 69 | } 70 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # Syntax Coloring Map For VictronVEDirectArduino 2 | 3 | # Datatypes (KEYWORD1) 4 | VE_DIRECT_DATA KEYWORD1 5 | VEDirect KEYWORD1 6 | 7 | # Methods and Functions (KEYWORD2) 8 | begin KEYWORD2 9 | read KEYWORD2 10 | 11 | # Instances (KEYWORD2) 12 | 13 | # Structures (KEYWORD3) 14 | 15 | # Constants (LITERAL1) 16 | ved_labels LITERAL1 17 | VED_LINE_SIZE LITERAL1 18 | VED_MAX_LEBEL_SIZE LITERAL1 19 | VED_MAX_READ_LOOPS LITERAL1 20 | VED_MAX_READ_LINES LITERAL1 21 | VED_BAUD_RATE LITERAL1 22 | VE_DUMP LITERAL1 23 | VE_SOC LITERAL1 24 | VE_VOLTAGE LITERAL1 25 | VE_POWER LITERAL1 26 | VE_CURRENT LITERAL1 27 | VE_ALARM LITERAL1 28 | VE_LAST_LABEL LITERAL1 29 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=VictronVEDirectArduino 2 | version=1.0.0 3 | author=Brendan McLearie 4 | maintainer=Brendan McLearie 5 | sentence=Read VE.Direct protocol data from Victron Energy devices 6 | paragraph=Lightweight Arduino library to read data using the VE.Direct protocol from Victron Energy 7 | category=Communication 8 | url=https://github.com/winginitau/VictronVEDirectArduino 9 | architectures=avr 10 | includes=VEDirect.h 11 | -------------------------------------------------------------------------------- /src/VEDirect.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************** 2 | VEDirect Arduino 3 | 4 | Copyright 2018, 2019, Brendan McLearie 5 | Distributed under MIT license - see LICENSE.txt 6 | 7 | See README.md 8 | 9 | File: VEDirect.cpp 10 | - Implementation 11 | Updates: 12 | - 2019-07-14 See VEDirect.h 13 | - 2020-04-10 Converted to SoftwareSerial, added checks for null pointers for ESP8266 14 | - 2020-08-31 Removed errant constructor 15 | ******************************************************************/ 16 | 17 | #include "VEDirect.h" 18 | 19 | VEDirect::VEDirect(byte rxPin, byte txPin): 20 | VESerial(*new SoftwareSerial(rxPin, txPin)) 21 | // Initialise the serial port that the 22 | // VE.Direct device is connected to and 23 | // store it for later use. 24 | { 25 | } 26 | 27 | VEDirect::~VEDirect() { 28 | // virtual destructor 29 | } 30 | 31 | uint8_t VEDirect::begin() { 32 | // Check connection the serial port 33 | VESerial.begin(VED_BAUD_RATE); 34 | if (VESerial) { 35 | delay(500); 36 | if(VESerial.available()) { 37 | VESerial.flush(); 38 | VESerial.end(); 39 | return 1; 40 | } 41 | } 42 | return 0; 43 | } 44 | 45 | int32_t VEDirect::read(uint8_t target) { 46 | // Read VE.Direct lines from the serial port 47 | // Search for the label specified by enum target 48 | // Extract and return the corresponding value 49 | // If value is "ON" return 1. If "OFF" return 0; 50 | 51 | uint16_t loops = VED_MAX_READ_LOOPS; 52 | uint8_t lines = VED_MAX_READ_LINES; 53 | int32_t ret = 0; // The value to be returned 54 | char line[VED_LINE_SIZE] = "\0"; // Line buffer 55 | uint8_t idx = 0; // Line buffer index 56 | char* label; 57 | char* value_str; 58 | int8_t b; // byte read from the stream 59 | 60 | VESerial.begin(VED_BAUD_RATE); 61 | 62 | while (lines > 0) { 63 | if (VESerial.available()) { 64 | while (loops > 0) { 65 | b = VESerial.read(); 66 | if ((b == -1) || (b == '\r')) { // Ignore '\r' and empty reads 67 | loops--; 68 | } else { 69 | if (b == '\n') { // EOL 70 | break; 71 | } else { 72 | if (idx < VED_LINE_SIZE) { 73 | line[idx++] = b; // Add it to the buffer 74 | } else { 75 | return 0; // Buffer overrun 76 | } 77 | } 78 | } 79 | } 80 | line[idx] = '\0'; // Terminate the string 81 | 82 | // Line in buffer 83 | if (target == VE_DUMP) { 84 | // Diagnostic routine - just print to Serial0; 85 | Serial.println(line); 86 | // Continue on rather than break to reset for next line 87 | } 88 | 89 | label = strtok(line, "\t"); 90 | if (label) { 91 | if (strcmp_P(label, ved_labels[target]) == 0) { 92 | value_str = strtok(0, "\t"); 93 | if (value_str) { 94 | if (value_str[0] == 'O') { //ON OFF type 95 | if (value_str[1] == 'N') { 96 | ret = 1; // ON 97 | break; 98 | } else { 99 | ret = 0; // OFF 100 | break; 101 | } 102 | } else { 103 | sscanf(value_str, "%ld", &ret); 104 | break; 105 | } 106 | } 107 | } else { // Line not of interest 108 | lines--; 109 | loops = VED_MAX_READ_LOOPS; 110 | line[0] = '\0'; 111 | idx = 0; 112 | } 113 | } 114 | } 115 | } 116 | return ret; 117 | } 118 | 119 | void VEDirect::copy_raw_to_serial0() { 120 | read(VE_DUMP); 121 | } 122 | 123 | -------------------------------------------------------------------------------- /src/VEDirect.h: -------------------------------------------------------------------------------- 1 | /****************************************************************** 2 | VEDirect Arduino 3 | 4 | Copyright 2018, 2019, Brendan McLearie 5 | Distributed under MIT license - see LICENSE.txt 6 | 7 | See README.md 8 | 9 | File: VEDirect.h 10 | - Class / enums / API 11 | 12 | Updates: 13 | - 2019-07-14: 14 | - Rewrite of read - cleaner. 15 | - Target labels extendible with enum and PROGMEM strings 16 | - Retired copy_raw_to_serial0() code - use VE_DUMP on read 17 | - Added some tunable parameters see #defines 18 | - 2020-04-10: 19 | - Convert to SoftwareSerial so ESP8266 can use native usb serial for debug 20 | ******************************************************************/ 21 | 22 | #ifndef VEDIRECT_H_ 23 | #define VEDIRECT_H_ 24 | 25 | #include 26 | #include 27 | 28 | // Tunable parameters - defaults tested on mega2560 R3 29 | #define VED_LINE_SIZE 30 // Seems to be plenty. VE.Direct protocol could change 30 | #define VED_MAX_LEBEL_SIZE 6 // Max length of all labels of interest + '\0'. See ved_labels[] 31 | #define VED_MAX_READ_LOOPS 60000 // How many read loops to be considered a read time-out 32 | #define VED_MAX_READ_LINES 50 // How many lines to read looking for a value 33 | // before giving up. Also determines lines for diag dump 34 | #define VED_BAUD_RATE 19200 35 | 36 | // Extend this and ved_labels[] for needed inclusions 37 | enum VE_DIRECT_DATA { 38 | VE_DUMP = 0, 39 | VE_SOC, 40 | VE_VOLTAGE, 41 | VE_POWER, 42 | VE_CURRENT, 43 | VE_ALARM, 44 | VE_LAST_LABEL, 45 | }; 46 | 47 | const char ved_labels[VE_LAST_LABEL][VED_MAX_LEBEL_SIZE] PROGMEM = { 48 | "Dump", // a string that won't match any label 49 | "SOC", 50 | "V", 51 | "P", 52 | "I", 53 | "Alarm", 54 | }; 55 | 56 | class VEDirect { 57 | public: 58 | VEDirect(byte rxPin, byte txPin); 59 | virtual ~VEDirect(); 60 | uint8_t begin(); 61 | int32_t read(uint8_t target); 62 | void copy_raw_to_serial0(); // kept for backwards compatibility 63 | private: 64 | SoftwareSerial& VESerial; 65 | }; 66 | 67 | #endif /* VEDIRECT_H_ */ 68 | --------------------------------------------------------------------------------