fab-lab.eu
Published

Solartisch

Balkon-Solaranlagen helfen die Strom-Grundlast zu senken und so kann fast jede/r einen Beitrag zur Energiewende leisten. Hier als Tisch!

AdvancedWork in progress12,020
Solartisch

Things used in this project

Hardware components

IoT Octopus
Das Hirn - oder die Krake, welche die Daten sammelt und die Steuerung übernimmt. Basiert auf einem ESP8266 und kann Display im Adafruit Feather Stecksystem tragen.
×1
EET LIGHTMATE G
Eine Möglichkeit für ein plug&play Angebot. Ideal sind aber gebrauchte Panels, man muss bei alten Panels jedoch beachten das die Stecker nicht zu den neuen Wechselrichtern passen. Hier muss man ggfs Adapter nutzen oder zum Elektriker ;-) Mit Wandhalterung (die Schienen sind ideal auch zur Befestigung auf dem Tisch)
×1
Shelly 1PM, WLAN Schalter mit Messfunktion
Misst den Solarstrom, eingebaut in die Verteilerbox am Tisch.
×1
Shelly Plug S, schmale WLAN Steckdose mit Messfunktion
Steuert die Pufferbatterie an.
×1
EcoFlow River Wireless
Pufferbatterie. Kann bis zu 600W bei Bedarf liefern und funktioniert als USV oder Stromlieferant für Kleingeräte. Hat eine Kapazität von 210Wh und lädt mit 248W in 45min auf 80%.
×1
Raspberry Pi 400 KIT DE
Homeserver. Hier läuft MQTT, InfluxDB, Telegraph, Grafana - zur Visualisierung und Auswertung der Verbrauchsdaten ... Man muss beachten das dies eine weitere Energiesenke ist ... also nur Optional!
×1

Software apps and online services

IoT Werkstatt (Arduino mit Ardublock) grafische Programmierungn von Shelly/MQTT etc

Story

Read more

Custom parts and enclosures

Tisch

nicht für den Drucker, es wird echtes Holz benötigt ;-)

Code

IoT Octopus sammelt Leistungsdaten vom Panel (Shelly 1 PM) und steuert Shelly Plug S füttert Grafana

Arduino
wenn mehr als 180W Solarstrom produziert werden, wird der Netzstrom am Ecoflow River Wireless (Powerbank) eingeschaltet ...
/* This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details. */
 
// by fab-lab.eu and IoT Werkstatt

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_IS31FL3731.h>

String matrixausgabe_text  = " "; // Ausgabetext als globale Variable

volatile int matrixausgabe_index = 0;// aktuelle Position in Matrix

IPAddress myOwnIP; // ownIP for mDNS 

//--------------------------------------- http-GET with wifi-Client
int httpClientGET(String host, String cmd, String &antwort) {
  int ok = 0;
  String message = "http://"+host+cmd;
  WiFiClient client;
  HTTPClient http;
  //Serial.println(message);
  if (http.begin(client, message)){  // HTTP
    // start connection and send HTTP header
    int httpCode = http.GET();
    // httpCode will be negative on error
    if (httpCode > 0) {
      // HTTP header has been send and Server response header has been handled
      String payload = http.getString();
      antwort = payload;
      //Serial.println(payload);
      // file found at server
      if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
        ok = 1;
      }
    } 
    else {
      Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }
    http.end();
  } 
  else {
    Serial.printf("[HTTP] Unable to connect\n");
  }
  return ok;
}

