Reading irda output on energy meter

Hi I dont know if anybody can help me

What im trying to do is recieve data over ir from an energy meter with a tx ir port. It chucks out 110 bytes of serial data every second.
I need to read at least a full 2 seconds worth so i can grab the full 110 bytes if it starts recieving halfway through a tansmittion. i then need the data converted to HEX and to be printed into the serial window.

I have tried lots of code and tried some ir librarys and i am really struggling because they have all been written for remote codes which are very short in comparison.

If you can help me in any way or point me in the right direction i would much appreciate it.
Many Thanks

IRDA is simply baseband signaling, i.e., no modulation, so if you're using a 38kHz receiver, it may not work at all.
What do your hardware and software look like?

Hi thanks for helping

I have a 5volt and grnd from arduino to 38khz ir reciever and the ir output goes to pin 11

I am using this code (not my work) and it shows me the raw ir dump. The problem i am having is it stops recording data at irregular times instead of reading the full 110bytes (880 bits). This causes me to get random data from the stream. I cant figure out how to change the code so it will let me read the full dump and not just parts at a time. Whatever i do it just does not work.

Any advise

IRrecvDump.pde

#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.println("Could not decode message");
  } 
  else {
    if (results->decode_type == NEC) {
      Serial.print("Decoded NEC: ");
    } 
    else if (results->decode_type == SONY) {
      Serial.print("Decoded SONY: ");
    } 
    else if (results->decode_type == RC5) {
      Serial.print("Decoded RC5: ");
    } 
    else if (results->decode_type == RC6) {
      Serial.print("Decoded RC6: ");
    }
    Serial.print(results->value, HEX);
    Serial.print(" (");
    Serial.print(results->bits, DEC);
    Serial.println(" bits)");
  }
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 0; i < count; i++) {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    } 
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}


void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

if you need the IRremote.cpp and IRremote.h files they are here

They were too big to post

Many Thanks

I have a 5volt and grnd from arduino to 38khz ir reciever

Are you sure the output is modulated at 38kHz?
See my comments about lack of modulation in IRDA.

I know someone who has done exactly that, has the right hardware and a working program. He only wanted certain data but it's all mapped and he got mostly or all solid 110 byte data messages.

I've sent him a PM, maybe he's got time to help.

You have got me questioning the output modulation now.
If it was not outputting at 38khz I would not recieve anything would i???

GoForSmoke any information your friend can provide will be excellent. I Really hope he can help. It sounds like that is just what i need.

Many thanks

Well , he's got the hardware and I have to wonder how many companies would use 110 bytes for their data message length? My guess, you both bought the same thing.

Near the start he did get data on the unit and the message format:

Unfortunately these is no information online for the IrDA.
I have managed to get the following from the device manufacturer:
The Baud rate is 2400
The character format is one start bit, followed by 8 data bits and one stop bit (no parity)

The IrDA output data adheres to the following format:

[SOH (Hex01)][NULL (Hex00)][LEN (nn)][STX (Hex02)][DATA (Len)][ETX (Hex03)][BCC (nn)]

SOH: Start of Header (Hex 01)
NULL: Null character Hex 00
LEN: Data length (hex 00-FF) Indicates the number of bytes between ETX and STX, exclusive.
STX: Start of text character (hex 02)
DATA: Actual sensor data as defined below.
ETX: End of text character (hex 03)
BCC: Binary Checksum of all message bytes from SOH to ETX (inclusive).

DATA FIELD: (BYTE TOTAL = 104)
PC: Len=12, ASCII
FRC: Len=9, ASCII
MSN: Len=3, Binary
CN: Len=2, Binary
USN: Len=16, ASCII
MD: Len=3, Bit Field
R1R1: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
R1R2: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
R1R3: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
R2R1: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
R2R2: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
R2R3: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Reserved: Len=1, Binary
SF: Len=1, Bit Field
EF: Len=1, Bit Field
ACT: Len=3, BCD
R1T: Len=3, BCD
R2T: Len=3, BCD
PUT: Len=3, BCD
PFC: Len=2, Binary
WC: Len=1, Binary
RWC: Len=1, Binary
Reserved: Len=10, Binary

Identifying the Start of the Message:
As the message is in binary format it might very well contain the SOH, STX and ETX characters
that makes finding the start of the message more challenging. To simplify the process of identifying the
start of a message it is probably best to wait for the quiet time that occurs between each message.

The sensor transmits a message once every second. We suggest that the receiver program should wait
approximately 100 ms without receiving a character from the sensor to identify the quiet time preceding the SOH
character that marks the start of the next message. Message parsing should then proceed to verify that the
message is properly frames abd that the BCC is valid.

We never did get around to checking the checksum, but that wouldn't be enormously hard to do. For end of line there is a check for over something like 250 ms without serial.available being an end of line condition. Hey, it works.

To tell the truth, I don't know what most of the data is. Never got a map or guide to those bit fields.

Wow that is exactly my layout. So we have got the same thing.

