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
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
}
Lesezeichen