//--------------------------------------- Shelly Plug (Switch/Metering)
// https://shelly-api-docs.shelly.cloud/gen1/#shelly-plug-plugs
String parseShellyInfo(String xml,String suchtext) {
  String valStr = "";                // Hilfsstring
  int start, ende;                   // Index im Text
  start = xml.indexOf(suchtext);     // Suche Text
  if (start > 0) {                   // Item gefunden
    start = start+suchtext.length(); // hinter Item kommt Zahl
    ende =  xml.indexOf(',',start);  // Ende der Zahl
    valStr= xml.substring(start,ende);// Zahltext
  } 
  else                             // Item nicht gefunden
  Serial.print("error - no such item: "+suchtext);
  return valStr;
}
void ShellySwitch(String host,int state) { 
  String cmd;
  if (state == 1) cmd = "/relay/0?turn=on" ;
  else cmd = "/relay/0?turn=off";
  String antwort;
  httpClientGET(host,cmd,antwort);
}
float ShellyMeter(String host,int para) { 
  float  val    =  NAN;
  String valStr = "NAN";
  String antwort;
  if (httpClientGET(host,"/status",antwort)) { // success
    if (parseShellyInfo(antwort,"\"is_valid\":") == "true") {
      if (para == 1) {         
        valStr=parseShellyInfo(antwort,"\"power\":");
        val = valStr.toFloat();
      }
      if (para == 2) {         
        valStr=parseShellyInfo(antwort,"\"total\":");
        val = valStr.toFloat()/60.0;
      }
    }
  }
  return val;
}

//-------------- definition mqtt-object ueber WiFi
WiFiClient   espClient; 
PubSubClient mqttclient(espClient);

//--------- list of mqtt callback functions 
#define MAX_MQTT_SUB 10 // maximal 10 subscriptions erlaubt
typedef void (*mqtthandle) (byte*,unsigned int);
typedef struct {       // Typdeklaration Callback
  String topic;        // mqtt-topic
  mqtthandle fun;      // callback function 
}
subscribe_type; 
subscribe_type mqtt_sub[MAX_MQTT_SUB];
int mqtt_sub_count=0;

String MQTT_Rx_Payload = "" ;
//--------- mqtt callback function 
void mqttcallback(char* to, byte* pay, unsigned int len) {
  String topic   = String(to);
  String payload = String((char*)pay);
  MQTT_Rx_Payload=payload.substring(0,len);
  Serial.println("\ncallback topic:" + topic + ", payload:" + MQTT_Rx_Payload);
  for (int i=0;i<mqtt_sub_count;i++) { // durchsuche alle subscriptions, bis topic passt 
    if (topic==mqtt_sub[i].topic) 
      mqtt_sub[i].fun(pay,len);         // Aufruf der richtigen callback-Funktion
  }
}

//------------ reconnect mqtt-client
void mqttreconnect() { // Loop until we're reconnected 
  if (!mqttclient.connected()) { 
    while (!mqttclient.connected()) { 
      Serial.print("Attempting MQTT connection...");
      if (mqttclient.connect("Solartisch" , "telegraf", "telegraf" )) {
        Serial.println("connected");
        for (int i=0;i<mqtt_sub_count;i++) { // subscribe topic
          mqttclient.subscribe(mqtt_sub[i].topic.c_str());
          Serial.println("\nsubscribe");
          Serial.print(mqtt_sub[i].topic);
        }
      } 
      else { 
        Serial.print("failed, rc=");
        Serial.print(mqttclient.state());
        Serial.println(" try again in 5 seconds");
        delay(5000);
      }
    }
  } 
  else { 
    mqttclient.loop(); 
  }
}

int Energy = 0 ;
int Power = 0 ;
volatile int matrixausgabe_wait  = 0;// warte bis Anzeige durchgelaufen ist

//--------------------------------------- Charlieplex Matrix
Adafruit_IS31FL3731_Wing matrix = Adafruit_IS31FL3731_Wing();

