IR photodiode to read LED pulse from meter?

Hi,

I am aiming to get the Stalker data logging Arduino to read the pulse LED from an electricity meter. CRS8291 has it all worked out and has kindly shared his code http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1273413449/9#9 and knowledge. The last part in the jigsaw for me is the sensor which I cannot get working, I expect because I am making some very basic errors.

The sensor I have is an OSRAM IR Photodiode: http://gb.mouser.com/ProductDetail/Osram-Opto-Semiconductor/SFH-203-FA/?qs=K5ta8V%252bWhtaq1pinUuBcnA%3d%3d - Using digital Pin 3 and GND how should I connect this sensor?

All help greatly appreciated :-)

A photo diode is not as good as a photo transistor in giving a large output. Use an analogue input connect the anode to ground cathode to the analogue input, then try a 1M pull up resistor between the analogue input and +5V.

The way it works is that it is reverse biased and photons going into the diode crate electron / hole pairs which get sweeped out of the intrinsic layer and form a small current.

However the only time I have ever used a photo diode was with an OP amp on the end of it.

Hi Mike,

Thanks for a very rapid reply :-)

I will give it a go.... for a test sketch would the following work? If I fire a TV remote at the sensor the LED should light?

int ledPin =  13;    // LED connected to digital pin 13
int sensorPin = 15   // SFH203FA connected to analgue pin 1

// The setup() method runs once, when the sketch starts

void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);  
}

// the loop() method runs over and over again,
// as long as the Arduino has power


void loop(){
  // read the state of the sensor value:
  sensorState = digitaRead(sensorPin);

  // check if the sensor is receiving IR.
  // if it is, the ledState is HIGH:
  if (sensorState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

Ooops, I'm no programmer but I should have got analogRead correct !!!

int ledPin =  13;    // LED connected to digital pin 13
int sensorPin = 15   // SFH203FA connected to analgue pin 1

// The setup() method runs once, when the sketch starts

void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);  
}

// the loop() method runs over and over again,
// as long as the Arduino has power


void loop(){
  // read the state of the sensor value:
  sensorState = analogRead(sensorPin);

  // check if the sensor is receiving IR.
  // if it is, the ledState is HIGH - have guessed a theshhold value of 100?
  if (sensorState > 100) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

OK... so the code below has the syntax sorted and it seems to work? It will not resond to either an LED or a TV remote but when I cup my hand round the sensor the LED blinks like mad - I guess IR radiation from my hand? I had to lower the threshold down to 4 to get a 'clean' off in ambient conditions.

Any ideas how I could get it to resond to an LED or TV remote?.... or should I just get another sesnor....? & if so which one?

Thanks always.

int ledPin =  13;    // LED connected to digital pin 13
int sensorPin = 15;   // SFH203FA connected to analgue pin 1
int sensorState = 0;

// The setup() method runs once, when the sketch starts

void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);  
}

// the loop() method runs over and over again,
// as long as the Arduino has power


void loop(){
  // read the state of the sensor value:
  sensorState = analogRead(sensorPin);

  // check if the sensor is receiving IR.
  // if it is, the ledState is HIGH - have guessed a theshhold value of 100?
  if (sensorState > 4) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

This line is wrong:- int sensorPin = 15 // SFH203FA connected to analgue pin 1 it should be int sensorPin = 1 // SFH203FA connected to analgue pin 1

You are addressing the pin as if it were digital, it is not you want to use it as analogue. It is not radiation at all from your hand, is is simply you are shealding it from ambient light. In place of blinking a light just get the readings printed out and look at them change through the monitor.

A TV remote is a modulated signal, that is it turns on and off rapidly, it is not the best source of IR for this sensor.

Ah... that makes all the difference - thanks mike. Thanks also Richard.

In total darkness I am getting a value of 75 and with a torch on the sesnor I am getting 120 - setting the threshold to 100 produces good results even with a tv remote :-)

Now I need to get it to see an LED pulse from the meter of about 100ms!! I'm not feeling hopefull as I can't get it to register a full on red LED let alone a small LED with a short pulse? Perhaps I am barking up the wrong tree with this sensor?... although it does seem to have a very fast response time. To be honest I'm not sure why an IR sensor is recomended, I expect there is a good reason.

HeHe… yeah, this is a UK torch… we would call a US Torch a Blow Torch or Blow Lamp… that mean anything in the States? :slight_smile:

OK… with your kind help I now have the sketch below successfully picking up the LED pulse, albeit with a different sensor :slight_smile:

I think the last hurdle to jump is amalgamating this test sketch with the original and I should be there? CRS8291 has his sensor on Digital Pin 3 but I cannot see how its done?

The IR sensor is connected to digital pin 3 and is declared in the attachInterrupt statement:

attachInterrupt(1, wattSensorInterrupt, FALLING);  //interrupt1 - digital pin 3 - If we detect a change from HIGH to LOW we call wattSensorInterrupt

My working test code is below, I have the sensor on analog pin 1 with a threshold value… how would I transpose this into the Stalker code? (shown right at the bottom).

Sorry, I am slowly learning with much help :slight_smile: it is certainly appreciated.

Working code for sensor on analog pin 1

