2021-03-24, 11:04 AM
(2021-03-22, 08:46 PM)PaddyB Wrote:(2021-03-22, 08:10 PM)affinite Wrote: So the VE.Direct cable is plugged into your battery monitor, not the charge controller ?
The reason I ask is that, if I ever get back to my boat, I plan to fit a Victron Smart Solar MPTT and wondered if anything other than the VE.Direct cable was necessary to get SK out to Openplotter ?
(I dont have a Victron battery monitor or shunt - Ive made my own)
I have an arduino nano doing that, just one wire from the smart solar ve direct, TX. Only 4 data fields so far, but useful. The smartsolar ve direct is 5v so no voltage stepdown needed. Well worth thinking about a smart shunt if you spend a lot of time onboard away from mains power, the smartshunt talks to the mppt so it knows when to go to float based on battery info, otherwise it goes to float too early and the batteries never get fully charged.
Code:#include <SoftwareSerial.h>
#include <ArduinoJson.h> //Must be version 5, not 6.
SoftwareSerial mySerial(10, 11); // RX, TX
String Data = "";
unsigned long currentMillis;
unsigned long timer1_Millis = currentMillis;
String input_flag = "mppt";
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// set the data rate for the SoftwareSerial port
mySerial.begin(19200);
mySerial.println("Hello, world?");
}
void loop() { // run over and over
currentMillis = millis();
if (currentMillis - timer1_Millis > 5000)
{
if (input_flag == "mppt") {
input_flag = "smartCharger";
// Serial.println(input_flag);
}
else if (input_flag = "smartCharger") {
input_flag = "mppt";
// Serial.println(input_flag);
}
timer1_Millis = currentMillis; //reset timing
}
if (input_flag == "mppt") {
while (mySerial.available())
{
char character = mySerial.read(); // Receive a single character from the software serial port
Data.concat(character); // Add the received character to the receive buffer
// if (character == 10)
if (character == 10)
{
int myindex = Data.indexOf("\t");
String dataType = Data.substring(0, myindex);
String dataValue = Data.substring(myindex + 1);
if (dataType == "V") { //battery voltage
sendSigK("lx.mppt.voltage", dataValue.toFloat());
// Serial.println(dataType + ":" + (dataValue));
}
else if (dataType == "I") { // output current
sendSigK("lx.mppt.current", dataValue.toFloat());
// Serial.println(dataType + ":" + (dataValue));
}
else if (dataType == "VPV") { // panel voltage
sendSigK("lx.mppt.panel_voltage", dataValue.toFloat());
// Serial.println(dataType + ":" + (dataValue));
}
else if (dataType == "CS") { // charger state.Off 0, Fault 2, Bulk 3, Absorption 4, Float 5
sendSigK("lx.mppt.state", dataValue.toFloat());
// Serial.println(dataType + ":" + (dataValue));
}
Data = "";
}
}
}
}
void sendSigK(String sigKey, float data)
{
DynamicJsonBuffer jsonBuffer;
String deltaText;
// build delta message
JsonObject &delta = jsonBuffer.createObject();
//updated array
JsonArray &updatesArr = delta.createNestedArray("updates");
JsonObject &thisUpdate = updatesArr.createNestedObject(); //Json Object nested inside delta [...
JsonArray &values = thisUpdate.createNestedArray("values"); // Values array nested in delta[ values....
JsonObject &thisValue = values.createNestedObject();
thisValue["path"] = sigKey;
thisValue["value"] = data;
thisUpdate["Source"] = "ESP32";
delta.printTo(Serial);
Serial.println();
}
/*
PID 0xA04C - product ID
FW 130 - firmware versiomn
SER# HQ1621FRG7Z - Serial number
V 13140 - Voltage mV
I 0 - battery current
VPV 0 - Panel voltage
PPV 0 - panel power
CS 0 - charger state
Off 0
Fault 2
Bulk 3
Absorption 4
Float 5
ERR 0 - error code
LOAD OFF - load output state
IL 0 - Load current
H19 9419 - Yield total Kwh
H20 1 - Yield today Kwh
H21 11 - Max power today W
H22 0 - yield yesterday
H23 0 - max power yesterday
HSDS 120 - day sequence number (0-364)
Checksum g
* */
Looks good.
That another job on the task list then ...