Here is what the data represents.
II have a pdf with info on the irda from the device if you need it?

Product code: Len=12, ASCII
Firmware Rev Code: Len=9, ASCII
Mfg Serial Number: Len=3, Binary
ConfigNumber: Len=2, Binary
Utility Serial Number: Len=16, ASCII
Reg Sourcec 1-3: Len=3, Bit Field
Tarif 1 kwh Register 1: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Tarif 1 Register 2: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Tarif 1 Register 3: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Tarif 2 kwh Register 1: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Tarif 2 Register 2: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Tarif 2 Register 3: Len=5, BCD (Represents 7 integer digits and 3 decimal digits)
Current Power Factor: Len=1, Binary
Status Flags: Len=1, Bit Field
Error Flags: Len=1, Bit Field
Anti Creep Time: Len=3, BCD
Time in Service for rate 1: Len=3, BCD
Time in Service for rate 2: Len=3, BCD
power up time: Len=3, BCD
power fail count: Len=2, Binary
watchdog counter: Len=1, Binary
Reverse warniung count: Len=1, Binary
Phase offset gain: Len=10, Binary

Is there any chance you could get hold of the code for the arduino and a schematic for the hardware?
I would owe you one if you could get this for me.

Many Thanks

I have the code. I wrote it. But the hardware is about halfway around the world (USA to SA) and I never laid eyes on it! He did have a wiring problem early on but got that fixed. It was solid last I heard. Also he only wanted certain fields, 20-some bytes IIRC. And the code only outputs data when it has seen what it takes for whole, good data messages.

What you show there looks like the DATA FIELD. You should see hex 01 00 68 02 before the Product code. BTW, thanks for the look. It's often interesting to see what I missed before.

Digging through PM's and some of the "lets see all the data" code, his product code is (in hex) 45 6C 73 74 65 72 20 41 31 30 30 43 ==== Elster A100C. That's what he's got.

I see web traffic on the A100C's from manual to forum discussions:
http://www.navitron.org.uk/forum/index.php?topic=16709.0
And they ARE 38k pulse, BTW.

But what he uses to read it with, I dunno and that's probably not a problem anyway if yours works.

Once you start reading data, it doesn't cut out or quit on you? I re-read the OP and see you only get half-lines when you start in the middle of one. It sounds like you have working circuit.

Do you really only want the data in hex? No ASCII or BCD translations or any of that?

That sounds perfect
Ideally i would like the code to show how it should be e.g ASCII BCD. So i can be read the data directly without any translation.

I only asked for hex for simplicity.

So you think i have a working circuit. Would be good if that is correct.
I will have to try your code if that is OK and let you know what i get.

Many Thanks

Rob did write some parts, pieces of his original code are still in there. One thing though, he got his IrDA reader data through NewSoftSerial which let him keep using the PC Serial Monitor. I don't know everything about NSS and I wonder how you are connected? Also both at once?

Newsoftserial is not a problem for me. I will set up my hardware to how your code needs it. Newsoftserial just turns one of my digital outputs into a serial pin.

Many Thanks

This was a debug version that printed the data in hex along with message length and the minimum gap in microseconds between any 2 characters received. What I don't remember is if this one had fixed a problem where bytes with the high bit set showed as FFxx (xx being the hex byte) that was making the data harder to read.

Give it a try and if you get good data lines then post a few?

#include <NewSoftSerial.h>

NewSoftSerial MyPort(4,3,true);

unsigned long  lastRead = 0UL, messageLen = 0UL; // messageLen is for debug check
unsigned char  serIn,  reading = 0;
unsigned long  Gap=0UL, minGap=0UL, lastReadMics = 0UL; // for EOL info

void setup(){
  MyPort.begin(2400);
  Serial.begin(9600);
}

void  loop(void){
  if (MyPort.available()) {  // a serial character showed up
    serIn = MyPort.read();
    if (serIn < 0x10)  Serial.print("0");
    Serial.print(serIn, HEX); // hex will print the character codes in base 16
    Serial.print(" ");
    lastRead = millis();
    lastReadMics = micros();
    reading = 1;
    messageLen++;
  }
  else if (reading)  {  // so to not print 100's of EOL reports while waiting
    if (millis() - lastRead >= 250)  { // 1/4 second after last available, assume end of line
      Serial.print(" length = ");
      Serial.print(messageLen);
      Serial.print(", min gap micros = ");
      Serial.println(minGap);
      Gap = minGap = 0UL;
      reading = 0;  // none of this if-else block will run until the next serial read
      messageLen = 0UL;
    }
    else  {  // getting info on how long between available characters during read
      Gap = micros() - lastReadMics;
      if (!minGap || Gap < minGap)  minGap = Gap;
    }
  }
}

This can't be right can it??
Should it not be giving me 110 length. seem to be getting garbled data I think for some reason.
Is this what I should be expecting??
It would be nice to see the hardware he had so i rule that out of the equation.

Here is a sample of data

