Pulse generator not triggering RISING interrupt

I've attached a pulse generator to a digital pin on an Arduino DUE and am trying to use the RISING interrupt to record the timestamps of the pulses. The issue is that the interrupt is not triggering. I've confirmed the pulse generator is working by connecting it to an oscilloscope; the pulse is ~800mV with a period of ~1second. I've tried connecting the pulse generator to different digital pins to no success. Any insight into why the board isn't seeing the pulse?

Here is the code I'm running

#include <DueFlashStorage.h>
DueFlashStorage dueFlashStorage;

volatile uint32_t start = 0;
volatile uint32_t now = 0;
volatile uint32_t writeAddress = 0;
static uint32_t MAX_WRITE_ADDRESS = 148;
static bool DEBUG = true;

void setup() {
  Serial.begin(9600);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(3), pulseHandler, RISING); 
  start=millis();
}

/**
* Writes a timestamp to flash memory.
*
* @param pulsetime  The timestamp to write to memory.
* @return true if write was successful, otherwise false.
*/
bool writeTimestamp(uint32_t pulseTime) {
  if (writeAddress + sizeof(uint32_t) >= MAX_WRITE_ADDRESS) {
    // Don't write while reading
    return false;
  }
  byte bArr[sizeof(uint32_t)];
  memcpy(bArr, &pulseTime, sizeof(uint32_t));
  dueFlashStorage.write(writeAddress, bArr, sizeof(uint32_t));
  writeAddress += sizeof(uint32_t);
  if (DEBUG) {
    Serial.print("Pulse written to memory. Write adress is ");
    Serial.print(writeAddress);
    Serial.print("\n");
  }
  
  return true;
}

volatile int readAddress = 0;
volatile int readStage = 0;
volatile int maxReadStage = 3;
/**
* Reads timestamps from flash memory.
*/
void readTimestamps() {
  if (readStage == 0 && DEBUG) {
    Serial.println("Buffer is full, reading timestamps");
  }

  // Split up the memory into stages to read over multiple loops
  int stageReadLimit = (readStage < maxReadStage - 1) ? (readStage+1) * (writeAddress / maxReadStage) : writeAddress;
  while (readAddress + sizeof(uint32_t) < stageReadLimit) {
    byte* b = dueFlashStorage.readAddress(readAddress);
    uint32_t timestamp;
    memcpy(&timestamp, b, sizeof(uint32_t));
    readAddress += sizeof(uint32_t);
    // Print to monitor so external script can store in CSV
    Serial.println(timestamp);
    if (DEBUG) {
      Serial.print("readAddress is ");
      Serial.print(readAddress);
      Serial.print("\n");
    }
  }
  readStage++;

  // Reset addresses after reading
  if (readStage == maxReadStage) {
    if (DEBUG) {
      Serial.println("Done reading timestamps");
    }
    writeAddress = 0;
    readAddress = 0;
    readStage = 0;
  }
}

// Interrupt service routine (ISR)
void pulseHandler() {
  now=millis();
  writeTimestamp(now);
}

void loop() {
  for (int i = 0; i < 12; i++) {
    Serial.print(i);
    Serial.println(digitalRead(i));
    // Serial.println(analogRead(i)* 3.3/1023.0);
  }
  if (writeAddress + sizeof(uint32_t) >= MAX_WRITE_ADDRESS) {
    // Memory is full, read to computer and clear
    readTimestamps();
  }
  delay(500);
}

That is not enough to guarantee HIGH trigger.

3 Likes

Check the processor data sheet. 800mv is not enough. For estimating CMOS I use .4 and .6 as the thresholds. For example, with a 3.3V supply:

  • High threshold: 3.3V×0.6=1.98V3.3V \times 0.6 = 1.98V3.3V×0.6=1.98V → The signal must exceed this to be considered a stable high.
  • Low threshold: 3.3V×0.4=1.32V3.3V \times 0.4 = 1.32V3.3V×0.4=1.32V → The signal must fall below this to be considered a stable low.

Note these are approximations, not exact. You must read the data sheet to be sure.

1 Like

With 800mV a simple transistor (BJT) circuit could work to shape the signal or maybe the built-in comparator (if available). For a 1Hz signal maybe the ADC is fast enough for your application simply polling instead of using interrupts.

1 Like