Skip to content

Commit

Permalink
⛏ PowerSupply::make() and optional psu logic
Browse files Browse the repository at this point in the history
- allows for upcoming more advanced psu instantiation
  • Loading branch information
t413 committed Jul 15, 2020
1 parent 17d7745 commit c711d82
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 52 deletions.
25 changes: 19 additions & 6 deletions lib/MPPTLib/powerSupplies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@
#include <ModbusMaster.h> // ModbusMaster
#include "utils.h"

PowerSupply* PowerSupply::make(const String &type) {
PowerSupply* ret = NULL;
String typeUp = type;
typeUp.toUpperCase();
if (typeUp.startsWith("DP")) {
ret = new DPS(&Serial2);
Serial2.begin(19200, SERIAL_8N1, -1, -1, false, 1000);
} else if (typeUp.startsWith("DROK")) {
ret = new Drok(&Serial2);
Serial2.begin(4800, SERIAL_8N1, -1, -1, false, 1000);
} else { //default
ret = NULL;
}
if (ret) ret->type_ = type;
return ret;
}


// ----------------------- //
// ----- PowerSupply ----- //
Expand Down Expand Up @@ -31,16 +48,14 @@ void PowerSupply::doTotals() {
// -------- Drok -------- //
// ---------------------- //

Drok::Drok(Stream* port) : PowerSupply(), port_(port) { }
Drok::Drok(Stream* port) : PowerSupply() { port_ = port; }
Drok::~Drok() { }

bool Drok::begin() {
flush();
return doUpdate();
}

String Drok::getType() const { return "Drok"; }

bool Drok::doUpdate() {
bool res = readVoltage() &&
readCurrent() &&
Expand Down Expand Up @@ -136,11 +151,9 @@ bool Drok::setCurrent(float v) {
// --------- DPS --------- //
// ----------------------- //

DPS::DPS(Stream* port) : PowerSupply(), port_(port), bus_(new ModbusMaster) { }
DPS::DPS(Stream* port) : PowerSupply(), bus_(new ModbusMaster) { port_ = port; }
DPS::~DPS() { }

String DPS::getType() const { return "DPS"; }

bool DPS::begin() {
bus_->begin(1, *port_);
return doUpdate();
Expand Down
17 changes: 9 additions & 8 deletions lib/MPPTLib/powerSupplies.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
#pragma once
#include <cstdint>
#include <WString.h>

class String;
class Stream;

class PowerSupply {
public:
String type_;
Stream *port_ = NULL;
bool debug_ = false;
float outVolt_ = 0, outCurr_ = 0;
float limitVolt_ = 0, limitCurr_ = 0;
float currFilt_ = 0.0, wh_ = 0;
bool outEn_ = false;
uint32_t lastSuccess_ = 0, lastAmpUpdate_ = 0;

static PowerSupply* make(const String &type);
PowerSupply();
virtual ~PowerSupply();
virtual bool begin() = 0;
Expand All @@ -28,18 +31,17 @@ class PowerSupply {
virtual bool isCollapsed() const;
virtual bool getInputVolt(float* v) { return false; }
virtual String toString() const;
virtual String getType() const = 0;
String getType() const { return type_; }
virtual bool isDrok() const { return true; }
protected:
void doTotals();
};

class Drok : public PowerSupply {
Stream *port_;
public:
Drok(Stream* port);
Drok(Stream*);
~Drok();
bool begin() override;
virtual String getType() const;

String cmdReply(const String &cmd);
bool setVoltage(float) override;
Expand All @@ -60,16 +62,14 @@ class Drok : public PowerSupply {
class ModbusMaster;

class DPS : public PowerSupply {
Stream *port_;
ModbusMaster* bus_;
public:
float inputVolts_ = 0;
bool cc_ = false;

DPS(Stream* port);
DPS(Stream*);
~DPS();
bool begin() override;
virtual String getType() const;

bool setVoltage(float) override;
bool setCurrent(float) override;
Expand All @@ -79,4 +79,5 @@ class DPS : public PowerSupply {

bool isCC() const override;
bool getInputVolt(float* v) override;
bool isDrok() const override { return false; }
};
76 changes: 38 additions & 38 deletions lib/MPPTLib/solar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <HTTPUpdate.h>

using namespace std::placeholders;
#define ckPSUs() if (!psu_) { return String("no psu"); }

WiFiClient espClient;

Expand Down Expand Up @@ -62,11 +63,11 @@ void Solar::setup() {
pub_.add("inPin", pinInvolt_).pref();
pub_.add("lvProtect", std::bind(&Solar::setLVProtect, this, _1)).pref();
pub_.add("psu", std::bind(&Solar::setPSU, this, _1)).pref();
pub_.add("outputEN",[=](String s){ if (s.length()) psu_->enableOutput(s == "on"); return String(psu_->outEn_); });
pub_.add("outvolt", [=](String s){ if (s.length()) psu_->setVoltage(s.toFloat()); return String(psu_->outVolt_); });
pub_.add("outcurr", [=](String s){ if (s.length()) psu_->setCurrent(s.toFloat()); return String(psu_->outCurr_); });
pub_.add("outpower",[=](String){ return String(psu_->outVolt_ * psu_->outCurr_); });
pub_.add("currFilt",[=](String){ return String(psu_->currFilt_); });
pub_.add("outputEN",[=](String s){ ckPSUs(); if (s.length()) psu_->enableOutput(s == "on"); return String(psu_->outEn_); });
pub_.add("outvolt", [=](String s){ ckPSUs(); if (s.length()) psu_->setVoltage(s.toFloat()); return String(psu_->outVolt_); });
pub_.add("outcurr", [=](String s){ ckPSUs(); if (s.length()) psu_->setCurrent(s.toFloat()); return String(psu_->outCurr_); });
pub_.add("outpower",[=](String){ ckPSUs(); return String(psu_->outVolt_ * psu_->outCurr_); });
pub_.add("currFilt",[=](String){ ckPSUs(); return String(psu_->currFilt_); });
pub_.add("state", state_ );
pub_.add("pgain", pgain_ ).pref();
pub_.add("ramplimit", ramplimit_ ).pref();
Expand All @@ -79,14 +80,14 @@ void Solar::setup() {
pub_.add("autosweep", autoSweep_ ).pref();
pub_.add("currentcap", currentCap_ ).pref();
pub_.add("involt", inVolt_);
pub_.add("wh", [=](String s) { if (s.length()) psu_->wh_ = s.toFloat(); return String(psu_->wh_); });
pub_.add("wh", [=](String s) { ckPSUs(); if (s.length()) psu_->wh_ = s.toFloat(); return String(psu_->wh_); });
pub_.add("collapses", [=](String) { return String(getCollapses()); });
pub_.add("sweep",[=](String){ startSweep(); return "starting sweep"; }).hide();
pub_.add("connect",[=](String s){ doConnect(); return "connected"; }).hide();
pub_.add("disconnect",[=](String s){ db_.client.disconnect(); WiFi.disconnect(); return "dissed"; }).hide();
pub_.add("restart",[](String s){ ESP.restart(); return ""; }).hide();
pub_.add("clear",[=](String s){ pub_.clearPrefs(); return "cleared"; }).hide();
pub_.add("debug",[=](String s){ psu_->debug_ = !(s == "off"); return String(psu_->debug_); }).hide();
pub_.add("debug",[=](String s){ ckPSUs(); psu_->debug_ = !(s == "off"); return String(psu_->debug_); }).hide();
pub_.add("version",[=](String){ log("Version " + version_); return version_; }).hide();
pub_.add("update",[=](String s){ doOTAUpdate_ = s; return "OK, will try "+s; }).hide();
pub_.add("uptime",[=](String){ String ret = "Uptime " + timeAgo(millis()/1000); log(ret); return ret; }).hide();
Expand Down Expand Up @@ -145,10 +146,12 @@ void Solar::setup() {
//fn, name, stack size, parameter, priority, handle
xTaskCreate(runPubt, "publish", 10000, this, 1, NULL);

if (!psu_->begin())
log("PSU begin failed");
newDesiredCurr_ = psu_->currFilt_ = psu_->limitCurr_ = psu_->outCurr_;
log(str("startup current is %0.3fAdes/%0.3fAfilt/%0.3fAout", newDesiredCurr_, psu_->currFilt_, psu_->outCurr_));
if (!psu_) log("no PSU set");
else if (!psu_->begin()) log("PSU begin failed");
else if (psu_) {
newDesiredCurr_ = psu_->currFilt_ = psu_->limitCurr_ = psu_->outCurr_;
log(str("startup current is %0.3fAdes/%0.3fAfilt/%0.3fAout", newDesiredCurr_, psu_->currFilt_, psu_->outCurr_));
}
nextAutoSweep_ = millis() + 10000;
log("finished setup");
log("OSPController Version " + version_);
Expand All @@ -167,16 +170,10 @@ String Solar::setPSU(String s) {
log("setPSU " + s);
if (s.length() || !psu_) {
//TODO Parse softserial pins, bluetooth comms, and moar.
s.toUpperCase();
if (s.startsWith("DP")) {
psu_.reset(new DPS(&Serial2));
Serial2.begin(19200, SERIAL_8N1, -1, -1, false, 1000);
if (measperiod_ == 200) //default
measperiod_ = 500;
} else { //default
psu_.reset(new Drok(&Serial2));
Serial2.begin(4800, SERIAL_8N1, -1, -1, false, 1000);
}
psu_.reset(PowerSupply::make(s));
if (psu_ && ! psu_->isDrok() && (measperiod_ == 200)) //default
measperiod_ = 500; //slow down, DSP5005 meas does full update()
ckPSUs();
psu_->begin();
return "created PSU=" + psu_->getType();
}
Expand Down Expand Up @@ -216,7 +213,7 @@ String SPoint::toString() const {
}

void Solar::applyAdjustment() {
if (newDesiredCurr_ != psu_->limitCurr_) {
if (psu_ && newDesiredCurr_ != psu_->limitCurr_) {
if (psu_->setCurrent(newDesiredCurr_))
pub_.logNote(str("[adjusting %0.3fA (from %0.3fA)]", newDesiredCurr_ - psu_->limitCurr_, psu_->limitCurr_));
else log("error setting current");
Expand All @@ -231,19 +228,20 @@ void Solar::startSweep() {
if (state_ == States::error)
return log("can't sweep, system is in error state");
log(str("SWEEP START c=%0.3f, (setpoint was %0.3f)", newDesiredCurr_, setpoint_));
if (state_ == States::collapsemode) {
if (psu_ && state_ == States::collapsemode) {
psu_->enableOutput(false);
psu_->setCurrent(psu_->currFilt_* 0.75);
delay(200);
log(str("First coming out of collapse-mode to clim of %0.2fA", psu_->limitCurr_));
}
setState(States::sweeping);
if (!psu_->outEn_)
if (psu_ && !psu_->outEn_)
psu_->enableOutput(true);
lastAutoSweep_ = millis();
}

void Solar::doSweepStep() {
if (!psu_) return;
if (!psu_->outEn_)
return setState(States::mppt);

Expand Down Expand Up @@ -306,7 +304,7 @@ void Solar::doSweepStep() {
}

bool Solar::hasCollapsed() const {
if (!psu_->outEn_) return false;
if (!psu_ || !psu_->outEn_) return false;
bool simpleClps = (inVolt_ < (psu_->outVolt_ * 1.11)); //simple voltage match method
float collapsePct = (inVolt_ - psu_->outVolt_) / psu_->outVolt_;
if (simpleClps && psu_->isCollapsed())
Expand All @@ -326,7 +324,7 @@ void Solar::loop() {
return delay(100);

if (now > nextVmeas_) {
if (psu_->getInputVolt(&inVolt_)) {
if (psu_ && psu_->getInputVolt(&inVolt_)) {
psu_->doUpdate();
psu_->getInputVolt(&inVolt_);
} else {
Expand All @@ -336,7 +334,7 @@ void Solar::loop() {
pub_.setDirtyAddr(&inVolt_);
if (state_ == States::sweeping) {
doSweepStep();
} else if (setpoint_ > 0 && psu_->outEn_) { //corrections enabled
} else if (setpoint_ > 0 && psu_ && psu_->outEn_) { //corrections enabled
double error = inVolt_ - setpoint_;
double dcurr = constrain(error * pgain_, -ramplimit_ * 2, ramplimit_); //limit ramping speed
if (error > 0.3 || (-error > 0.2)) { //adjustment deadband, more sensitive when needing to ramp down
Expand All @@ -349,7 +347,9 @@ void Solar::loop() {
}

//update system states:
if (state_ != States::sweeping && state_ != States::collapsemode) {
if (!psu_) {
setState(States::error);
} else if (state_ != States::sweeping && state_ != States::collapsemode) {
int lastPSUsecs = (millis() - psu_->lastSuccess_) / 1000;
if (psu_->outEn_) {
if (lastPSUsecs > 11) setState(States::error, "enabled but no PSU comms");
Expand All @@ -373,7 +373,7 @@ void Solar::loop() {
if (now > nextSolarAdjust_) {
try {
if (state_ == States::error) {
if ((now - psu_->lastSuccess_) < 30000) { //for 30s after failure try and shut it down
if (psu_ && (now - psu_->lastSuccess_) < 30000) { //for 30s after failure try and shut it down
psu_->enableOutput(false);
psu_->setCurrent(0);
throw Backoff("PSU failure, disabling");
Expand All @@ -386,7 +386,7 @@ void Solar::loop() {
log(str("collapsed! %0.2fV set recovery to %0.1fA ", inVolt_, newDesiredCurr_) + psu_->toString());
psu_->enableOutput(false);
psu_->setCurrent(newDesiredCurr_);
} else if (!psu_->outEn_) { //power supply is off. let's check about turning it on
} else if (psu_ && !psu_->outEn_) { //power supply is off. let's check about turning it on
if (inVolt_ < psu_->outVolt_ || psu_->outVolt_ < 0.1) {
throw Backoff("not starting up, input voltage too low (is it dark?)");
} else if ((psu_->outVolt_ > psu_->limitVolt_) || (psu_->outVolt_ < (psu_->limitVolt_ * 0.60) && psu_->outVolt_ > 1)) {
Expand All @@ -398,7 +398,7 @@ void Solar::loop() {
psu_->enableOutput(true);
}
}
if (psu_->outEn_ && state_ != States::collapsemode) {
if (psu_ && psu_->outEn_ && state_ != States::collapsemode) {
applyAdjustment();
}
}
Expand All @@ -420,7 +420,7 @@ void Solar::loop() {
nextPrint_ = now + printPeriod_;
}

if (now > nextPSUpdate_) {
if (psu_ && now > nextPSUpdate_) {
bool res = psu_->doUpdate();
if (res) {
pub_.setDirty({"outvolt", "outcurr", "outputEN", "outpower", "currFilt"});
Expand All @@ -433,13 +433,13 @@ void Solar::loop() {
}

if (lvProtect_ && now > lvProtect_->nextCheck_) {
if (!lvProtect_->isTriggered() && psu_->outVolt_ < lvProtect_->threshold_) {
if (!lvProtect_->isTriggered() && psu_ && psu_->outVolt_ < lvProtect_->threshold_) {
log(str("LOW VOLTAGE PROTECT TRIGGERED (now at %0.2fV)", psu_->outVolt_));
sendOutgoingLogs(); //send logs, tripping this relay may power us down
delay(200);
lvProtect_->trigger(true);
lvProtect_->nextCheck_ = now + 5 * 1000;
} else if (lvProtect_->isTriggered() && psu_->outVolt_ > lvProtect_->threshRecovery_) {
} else if (lvProtect_->isTriggered() && psu_ && psu_->outVolt_ > lvProtect_->threshRecovery_) {
log("low voltage recovery, re-enabling.");
lvProtect_->trigger(false);
lvProtect_->nextCheck_ = now + 10000;
Expand Down Expand Up @@ -475,7 +475,7 @@ void Solar::publishTask() {
db_.client.setCallback([=](char*topicbuf, uint8_t*buf, unsigned int len){
String topic(topicbuf), val = str(std::string((char*)buf, len));
log("got sub value " + topic + " -> " + val);
if (topic == (db_.feed + "/wh")) {
if (topic == (db_.feed + "/wh") && psu_) {
psu_->wh_ = (psu_->wh_ > 2.0)? val.toFloat() : psu_->wh_ + val.toFloat();
log("restored wh value to " + val);
db_.client.unsubscribe((db_.feed + "/wh").c_str());
Expand Down Expand Up @@ -509,7 +509,7 @@ void Solar::publishTask() {
}
sendOutgoingLogs();
heap_caps_check_integrity_all(true);
nextPub_ = now + (psu_->outEn_? db_.period : db_.period * 4); //slower when disabled
nextPub_ = now + ((psu_ && psu_->outEn_)? db_.period : db_.period * 4); //slower when disabled
}
db_.client.loop();
pub_.poll(&Serial);
Expand All @@ -521,10 +521,10 @@ void Solar::publishTask() {
void Solar::printStatus() {
String s = state_;
s.toUpperCase();
s += str(" %0.1fVin -> %0.2fWh ", inVolt_, psu_->wh_) + psu_->toString();
s += str(" %0.1fVin -> %0.2fWh ", inVolt_, psu_? psu_->wh_ : 0) + (psu_? psu_->toString() : "[no PSU]");
if (lvProtect_ && lvProtect_->isTriggered()) s += " [LV PROTECTED]";
s += pub_.popNotes();
if (psu_->debug_) log(s);
if (psu_ && psu_->debug_) log(s);
else Serial.println(s);
}

Expand Down

0 comments on commit c711d82

Please sign in to comment.