int ledPin =  13;    // LED connected to digital pin 13
int sensorPin = 1;   // SFH203FA connected to analog pin 1
int sensorState = 0;

// The setup() method runs once, when the sketch starts

void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT); 
 Serial.begin(9600); 
}

// the loop() method runs over and over again,
// as long as the Arduino has power


void loop(){
  // read the state of the sensor value:
  sensorState = analogRead(sensorPin);

  // check if the sensor is receiving IR.
  // if it is, the ledState is HIGH - have guessed a theshhold value of 100?
  if (sensorState > 100) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
  Serial.println(sensorState);
}

CRS8291’s Stalker code using sensor on digital pin 3:

//Meter reading program using Itron smart meter
//Added LED that turns on/off with each watt

#include "FileLogger.h" // http://code.google.com/p/arduino-filelogger/
#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h> // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time

const int ledPin = 14; // LED watt indicator initialization. Turns on or off each time a watt is measured
int ledState = LOW;

volatile unsigned long wattSensor=0;  //Counts power pulses in interrupt, 1 pulse = 1 watt
unsigned long wattSensorTemp=0;  //Temporary power pulse counts for printing - watts
unsigned long totalWatts=0; //Temporary total power used for printing - watts

byte start[7]= {
  'B','e','g','i','n',0x0D,0x0A};
byte Buffer[31]; //Buffer for printing to SD card
time_t oldtime=0; //last time loop has ran
int result; //status of SD card write - 0 = "OK", 1 = "Fail initializing", 2 = "Fail appending"
unsigned long loggingRate=5; //logging rate in seconds
int length; //length of buffer string

void setup(void)
{
  pinMode(ledPin, OUTPUT);  // LED watt indicator initialization
  attachInterrupt(1, wattSensorInterrupt, FALLING);  //interrupt1 - digital pin 3 - If we detect a change from HIGH to LOW we call wattSensorInterrupt

  do
  {
    result = FileLogger::append("data.txt", start, 7);//Initialize the SD Card
  }
  while(result != 0);

  // the next two lines can be removed if the RTC has been set
  //  setTime(17,05,0,1,3,10); // set time to 17:05:00  1 Mar 2010
  //  RTC.set(now());  // set the RTC to the current time (set in the previous line)

  // format for setting time - setTime(hr,min,sec,day,month,yr);

  setSyncProvider(RTC.get);   // the function to get the time from the RTC

  Serial.begin(9600);
}

void loop(void)
{
  time_t t = now();
  //  if(t >= oldtime + loggingRate) //proceed with loop if loggingRate seconds have elapsed
  if( minute(t) != oldtime) //use this if 1 minute intervals is desired
  {
    wattSensorTemp=wattSensor; //number of watts for interval
    wattSensor=0; //reset watts counter
    totalWatts=totalWatts+wattSensorTemp; //total watts counter
    oldtime = minute(t); //use this for one minute interval
    //oldtime = t; //or this for loggingRate interval

    do
    {
      Buffer[0]='A'; //start packet/Site ID
      Buffer[1]=','; //start of data string
      //format of printDigits - printDigits(tempBuffer,bufferPntr,numberDigits)
      printDigits(t,2,10); //t = now()
      Buffer[12]=',';
      printDigits(wattSensorTemp,13,5); //wattSensorTemp
      Buffer[18]=',';
      printDigits(totalWatts,19,8); //totalWatts
      Buffer[27]=',';
      Buffer[28]='>'; //end data packet
      Buffer[29]=0x0D;
      Buffer[30]=0x0A;

      length=sizeof(Buffer);
      result = FileLogger::append("data.txt", Buffer, length);
    }
    while( result != 0);

    for (int i=0; i < length ;i++) {
      Serial.print(Buffer[i]); //Serial print buffer string to serial monitor or xBee
    }
  }
}

void wattSensorInterrupt() //Interrupt1 counter routine for counting watts
{
  wattSensor=wattSensor+1;  //Update number of pulses, 1 pulse = 1 watt
  if (ledState == LOW) //Cycle LED on or off each time one watt is counted
    ledState = HIGH;
  else
    ledState = LOW;
  digitalWrite(ledPin, ledState);
}

void printDigits(unsigned long tempBuffer, int bufferPntr, int numberDigits) //assign data to output array
{
  unsigned long modDivide = 1;
  for (int i = 0; i < numberDigits; i++) {
    Buffer[bufferPntr+numberDigits-1-i]=((tempBuffer%(modDivide*10))/modDivide)+'0';
    modDivide=modDivide*10;
  }
}

Hi,

It's WORKING :-) I now understand a little bit more thanks to the kind help of you good folk and the logger is recording our power usage as I type.

One of the problems I was having turned out to be the power supply - I was running the Stalker off the Seeedstudio Solar Sheild with LiPo battery - this casued the sensor to flicker on and off very quickly. Swapping to a 9V battery straight in to the Stalker has solved this, I guess it must be noise of some kind? Not sure if I can solve this - the solar shield is very neat - ideal for a data logging application.

Cheers.

I did something similar a while back, but just used a LDR, but have 'tuned' it to pulse on a digital pin. I just care about on and off and timing that.