why does my interrupt keep firing?

I am still an Arduino noob so please bare with me.
I have a simple setup with a TLS261 light sensor and an LED blue tacked together (ok, not perfect) so the tls261 only sees light from the LED. A push switch switches the LED on and on releasing the switch the LED is turned off. I have the code below and it works fine so long as I don’t turn another LED on and off. Why? As soon as I turn the LED dataLedPin on/off then whilst I am holding the switch down to light the LED sat next to the sensor the interrupt keeps firing.

// LED pins
const int  dataLedPin    =  4;  // LED indicating sensor data is received
const int  logLedPin     =  5;  // LED flashes during a log attemp

const int logInterrupt = 1; // ATmega 168 and 328 - interrupt 0 = pin 2, 1 = pin 3
const int interruptPin = 3;

volatile unsigned long sensor = 0;  // Counts power pulses in interrupt, 1 pulse = 1 watt
unsigned long total = 0;  // Total power used since the sketch started ???
unsigned long last_reading = 0;


void setup(void)
{
  Serial.begin(19200);      // opens serial port, sets data rate to 19200 bps
  pinMode(dataLedPin, OUTPUT);    // LED interrupt indicator initialization
  pinMode(logLedPin, OUTPUT); 

  pinMode(interruptPin, INPUT);  
  // enable 20k pullup resistor:  
  digitalWrite(interruptPin, HIGH);  
 
  attachInterrupt(logInterrupt, interruptHandler, FALLING); 
 
  Serial.println("Start");
}

void loop(void)
{ 
  // If I uncomment the following the interrupt keeps firing
  // whilst I hold the push switch down to light
  // LED next to TLS261
  //if (digitalRead(dataLedPin) == HIGH) {
  //       digitalWrite(dataLedPin, LOW); 
  //} else {
  //     digitalWrite(dataLedPin, HIGH);   
  //}
  if( sensor != last_reading ) { 
     digitalWrite(logLedPin, HIGH);
     Log();
     Serial.println();
     digitalWrite(logLedPin, LOW);
     
    last_reading = sensor;
  }

  delay(50);
}

void Log()
{
    unsigned long sensor_count;
    uint8_t oldSREG = SREG;   // save interrupt register
    cli();                    // prevent interrupts while accessing the count  
    sensor_count = sensor; //get the count from the interrupt handler
    sensor = 0;           //reset the watts count
    SREG = oldSREG;           // restore interrupts

    total += sensor_count; //total watts counter
    Serial.print(',');   // print comma to seprate from previous data
    Serial.print(sensor_count);
    Serial.print(',');
    Serial.println(total);       
}


void printDigits(int digits, char seperator)
{
  // utility function time with leading 0
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
  Serial.print(seperator); 
}

void interruptHandler() // routine called when external interrupt is triggered
{
  sensor += 1;  //Update number of pulses, 1 pulse = 1 watt
  Serial.println("interrupt");
}

Feeling pretty stupid here without any clothes on. Doing serial prints in interrupt service routines is not sensible.

ok, point taken (I did say I was a noob) - it was left in from debugging. However, it makes no difference if the Serial.println is taken out of the interrupt routine. All that happens is the interrupt fires more quickly whilst the LED attached to the sensor is lit.

Got a pull-up/down resistor on?

ah it is the internal.. tried with an external?

Perhaps, could you expand please?

const int logInterrupt = 1

Should this be 2?

I don't think so as the sensor is on pin 3 (but I could be wrong).

How about posting a schematic for your interrupt circuit.

Sorry, you are correct, it should be 1.

I don't have a schematic but it is very simple - perhaps you could suggest a tool.

I have an arduino Duemilanove board.

dataLedPin (see code) is an LED connected to pin digital 4 via a 100 ohm resistor to ground. Likewise, logLedPin (see code) is is connected to digital pin 5 via 100 ohm resistor to ground.

Totally separate from the arduino (other than the power which comes from the 3.3v line and gnd) is a push switch in serial with an LED and a 100 ohm resistor. This is the LED which is sat next to the light sensor and is activated via the push switch.

The tls261 has the left left ping grounded, the middle pin connected to +3.3v and the right pin connected to digital 3 on the arduino.

My meter on the output of the tls sensor shows around 100mV when the LED is not on and 2.7V when it is. However, when the commented code which sets dataLedPin is uncommented and the push switch is held down the interrupt continually fires.

The problem with your circuit is that the TLS261 is an analog light sensor. The output goes up linearly with light input. (Look at the datasheet for the graph of output voltage vs irradiance.) But you're connecting it to the interrupt input pin which is a digital input. Digital inputs (especially edge triggered inputs like an interrupt) are very unreliable when you drive them with analog signals.

You could add a comparator to your interrupt circuit that compares the output of the TLS261 to a ref voltage set by a pot. This would generate a clean digital signal for the interrupt and would allow you to calibrate the switching point of the sensor.

Edit: Also, I'd power the sensor and comparator from 5V instead of 3.3 so that the sensor circuit can swing in the 5V range.

Good luck!

I don't have a schematic but it is very simple - perhaps you could suggest a tool.

I'd suggest expresspcb.com. Very easy to work with. For posting, I do a screen capture & paste into powerpoint, then "save as" a jpg file for posting to the internet.

