Skip to content

Instantly share code, notes, and snippets.

@ij96
Last active August 8, 2018 15:22
Show Gist options
  • Select an option

  • Save ij96/95e98ede2c1add2c1b1d61c718ba2d4d to your computer and use it in GitHub Desktop.

Select an option

Save ij96/95e98ede2c1add2c1b1d61c718ba2d4d to your computer and use it in GitHub Desktop.
Delay a signal by a fixed time accurately, by using interrupt
// Arduino UNO
// faster digital read and write using register and bit mask
#define FAST_DIGITAL_READ(REG, MASK) (*REG & MASK) != 0;
#define FAST_DIGITAL_WRITE(REG, MASK, VAL) (VAL == LOW) ? (*REG &= ~MASK) : (*REG |= MASK);
// pin definition
#define OUTPUT_PIN 13
#define INTERRUPT_PIN 2
// interrupt delay
#define INTERRUPT_DELAY_US 8 // using interrupt introduces a consistent, extra delay of ~8us
uint8_t output_pin_mask;
volatile uint8_t *output_pin_reg;
uint8_t interrupt_pin_mask;
volatile uint8_t *interrupt_pin_reg;
volatile uint8_t output_pin_state = LOW;
uint32_t delay_time_us = 0;
void setup() {
// setup output pin
pinMode(OUTPUT_PIN, OUTPUT);
output_pin_mask = digitalPinToBitMask(OUTPUT_PIN);
output_pin_reg = portOutputRegister(digitalPinToPort(OUTPUT_PIN));
// setup interrupt
pinMode(INTERRUPT_PIN, INPUT_PULLUP);
interrupt_pin_mask = digitalPinToBitMask(INTERRUPT_PIN);
interrupt_pin_reg = portInputRegister(digitalPinToPort(INTERRUPT_PIN));
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), update_output, CHANGE);
// set delay time length through Serial
String delay_time_buffer = "";
bool is_delay_time_set = false;
uint32_t delay_time_us_unadjusted = 0;
Serial.begin(9600);
Serial.print("Enter the desired delay length (in microseconds, minimum delay ");
Serial.print(INTERRUPT_DELAY_US);
Serial.println(" us)");
while(!is_delay_time_set) {
while(Serial.available()) {
delay_time_buffer = Serial.readStringUntil('\n');
delay_time_us_unadjusted = delay_time_buffer.toInt();
// adjust the actual delay time, by taking off the interrupt delay
if(delay_time_us_unadjusted < INTERRUPT_DELAY_US) {
delay_time_us = 0;
Serial.print("Cannot set to ");
Serial.print(delay_time_us_unadjusted);
Serial.println(" us, since it is below the minimum delay possible");
Serial.print("Delay set to minimum: ");
Serial.print(INTERRUPT_DELAY_US);
Serial.println(" us");
} else {
delay_time_us = delay_time_us_unadjusted - INTERRUPT_DELAY_US;
Serial.print("Delay set to ");
Serial.print(delay_time_us_unadjusted);
Serial.println(" us");
}
is_delay_time_set = true;
}
}
Serial.end();
}
void loop() {
FAST_DIGITAL_WRITE(output_pin_reg, output_pin_mask, output_pin_state);
}
void update_output() {
output_pin_state = FAST_DIGITAL_READ(interrupt_pin_reg, interrupt_pin_mask);
delayMicroseconds(delay_time_us);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment