- 12V Akku mit 280 Ah bauen         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 85

Thema: Projekt vorgestellt: Strommessung im Haushalt bis 30A mit Arduino

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Ich weiß, ich habe aber keine Lust mich da jetzt durch den Arduino-Code zu quälen. Allzumal ich nicht bereit bin, mir dafür jetzt die Arduino-IDE zu installieren um das Projekt zu begutachten.

  2. #2
    @ stfan1409
    Welche Nennspannungen haben die eingesetzten Elkos und Kondensatoren?

    @ newbee90
    Auf deinem Foto sind nur 4 Elkos und 4 Kondensatoren zu sehen. Müssten es gemäß stfan1409 Schaltplan je 6 Stück sein (je einer für den MCP1525 und je zwei für den MCP3304)?

    Und lässt sich das ganze auch direkt auf einem ESP Chip umsetzen?
    Geändert von TM4889 (03.10.2018 um 16:03 Uhr)

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.10.2008
    Ort
    Kehnert
    Beiträge
    1.159
    Drehstrom geht, einfach 3 Sensoren auswerten. Um über den Strom die Energiekosten auszuwerden, muss der Verbraucher
    jedoch ohmsches Verhalten haben oder kompensiert sein.
    VG Micha
    Was brauche ich für Werkzeug - in dieser Reihenfolge seht ihr es:
    Vorschlaghammer, Notebook, BASCOM, Lötequipment, Rohrzange, Bolzenschneider ...

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    29.04.2017
    Beiträge
    13
    @ TM4889
    Überleg mal mit welcher Spannung die Schaltung funktioniert, dann kommst du auch auf die Spannung der Kondensatoren
    mein Schaltplan ist ja auch anders als der von Stfan1409, denn ich habe nur einen 4fach Wandler und er hat 3 single Wandler verwendet

  5. #5
    Hallo zusammen,

    ich habe/ hatte mal ein recht ähnliches Projekt bei mir zu Hause vor. Bei mir war es ein wenig einfacher gestrickt, da ich einfach ein Sensorboard von der Firma controleverything genutzt hatte. Allerdings ist bei mir daraus nie so richtig etwas geworden da es bei mir im Haus nur sehr wenig Ohmsche Lasten gibt. LED Lampen, Trafos usw. Sprich die Werte waren immer falsch.
    Ich bin an so einer Lösung aber immer noch recht stark interessiert. Daher wollte ich euch einmal meine Fragen/ Gedanken vorstellen. Bin da nämlich nur ein Amateur...
    Einmal die Grundsätzliche Frage ob es diese Art von Sensoren gibt, die vielleicht auch gut mit Induktiven Lasten auskommen. Könnten das z. B. Hall Effect Sensoren? Alternativ wäre ja eine Möglich über die Phasenverschiebung (habe ich das richtig verstanden?) den richtigen Wert zu berechnen. Sprich die Schaltung müsste erweitert werden. Hättet ihr da Ideen was da zu tun wäre?

    Was ich ja so richtig gut finden würde wäre so eine Art 12 Kanal Platine, die (natürlich in einem Gehäuse) direkt auf den Sicherungsschaltern im Verteiler angebracht werden kann. Sprich auf die Schalter aufsetzen, Kabel durch die Sensoren ziehen, glücklich sein. Da fehlt mir aber leider das passende wissen zu...

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    19.07.2011
    Beiträge
    66

    LEISTUNGSMESSUNG für 9 Sensoren

    Hallo,
    ich war lange nicht hier und habe auch keine Benachrichtigungen bekommen dass sich hier was tut...

    Grundsätzlich zu den Wandlern: die können nicht nur ohmsche, sondern auch kappazitive und induktive Lasten messen. Man muss die nur richtig auswerten...




    In der Zwischenzeit bin ich mehrfach gefragt worden aus der STROMESSUNG eine LEISTUNGSMESSUNG zu machen.
    Der erste Versuch ist fertig und sieht so aus:

    9x Strommessungen und 1x Spannungsmessung. Also vorerst die Leistungsmessung nur für alle Verbraucher einer Phase z.B. L1.

    Funktionsbeschreibung SOFTWARE:
    Ein µC misst 200-mal pro Periode Spannung und Strom, multipliziert beides und addiert diese Werte für eine Halbwelle auf. Anschließend wird die Summe durch die Anzahl der Messungen geteilt. Das Ganze passiert 4-mal, wird aufsummiert und durch 4 geteilt. Also ein Mittelwert über 4 Messungen. Anschließend wird das Ergebnis mit den Umrechnungs- und Korrekturfaktoren zum endgültigen Messwert umgerechnet und 1-mal pro Sekunde ausgegeben/angezeigt (I²C).

    Funktionsbeschreibung HARDWARE:
    Der Strom wird berührungslos über eine Spule gemessen, durch die das zu messende Stromkabel geführt wird. Da die Spule/der Wandler einen Strom ausgibt, wird noch ein Messwiderstand angeschlossen. Der Spannungsabfall wird mit dem Analog/Digitalwandler „MCP3301“ gemessen und an den µC weitergegeben. Der MCP1525 ist ein Spannungswandler, der eine Referenzspannung von 2,5V zur Verfügung stellt.

    Klicke auf die Grafik für eine größere Ansicht

