Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: Resolve noisy data #84

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 55 additions & 23 deletions Sofar2mqtt/Sofar2mqtt.ino
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// Update these to match your inverter/network.
#define INVERTER_ME3000 // Uncomment for ME3000
//#define INVERTER_HYBRID // Uncomment for Hybrid
#define INVERTER_HYBRID // Uncomment for Hybrid

// The device name is used as the MQTT base topic. If you need more than one Sofar2mqtt on your network, give them unique names.
const char* deviceName = "Sofar2mqtt";
const char* version = "v2.1.1";

#define WIFI_SSID "xxxxx"
#define WIFI_PASSWORD "xxxxx"
#define MQTT_SERVER "mqtt"
#define WIFI_SSID "Adtran"
#define WIFI_PASSWORD "Dog7Mouse"
#define MQTT_SERVER "raspberrypi"
#define MQTT_PORT 1883
#define MQTT_USERNAME "auser" // Empty string for none.
#define MQTT_PASSWORD "apassword"
#define MQTT_USERNAME "mqtt" // Empty string for none.
#define MQTT_PASSWORD "Rug5Lamp"

/*****
Sofar2mqtt is a remote control interface for Sofar solar and battery inverters.
Expand Down Expand Up @@ -94,7 +94,7 @@ calcCRC by [email protected] and [email protected]
#ifdef INVERTER_ME3000
#define MAX_POWER 3000 // ME3000 is 3000W max.
#elif defined INVERTER_HYBRID
#define MAX_POWER 6000
#define MAX_POWER 3680
#endif

#define RS485_TRIES 8 // x 50mS to wait for RS485 input chars.
Expand All @@ -103,6 +103,8 @@ calcCRC by [email protected] and [email protected]
const char* wifiName = WIFI_SSID;
WiFiClient wifi;

static int battwatterr = 0; //** var declared for error condition of unsigned int in the function batteryWatts

// MQTT parameters
#include <PubSubClient.h>
const char* mqttClientID = deviceName;
Expand Down Expand Up @@ -218,6 +220,8 @@ static struct mqtt_status_register mqtt_status_reads[] =
#elif defined INVERTER_HYBRID
{ SOFAR_REG_PV1, "Solarpv1" },
{ SOFAR_REG_PV2, "Solarpv2" },
{ SOFAR_REG_EXPDAY, "today_exported" }, //***Added for Hybrid too
{ SOFAR_REG_IMPDAY, "today_purchase" }, //***Added for Hybrid too
#endif
{ SOFAR_REG_LOADDAY, "today_consumption" },
{ SOFAR_REG_INTTEMP, "inverter_temp" },
Expand All @@ -231,7 +235,7 @@ struct modbusResponse
uint8_t errorLevel;
uint8_t data[MAX_FRAME_SIZE];
uint8_t dataSize;
char* errorMessage;
String errorMessage; // *** changed from char*
};

// These timers are used in the main loop.
Expand Down Expand Up @@ -324,6 +328,8 @@ void updateOLED(String line1, String line2, String line3, String line4)
display.println(oledLine4);

display.display();
delay(50);
display.display();
}

// Connect to WiFi
Expand Down Expand Up @@ -362,7 +368,7 @@ int addStateInfo(String &state, uint16_t reg, String human)
val = ((rs.data[0] << 8) | rs.data[1]);

if (!( state == "{"))
state += ",";
state += ","; // if its not the first run add a ,

state += "\"" + human + "\":" + String(val);
return 0;
Expand All @@ -379,7 +385,12 @@ void sendData()
String state = "{";

for(l = 0; l < sizeof(mqtt_status_reads)/sizeof(struct mqtt_status_register); l++)
addStateInfo(state, mqtt_status_reads[l].regnum, mqtt_status_reads[l].mqtt_name);
if(addStateInfo(state, mqtt_status_reads[l].regnum, mqtt_status_reads[l].mqtt_name))
{
Serial.println("Error from addStateInfo");
return;
}
// ** if an error state from readSingleReg in addStateInfo then return without making a new set of registers.

state = state+"}";

Expand Down Expand Up @@ -619,7 +630,13 @@ int listen(modbusResponse *resp)
break;

default:
if(inByteNum < inDataBytes + 3)
// ** Ammendments to debug
//char temp[3];
//if (inFrame[1] == 0x04)
//Serial.print("Function Code: ");
//Serial.print(sprintf(temp,"%x",inFrame[1]));
//
if(inByteNum < inDataBytes + 3)
{
//This is presumed to be a data byte.
resp->data[inByteNum - 3] = inFrame[inByteNum];
Expand Down Expand Up @@ -647,7 +664,7 @@ int listen(modbusResponse *resp)
{
resp->errorLevel = 0;
resp->errorMessage = "Valid data frame";
}
}
else
{
resp->errorLevel = 1;
Expand Down Expand Up @@ -749,7 +766,8 @@ void heartbeat()

void updateRunstate()
{
static unsigned long lastRun = 0;
unsigned int BattWattRes;
static unsigned long lastRun = 0;

//Check the runstate
if(checkTimer(&lastRun, RUNSTATE_INTERVAL))
Expand Down Expand Up @@ -777,16 +795,20 @@ void updateRunstate()
break;

case charging:
updateOLED("NULL", "NULL", HUMAN_CHARGING, String(batteryWatts())+"W");
break;
BattWattRes = batteryWatts();
if(!battwatterr) //** take note of batteryWatts error condition
updateOLED("NULL", "NULL", HUMAN_CHARGING, String(BattWattRes)+"W");
break;

#ifdef INVERTER_ME3000
case checkDischarge:
updateOLED("NULL", "NULL", "Check Dis", "NULL");
break;
#endif
case discharging:
updateOLED("NULL", "NULL", HUMAN_DISCHARGING, String(batteryWatts())+"W");
BattWattRes = batteryWatts();
if(!battwatterr) //** take note of batteryWatts error condition
updateOLED("NULL", "NULL", HUMAN_DISCHARGING, String(BattWattRes)+"W");
break;

case epsState:
Expand Down Expand Up @@ -814,6 +836,7 @@ void updateRunstate()
}
}


unsigned int batteryWatts()
{
if(INVERTER_RUNNINGSTATE == charging || INVERTER_RUNNINGSTATE == discharging)
Expand All @@ -833,13 +856,14 @@ unsigned int batteryWatts()
case discharging:
w = (65535 - w)*10;
}

return w;
battwatterr = 0; //** no error
return w;
}
else
{
Serial.println(response.errorMessage);
updateOLED("NULL", "NULL", "CRC-FAULT", "NULL");
battwatterr = -1; //** set error condition
}
}

Expand All @@ -848,7 +872,8 @@ unsigned int batteryWatts()

void setup()
{
Serial.begin(9600);
delay(1000);//** added for bad startup
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);

pinMode(SERIAL_COMMUNICATION_CONTROL_PIN, OUTPUT);
Expand All @@ -859,7 +884,9 @@ void setup()

//Turn on the OLED
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize OLED with the I2C addr 0x3C (for the 64x48)
display.clearDisplay();
delay(500); //** added for bad startup

display.clearDisplay();
display.display();
updateOLED(deviceName, "connecting", "", version);

Expand All @@ -869,10 +896,15 @@ void setup()
mqtt.setCallback(mqttCallback);

//Wake up the inverter and put it in auto mode to begin with.
heartbeat();
delay(500);//** added for bad startup
heartbeat();
mqttReconnect();
Serial.println("Set start up mode: Auto");
sendPassiveCmd(SOFAR_SLAVE_ID, SOFAR_FN_AUTO, 0, "startup_auto");
while(sendPassiveCmd(SOFAR_SLAVE_ID, SOFAR_FN_AUTO, 0, "startup_auto")) //** added while
{
delay(100);//** added for bad startup
Serial.println("sendPassiveCmd Failed in startup");
}
}

void loop()
Expand Down Expand Up @@ -934,5 +966,5 @@ bool checkCRC(uint8_t frame[], byte frameSize)
received_crc = ((frame[frameSize-2] << 8) | frame[frameSize-1]);
calcCRC(frame, frameSize);
calculated_crc = ((frame[frameSize-2] << 8) | frame[frameSize-1]);
return (received_crc = calculated_crc);
return (received_crc == calculated_crc);
}