Digital input to read dataout from Energy Monitor

I would like to log 9 bytes of data from a MC at a known interval, the data is collected from dataout pin 18 on a AMICCOM A7201A chip and is connected to Arduino Digital Input. (GND to GND also ).

The 9 bytes (including checksum) start after a long LOW period of 500ms and a HIGH period of 500us then 72 bits at 200us intervals are read and stored.

The data will then be then passed to WRT54GL Router with modified serial port onto the internet for pachube to graph with my other data.

Data is sent every 6 seconds to the RX module. the header part of the transmition is ignored.

I have been following this link

http://electrohome.pbworks.com/w/page/34379858/Efergy-Elite-Wireless-Meter-Hack#comment1306967574

for the project the guy Alex has the same efergy E2 unit as me and made it work in PIC but has no Arduino experience .

Hence my questions are :-

  1. Do I need to activate pull up resistor on digital pin to make it work ?
  2. How do I debug such a program given speed of 200us ?
  3. Is my logic correct to concatenate bits into bytes ?
  4. Is pulseIn() the right function to use to wait for the right intervals ?

My code so far (untested)

int E2Pin = 8; // Digital Input Pin allocated to E2 output
int E2Bytes = 8; // actual bytes of data required  
int pulseDUR = 200; // pulse duration of data in usecs
int leadHIGH = 500; // lead HIGH duration in usecs
long longLOW = 500000;// long LOW duration in usecs before leadHIGH
boolean  DataINflg = LOW;// flag to determine when to collect DataINflgflg  
boolean  pauseLOWflg = LOW;//  flag to determine of pauseLOWflg period has occured
int E2pulse; // pulse of data reived from E2
byte byte_array[9]; // array of bytes read 

//pulseIn() used here to our benefit
//Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, 
//starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds.
//Gives up and returns 0 if no pulse starts within a specified time out.
//The timing of this function has been determined empirically and will probably show errors in longer pulses. 
//Works on pulses from 10 microseconds to 3 minutes in length.

//Syntax

//pulseIn(pin, value)
//pulseIn(pin, value, timeout) 

// main loop starts here

void setup()
{
  Serial.begin(9600);
  Serial.print("SETUP > ");
  pinMode(13, OUTPUT); // init LED to show progress     
  pinMode(E2Pin,INPUT);
  DataINflg = LOW;
  pauseLOWflg = LOW;
}  

void loop()
{  
  E2pulse = digitalRead(E2Pin); // get à value on E2 Digital Pin
  digitalWrite(13,E2pulse);
  if (E2pulse == HIGH) {
    if ( pulseIn(E2Pin, HIGH) >= leadHIGH) { // see if we have reached start of data 
       if (pauseLOWflg == HIGH) { // only set ready to accept reading data if pauseLOWflg has passed
         DataINflg = HIGH;
         Serial.print("READY DATA > ");
       }  
    } // else ignore and go round again
  }
  else { // pulse is LOW check if short or long
     if ( pulseIn(E2Pin, LOW) >= longLOW) { // skip the long low period
       pauseLOWflg = HIGH;
       Serial.print("PAUSE LOW >");
      }
  }
  
  if ( DataINflg == HIGH ) { // time to collect the get the data we want
      get_next_nbytes( E2Bytes+1, pulseDUR);
     // send data here if we want
      for (int Byte = 1 ; Byte <= 9 ; Byte++){
        Serial.print(byte_array[Byte],BYTE);
        Serial.print(" :");
      }
      Serial.println();
      DataINflg = LOW; // reset vars
      pauseLOWflg = LOW;
  }
} // end of loop
  
// function to read next nbytes at Cycle microsecond intervals last byte checksum
void get_next_nbytes(int Nbytes,int Cycle)
{
  int CheckSum = 0;
  int bitval;
  int Nbits = 8;
    
  delayMicroseconds(Cycle/2); // delay a 1/2 cycle to be bang in middle of pulse
  for (int Byte = 1 ; Byte <= Nbytes ; Byte++) {// for each byte to be read
    for (int Bit = 1 ; Bit <= Nbits ; Bit++) { // for each bit within the byte
      bitval = digitalRead(E2Pin); // read databit from digital pin
      if (bitval == HIGH) {
        byte_array[Byte] |= (1 << Bit); // bitshift data into this byte
      }  
      else { 
        byte_array[Byte] &= ~(1 << Bit); // bitshift data into this byte
      }  
      delayMicroseconds(Cycle) ; // delay to land in the middle of each bit
    }  
    CheckSum += byte_array[Byte]; // keep track of data received
  }  
  if (CheckSum != byte_array[Nbytes]){ // bad checksum 
  }  
}

Any Help/Guidance welcome.

Kind Regards

Jean

Hence my questions are :-

  1. Do I need to activate pull up resistor on digital pin to make it work ?
  2. How do I debug such a program given speed of 200us ?
  3. Is my logic correct to concatenate bits into bytes ?
  4. Is pulseIn() the right function to use to wait for the right intervals ?
  1. 200 uSec is quite short so a pull up will give better signals.
  2. with a scope, or make a run and see if the value's make sense
  3. didn't dive into your code
  4. look at the internals of pulseIn() that's something like the code you need

The good way to sample such fast signals is to have an array of 72 bytes and sample the line every 200usec. You must take into account the time a digitalRead costs;

...
  uint8_t samples[72];
  delayMicroseconds(100);       // will get us in the middle of the first bit !! important
  //   unsigned long t = micros();
  for (uint8_t i=1; i< 72; i++)
  {
    samples[i] = digitalRead(4);
    delayMicroseconds(198);       // this value is < 200uSec to compensate for the digitalRead() and increasing i etc.  
  }
  // Serial.println(micros() - t, DEC);
...

This loop takes 14412 uSec on my A2009 compared to 72 * 200 = 14400 is error of 0.1%. Note that 4 is a constant, when I use a variable I got 14424 uSec 0.2% error - still OK; by altering the initial delayMIcroseconds(100) => 88 - the samples will be taken at max 12 uSec from the middle of the signal.

After this loop you can sort out the samples into bytes. Of course this can be done immediately in the loop but you need to adjust the "microtiming" accordingly.

if (bitval == HIGH) {
        byte_array[Byte] |= (1 << Bit); // bitshift data into this byte
      }  
      else { 
        byte_array[Byte] &= ~(1 << Bit); // bitshift data into this byte
      }

aka         byte_array[Byte] |= (bitval << Bit); // bitshift data into this byte