Solar-Inselanlage überwachen

Entwicklung und Bau von Hardware aller Art, die im HM-Umfeld eingesetzt werden kann

Moderator: Co-Administratoren

dondaik
Beiträge: 12925
Registriert: 16.01.2009, 18:48
Wohnort: Steingaden
Hat sich bedankt: 1599 Mal
Danksagung erhalten: 222 Mal

Re: Solar-Inselanlage überwachen

Beitrag von dondaik » 09.03.2020, 17:41

dann sollte die lösung auch hier vollständig dokumentiert gezeigt werden ... der titel des themas sagt das ja :mrgreen:
-------
!!! der download der handbüchern auf den seiten von eq3 und das lesen der tips und tricks kann das hm-leben sehr erleichtern - das nutzen der suche nach schlagworten ebenso :mrgreen: !!!
wer schreibfehler findet darf sie behalten.

Benutzeravatar
Hoppla
Beiträge: 341
Registriert: 29.12.2018, 19:39
System: Alternative CCU (auf Basis OCCU)
Wohnort: Leipzsch
Hat sich bedankt: 35 Mal
Danksagung erhalten: 12 Mal

Re: Solar-Inselanlage überwachen

Beitrag von Hoppla » 11.03.2020, 16:08

Nun, da ich nur so lange an dem Quelltext von Papa und jp112sdl rumgemalt habe bis ich mein Ergebnis hatte erhebe ich nicht den Anspruch, etwas entwickelt zu haben.
Wenn einer der Autoren durch meinen Quelltext geht schlagen die sicher die Hände über dem Kopf zusammen.
Ich hab die Adafruit-Bibliothek zum INA eingebunden und folgenden Quelltext verwendet.

Code: Alles auswählen

//- -----------------------------------------------------------------------------------------------------------------------
// AskSin++
// 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
// 2018-09-14 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
// dranrumgemalt durch Hoppla
//- -----------------------------------------------------------------------------------------------------------------------
// define this to read the device id, serial and device type from bootloader section
// #define USE_OTA_BOOTLOADER

//#define USE_LCD
//#define LCD_ADDRESS 0x3f

#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <AskSinPP.h>
#include <LowPower.h>
// INA  _____________________
#include <Wire.h>
#include <Adafruit_INA219.h>

Adafruit_INA219 ina219;  // Initialize first board (default address 0x40)
//Adafruit_INA219 ina219_A;
//Adafruit_INA219 ina219_B(0x41);


// INA ________________

#include <Register.h>
#include <MultiChannelDevice.h>

//#ifdef USE_LCD
//#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(0x27, 20, 2);
//#endif

// Arduino Pro mini 8 Mhz
// Arduino pin for the config button
#define CONFIG_BUTTON_PIN  8
#define LED_PIN            4

// Number of voltage measurement channels
#define NUM_CHANNELS       1
// number of available peers per channel
#define PEERS_PER_CHANNEL  6

// all library classes are placed in the namespace 'as'
using namespace as;

//Korrekturfaktor der Clock-Ungenauigkeit, wenn keine RTC verwendet wird
#define SYSCLOCK_FACTOR    0.88

// define all device properties
const struct DeviceInfo PROGMEM devinfo = {
  {0xF3, 0x4A, 0x00},          // Device ID
  "JPVOLT0000",                // Device Serial
  {0xF3, 0x4A},                // Device Model
  0x20,                        // Firmware Version
  0x53,                        // Device Type
  {0x01, 0x01}                 // Info Bytes
};

/**
   Configure the used hardware
*/

typedef AskSin<StatusLed<LED_PIN>, BatterySensor, Radio<AvrSPI<10, 11, 12, 13>, 2>> BaseHal;
class Hal : public BaseHal {
  public:
    void init (const HMID& id) {
      BaseHal::init(id);
       //measure battery every 1h
      battery.init(seconds2ticks(60UL * 60), sysclock);
      battery.low(22);
      battery.critical(19);
    }

    bool runready () {
      return sysclock.runready() || BaseHal::runready();
    }
} hal;

DEFREGISTER(UReg0, MASTERID_REGS, DREG_LOWBATLIMIT, 0x20, 0x21)
class UList0 : public RegList0<UReg0> {
  public:
    UList0 (uint16_t addr) : RegList0<UReg0>(addr) {}

    bool Sendeintervall (uint16_t value) const {
      return this->writeRegister(0x20, (value >> 8) & 0xff) && this->writeRegister(0x21, value & 0xff);
    }
    uint16_t Sendeintervall () const {
      return (this->readRegister(0x20, 0) << 8) + this->readRegister(0x21, 0);
    }

    void defaults () {
      clear();
      lowBatLimit(22);
      Sendeintervall(15);
    }
};

DEFREGISTER(UReg1, 0x01, 0x02, 0x03)
class UList1 : public RegList1<UReg1> {
  public:
    UList1 (uint16_t addr) : RegList1<UReg1>(addr) {}
    void defaults () {
      clear();
    }
};

