Uno - Unwanted Interrupt Event

Hardware:
I have a Uno INT0 connected to a radar sensor digital output active high. Interrupt is attached to trigger on rising edge.

Also connected in parasitic power mode is two temperature sensors DS18B20.

And one analogue input.

And one radio transcever nRF24L01.

Software:
The test software loop is configured to read analogue input, temperatures and transmit any changed data then sleep. An interrupt means the radar has gone active this is registered as a change in data.

Everything works fine, temperatures are sensed, radar detects movement and radio transmits correct data.

The Problem
When the temperatures are sensed it triggers a radar interrupt.
I have traced the issue to the function call:
sensors.requestTemperatures();
Is there some known reason why the OneWire library would set the interrupt flag for INT0?
In case stray capacitance is coupling a spike on the inerrupt connection I have place a 100nF capacitor to ground.
My intention is to have a longer sleep period hence the need to connect the radar to interrupt sleep.

Any ideas would be most welcome.

Code:

#ifndef CONSTANTS_H_INCLUDED
#define CONSTANTS_H_INCLUDED
#include <Arduino.h>
#include <EEPROM.h>
#include "LowPower.h"
#include "printf.h"
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <DallasTemperature.h>

//--- comment to send dbug info to serial console  ------------
#define dbserial //
//-------------------------------------------------------------
// Inputs:
#define ONE_WIRE_BUS 4 // Temperature sensor(s)
#define RADAR_ONE 2 // Radar motion sensor
#define ANALOGUE1 A0

// Outputs:
#define RF_CE 9 // nRF24L01P radio transceiver
#define RF_CSN 10
#define LED_GREEN 6 // LED for status
#define LED_RED 5
#define RADIO_VCC 13 // Radio vcc high = 3.3V, low = 0 Volts

// Macros:
#define GREEN_LED(state) { digitalWrite(LED_GREEN, (state)); }
#define RED_LED(state) { digitalWrite(LED_RED, (state)); }

// Flags
#define FLAG_RADAR_A 0b00000001 ; true means radar active

typedef struct {
  byte  Flags, // senders id
 Batt, // analogue input 
 TxFails; // failed tx attempts (resets daily)
  word  TemperatureOne, // temp sensor one deg C x 10
   TemperatureTwo; // temp sensor two deg C x 10
 bool flagTest(byte fn) { return (Flags & fn) > 0; }
 void flagSet(byte fn) { Flags |= fn; }
 void flagClear(byte fn) { Flags &= ~fn; }
} TRadioData;

#endif


// main.cpp:
#include "vars.h"


//-- nRF24L01 radio --------------------------------------------
TRadioData radioData, lastRadioData;
typedef struct {
 byte baseStationNextTx; 
} _radioAckData; // ack data sent back from base station 
_radioAckData radioAckData;

RF24 radio(RF_CE, RF_CSN); // (CE, CSN) nRF24L01P radio transceiver
// Write radio pipe.
const uint64_t rfWritePipe = 0xF0F0F0F0D3LL;
//-------------------------------------------------------------
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// temperature sensor device addresses
DeviceAddress temperatureSensor1, temperatureSensor2;
//-------------------------------------------------------------
word
 loopCount = 0,
 txCount = 0;

void setup() {
 pinMode(RADAR_ONE, INPUT_PULLUP);
 pinMode(RADIO_VCC, OUTPUT);
 pinMode(LED_GREEN, OUTPUT);
 pinMode(LED_RED, OUTPUT);
 
 Serial.begin(115200);
 delay(10);
 printf_begin();

 analogReference(EXTERNAL); // REF pin is connected to 3V3
 delay(1);
 //do A-D readings to avoid errors after changing analogReference
 for (int i = 0; i < 10; i++)
 analogRead(0);
 
 // Start oneWire library for temperature sensors
 sensors.begin();

 radio.begin();
 // note delay between retries is staggered for outside weather and aux sensor modules  
  radio.setRetries(15, 15); // (delay between retries 0-15 * 250uS, # retries: 0-15) 
  radio.setPayloadSize(sizeof(radioData));
 // enable ack payloads
 radio.enableAckPayload();
 // data rate
 radio.setDataRate(2); // 0 1Mbps; 1 2Mbps; 2 250kbps
 radio.setChannel(0x6c); // default 0x4C (76); F0= 2400 + RF_CH [MHz]
 //RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, and RF24_PA_HIGH=0dBm
 radio.setPALevel(RF24_PA_MAX);
 radio.enableAckPayload(); // ack payload contains base station next tx time
 radio.openWritingPipe(rfWritePipe);
 radio.printDetails();
 //-----------------------------------------------------------

 analogReference(INTERNAL);
 //do A-D readings to avoid errors after changing analogReference
 for(int i = 0; i < 10; i++)
 analogRead(0);

 loopCount = 0;

  // get addresses of temperature sensors, we have two temperature sensors
  if(sensors.getAddress(temperatureSensor1, 0)) {
 } else {
 Serial.println("Unable to find address temperature sensor 1");
 }
  if(sensors.getAddress(temperatureSensor2, 1)) {
 } else {
 Serial.println("Unable to find address temperature sensor 2");
 }

 radioData.TemperatureOne = 0;
 radioData.TemperatureTwo = 0;
 radioData.Batt = 0; 
 radioData.Flags = 0;
 lastRadioData = radioData;

 delay(50); // allow time for console output

 // connect ISR for radar
 attachISRs();
}