Name:	Schaltplan Strommessung.jpg
Hits:	137
Größe:	47,0 KB
ID:	33755

    Die 230VAC Spannung wird mit einem Trafo auf 6VAC transformiert und über einen Spannungsteiler mit dem Analog/Digitalwandler „MCP3301“ gemessen.

    Klicke auf die Grafik für eine größere Ansicht

Name:	Schaltplan Spannungsmessung.jpg
Hits:	113
Größe:	33,7 KB
ID:	33756

    Hier die Platine mit Arduino und 10 A/D-Wandlern
    Klicke auf die Grafik für eine größere Ansicht

Name:	Platine.jpg
Hits:	136
Größe:	123,7 KB
ID:	33758

    Der aktuelle Stand ist, dass die Leistung ohmscher Verbraucher problemlos gemessen werden kann. Bei induktiven und kapazitiven Verbrauchern stimmen die Werte nicht.
    Und genau hier benötige ich Unterstützung aus dem Forum. Vielleicht kann mir jemand sagen wo der Fehler ist, ODER wie ich den Fehler einkreisen kann. Ich bin der Meinung, dass das Messverfahren für alle Verbraucher richtig ist. Also muss hardwaremäßig ein Problem / Fehler vorliegen um induktive / kapazitive Lasten zu messen.

    Eine Idee ist, dass durch den Trafo für die Spannungsmessung eine Phasenverschiebung entsteht. Nun wäre die Möglichkeit, diese Phasenverschiebung softwaremäßig zu korregieren.
    Als Versuch habe ich mir mal alle Strom und Spannungswerte pro Halbwelle einzeln ausgeben lassen und in Excel kopiert. Eine Spalte Strom und eine Spalte Spannung. Nun habe ich die Stromwerte soweit verschoben, dass die errechnete Leistung passt. Leider kann ich nicht sagen, dass ich die Stromwerte IMMER um 5 Werte verschieben muss, damit die Leistung passt, sondern es sind auch mal z.B. 10. -> so kann ich keinen Korrekturfaktor festlegen.

    Natürlich werden Strom und Spannung NICHT 100%ig gleichzeitig gemessen sondern erst der Strom und 30 uS später die Spannung. Das sollte aber nicht so ins Gewicht fallen, da bei 209 Messungen je Vollwelle nur alle 95,7uS gemessen wird.

    Wenn ich Strom und Spannung auf dem Oszilloskop anzeige, stelle ich sogar bei der 60W Glühlampe eine Phasenverschiebung fest. In etwa 22° was einem CosPhi von 0,92 entspricht. Oszilloskop natürlich hinter der eben beschriebenen Hardware(Trafo, Stromwandler…)
    Klicke auf die Grafik für eine größere Ansicht