Crossroads - thanks for the suggestions on producing schematics.

MurMan - thanks, all your points taken. I stole the idea from http://www.airsensor.co.uk/component/zoo/item/energy-monitor.html and that is why it is set at 3.3V and also why I am using the TLS261 as I am. When I switch to 5V I get a swing from 19mV to 3.92V which is more obvious than the 2.7V I was getting before. The best bit is when I switch to 5V the circuit works as expected and the interrupt only fires when I release the switch to the LED. I'm sure I've got some LM339 or the like lying around which I can use for the comparator.

Once you have expresspcb setup, it should create these directory structures for you: C:\Users\Owner\Documents\ExpressPCB\SchComponents_Custom\ You can then paste these 2 files in to have a headstart on arduino based schematics

http://www.crossroadsfencing.com/Arduino Mini-Pro.s http://www.crossroadsfencing.com/Generic 328 Arduino.s

I've not actually tried that, so it may or may not work. The directory does just seem to list all the symbols I have created tho.

Glad that the switch to 5V made the interrupt operational. :)

Since the output of the sensor is sensitive to ambient light levels, adding the comparator is still a good idea. And you can add some hysteresis to the comparator with a feedback resistor circuit. This will prevent the interrupt from false triggering if the light levels are changing slowly.

CrossRoads, I got page not found errors for your 2 links. Perhaps you took them down before I had a chance to download them. Any chance you could do it again.

The spaces in the file name appears to be messing things up. If you copy the link manually all the way thru the .s the link will work - but IE & Chrome then open the file as a bunch of gibberish characters.

PM with an e-mail, I'll send them to you.

Robert

The sensor is not really subject to ambient light levels because no light can get to it once it is stuck over the LED on the meter.

I solved some of the issues brought up here in a slightly different way because I ran into problems when I actually stuck the TLS261 light sensor over the actual electricty meter LED. The voltage I was seeing when the meter LED flashed was way too small. I thought about amplifying it then I remembered I had a 4N25 optical isolator lying around. I fed the output of the TLS261 via a 150 ohm resitor into the 4N25 and this is enough to light the internal LED then simply wired a 1K resitor between +5v and the 4N25 collector and wired the emitter to ground. I attached digital pin 3 to the collector and interrupt on a falling edge.

Seems to work ok so far. Would post a schematic but I’m new to the suggested expressPCB software and have not got to grips with it yet.

Thank you to all who helped.

ok, everthing has been working for a few days now and all of sudden it has stopped working. All of a sudden I see no interrupts. The TSL261 is blue tacked over the LED on my electricity meter which flashes once for every watt. I'm new to express sch so bare with me:

In addition to the above there are 2 LED outputs from arduino digital pins 4 and 5 to show a loop has completed and we've logged a meter reading (i.e. written meter readings to the serial port). I added the println if no pulses were detected to help debug it and all it outputs is 0 (indicating no interrupts incremented the sensor variable).

I only put the LED from 4n25 emitter to ground to show the pulses from my electricity meter and the same problem exists when the emitter is grounded.

The script follows:

const int  dataLedPin    =  4;  // LED indicating sensor data is received
const int  logLedPin     =  5;  // LED flashes during a log attemp

const int logInterrupt = 1; // ATmega 168 and 328 - interrupt 0 = pin 2, 1 = pin 3
const int interruptPin = 3;

volatile unsigned long sensor = 0;  // Counts power pulses in interrupt, 1 pulse = 1 watt
unsigned long total = 0;  // Total power used since the sketch started

void setup(void)
{
  Serial.begin(19200);      // opens serial port, sets data rate to 19200 bps
  pinMode(dataLedPin, OUTPUT);    // LED interrupt indicator initialization
  pinMode(logLedPin, OUTPUT); 

  pinMode(interruptPin, INPUT);  
  // enable 20k pullup resistor:  
  digitalWrite(interruptPin, HIGH);  
  attachInterrupt(logInterrupt, interruptHandler, FALLING); 
  interrupts();  
  
  Serial.println("Start");
}

void loop(void)
{ 
  // flash the data LED
  digitalWrite(dataLedPin, HIGH);
  delay(50); 
  digitalWrite(dataLedPin, LOW);   
  
  if( sensor != 0 ) { 
     digitalWrite(logLedPin, HIGH);
     Log();
     digitalWrite(logLedPin, LOW);
  } else {
      Serial.println(sensor, DEC);
  }

  delay(6000);
}

void Log()
{
    unsigned long sensor_count;
    uint8_t oldSREG = SREG;   // save interrupt register
    cli();                    // prevent interrupts while accessing the count  
    sensor_count = sensor; //get the count from the interrupt handler
    sensor = 0;           //reset the watts count
    SREG = oldSREG;           // restore interrupts

    total += sensor_count; //total watts counter
    Serial.print(sensor_count, DEC);
    Serial.print(',');
    Serial.println(total);       
}

void interruptHandler() // routine called when external interrupt is triggered
{
  sensor += 1;  //Update number of pulses, 1 pulse = 1 watt
}

When I run this now I see the LED from the opto isolator (4N25) flash for every pulse from my electricity meter which should pull digital pin3 on the arduino to ground and yet the interrupt does not seem to fire.

In your drawing I assume the cathode of the LED internal to the opto is wired to somewhere?

Lefty