Ticker matrixausgabe;
void matrixUpdate(){ // Update Charlieplexmatrix über Ticker
  int anzahlPixel=(matrixausgabe_text.length())*6;
  if (anzahlPixel > 15) { // Scrollen 
    if (matrixausgabe_index >= -anzahlPixel) {
      matrix.clear();
      matrix.setCursor(matrixausgabe_index,0);
      matrix.print(matrixausgabe_text);
      matrixausgabe_index--;
    } 
    else {
      matrixausgabe_index = 12;
      matrixausgabe_wait=0;
    }
  } 
  else {// nur 3 Zeichen lang-> kein Scroll 
    matrix.setCursor(0,0);
    matrix.print(matrixausgabe_text);
    matrixausgabe_wait  = 0; // no wait
  }
}
void matrixAnzeige(String text, int wait) { // Setze Ausgabetext
  if (matrixausgabe_text  != text) { // update nur bei neuem Text 
    matrix.clear();
    matrixausgabe_index = 0;
    matrixausgabe_text  = text;
    matrixausgabe_wait  = wait;
    while (matrixausgabe_wait) delay(10); // warte bis Text einmal ausgegeben ist
  }
};


void setup(){ // Einmalige Initialisierung
  Serial.begin(115200);
  //----------------------------------MQTT-Client 
  mqttclient.setServer("192.168.178.72", 1883); // <<<<< change IP !!!!
  mqttclient.setCallback(mqttcallback);

  Serial.println();
  Wire.begin(); // ---- Initialisiere den I2C-Bus 

  if (Wire.status() != I2C_OK) Serial.println("Something wrong with I2C");

  matrix.begin();// Matrix initialisieren 
  delay(10);
  matrix.clear(); 

  matrix.setTextColor(60); // Helligkeit begrenzen 
  matrixausgabe.attach(0.08, matrixUpdate); // zyklisch aktualisieren

  //------------ WLAN initialisieren 
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  delay(100);
  Serial.print ("\nWLAN connect to:");
  Serial.print("SSID");
  WiFi.begin("SSID","password"); // <<<<< change SSID and PWD !!!!
  while (WiFi.status() != WL_CONNECTED) { // Warte bis Verbindung steht 
    delay(500); 
    Serial.print(".");
  };
  Serial.println ("\nconnected, meine IP:"+ WiFi.localIP().toString());
  matrixausgabe_text = " Meine IP:" + WiFi.localIP().toString();
  myOwnIP = WiFi.localIP();
  matrixausgabe_index=0;

  ShellySwitch("192.168.178.29",HIGH); // <<<<< change IP !!!!

  ShellySwitch("192.168.178.71",LOW); // <<<<< change IP !!!!


}

void loop() { // Kontinuierliche Wiederholung 
  Energy = abs( ShellyMeter("192.168.178.29",2) ) ; // <<<<< change IP 
  Power = abs( ShellyMeter("192.168.178.29",1) ) ; // <<<<< change IP
  Serial.print("Energy(Wh):"+String(String(Energy)));
  Serial.print(", Power(W):"+String(String(Power)));
  Serial.println();
  if (( ( Power ) < ( 2500 ) ))
  {
    mqttreconnect();
    {
      String pay=String("power,site=001 value="+String(String(Power)));
      mqttclient.publish("sensors",pay.c_str());
      Serial.print("\nmqtt publish: "); 
      Serial.print(pay);
    };
    matrixAnzeige(String(String(Power)),1);
    if (( ( Power ) > ( 180 ) ))
    {
      delay( 60000 );
      if (( ( Power ) > ( 180 ) ))
      {
        Serial.print("speichere Solarenergie in Batteriepuffer.");
        Serial.println();
        ShellySwitch("192.168.178.71",HIGH); // <<<<< change IP !!!!
      }
    }
    else
    {
      delay( 60000 );
      if (( ( Power ) < ( 100 ) ))
      {
        Serial.print("stoppe laden des Batteriepuffers");
        Serial.println();
        ShellySwitch("192.168.178.71",LOW); // <<<<< change IP !!!!
      }
    }
  }
  delay( 10000 );
} //end loop

Credits

fab-lab.eu

fab-lab.eu

22 projects • 276 followers
Maker!

Comments