class MeasureEventMsg : public Message {
  public:
    void init(uint8_t msgcnt, uint8_t channel, uint16_t voltage) {
      Message::init(0x0e, msgcnt, 0x53, BIDI | WKMEUP, channel & 0xff, (voltage >> 8) & 0xff);
      pload[0] = voltage & 0xff;
    }
};

class MeasureChannel : public Channel<Hal, UList1, EmptyList, List4, PEERS_PER_CHANNEL, UList0>, public Alarm {
    MeasureEventMsg msg;
    uint16_t        voltage;
    uint8_t         last_flags = 0xff;

  public:
    MeasureChannel () : Channel(), Alarm(0), voltage(0) {}
    virtual ~MeasureChannel () {}

    void measure() {

      // HIER DIE MESSUNG DURCHFÃœHREN
      // Spannung muss mit Faktor 10 übertragen werden
      // 12.8V -> voltage = 128;
      //voltage = random(2300);

float shuntvoltage = 0;
  float busvoltage = 0;
  float current_mA = 0;
  float loadvoltage = 0;
  float power_mW = 0;
  //float voltage = 0;
  shuntvoltage = ina219.getShuntVoltage_mV();
  busvoltage = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getPower_mW();
  loadvoltage = busvoltage + (shuntvoltage / 1000);

  Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
  Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
  Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(power_mW); Serial.println(" mW");
  Serial.println("");
    voltage = ina219.getBusVoltage_V()* 10;
  Serial.print("voltage:  "); Serial.print(voltage); //Serial.println(" V");
  Serial.println("");
//  lcd.print(voltage);
//  delay(2000);
    }

    virtual void trigger (__attribute__ ((unused)) AlarmClock& clock) {
      uint8_t msgcnt = device().nextcount();
      measure();

      if (last_flags != flags()) {
        if (number() == 1) this->changed(true);
        last_flags = flags();
      }
      tick = delay();
      msg.init(msgcnt, number(), voltage);
      if (msgcnt % 20 == 1) device().sendPeerEvent(msg, *this); else device().broadcastEvent(msg, *this);
      sysclock.add(*this);
    }

    uint32_t delay () {
      uint16_t d = (max(10, device().getList0().Sendeintervall()) * SYSCLOCK_FACTOR) + random(10); //add some small random difference between channels
      return seconds2ticks(d);
    }

    void configChanged() {
    }

    void setup(Device<Hal, UList0>* dev, uint8_t number, uint16_t addr) {
      Channel::setup(dev, number, addr);
      sysclock.add(*this);
    }

    uint8_t status () const {
      return 0;
    }

    uint8_t flags () const {
      uint8_t flags = this->device().battery().low() ? 0x80 : 0x00;
      return flags;
    }
};

class UType : public MultiChannelDevice<Hal, MeasureChannel, NUM_CHANNELS, UList0> {
  public:
    typedef MultiChannelDevice<Hal, MeasureChannel, NUM_CHANNELS, UList0> TSDevice;
    UType(const DeviceInfo& info, uint16_t addr) : TSDevice(info, addr) {}
    virtual ~UType () {}

    virtual void configChanged () {
      TSDevice::configChanged();
      DPRINT(F("*LOW BAT Limit: "));
      DDECLN(this->getList0().lowBatLimit());
      this->battery().low(this->getList0().lowBatLimit());
      DPRINT(F("*Sendeintervall: ")); DDECLN(this->getList0().Sendeintervall());
    }
};

UType sdev(devinfo, 0x20);
ConfigButton<UType> cfgBtn(sdev);

void setup () {
  DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER);
  sdev.init(hal);
  buttonISR(cfgBtn, CONFIG_BUTTON_PIN);
  sdev.initDone();

  // Initialize the INA219.
  // By default the initialization will use the largest range (32V, 2A).  However
  // you can call a setCalibration function to change this range (see comments).
  ina219.begin();
  // To use a slightly lower 32V, 1A range (higher precision on amps):
  //ina219.setCalibration_32V_1A();
  // Or to use a lower 16V, 400mA range (higher precision on volts and amps):
  ina219.setCalibration_16V_400mA();

  Serial.println("Measuring voltage and current with INA219 ...");
}

void loop() {
  bool worked = hal.runready();
  bool poll = sdev.pollRadio();
  if ( worked == false && poll == false ) {
    hal.activity.savePower<Sleep<>>(hal);
  }
}
Den Strom messe ich nicht, dazu müsste der elektrische Aufbau komplett anders gestaltet werden um auch die Ströme im Fehlerfall zu überleben.
Ausserdem macht das der Laderegler schon. Primär geht es darum den Akku mit dem bösen Kohlestrom nachzuladen, wenn die Sonne schwächelt. Und das funktioniert klasse.
Die Verdrahtung sollte sich von selbst ergeben aus den Datenblatt der Sensorplatine und der Doku zu AskSinPP.

ps: Ich hab versucht, eine LCD-Anzeige einzubinden, das überstieg meine Fähigkeiten und habs sein lassen....

Antworten

Zurück zu „Hardwareentwicklung und Selbstbau von Aktoren und Sensoren“