/* Program för att mäta aktuell uttagen effekt från husets elmätare genom att detektera frekvensen av den blinkande lysdioden på elmätaren. På min elmätare blinkar dioden 10.000ggr per kWh Det finns även elmätare med 1.000 pulser per kWh. Genom att mäta tiden mellan pulserna med hjälp av den interna ms-räknaren (millis) så kan vi kalkylera en PWM utgång till ett instrument- På en annan utgång styr vi ett servo som med en visare på axeln visar mellan 0-180 grader 0 till 10kW Nu visas oxo effekten på en OLED display Det är lite trögt att skriva till displayen Därför mätes tiden över 2 pulser, vilket ger gott om tid för att uppdatera displayen Dessutom blir det inte så fladdriga siffror SM7UCZ/ Johnny Apell 20161109, 20161115, 20161120 */ #include // I2C kommunikationen till Displayen #include // Innehåller teckentyperna till displayen bl.a //#include // Om ett servo skall vara "visarinstrument" //Servo servoMain; // Define our Servo unsigned long timecalc=0; // innehåller aktuell mätvärde i ms unsigned long Puls_old=millis(); // innehåller gamla mätvärdet i ms unsigned long Puls_new=millis(); // innehåller nya mätvärdet i ms unsigned long Power=0; // innehåller mätvärdet i Watt medelvärdesberäknat unsigned long Pow=0; // innehåller mätvärdet i Watt volatile int i=0; // räknaren i interruptrutinen int z; // mätvärdet till servot i grader int y; // mätvärdet till visarinstrumentet PWM int interruptPin = 2; // interruptingången från elmätaren int Instrument = 11; // PWM-utgång int LED = 13; // hjälpflaggan på LED-pinnen String Power_now = ""; // Strängen till dispayen med effekten int sensorPin = A0; // select the input pin for ldr int sensorValue = 0; // variable to store the value coming from the sensor int light = 12; // Instrumentbelysning //**************************************************************************************** void setup(){ pinMode(interruptPin, INPUT_PULLUP); // Interruptingången pinMode (LED,OUTPUT); // LED-pinnen som output och flagga pinMode (light,OUTPUT); // LED-pinnen som output och flagga attachInterrupt(digitalPinToInterrupt(interruptPin), fire, RISING); // Pin 2 puls input OzOled.init(); // initialze OLED display OzOled.sendCommand(0x8d); // Displayen startar inte utan detta OzOled.sendCommand(0x14); // nånting med charge pump?? OzOled.setNormalDisplay(); // ställ displayen i normal mode //OzOled.setInverseDisplay(); // Inverterad display, om det önskas OzOled.clearDisplay(); // töm displayen OzOled.setPageMode(); // Set addressing mode to Horizontal Mode OzOled.setBrightness(200); // Ljusstyrkan på displayen 0...255 OzOled.sendCommand(0xA0 | 0x1); // Rotera displayen 180 grader OzOled.sendCommand(0xC8); // -"- OzOled.printString("Apell_effekt",2,0); // Print the String OzOled.printString("Watt",6,2); // Print the String //Serial.begin(115200); // Initialize serial port användes vid testning //servoMain.attach(10); // servo on digital pin 10 } //*************************************************************************************** void loop() { if (digitalRead(LED)==HIGH ){ // Kolla om LED-flaggan är tänd och kör nedanstående // endast en gång efter LED TILL timecalc = Puls_new - Puls_old; // beräkna tidsskillnaden från förra pulsen Puls_old = Puls_new; // spara ms räknaren till nästa beräkning } else { return;} // om ingen interrupt... gör inget if (timecalc >30 && timecalc < 30000){ // kolla om det är "verkliga värden" från pulserna Power = 3600UL * 500UL / timecalc; // kalkylera effekten i Watt (5000UL vid 1000 pulsers mätare) //**************************** Skriv till Instrumentet ******************************************' y = map(Power,0,10000, 0, 255); // mappa mätvärdet så att det passar PWM till instrumentet analogWrite(Instrument, y); // skriv det beräknade PWM-värdet till instrumentet utgång 11 //**************************** Skriv till Servot ***************************************************' //z = map(Power, 0,10000, 179, 0); // mappa, skala detta värde y så att det passar servots vinkel 0...179 grader //servoMain.write(z); // kör servot till aktuell gradtal //**************************** Skriv till Displayen *************************************************' Power_now = String(Power); // gör en sträng av Power const char* Pow = (const char*)Power_now.c_str(); // gör en sträng av Power till Displayen // Displayen kommer ihåg siffror till höger som måste suddas när effekten sjunker! if (Power <10){ OzOled.printBigNumber(" ",3,4);} // rensa gamla siffror i displayen if (Power <100){ OzOled.printBigNumber(" ",6,4);} // rensa gamla siffror i displayen if (Power <1000){ OzOled.printBigNumber(" ",9,4);} // rensa gamla siffror i displayen if (Power <10000){ OzOled.printBigNumber(" ",12,4);} // rensa gamla siffror i displayen OzOled.printBigNumber(Pow,0,4); // Skriv effekten som stora siffror //************************************************************************************************** digitalWrite (LED,LOW); // släck LED så att rutinen inte körs fler ggr innan ny interrupt //****************************** Ljussensorn tänder/släcker instrumentbelysningen och dimmrar displayen *************** sensorValue = analogRead(sensorPin); // read the value from the sensor if (sensorValue < 200){digitalWrite(light, HIGH); } if (sensorValue > 500){digitalWrite(light, LOW); } if (sensorValue < 200){OzOled.setBrightness(25);} // Ljusstyrkan på displayen 0...255); } if (sensorValue > 500){OzOled.setBrightness(200);} // Ljusstyrkan på displayen 0...255); } //****************************** användes till serieporten vid testning av programmet*************** Serial.println(sensorValue); //prints the values coming from the sensor on the screen Serial.print(timecalc); // skriv till serieporten Serial.print(" ms"); // användes vid testningen Serial.print(" Power= "); Serial.print(Power); Serial.print(" Pow= "); Serial.println(Pow); //Serial.print(" y= "); //Serial.print(y); //Serial.print(" y= "); //Serial.print(z); //Serial.println(" grader "); } } //********************* Interruptrutinen *********************************************************' void fire() { // Interrupt routine när lysdioden på mätaren blinkar i=i+1; // spara 2 pulser innan kalkyleringen if (i>=5){ // kolla om vi har två pulser?? Puls_new = millis(); // spara då millis räknaren digitalWrite (LED,HIGH); // tänd LED som flagga TILL Vi har mätvärde att bearbeta! i=0; // nollställ räknaren } } //************************************************************************************************