Mijn naam is John en ik ben nieuw op dit forum. Ik heb mij net pas aangemeld dus mijn profiel is nog niet up to date, maar dat komt nog wel.
Ik heb het volgende probleem. Ik ben bezig met een KWh logger dmv een aparte KWh meter die ik in mijn meterkast wil inbouwen.
Ben nu bezig met de code hiervoor te schrijven maar moet erbij vermelden dat ik nog niet zoveel ervaring hiermee heb. Vooral lang bezig geweest met inlezen. Heb hier en daar wat stukjes code geleend om de pulsen die mijn KWh meter geeft te tellen en om te zetten in verbruikt vermogen en totaal Kwh verbruik. Ik laat alles even naar de seriele monitor gaan om alles te controleren.
Het aantal pulsen dat mijn KWh meter geeft( 1000 pulsen = 1KWh) wil ik delen door duizend zodat de uitkomst in KWh gegeven wordt.
Alleen krijg ik geen resultaat als ik door duizend deel. Als ik bijvoorbeeld 100 invul, krijg ik wel resultaat. Volgens mij zit ik mij nu blind te staren op iets wat misschien betrekkelijk eenvoudig is maar ik zie het niet(meer) 8).
Kan iemand hier een (deskundige) blik op werpen en mij een stukje op gang helpen. Een complete oplossing is niet nodig, ik moet zelf ook nog iets te doen hebben.
Hieronder de code tot zover:
#include <LiquidCrystal.h>
LiquidCrystal lcd (12,11,10,6,5,4,3);
//instellen vaste variabelen voor tellen pulsjes
const int KwhPulse = 2; // puls aangesloten op digitale ingang 2
// instellen variabelen voor bijhouden aantal pulsjes
int pulseState = 1; // huidige staat van kwh puls, deze is äctief laag" dus hier inverteren
long KwhpulseCounter = 0; // teller voor aantal pulsen
int lastPulseState = 1; // vorige staat van Kwh puls
// instellen variabelen berekenen pulstijd
float pulseAan = 0;
float pulseUit = 1;
float verstrekenTijd =0;
//instellen variabelen berekenen Kwh en huidig vermogen
int currentWatts = 0;
float totalKwh = 0.00;
int tijd=0;
//setup
void setup() {
pinMode(KwhPulse, INPUT); // maak van (digitale)pin 2 een input
Serial.begin(9600); // seriele communicatie op 9600 baud
lcd.begin(16,2); // lcd met 2 regels en 16 karakters per regel
//lcd.print("Kwh"); // boodschap op lcd schrijven
}
void loop() {
pulseState = digitalRead(KwhPulse); // lees waarde digitale ingang en bewaar de waarde in "pulseState"
if (pulseState != lastPulseState){ //vergelijk de staat van de Kwhpulse met zij vorige staat
if (pulseState == LOW){ //als de huidige staat laag is ging de puls van uit naar aan
KwhpulseCounter++; // als de staat is veranderd, verhoog de teller
Serial.print ("aantal pulsen: "); //controle
Serial.println (KwhpulseCounter); //controle
pulseAan = millis(); //tijd in milliseconden vanaf start arduino
verstrekenTijd = (pulseAan - pulseUit)/1000; //gemeten tijd tussen twee pulsen
pulseUit = pulseAan; //bewaren voor volgende ronde
Serial.print("tijd tussen pulsen: "); //controle
Serial.print (verstrekenTijd); //controle
Serial.println(" sec"); //controle
currentWatts = 3600000 / (1000 * verstrekenTijd);
Serial.print ("huidig verbruik: "); //controle
Serial.print (currentWatts); //controle
Serial.println(" Watt"); //controle
totalKwh = KwhpulseCounter / 1000;
Serial.print ("Totaal Kwh verbruik: ");
Serial.println(totalKwh);
}
}
//bewaar de huidige staat als de laatste staat voor de volgende keer in de loop
lastPulseState = pulseState;
}
Dag comteccie
Welkom op het nederlandstalige gedeelte van het arduino forum.
Ik ben blij te zien dat je je code toevoegde. Dat maakt de zaak direct wat handiger.
Ik heb voor jou code tags toegevoegd ant dat leest makkelijker. Best doe je dat natuurlijk zelf.
Ik ben niet helemaal zeker van wat ik ga voorstellen maar vervang eens volgende lijn
You better do the calculations with either all floats or all unsigned long.
I prefer unsigned long in this case.
You have a mix of integer, float and long, that is bound to go wrong someday.
Add comment to every calculation, about what is calculated, and how the conversion is and if it will fit in the resulting variable.
Bedankt Jan voor de snelle reactie.
Dat van die code tags wist ik niet maar zal er voortaan rekening mee houden.
Helaas werkt jouw oplossing ook niet. Het resultaat blijft 0. Verander ik die 1000 in 100 dan krijg ik wel resultaten.
I changed some calculations and added some comments. But it still doesn't work.
Suggestions are welcome
Greetings,
John
// invoegen bibliotheek
#include <LiquidCrystal.h>
LiquidCrystal lcd (12,11,10,6,5,4,3);
//instellen vaste variabelen voor tellen pulsjes
const int KwhPulse = 2; // puls aangesloten op digitale ingang 2
// instellen variabelen voor bijhouden aantal pulsjes
int pulseState = 1; // huidige staat van kwh puls, deze is äctief laag" dus hier inverteren
float KwhpulseCounter = 0; // teller voor aantal pulsen
int lastPulseState = 1; // vorige staat van Kwh puls
// instellen variabelen berekenen pulstijd
float pulseAan = 0;
float pulseUit = 1;
float verstrekenTijd =0;
//instellen variabelen berekenen Kwh en huidig vermogen
float currentWatts = 0;
float totalKwh = 0;
//setup
void setup() {
pinMode(KwhPulse, INPUT); // maak van (digitale)pin 2 een input
Serial.begin(9600); // seriele communicatie op 9600 baud
lcd.begin(16,2); // lcd met 2 regels en 16 karakters per regel
//lcd.print("Kwh"); // boodschap op lcd schrijven
}
void loop() {
pulseState = digitalRead(KwhPulse); // lees waarde digitale ingang en bewaar de waarde in "pulseState"
if (pulseState != lastPulseState){ //vergelijk de staat van de Kwhpulse met zij vorige staat
if (pulseState == LOW){ //als de huidige staat laag is ging de puls van uit naar aan
KwhpulseCounter++; // als de staat is veranderd, verhoog de teller
Serial.print ("aantal pulsen: "); //controle
Serial.println (KwhpulseCounter); //controle
pulseAan = millis(); //tijd in milliseconden vanaf start arduino
verstrekenTijd = (pulseAan - pulseUit)/1000; //gemeten tijd tussen twee pulsen
pulseUit = pulseAan; //bewaren voor volgende ronde
Serial.print("tijd tussen pulsen: "); //controle
Serial.print (verstrekenTijd); //controle
Serial.println(" sec"); //controle
currentWatts = 3600000 / (1000 * verstrekenTijd); // het huidige afgenomen vermogen berekenen
Serial.print ("huidig verbruik: "); //controle
Serial.print (currentWatts); //controle
Serial.println(" Watt"); //controle
totalKwh = KwhpulseCounter / 1000.0; // het totale KWh verbruik berekenen
Serial.print ("Totaal Kwh verbruik: "); // controle
Serial.println(totalKwh); //controle
}
}
//bewaar de huidige staat als de laatste staat voor de volgende keer in de loop
lastPulseState = pulseState;
}
Ik heb de code wat aangepast naar de juiste type variabelen. Alleen is het me nog niet duidelijk waar de puls voor staat. KW? KWH?
@edit: Laat die vraag maar ff zitten het is 1000 pulsen per KWH. kijk nog wel ff verder
Dat je een float nog als 0 ziet komt vermoedelijk omdat bij print je maar 2 decimalen ziet van een in totaal 7 cijferig getal. Meer precisie kent float niet. Ik heb nu in jouw code een splitsing gemaakt van het getal voor en na de punt een een format gemaakt met voorloop nullen voor de decimalen,
Nu met de juiste code.
// invoegen bibliotheek
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 6, 5, 4, 3);
//instellen vaste variabelen voor tellen pulsjes
const int KwhPulse = 2; // puls aangesloten op digitale ingang 2
// instellen variabelen voor bijhouden aantal pulsjes
int pulseState = 1; // huidige staat van kwh puls, deze is äctief laag" dus hier inverteren
unsigned long KwhpulseCounter = 0; // teller voor aantal pulsen
int lastPulseState = 1; // vorige staat van Kwh puls
// instellen variabelen berekenen pulstijd
unsigned long pulseAan = 0; // pulse aan en uit makengebruik van millis dus long gebruiken
unsigned long pulseUit = 1;
unsigned long verstrekenTijd = 0; // en het verschil ook
unsigned int KWH_cijfer; // cijfers voor de komma
unsigned int KWH_decimaal; // cijfers achter de komma
//instellen variabelen berekenen Kwh en huidig vermogen
unsigned int currentWatts = 0; // we kunnen max 65536 Watts verwerken. Anders unsigned long gebruiken
unsigned long totalKwh = 0;
//setup
void setup() {
pinMode(KwhPulse, INPUT); // maak van (digitale)pin 2 een input
Serial.begin(9600); // seriele communicatie op 9600 baud
lcd.begin(16, 2); // lcd met 2 regels en 16 karakters per regel
//lcd.print("Kwh"); // boodschap op lcd schrijven
}
void loop() {
char kwhStr[9];
pulseState = digitalRead(KwhPulse); // lees waarde digitale ingang en bewaar de waarde in "pulseState"
if (pulseState != lastPulseState) { //vergelijk de staat van de Kwhpulse met zij vorige staat
if (pulseState == LOW) { //als de huidige staat laag is ging de puls van uit naar aan
KwhpulseCounter++; // als de staat is veranderd, verhoog de teller
Serial.print("aantal pulsen: "); //controle
Serial.println(KwhpulseCounter); //controle
pulseAan = millis(); //tijd in milliseconden vanaf start arduino
verstrekenTijd = (pulseAan - pulseUit) / 1000; //gemeten tijd tussen twee pulsen
pulseUit = pulseAan; //bewaren voor volgende ronde
Serial.print("tijd tussen pulsen: "); //controle
Serial.print(verstrekenTijd); //controle
Serial.println(" sec"); //controle
currentWatts = 3600000 / (1000 * verstrekenTijd); // het huidige afgenomen vermogen berekenen
Serial.print("huidig verbruik: "); //controle
Serial.print(currentWatts); //controle
Serial.println(" Watt"); //controle
//
// eerst de cijfers voor en na de decimale punt bepalen
//
KWH_cijfer = KwhpulseCounter / 1000; // eerst de cijfers voor de komma
KWH_decimaal = KwhpulseCounter - (KWH_cijfer * 1000); // dan de decimalen
//
// dan een mooie strin opmaken
//
sprintf(kwhStr, "%4d.%03d", KWH_cijfer, KWH_decimaal);
totalKwh = KwhpulseCounter / 1000; // het totale KWh verbruik berekenen
Serial.print("Totaal Kwh verbruik: "); // controle
Serial.println(kwhStr);
}
}
//bewaar de huidige staat als de laatste staat voor de volgende keer in de loop
lastPulseState = pulseState;
}
Bedankt voor de moeite. Ik heb je aangepaste code geprobeerd en hij werkt!
Helemaal begrijpen doe ik het nog niet, maar ik ga mij beetje voor beetje verdiepen in de aanpassingen die je hebt gemaakt.
Weer even een leermomentje zal ik maar zeggen.
In grote lijnen samengevat:
millis() geeft een 32 bits getal terug (dus unsigned long)
Omdat je er mee rekent wordt het verschil ook unsigned long
de KWH splits je in cijfers en decimalen. Dus KWH / 1000 voor de cijfers voor de punt. Daar het een long is heeft deze geen decimalen en ben je die automatisch kwijt in de cijfers.
Het decimalen gedeelte bepaal je door de cijfers voor de komma met 1000 te vermenigvuldigen en van het totaal KWH af te trekken.
Het printen doe ik door eerst de cijders in een string (char []) te zetten gebruikmakend van sprintf.
format string;
"%4d.03d" = 4 cijfers (%4d) voor de punt zonder voorloopnullen.
dan de Punt
dan 3 cijfers met voorloop nullen. (%03d).
En als laatste de variabelen die ik erin wil zetten in volgorde van de format string
Mijn mening:
Laat float vallen en werk met WH.
Dus alleen integer rekenen das veeeeeeeeeeeeel makkelijker en veeeeeeeeeeeel sneller en eigenlijk nog preciezer ook.