Last active
August 8, 2018 15:22
-
-
Save ij96/95e98ede2c1add2c1b1d61c718ba2d4d to your computer and use it in GitHub Desktop.
Delay a signal by a fixed time accurately, by using interrupt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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