Photon does not wake up from interrupt

Hi,

I have connected a sensor to my Photon which generates an interrupt when something is in front of it. I think this works so far because I can digitalRead the interrupt pin.
I am getting a 1 when there is no interrupt and a 0 when the sensor generates an interrupt.
So I think it should be possible to wake the Photon up.

I did the following in Setup:

  pinMode(interruptPin, INPUT_PULLUP);

I am using INPUT_PULLUP because the datasheet of the sensor says:

The interrupt pin is an open drain output. The needed pull-up resistor may be connected to the same supply voltage as the application
controller and the pull-up resistors at SDA/SCL. Proposed value R2 should be >1 kΩ , e.g. 10 kΩ to 100 kΩ.
Proposed value for R3 and R4, e.g. 2.2 kΩ to 4.7 kΩ, depend also on the I2C bus speed. 

in loop:

//Serial.print("State: "); 
//Serial.println(digitalRead(interruptPin));
System.sleep(interruptPin, FALLING, 500);

But this does not work. I have also tried RISING and CHANGE.
When I use CHANGE my Photon wakes up immediatly after going to sleep forever.
Firmware Version: 0.6.0 RC2

I have really no idea why this does not work and I would be very grateful if you could help me :smile:

Might be useful to post all the code. Taking your code at face value; with System.sleep() in loop() it seems to me that the photon will wake when the pin value alters, but then will immediately go back to sleep again?

1 Like

Thank you very much for your answer! I have taken care of the problem that it maybe immediately go back to sleep but it did not change anything so far.
Here is my code:

#include "VCNL40x0.h"

VCNL40x0 vcnl;

const byte interruptPin = D4;
volatile byte state = LOW;

unsigned int nextTime = 0;

unsigned int i=0;
uint8_t ID=0;
uint8_t Command=0;
uint8_t Current=0;
unsigned int  ProxiValue=0;
unsigned long  SummeProxiValue=0;
unsigned int  AverageProxiValue=0;
unsigned int  AmbiValue=0;
uint8_t InterruptStatus=0;
uint8_t InterruptControl=0;

void setup() {
  Serial.begin(9600);
  Serial.println("VCNL40x0 test");
  
  pinMode(interruptPin, INPUT_PULLUP);
  //attachInterrupt(interruptPin, VCNL40x0Isr, CHANGE);

  if (! vcnl.begin()){
    Serial.println("Sensor not found :(");
    while (1);
  }
  Serial.println("Found VCNL4010");
  
  Serial.println(vcnl.readID());	// Read VCNL40x0 product ID revision register
	
  vcnl.writeCurrent(20);	// Set current to 20mA
  
  Serial.println(vcnl.readCurrent());	// Read back IR LED current
  
  // stop all activities (necessary for changing proximity rate, see datasheet)
  vcnl.setCommandRegister (COMMAND_ALL_DISABLE);
  
  // set proximity rate to 2/s
  vcnl.setProximityRate (PROX_MEASUREMENT_RATE_2);
  
  // enable prox and ambi in selftimed mode
  vcnl.setCommandRegister (COMMAND_PROX_ENABLE |
                           COMMAND_AMBI_ENABLE |
                           COMMAND_SELFTIMED_MODE_ENABLE);
						   
  // set interrupt control for threshold
  vcnl.setInterruptControl (INTERRUPT_THRES_SEL_PROX |
                            INTERRUPT_THRES_ENABLE |
                            INTERRUPT_COUNT_EXCEED_2);
  
  
  // set ambient light measurement parameter
  vcnl.setAmbiConfiguration (AMBI_PARA_AVERAGE_32 |
                        AMBI_PARA_AUTO_OFFSET_ENABLE |
                        AMBI_PARA_MEAS_RATE_2);
						
  // measure average of prox value
  SummeProxiValue = 0;
 
    for (i=0; i<30; i++) {  
		  /*do {
			  vcnl.readCommandRegister(); // read command register
		  } while (!COMMAND_MASK_PROX_DATA_READY);
        */
       SummeProxiValue += vcnl.readProxiValue();           // read prox value and sum of all measured prox values                      
    }
 
    AverageProxiValue = SummeProxiValue / 30;                     // calculate average
 
    vcnl.setHighThreshold (AverageProxiValue + 1000);   // set upper threshold for interrupt
    Serial.print("Upper Threshold Value: ");
	Serial.println(AverageProxiValue + 1000);
	Particle.publish("AverageProxy",String(AverageProxiValue));
}

void loop() {
   Serial.print("Ambient: "); Serial.println(vcnl.readAmbiValue());
   Serial.print("Proximity: "); Serial.println(vcnl.readProxiValue());
   Serial.print("State: "); 
   Serial.println(digitalRead(interruptPin));  

   if (nextTime > millis()) {
        return;
   }
   nextTime = millis() + 30000;
   System.sleep(interruptPin, FALLING, 500);
}

When I uncomment System.sleep I receive the following output in the serial monitor:
Nothing in front of the sensor:

State: 1
Ambient: 773
Proximity: 2463
State: 1
Ambient: 773
Proximity: 2470
State: 1
Ambient: 691
Proximity: 2466
State: 1
Ambient: 734
Proximity: 2467
State: 1
Ambient: 775
Proximity: 2465
State: 1
Ambient: 765
Proximity: 2468
State: 1
Ambient: 743
Proximity: 2466
State: 1
Ambient: 665
Proximity: 2466
State: 1
Ambient: 778
Proximity: 2470

My hand in front of it:

State: 0
Ambient: 116
Proximity: 3886
State: 1
Ambient: 106
Proximity: 3912
State: 0
Ambient: 124
Proximity: 3885
State: 1
Ambient: 123
Proximity: 3879
State: 0
Ambient: 120
Proximity: 3858
State: 1
Ambient: 113
Proximity: 3862
State: 0
Ambient: 114
Proximity: 3998
State: 1
Ambient: 126
Proximity: 3968
State: 0
Ambient: 120
Proximity: 3970
State: 1
Ambient: 116
Proximity: 3948

Could it be that an interrupt is to short so the Photon does not recognize it?

Edit: When I use INTERRUPT_COUNT_EXCEED_1 instead of INTERRUPT_COUNT_EXCEED_2 then I get the following output when my hand is in front of the sensor:

State: 0
Ambient: 116
Proximity: 3886
State: 0
Ambient: 106
Proximity: 3912
State: 0
Ambient: 124
Proximity: 3885
State: 0
Ambient: 123
Proximity: 3879
State: 0
Ambient: 120
Proximity: 3858
State: 0
Ambient: 113
Proximity: 3862
State: 0
Ambient: 114
Proximity: 3998
State: 0
Ambient: 126
Proximity: 3968
State: 0
Ambient: 120
Proximity: 3970
State: 0
Ambient: 116
Proximity: 3948

I am not sure I understand your output, what would you expect the output to look like if it was working as you expect?

Did you notice this in the data sheet which seems to suggest you need to clear interrupt status bits after the sensor sends an interrupt:

Once an interrupt is generated the corresponding status bit goes to 1 and stays there unless it is cleared by writing a 1 in the corresponding bit. The int pad will be pulled down while at least one of the status bit is 1.

The data sheet (page 5) refers to an app note which on page 17 also seems to suggest clearing interrupt status flags may be required?

@chrisb2, the system firmware handles resetting the interrupt bit. As for the pull-up, I highly recommend using an external pull-up which is guaranteed to work even during sleep. At what rate is the interrupt firing?

That’s true for the µC but I think @chrisb2 is refering to the proximity sensor INT output.

1 Like

Thank you all very much for your support!

I would expect that when I power my Photon it goes to sleep. After 500 seconds, or when I move my hand in front of the sensor it also wakes up. Then it stays online for 30 seconds and goes to sleep again. It is a work in progress, the next step would be to measure the time between a HIGH threshold and a LOW threshold.

I did not see the notice to clear the interrupt status bits. But shouldn’t it work at least once? For a second time it would be necessary to clear the status bits.

Edit:
And because of this:

State: 0
Ambient: 116
Proximity: 3886
State: 1
Ambient: 106
Proximity: 3912
State: 0
Ambient: 124
Proximity: 3885
State: 1
Ambient: 123
Proximity: 3879
State: 0
Ambient: 120
Proximity: 3858
State: 1
Ambient: 113
Proximity: 3862
State: 0
Ambient: 114
Proximity: 3998
State: 1
Ambient: 126
Proximity: 3968
State: 0
Ambient: 120
Proximity: 3970
State: 1
Ambient: 116
Proximity: 3948

I assume that it is working. Because “State” is the state of the interrupt pin. And it switches between HIGH and LOW when I use INTERRUPT_COUNT_EXCEED_2.

@peekay123 I am now using an external pull-up with 10kOhm and changed INPUT_PULLUP to INPUT. I put it between Vin and Int of the sensor. Interrupts will fire only a few times a day.

I really would like to make the library public but I am unsure which license I have to use. Because it is a mix between the Adafruit library here (BSD license) and the mbed library here (Apache license).
I was not successful in porting only the mbed library.

I notice you may have experimented with attaching an ISR to D4:

//attachInterrupt(interruptPin, VCNL40x0Isr, CHANGE);

Did you get this work?

One other ‘crazy’ thought is that you have declared the interruptPin variable as a byte, the argument to Sytem.sleep() is shown as a uint16_t in the docs, same for attachInterrupt(). Examples in the docs show pin variables declared with int data type. I do not see why byte should cause a problem, but maybe something weird is going on.

Hi @chrisb2,

yes this works, I can see it in the serial monitor. I have uncommented that line and put this at the end of my code and made some small modifications of my loop:

void VCNL40x0Isr(){
    Serial.println("H");
}

I have also changed the pin declaration to int but it did not change anything. I really do not understand why my Photon does not wake up.

@hl68fx, one thing you could try is to disconnect the interrupt line from the VCNL40 board and connect D4 to a wire that you can manually ground. Wait for your photon to go to sleep and try waking it by grounding D4. Let me know what happens. :grinning:

Hi @peekay123,

when the Photon is sleeping and I connect the wire between INT and D4 to D4 and GND it wakes up :smile:

@hl68fx, so there may be an issue with the INT output of the board. What pull-up resistor value are you using?

I am using 10 kOhm and I have also tried 100 kOhm.

Can you provide a link to the exact board you are using?

sure @peekay123 , I am using this sensor from [Adafruit][1]

I have two of this boards but it did not help changing them.
[1]: https://www.adafruit.com/product/466

@hl68fx, I’ll take a look at the datasheet and appnotes tonight and get back to you.

1 Like

Thank you very much @peekay123! I am really grateful for the help!

@hl68fx, which library are you using?

@peekay123 I am using a mix between this and this library from Adafruit. The Adafruit library does not support interrupts. After some research I have found the library from mbed. I did not get it to compile so I have “ported” the missing parts to the Adafruit library.
The problem is I do not know how to publish my library because both libraries use different licenses (Adafruit -> BSD license, mbed -> Apache license).