02 00 0A 00 07 00 00 00 0E 00 length = 10, min gap micros = 24
03 00 02 00 02 00 0E 00 0E 00 length = 10, min gap micros = 28
08 00 02 00 02 00 03 00 04 00 length = 10, min gap micros = 24
01 00 02 00 02 00 00 00 01 00 length = 10, min gap micros = 24
00 00 00 00 02 00 0A 00 00 00 length = 10, min gap micros = 24
05 00 02 00 02 00 00 00 02 00 length = 10, min gap micros = 28
01 00 02 00 02 00 02 00 03 00 length = 10, min gap micros = 24
03 00 02 00 0A 00 03 00 0A 00 length = 10, min gap micros = 28
03 00 02 00 0E 00 00 00 01 00 length = 10, min gap micros = 24
00 00 00 00 02 00 02 00 02 00 00 00 length = 12, min gap micros = 24
05 00 01 00 00 00 02 00 03 00 length = 10, min gap micros = 24
0A 00 03 00 02 00 0A 00 08 00 length = 10, min gap micros = 24
04 00 02 00 02 00 03 00 06 00 length = 10, min gap micros = 24
03 00 03 00 02 00 0E 00 0A 00 length = 10, min gap micros = 24
02 00 02 00 08 00 02 00 02 00 length = 10, min gap micros = 24
0E 00 02 00 0E 00 00 00 01 00 length = 10, min gap micros = 28
00 00 00 02 00 02 00 02 00 03 00 04 00 length = 13, min gap micros = 24
02 00 03 00 0A 00 06 00 03 00 length = 10, min gap micros = 24
01 00 02 00 02 00 0E 00 0A 00 length = 10, min gap micros = 28
02 00 0E 00 03 00 03 00 03 00 length = 10, min gap micros = 28
0E 00 02 00 02 00 00 00 0E 00 length = 10, min gap micros = 24
03 00 02 00 00 00 0E 00 03 00 length = 10, min gap micros = 24
02 00 01 00 02 00 03 00 03 00 length = 10, min gap micros = 24
03 00 03 00 00 00 02 00 0A 00 length = 10, min gap micros = 24
0A 00 02 00 02 00 03 00 06 00 length = 10, min gap micros = 28
0A 00 01 00 0E 00 02 00 08 00 length = 10, min gap micros = 28
00 00 0A 00 04 00 0E 00 05 00 length = 10, min gap micros = 24
01 00 0A 00 03 00 02 00 02 00 length = 10, min gap micros = 24
05 00 00 00 00 00 00 00 02 00 length = 10, min gap micros = 24
02 00 01 00 02 00 03 00 06 00 length = 10, min gap micros = 28
02 00 03 00 00 00 0E 00 02 00 length = 10, min gap micros = 28
00 00 0A 00 0E 00 00 00 02 00 length = 10, min gap micros = 24
03 00 02 00 03 00 0E 00 0E 00 length = 10, min gap micros = 24
00 00 02 00 02 00 0E 00 0A 00 length = 10, min gap micros = 24
01 00 02 00 02 00 00 00 06 00 length = 10, min gap micros = 24
02 00 02 00 00 00 03 00 04 00 length = 10, min gap micros = 24
02 00 02 00 04 00 00 00 00 00 length = 10, min gap micros = 24
01 00 00 00 02 00 02 00 04 00 length = 10, min gap micros = 24
02 00 02 00 00 00 00 00 00 00 length = 10, min gap micros = 28
00 00 00 00 00 00 02 00 03 00 length = 10, min gap micros = 24
01 00 01 00 00 00 00 00 08 00 length = 10, min gap micros = 24
00 00 02 00 02 00 00 00 00 00 length = 10, min gap micros = 28

I just looked all over for how to check/change start/data/stop/parity for serial and can't find any. Funny but I thought that was part of getting started but dig and dig and I find nothing.

One thing I DID read is that NewSoftSerial is not to be used with Arduino 1.0. 1.0 has the 1.0 version of NSS now called SoftwareSerial. It's in the included libraries (look in the IDE under Sketch->Import Libraries). -Maybe- that's all you need is to change over.

You can also try to take out the word 'true' in the SoftSerial instantiation up top of the code there.

Maybe you can test the connect from the Arduino on your PC through a serial port? Fire up HyperTerminal, set it up right next to Serial Monitor and send a string of characters from your PC serial port to the Arduino just so you can see what comes back up the USB cable.

One thing. Do you have the IrDA grounded to the Arduino? Even the serial, if all you connect is RX you still need ground.

Do the docs on your IrDA reader show any differences to his? His might not be exactly the same.

That's as much as I can think of for now.

Directlinq, I tried to send you a Private Message on this, maybe you don't get PM's?

Here is something else to try. Change the 250 to something larger, 400 to 900, lower that works is better.

    if (millis() - lastRead >= 250)  { // 1/4 second after last available, assume end of line

Or maybe you have it working and don't bother to say?