Name:	Glühlampe60W_Oszi.JPG
Hits:	73
Größe:	63,0 KB
ID:	33757

    In der Messung sind 2 Spulen eingebaut(Trafo für Spannungsmessung und der Strommesswandler). Kann dadurch eine weitere Verschiebung stattfinden? Dann wäre es vielleicht möglich einen Korrekturfaktor einzurechnen…?
    Auch wäre es eine Möglichkeit, dass durch Sättigungseffekte des Trafokerns der sinusförmige Verlauf (oder auch ein schon netzseitig etwas verformter Sinus) verfälscht auf die Sekundärseite abgebildet wird.
    Das könnte man umgehen, wenn man den Trafo durch ein Kondensatornetzteil ersetzt - ist allerdings etwas aufwändiger, da einiges durch Optokoppler galvanisch getrennt werden muss...

    Bitte Vorschläge um den Fehler einzugrenzen...

    Hier noch der Schaltplan in Eagle
    eagleSchaltplan.zip

    und natürlich das Programm für den Arduino:
    LeistMess_L2.zip

    Gruß, stfan

  7. #7
    Hallo,

    genau das war/ ist auch mein Problem bei meiner Lösung gewesen. Bei der, von mir verwendeten Platine, war es noch etwas blöder. Die Werte wurden per I2C Bus zur Verfügung gestellt. Das heißt mehrere Messungen und Mittelwert wären viel zu langsam. Die von @stfan1409 genutzte Schaltung finde ich schon sehr gut. Aber auch hier schlägt das Thema verschiedene Lastarten wieder zu. Auch eine Verschiebung um z. B. 5 Werte wird nicht funktionieren. Ist ein Trafo oder ähnliches im Stromkreis gibt es eine Phasenverschiebung. Die ist bei jedem Trafo, soweit ich es verstehe, unterschiedlich. Sprich eigentlich müsste man bei der Messung direkt die Phasenverschiebung mit messen und dann den Wert korrigieren. Glaube ich...
    Vielleicht hat da noch jemand eine Idee?

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    19.07.2011
    Beiträge
    66
    Entschuldigung für die Verwirrung. Der Stromwandler ist der gleiche geblieben. Ich habe lediglich den 6 Volt Trafo für die Spannungsmessung gegen einen 12 Volt Trafo mit viel mehr Leistung getauscht. Das hat ergeben dass der Sinus für die Spannungsmessung jetzt sinusförmig angezeigt wird. Mit dem 6 Volt Trafo hatte ich in dem Sinus leichte Ecken drin. Die ersten beiden Diagramme in der Excel Tabelle sind mit dem alten 6 Volt Trafo der einzige Unterschied ist, dass ich bei der ersten Messung keinen Kondensator drin habe und bei der zweiten Messung ein 10 Mikrofarad Kondensator. Bei dem dritten Diagramm habe ich den 12 Volt Trafo für die Spannungsmessung eingebaut + den Kondensator an dem Stromwandler und als Last habe ich eine Leuchtstofflampe angeschlossen.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied Avatar von avr_racer
    Registriert seit
    01.04.2014
    Ort
    MecklenburgVorpommern
    Beiträge
    174
    Gut also ist der Sachstand wieder gleich und mit den Änderungen hat sich also nicht wirklich viel getan, dann warten wir mal bis die neu Messspule da ist und gucken dann weiter.

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    19.07.2011
    Beiträge
    66
    Fertig?
    Also ich habe lange weitergetestet und das Ergebnis ist, dass ich die Verschiebung durch den Trafo über die Software rausrechne.
    Der Messwert ist ganz passabel, wobei ich festgestellt habe, dass ich kein geeichtes Messgerät habe, um einen 100%igen Kontrollwert zu haben.
    Eine Glühlampe ist einfach, aber eine Waschmaschine mit "Frequenzumrichter" ist für mich nicht mehr sicher messbar. Auch hierfür extra gekaufte digitale Hutschienenzähler haben untereinander Abweichungen von mehreren % angezeigt.
    Hier nun das endgültige Programm:
    Datei: LeistMess_V3.0.ino

    Code:
    /*
       Zur Leistungsmessung in einer Elektroverteilung.
       Es werden mehrere Leistungen gemessen und über I2C zur Weiterverarbeitung weitergegeben.
       Herzstück ist ein Arduino Nano. Über SPI-Bus sind pro Messung ein MCP3301 A/D-Wandler angeschlossen,
       welcher wiederum an eine Stromzange angeschlossen ist. Die Leistungsmessung ist zur Zeit nur für Wechselspannung.
       Die Spannung wird über einen Trafo einphasig gemessen und mit den gemessenen Strömen multipliziert.
       Weitere Infos zur Messung siehe weiter unten.
    */
    
    // ProgrammName: LeistMess
    // Kurzbeschreibung: Strommessung, Effektivwertbildung, Datenaufbereitung und Übertragung
    // Datum: 04.03.2017 / Version: 1.0 - mit serieller Ausgabe
    // Datum: 10.07.2017 / Version: 1.1 - mit Ausgabe über I2C
    // Datum: 03.04.2018 / Version: 1.2 - I2C Ausgabe angepasst
    // Datum: 20.04.2018 / Version: 1.3 => Umstellung auf Leistungsmessung
    // Datum: 29.08.2018 / Version: 2.0 - Leistungsmessung eingebaut; Kalibrierungsmenü angepasst
    // Datum: 30.08.2018 / Version: 2.1 - 230V Spannung über I2C hinzugefügt; I2C-Adresse über Konstante
    // Diverse Änderungen und Tests
    // Datum: 07.03.2019 / Version: 3.0 - an Nano angepasst
    
    // Autor: Jürgen Stähr
    
    //Programm Version:
    const String Version = "3.0";
    
    //D12 -> Pin 50
    //D13 -> Pin 52230
    
    // Konfiguration
    //******* ACHTUNG ********** Hier an die vorhandene Hardware anpassen ******** ACHTUNG ***************
    const int csSpg = 8;          // Pin Nummer des CS für die Spannungsmessung hier eintragen
    const int PinKal = 17;           // PIN Nummer für die Kalibrierung (Für Kalibrierung auf Masse ziehen)
    const int ADCAnz = 2;           // Anzahl aller angeschlossenen ADC (Spannung- und Strommessung)
    const int CRundAnz = 4;         // Anzahl der Messungen je Sekunde
    const int I2C_Adr = 4;          // I2C Adresse für die Datenausgabe als Slave
    // Pin Nummern der cs Eingänge der ADC. Erlaubt sind 2 - 10 (digital Pins)
    //                                                  14 - 19 (analogPins A0 - A5)
    //const int cs[] = {10, 10,10,10,10,10,10,10,10,10};  // das geht auch, macht aber keinen Sinn
    const int cs[] = {9, 10}; // Muss mit ADCAnz übereinstimmen oder größer sein
    const int Shunt[] = {100, 56}; // Entsprechend dem cs[] Array die Widerstände eintrage//                   16A  16A   9A  16A  28A  9A  28A  9A  16A
    
    
    
    /*
         TESTPLATINE 2-Kanal:
         Kanal 7 = 100 Ohm
         Kanal 8 =  56 Ohm
    
         Kanal:  Bezeichnung: Phase "L1"
       (0) L1 D2   Spannungsmessung - 150 Ohm
       (1) L1 D3   Herd 16A - L1 - 100 Ohm
       (2) L1 D4
       (3) L1 D5
       (4) L1 D6
       (5) L1 D7   DG Steckdosen&Bel. 28A - 56 Ohm
       (6) L1 D8   G  Steckdosen&Bel. 28A - 56 Ohm
       (7) L1 D9   Steckdosen Keller 28A - 56 Ohm
       (8) L1 D10  Beleuchtung Keller 9A - 180 Ohm
       (9) L1 D14  Waschmaschine 16A - 100 Ohm
    
        Kanal:  Bezeichnung: Phase "L2"
       (0) L2 D2   Spannungsmessung - 150 Ohm
       (1) L2 D3   Herd 16A - L2 - 100 Ohm
       (2) L2 D4   Geschirrspüler 16A - 100 Ohm
       (3) L2 D5   Beleuchtung EG 9A - 180 Ohm
       (4) L2 D6   16A - 100 Ohm
       (5) L2 D7   Steckdosen EG 28A - 56 Ohm
       (6) L2 D8   28A - 56 Ohm
       (7) L2 D9
       (8) L2 D10
       (9) L2 D14
    
       Kanal:  Bezeichnung: Phase "L3"
       (0) L3 D2   Spannungsmessung - 150 Ohm
       (1) L3 D3   Backofen 16A - L3 - 100 Ohm
       (2) L3 D4
       (3) L3 D5   Kühlschrank 9A - 180 Ohm
       (4) L3 D6
       (5) L3 D7   OG Steckdosen&Bel. 28A - 56 Ohm
       (6) L3 D8
       (7) L3 D9
       (8) L3 D10
       (9) L3 D14
    */
    const unsigned long BaudRate = 115200;  // hier die Baudrate des seriellen Interfaces einstellen
    //********************************************************************
    // Beschreibung:
    /*--------------------------------------------------------------------------
       Das Programm läuft auf einem Arduiono (Nano, Mini,...) und soll den Wechselstrom von mehreren Installationsleitungen messen.
    
       Max. können 10 Wandler angeschlossen werden. Bei jedem Wandler wird 4 mal pro Sekunde je eine Periode gemessen und aus den
       Messergebnissen der RMS gebildet. Der Arduino schafft 586 Messungen in 20 ms bei Verwendung von unsigned long zum Speichern
       der Messergebnisse. Bei Verwendung von float können nur 380 - 400 Messungen durchgeführt werden.
       Die Integer Berechnung begrenzt den max. gemessenen Strom auf 2707 Wandlerzählern, entspricht bei 50 Ohm 33A  ->  100 Ohm 16,1A.
    
       Die Zusammengefassten Ergebnisse werden einmal pro Sekunde über die serielle Schnittstelle übertragen.
    
       Die Messwandler liefern 1mA pro 1A Messstrom, max. jedoch 2,5V. ( wenn das der Effektivwert ist, liegt der Spitzenwert schon zu hoch für den ADC!!!!)
       Ein 13 Bit ADC MCP 3301 digitalisiert die über einen Messshunt abfallende Spannung.
       Die Größe des Mess-Shunt ist je ADC wählbar und muss im Array Shunt[] eingetragen werden.
       Der ADC erhält eine Referenzspannung von 2,5V. Diese geteilt durch die halbe Auflösung=4096 ergibt den
       Spannungswert eines ADC-Zählers= 0,61035 mV. Die Referenzspannungsquelle muss damit hinreichend genau sein.
    
       Der ADC wird über SPI angesprochen. Er kann mit max 1,7 MHz getaktet werden. Der AVR läuft mit 16 MHz und kann den SPI Takt
       nur durch 2,4,8,16,.. teilen, so dass der ADC mit 1 MHz getaktet wird. Damit dauert die Übertragung eines
       Messwertes 16 uS. Weiter 18 uS werden für die Verarbeitung benötigt
    
       TEST MESSWERTE(Messwiderstand -> Messstrom):
       --------------------------------------------
       OHM - Strom MIN - Strom MAX
        56 Ohm - 11 mA - 28 A
       100 Ohm -  6 mA - 16 A
       180 Ohm -  4 mA -  9 A
    
      --------------------------------------------------------------------------
      Version 1.1 mit I2C
      Der Arduino verhält sich als I2C Slave. Sobald eine Anfrage vom Master empfangen wird,
      werden alle 10 Messwerte (in High- und Lowbyte aufgeteilt) per I2C gesendet. Wärend dieser Zeit
      können keine I2C Anfragen empfangen werden.
    
      Version 1.3 ==> Leistungsmessung
      Das Programm soll nun die Leistung der Verbraucher erfassen. Dazu wird ein frei wählbarer Wandler
      zur Messung der Spannung benutzt. Es kann auch ein elfter Wandler angeschlossen werden. der Controller
      kann dann 10 Verbraucher überwachen.
      Messprinzip:
      In der Funktion Messperiode wird der Strom des aktuellen Wandlers mit der gemessenen Spannung multipliziert und in einer
      long int var aufaddiert. Nach 20ms wird der Mittelwert durch Teilen mit der Anzahl der Messungen ermittelt.
      Ausgabe:
      Erst hier wird der Wert eines Stromzählers vom ADC und des Spannungszählers eingearbeitet:
      - Mittelwert aus den Runden
          StromWert eiens Zählers in Abhängigkeit vom MessShunt
          Wert eines Spannungszählers (400V Spitzenspannung/4096 ADC Zähler ungefähr 0,1V)
          Korrekturwert Spannung
      Hier wird von Integer auf Float umgeschaltet.
    
      Da die Spannung nicht so genau wie der Strom angliefert wird, kann die Spannungsmessung kalibriert werden.
      Hierzu muss z.B. der Pin A3 beim Einschalten auf Masse gezogen werden, das Programm geht dann in den Kalibriermodus.
      Es misst die Spannung und gibt sie über die Serielle Schnittstelle aus und wartet anschließend auf die Eingabe
      einer Spannungsmessung. Der Korrekturfaktor wird daraus errechnet und im EEPROM abgespeichert.
      (die max Eingangsspannung für den MCP3301 beträgt +/-2,5V)
    
    */
    
    
    // für Datenausgabe bei Fehlersuche(wenn auskommentiert = nicht aktiv)
    //#define debug //Status über RS232 ausgeben
    #define debug_Strom_Ausgabe //Strom über RS232 ausgeben
    
    const unsigned long CPeriode = 20000; // Microsekunden einer Halbwelle
    const unsigned long CRunde = 1000 / CRundAnz; // ms einer Messrunde über alle ADC
    const int EEAdr = 0;                          // Adresse im EEProm für den Spg. Korrekturwert
    
    // Array zur Aufnanme aller Messergebnisse einer Sekunde
    long Erg[ADCAnz * CRundAnz];
    boolean Flag_Ausgabe = false;  // Flag für die Ausgabe
    unsigned long SchlafRunden = 0; // zählt im Debugmodus die Looprunden
    float Korrektur;                // nimmt den Spannungskorrekturwert aus dem EEPROM auf
    int Wert_h[ADCAnz];   //Variable für I2C High
    int Wert_l[ADCAnz];   //Variable für I2C Low
    float MessSpg; //aktuelle 230V Spannung ausgeben
    int MessSpg2; //aktuelle 230V Spannung ABER Komma verschoben!!!
    
    
    //**************************************************************************************
    #include <SPI.h>                    // SPI Bibliothek
    #include <Streaming.h>              // Bibliothek zur besseren Ausgabeformatierung ==> Streaming.h ins Arduino Bibliotheksverzeichni kopieren
    #include <Wire.h>                   // Bibliothek für I2C
    #include <EEPROM.h>                 // EEPROM Zugriff
    
    //**************************************************************************************
    // Funktionsprototypen
    long MessPeriode(int csADC);
    
    void Ausgabe();
    void requestEvent();
    void Messung();
    //**************************************************************************************
    void setup() {
    
      Serial.begin(BaudRate);  // Serielle Schnittstelle mit 115200 Baud starten
    
      SPI.begin();            // SPI Interface starten
      for (int i = 0; i < ADCAnz; i++) {    // cs Pins initialisieren
        pinMode(cs[i], OUTPUT);
        digitalWrite(cs[i], HIGH);
      }
      // Pin für die Spannungsmessung init.
      pinMode(csSpg, OUTPUT);
      digitalWrite(csSpg, HIGH);
      // Pin für die Kalibrierung
      pinMode(PinKal, INPUT_PULLUP);
    
      SPI.beginTransaction(SPISettings(1700000, MSBFIRST, SPI_MODE0)); // SPI Parameter
    
      Wire.begin(I2C_Adr);                // I2C mit Adresse #... starten
      Wire.onRequest(requestEvent); // register event für I2C
    
    
      // Versionsausgabe:
      //____________________________________________________________________________________________________
      Serial.println("= = = = = = = = = = = = = = = = = = =");
      Serial.print("  NEUSTART: StromMess_I2C_V_v"); Serial.println(Version); //Damit später zu sehen ist, welche Datei auf dem Arduino ist
      Serial.print("  I2C Adresse L2: "); Serial.println (I2C_Adr);
      Serial.println("= = = = = = = = = = = = = = = = = = =");
      //____________________________________________________________________________________________________
    
    
    
      //normal starten oder Kalibrierung starten:
      if (digitalRead(PinKal) == LOW) {
        //if (digitalRead(PinKal) == HIGH) { //immer Kalibrierung ausrufen zum testen
        Serial << "Kalibrierung" << endl;
        Kalibrierung();
      }
      EEPROM.get(EEAdr, Korrektur);
    }
    
    
    //**************************************************************************************
    void loop() {
    
      if (digitalRead(PinKal) == HIGH) Flag_Ausgabe = true;
      //Serial.print ("Ausgabe - Flag_Ausgabe: ");
      //Serial.println (Flag_Ausgabe);
    
      if (Flag_Ausgabe == true) { // Falls I2C Master Daten haben will
        delay(10);
    
        //Spannung messen und auf ertem Kanal ausgeben
        int Spg = SpgMessung();
        MessSpg = Spg;
        MessSpg *= Korrektur;   // Korrekturfaktor aus dem EEProm befücksichtigen
        MessSpg2 = MessSpg; //Wert mit verschobenem Komma für I2C Ausgabe
        MessSpg *= 0.1;
    
        Messung();        // Neue Messung anstoßen
        Flag_Ausgabe = false;  // Flag zurücksetzen
      }
    #ifdef debug
      SchlafRunden += 1;    // Im Debugmodus die Anzahl der LoopRunden zählen
    #endif
    
    }
    
    //**************************************************************************************
    void requestEvent() {           // Diese Schleife wird bei I2C Empfang durchlaufen
    #ifdef debug
      Serial.println ("requestEvent - Anforderung von I2C Master");
    #endif
    
      for (int i = 0; i < ADCAnz; i++) {
        // I2C Ausgeben -> Daten müssen sofort ausgegeben werden, da sonst Schwierigkeiten mit I2C Master
        Wire.write(Wert_l[i]);
        Wire.write(Wert_h[i]);
    
    #ifdef debug
        Serial << Wert_l[i] << " : " << Wert_h[i] << endl;
    #endif
      }  // Ende Schleife über alle ADC
    
      Flag_Ausgabe = true;              // und es wird nichts weiter gemacht, als ein Flag zu setzen, das in Loop ausgewertet wird
    }
    
    
    //**************************************************************************************
    void Messung() {
    
      // Diese Schleife wird jede Sek. einmal durchlaufen
      // I2C abschalten
      TWCR = _BV(~TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(~TWINT);
    
      for (int i = 0; i < ADCAnz * CRundAnz; i++) Erg[i] = 0; // Ergebniise des vorherigen Laufes löschen
      // Schleife je Runde. In jeder Runde werden alle ADC für je 20ms abgefragt
      for (int runde = 0; runde < CRundAnz; runde++) {
        //Serial << "StartRunde:" << runde << endl;
        for (int ADCNr = 0; ADCNr < ADCAnz; ADCNr++) {
          int Index = runde * ADCAnz + ADCNr; // Zeigt auf das Ergebnisarray, Reihenfolge: Ergs der ersten Runde, Ergs der 2. Runde, usw.
          Erg[Index] = MessPeriode(cs[ADCNr]); // Messung für einen ADC durchführen und speichern;
          //Serial << "ADCNr:" << ADCNr << "Runde:" << runde << endl;
        }  // Ende, alle ADC einmal durchmessen
        if (runde == CRundAnz - 1) Ausgabe(); // wenn es die letzte Runde war ==> Daten ausgeben
      } // Ende Schleife über alle Mess-Runden
    
      // I2C einschalten
      TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT);
      return;
    } //Ende Messung
    
    
    /* Function MessPeriode
        Führt mit einem ADC die Messungen über eine Periode durch.
        Der cs-PIN des ADC wird übergeben
        führt dann die Spannungsmessung aus
        summiert Strom * Spg Werte auf
        nach Ablauf wird durch die Anzahl der Messungen geteilt (Mittelwert) ==> Rückgabewert
        Strom und Spannung müssen vorzeichenrichtig verarbeitet werden, deshalb nur long Variablen*/
    
    long MessPeriode(int csADC) {
      unsigned long ZeitPeriode = micros();
      int MessAnz = 0; // Anzahl der Messungen
      const int diff = 2; //Hier den Wert für die Differenz / Verschiebung eingeben - muss ausprobiert werden. 
      /*Einen ohmschen Verbraucher wie eine Glühlampe anschließen und den Wert im Testmodus so einstellen, 
       * dass die Werte von Strom und Spannung gleichzeitig im positiven/negativen Bereich sind.
       */
       
      // Initialisierung der Zähler
      // Der Strom wird jeweils einen Platz weiter ins Array als die Spannung geschrieben. Dadurch dauert es diff=8 mal bis zum ersten Mal
      // Platz null belegt wird. erst dann beginnt die Messung und damit auch die Zeitzählung
      int zaehler_i = 0; //Zeiger für Stromarray  ==> Im ersten Durchlauf wird Platz 1 im Array beschrieben
      int zaehler_u = diff; //Zeiger für Spannungsarray ==>  Im ersten Durchlauf wird Platz 0 im Array beschrieben
      int ADCStrom[diff + 1]; // nimmt den Strom-Messwert vom ADC auf
      int ADCSpg[diff + 1];  // desgl. für die Spannung
      boolean start = false; // false, bis diff=8 Durchgänge gelaufen sind.
    
      float Erg = 0; // nimmt die Summen einer Periode auf
    
      //..................................................
    
    
      do {
    
        //Zähler für Strom:
        if (zaehler_i < diff) {
          zaehler_i++;
        }
        else {
          zaehler_i = 0;
          // prüfen, ob wir am Anfang der Messung stehen
          if (!start) {
            // Das Array ist das erste Mal gefüllt, jetzt kann es losgehen
            ZeitPeriode = micros();  // Messzeit jetzt neu starten
            Erg = 0;                // Ergebnis noch mal nullen
            start = true;             // und Feuer frei
          }
        }
        //Zähler für Spannung:
        if (zaehler_u < diff) {
          zaehler_u++;
        }
        else {
          zaehler_u = 0;
        }
        // Strom und Spannung versetzt ins Array schreiben
        // Strommessung: mit zaehler_i
        digitalWrite(csADC, LOW);
        ADCStrom[zaehler_i] = SPI.transfer16(0);
        digitalWrite(csADC, HIGH);
        // der ADC liefert ein 13 Bit Ergebniss, das muss an 16 Bit int angepasst werden
        if (bitRead(ADCStrom[zaehler_i], 12)) {
          ADCStrom[zaehler_i] |= 0xF000;         // das int Signbit und das obere HalbByte auf 1 setzen (2er Complement)
        } else ADCStrom[zaehler_i] &= 0x0FFF;      // die 3 undefinierten und das Signbit auf null
    
        // Spannungsmessung: mit zaehler_u
        digitalWrite(csSpg, LOW);
        ADCSpg[zaehler_u] = SPI.transfer16(0);
        digitalWrite(csSpg, HIGH);
        // der ADC liefert ein 13 Bit Ergebniss, das muss an 16 Bit int angepasst werden
        if (bitRead(ADCSpg[zaehler_u], 12)) {
          ADCSpg[zaehler_u] |= 0xF000;  // das int Signbit und das obere HalbByte auf 1 setzen (2er Complement)
        } else ADCSpg[zaehler_u] &= 0x0FFF;      // die 3 undefinierten und das Signbit auf null
    
    
        //BERECHNUNG: mit den verschobenen Werten
        // Die Verschiebung ist bereits im Array enthalten. Der aktuellen Zähler ist zaehler_i,
        // er wird mit den bereits früher aufgezeichneten Spannungswerten mulzipliziert.
        Erg += (float)ADCStrom[zaehler_i] * (float)ADCSpg[zaehler_i];  // Strom * Spannung aufaddieren
    
        MessAnz++;                                               // Anzahl der Messungen erhöhen
      } while (micros() - ZeitPeriode < CPeriode);               // Ende MessSchleife über eine Periode
      //..................................................
    
      Erg /= MessAnz;                // Das Ergebnis aller Messungen durch die Anzahl teilen (Mittelwert)
    #ifdef debug
      Serial << "Anzahl der Messungen je Periode:" << MessAnz << " Messung: " << Erg <<  endl;;
    #endif
      return (long)Erg;        // Rückgabe ist der Mittelwert
    }
    
    /* Function Ausgabe
       gibt jede Sekunde die Messergebnisse über die Serielle Schnittstelle aus*/
    //**************************************************************************************
    void Ausgabe() {
    #ifdef debug
      Serial.println ("Ausgabe: ");
    #endif
      const long Uadc = 610350; // Wert eines Zählers
      float IuA;                 // Strom je Zähler eines ADC
      float SekWert;   // nimmt die Ergebnisse einer Runde eines ADC auf
      int Leistung;
    
      for (int ADCNr = 0; ADCNr < ADCAnz; ADCNr++) { // Schleife über alle ADC
        SekWert = 0;
        for (int Runde = 0; Runde < CRundAnz; Runde++) { // Schleife über alle Runden je ADC
          SekWert += Erg[Runde * ADCAnz + ADCNr]; // Messergebnisse eines ADC aufaddieren
        } // Ende Schleife über Runden eines ADC
        SekWert /= CRundAnz;    // Mittelwert bilden
        // Stromkorrektur einarbeiten
        IuA = Uadc / Shunt[ADCNr]; // Strom je Zähler in uA berechnen
        SekWert *= IuA;         // mit Strom-Zählerwert multiplizieren z.B. für 50 Ohm(12207 uA)
        SekWert /= 1000;        // auf mA runter rechnen
        SekWert /= 1000;        // auf A runter rechnen
        SekWert /= 10;          // ein ADC-Zähler ist ca. 100mV Wert => Umrechnung auf Volt
        SekWert *= Korrektur;   // Korrekturfaktor aus dem EEProm berücksichtigen
    
    
        if (SekWert >= 0) {     // Wert nur übernehmen, wenn >= 0, sonst 0 eintragen -> also keine negativen Werte
          Leistung = SekWert;
    
        }
        else {
          Leistung = 0;
        }
    
        // Ausgeben
        Wert_l[ADCNr + 1] = (lowByte(Leistung));   //aktuellen Wert an I2C Variable übergeben
        Wert_h[ADCNr + 1] = (highByte(Leistung));  //+1 damit Byte0 für die Spannung frei bleibt
    
    #ifdef debug_Strom_Ausgabe
        //Serial << "Leist." << ADCNr + 1 << ": " << SekWert << " W; " ; //Ausgabe mit 2 Nachkommastellen
        Serial << "Leist." << ADCNr + 1 << ": " << Leistung << " W; " ; //Ausgabe ohne Nachkommastellen
    #endif
      }  // Ende Schleife über alle ADC
    
      //Spannung über I2C auf dem ersten Byte übergeben
      Wert_l[0] = (lowByte(MessSpg2));   //aktuellen Wert an I2C Variable übergeben
      Wert_h[0] = (highByte(MessSpg2));  //aktuellen Wert an I2C Variable übergeben
      Serial.print ("Spg.: ");
      Serial.print (MessSpg2);
    
    #ifdef debug_Strom_Ausgabe
      Serial << endl;
    #endif
      return;
    } // Ende Function Ausgabe
    - - - Aktualisiert - - -

    und der zweite Teil für die Kalibrierung:
    Datei: Kalibrie.ino

    Code:
    /*
       Kalibrierung
       Hier wird die Spannungsmessung kalibriert. Durch einmaliges Eingeben der gemessenen Spannung errechnet das Programm
       einen Korrekturfaktor und speichert ihn im EEPROM ab. Der Faktor wird künftig bei der Berechnung verwendet
    */
    
    void Kalibrierung() {
      while (true) {
    
    
        float SpgVergl = 0; //ist die Spannung, welche als Vergleich vom Benutzer eingegeben wurde
        int Spg = SpgMessung();
        float MessSpg = Spg * 0.1;
    
    
        Serial << ">>>>>>>>>>> Kalibrierung <<<<<<<<<<" << endl;
        Serial << "Die gemessene Spannung (ohne Korrektur!) beträgt: " << _FLOAT(MessSpg, 1) << "V" << endl;
        Serial << "Bitte das Ergebnis der Vergleichsmessung eingeben: ";
        Serial.setTimeout(1000000);
        while (SpgVergl == 0) {
          String Eingabe = Serial.readStringUntil('\n');
          SpgVergl = Eingabe.toFloat();
        }
        Serial << endl << "Eingegeben wurde: " << SpgVergl << endl;
        Serial << " " << endl;
    
    
        float Korrektur = SpgVergl / MessSpg;
        Serial << "Korrekturfaktor ausrechnen: SpgVergl / MessSpg" << endl;
        Serial << "Korrekturfaktor ausrechnen:  " << SpgVergl << "V / " << MessSpg << "V" << endl;
        Serial << "Korrekturfaktor ist: " << _FLOAT(Korrektur, 5) << endl;
        Serial << " " << endl;
    
    
        Serial << "Daraus errechneter Messwert: "  << endl;
        Serial << "MessSpg * Korrektur = Messwert"  << endl;
        Serial << MessSpg << "V * " << Korrektur << " = " << MessSpg*Korrektur << "V" << endl;
        Serial << " " << endl;
    
    
        EEPROM.put(EEAdr, Korrektur); //Faktor in EEPROM speichern
        EEPROM.get(EEAdr, Korrektur); //Faktor zum Testen nochmal aus EEPROM auslesen
        Serial << "geänderter Korrekturfaktor: " << _FLOAT(Korrektur, 5) << endl;
        Serial << "wurde im EEPROM Abgespeichert!" << endl << endl;
    
      }
      return;
    }
    int SpgMessung() {
      unsigned long ZeitPeriode = micros();
      int MessAnz = 0; // Anzahl der Messungen
      int ADCdata;  // nimmt den Messwert vom ADC auf
      unsigned long Erg = 0; // nimmt die quadrierten Summen einer Periode auf
      do {
        digitalWrite(csSpg, LOW);
        ADCdata = SPI.transfer16(0);
        digitalWrite(csSpg, HIGH);
        // der ADC liefert ein 13 Bit Ergebniss, das muss an 16 Bit int angepasst werden
        if (bitRead(ADCdata, 12)) {
          ADCdata |= 0xF000;         // das int Signbit und das obere HalbByte auf 1 setzen (2er Complement)
        } else ADCdata &= 0x0FFF;      // die 3 undefinierten und das Signbit auf null
    
        Erg += (unsigned long)ADCdata * (unsigned long)ADCdata;  // Quadrieren
        MessAnz++;    // Anzahl der Messungen erhöhen
      } while (micros() - ZeitPeriode < CPeriode);               // Ende MessSchleife über eine Periode
      Erg /= MessAnz;                // Das Ergebnis aller Messungen durch die Anzahl teilen (quadratischer Mittelwert)
    
    #ifdef debug
      Serial << "Anz:" << MessAnz;
      Serial << "M:" << ADCdata << " E:" << (int(sqrt(Erg))) << "; ";
    #endif
      return int(sqrt(Erg));        // Rückgabe ist die Wurzel aus dem Mittelwert der Quadrate
    }

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Ähnliche Themen

  1. Suche Serviceleistung Arduino Programierer für mein Projekt gegen Bezahlung gesucht
    Von kkellner im Forum Jobs/Hilfen/Stellen - Gesuche und Angebote
    Antworten: 1
    Letzter Beitrag: 16.07.2015, 15:37
  2. Arduino 230V Relais Strommessung
    Von Fransch im Forum Elektronik
    Antworten: 4
    Letzter Beitrag: 14.07.2015, 21:39
  3. Arduino Projekt Fotofalle
    Von TKK-Arduino im Forum Arduino -Plattform
    Antworten: 20
    Letzter Beitrag: 18.02.2015, 18:35
  4. Antworten: 5
    Letzter Beitrag: 02.08.2013, 21:38
  5. Arduino-Projekt verkleinern
    Von IPlayWithLasers im Forum Arduino -Plattform
    Antworten: 4
    Letzter Beitrag: 28.01.2012, 10:55

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen