/*Read energy meter IR pulses with an Arduino Nano:
- each pulse triggers an interrupt that increments a counter
- time is determined by the crystal on the uC board
- reports number of pulses, energy per period, average power, cumulated energy
To do:
- save log on SD with number of pulses
*/

//Pulse handling
const byte pulsePin=2;
const float energyPerPulse=12; //energy per 1 pulse, in J = Ws; 1 kWs/(250/3) = 12 Ws
volatile word pulseCount;

//Energy
word pulsesPerPeriod;
unsigned long cumulatedPulses=0;
float energyPerPeriod;
float cumulatedEnergykWh;
float averagePower;

//Timekeeping
const float period=1.0; //period of reporting, in s
const unsigned long ticksPerSec=1000000; //in crystal µs per 1 actual s, nominally 1e6
const unsigned long ticksPerPeriod=round(period*ticksPerSec);
unsigned long tickCount=0; //tick counters, in crystal µs
unsigned long tickCountStep; //tick counters, in crystal µs
unsigned long prevTickCount=0; //in crystal µs
unsigned long periodFraction=0; //period fraction, in crystal µs

void setup() {
  Serial.begin(9600); Serial.println();
  Serial.print("ticksPerPeriod: "); Serial.println(ticksPerPeriod);

  pinMode(pulsePin,INPUT);
  attachInterrupt(digitalPinToInterrupt(pulsePin),pulseISR,RISING);
}

void loop() {
  //Timekeeping:
  do { //keep reading time
    tickCount=micros();
    tickCountStep=tickCount-prevTickCount; //time step, in μs; no overflow issues
    prevTickCount=tickCount; //for the next iteration
    //Keep current time from start of period:
    periodFraction+=tickCountStep;
  } while (periodFraction<ticksPerPeriod); //as long as the period is not full
  periodFraction-=ticksPerPeriod; //modulo

  //Report/display/record pulses:
  pulsesPerPeriod=pulseCount; pulseCount=0; //read pulse counter and reset
  unsigned long time=micros();
  energyPerPeriod=pulsesPerPeriod*energyPerPulse;
  averagePower=energyPerPeriod/period;
  cumulatedPulses+=pulsesPerPeriod;
  cumulatedEnergykWh=cumulatedPulses*energyPerPulse/3600000;
  Serial.print(time); Serial.print(" ticks, ");
  Serial.print(pulsesPerPeriod); Serial.print(" p, ");
  Serial.print(energyPerPeriod,1); Serial.print(" J, ");
  Serial.print(averagePower,1); Serial.print(" W, ");
  Serial.print(cumulatedEnergykWh,3); Serial.print(" kWh from start");
  Serial.println();
}

void pulseISR() {
  pulseCount+=1;
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r