void loop() {
 loopCount++;

 readAnalogueInputs();

 // every 10 loops or imediately flags have changed (eg radar detection)
 if(loopCount % 10 == 0 || lastRadioData.Flags != radioData.Flags) {

   GREEN_LED(HIGH); // high led on
   readTemperatures();
   GREEN_LED(LOW);

   if(!hasDataChanged()) {
     delay(1);
   } else
  {
     RED_LED(HIGH);
     RadioTx();
     RED_LED(LOW);
   }
 }

  LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); 
}

bool hasDataChanged() {
 return (
 lastRadioData.TemperatureOne != radioData.TemperatureOne
 || lastRadioData.TemperatureTwo != radioData.TemperatureTwo
 || lastRadioData.Flags != radioData.Flags
 || lastRadioData.Batt != radioData.Batt
 );
}

void readTemperatures() {
 // call sensors.requestTemperatures() to issue a global temperature
 // request to all devices on the bus
 sensors.requestTemperatures(); // CAUSES INTERRUPT! Send the command to get temperatures
 radioData.TemperatureOne = sensors.getTempC(temperatureSensor1) * 100;
 radioData.TemperatureTwo = sensors.getTempC(temperatureSensor2) * 100;
}

void readAnalogueInputs() {
 radioData.Batt = map(analogRead(ANALOGUE1), 0, 1023, 0, 255);
}

void radioVcc(bool on) {
 // switch power on to radio module
 radio.powerUp();
 delay(1);
 return;
}

bool RadioTx(void) {
 radioVcc(HIGH); // turn vcc to 3.3V
 txCount++;
 if(radio.write(&radioData, sizeof(radioData))) {
 // has base station sent us a command in ack payload?
 if(radio.isAckPayloadAvailable()) {
 // Process ack command
 radio.read(&radioAckData, sizeof(radioAckData));
 #ifdef dbserial
 printf("Ack payload: %d\n", radioAckData.baseStationNextTx);
 #endif
 } else {
 #ifdef dbserial
 printf("Ack without payload\n");
 #endif
 }
 lastRadioData = radioData;
 } else {
 radioData.TxFails++;
 #ifdef dbserial
 printf("Radio Tx Fails %d\n", radioData.TxFails);
 #endif
 return false;
 }
 radio.powerDown();
 radioVcc(LOW); // turn vcc to 0 V
 
 radioData.Flags &= ~FLAG_RADAR_A; // Reset radar flag
 lastRadioData.Flags &= ~FLAG_RADAR_A;

 return true;
}


void ISRRadar() {
 radioData.Flags |= FLAG_RADAR_A;
 GREEN_LED(LOW);
 RED_LED(HIGH); // test only
 Serial.println("."); // test only, yes i know no Serial prints in isr desperate times call for desperate measures
 RED_LED(LOW);
}

void attachISRs() {
 attachInterrupt(digitalPinToInterrupt(RADAR_ONE), ISRRadar, RISING);
}

void detachISRs() {
 detachInterrupt(digitalPinToInterrupt(RADAR_ONE));
}

My intention is to have a longer sleep period hence the need to connect the radar to interrupt sleep.

Your interrupt won't awake the Arduino. In a power down sleep only level interrupts are able to awake the Arduino from sleep.

Is there some known reason why the OneWire library would set the interrupt flag for INT0?

Power problems? Post a complete wiring diagram of your setup including the power sources and links to the used hardware!

oneis:
Also connected in parasitic power mode is two temperature sensors DS18B20.

I'd advise against using parasitic power mode. Start with properly powered devices and get everything else working. Then, if you absolutely must, switch the DS18B20s over to parasitic mode.

Thank you for comments.

pylon:
Your interrupt won't awake the Arduino. In a power down sleep only level interrupts are able to awake the Arduino from sleep.

The Atmeg328p will wake from deep sleep on a rising/change exteral interrupt. See here and it's is working for me too.
nickgammon:
They are a bit slow in releasing an updated datasheet, but they did indeed confirm it is wrong in that respect.

Power doesn't appear to be an issue, power is from USB plugged into the PC, the same issue happens powering from mains USB charger.

I posted mainly to see if external interrupts can be used with the OneWire and DallasTemperature libraries. I have read the OneWire library disables all interrupts instead of the specific pin. It made me wonder if it was somehow setting the INT0 flag when it re-enabled interrupts.

Since no one has said otherwise I assume this is a fault condition on my setup.

Having doubled checked everything, really only leaves the MCU chip. After replacing it I will report back.

Again, thank you all for responding.

Replacement MCU did not change the issue, not that surprising.

gfvalvo:
I'd advise against using parasitic power mode. Start with properly powered devices and get everything else working. Then, if you absolutely must, switch the DS18B20s over to parasitic mode.

But this did has solved the issue. gfvalvo thank you; was this a flash of insight or you have also experienced cross-talk between parasitic mode and external interrupts?

I'm interested to know what is the connection between external INT0 and the DS18B20s running in any mode?

I posted mainly to see if external interrupts can be used with the OneWire and DallasTemperature libraries. I have read the OneWire library disables all interrupts instead of the specific pin. It made me wonder if it was somehow setting the INT0 flag when it re-enabled interrupts.

The library disables all interrupts to get a precise timing, so there's no relation to a specific pin.

It's probably not the software that does that change but your hardware. The parasitic power probably induces a spike on the interrupt line which is then detected by the Arduino.

pylon:
The library disables all interrupts to get a precise timing, so there's no relation to a specific pin.

I see your point why OneWire needs to disable all interrupts.

It's probably not the software that does that change but your hardware. The parasitic power probably induces a spike on the interrupt line which is then detected by the Arduino.

As mentioned, a 100nF capacitor connected from the interrupt pin to 0V was to absorb any stray capacitance coupled pulse to the interrupt pin but had no effect.

No doubt somehow a pulse is being induced.

Thank you for your clarification.

That's strange IMO, I don't see why that should be happening.... how forcefully does the radar unit hold that pin low? Maybe "not very"? If that's the case, I'd try putting a pulldown resistor on that pin. I'd be inclined to start with 4.7k, but I'd be stunned if even 1k was too much, and would provide a firmer pulldown.

Are the wires for radar and OneWire right next to eachother? If so, try moving them further apart, physically - you can totally have capacitive coupling between wires, especially if they're right next to eachother for a longish distance....

If you have a digital scope that you can trigger from either the radar pin, or the OneWire data line, that would be the "sledgehammer" debugging route.

And - wait, so despite the datasheet saying otherwise, the INTn interrupts can wake chip on a RISING/FALLING edge? I am sure I remember someone here having tried that, found it not working, and getting helped out with sorting it out.

Note that you can definitely wake on a PCINT (pin change interrupt), and you can do that with any pin - though it's a bit more work, since the IDE doesn't provide an abstraction for it (this actually makes sense, especially once you start using multiples of them), and you can't tell it to trigger only on rising or falling - it will always trigger on change. There are lots of guides on how to use PCINTs though.

DrAzzy:
That's strange IMO, I don't see why that should be happening.... how forcefully does the radar unit hold that pin low? Maybe "not very"? If that's the case, I'd try putting a pulldown resistor on that pin. I'd be inclined to start with 4.7k, but I'd be stunned if even 1k was too much, and would provide a firmer pulldown.

Are the wires for radar and OneWire right next to eachother? If so, try moving them further apart, physically - you can totally have capacitive coupling between wires, especially if they're right next to eachother for a longish distance....

I just took another look at this and found that going away from operating the DS18B20's in parasitic mode had not resolved this, it was coincidental with different wiring proximity.
Being hooked into the idea of stray capacitance induction into the INT0 line as the cause led to tunnel vision.

The issue was due to wiring proximity of temperature sensor wires to the XY-WB-DC radar module. BUT it was causing a genuine interrupt, that is the radar module was responding as if motion was detected. This is why things didn't make sense. So easy to run off in search of what one thinks rather than what one observes. Why the radar module is responding like this I don't know. But it's OK and works fine with some separation.

Edit:
Placing a 39pF capacitor between gnd and the data signal to the DS18B20's made the system completely stable even with the wires in close proximity to the radar module. With DS18B20's connected in parasitic mode. Was there an RF component on the data wires that was being received by the radar module causing it to trigger?

DrAzzy:
And - wait, so despite the datasheet saying otherwise, the INTn interrupts can wake chip on a RISING/FALLING edge? I am sure I remember someone here having tried that, found it not working, and getting helped out with sorting it out.

For sure the datasheet is incorrect on this point. I have verified attached interrupts work for INT0 and INT1 on both rising and falling edges. You can read more on in the link above, Nick Gammon had documented this a while back.

Thanks to one and all.