Creating accurate delay between 2 pulses on different pins.
Posted: Mon Dec 12, 2022 11:53 am
Greetings, i
am new to the esp32. At first glance i though that 240mhz can get me really accurate delays, but turns out it uses 80mhz timer clock, and i have to use divider = 2 so it is 40mhz at the end(25ns each clock), and i cant make my code work.
I have a esp-wroom-32 module(esp32 dev module) and use arduino IDE, my task is to generate 2 pulses on different pins with as much accuracy as possible:
1) make GPIO_NUM_2 and GPIO_NUM_4 go HIGH
2)Generate single shot pulses on a button press with predefined delay:
2.1) Generate negative pulse ~100nS on pin 2 (after that pulse pin2 stays HIGH)
2.2) Wait certain amount of uS: from 3uS to 35uS with precise accuracy.(30nS or less each step i want to increase or decrease delay)
(like to
2.3)Generate another ~100nS pulse on pin4 (after that pulse pin4 stays HIGH)
Currently i came up with the following test code using a timer, but for some reason it does not works as i want:
1)it does not increment delay by 25ns each time (but it starts to work a little better at 22uS or more)
2) minimum delay is ~6.6us, after a while it jumps to 7.7 etc
Maybe there is better peripheral to do that task?
There is so many ways it seems to do that task: with DMA, RTC, LED pwm, creating some assembly code(i am not familiar with it) that can utilize 240mhz so we can get 4.16ns step.
All those ways just overwhelms me.
am new to the esp32. At first glance i though that 240mhz can get me really accurate delays, but turns out it uses 80mhz timer clock, and i have to use divider = 2 so it is 40mhz at the end(25ns each clock), and i cant make my code work.
I have a esp-wroom-32 module(esp32 dev module) and use arduino IDE, my task is to generate 2 pulses on different pins with as much accuracy as possible:
1) make GPIO_NUM_2 and GPIO_NUM_4 go HIGH
2)Generate single shot pulses on a button press with predefined delay:
2.1) Generate negative pulse ~100nS on pin 2 (after that pulse pin2 stays HIGH)
2.2) Wait certain amount of uS: from 3uS to 35uS with precise accuracy.(30nS or less each step i want to increase or decrease delay)
(like to
2.3)Generate another ~100nS pulse on pin4 (after that pulse pin4 stays HIGH)
Currently i came up with the following test code using a timer, but for some reason it does not works as i want:
1)it does not increment delay by 25ns each time (but it starts to work a little better at 22uS or more)
2) minimum delay is ~6.6us, after a while it jumps to 7.7 etc
- #include "driver/timer.h"
- int i = 0; // value added to match each loop
- static bool IRAM_ATTR onTimer(void *args) //ISR function
- {
- //2nd signal pulse
- REG_WRITE(GPIO_OUT_W1TC_REG, BIT4); //GPIO4 LOW(CLEAR)
- __asm__ __volatile__ (
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- );
- REG_WRITE(GPIO_OUT_W1TS_REG, BIT4); //GPIO4 HIGH (SET) !!!!!!!!!!!!!!
- timer_pause(TIMER_GROUP_0, TIMER_0);
- return false;
- }
- void setup() {
- ////TIMERS SETUP////
- timer_config_t config = {
- .alarm_en = TIMER_ALARM_EN, //ISR on
- .counter_en = TIMER_PAUSE, //timer off after init
- //.intr_type = TIMER_INTR_LEVEL, //can be ignored
- .counter_dir = TIMER_COUNT_UP, //up
- .auto_reload = TIMER_AUTORELOAD_EN, /hardware will load counter value after an alarm event;
- .divider = 2, //from 2 to 65536 if 2 = 40mhz =25ns
- }; //default clock source is APB (80mhz)
- timer_init(TIMER_GROUP_0, TIMER_0, &config); //init
- timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); //start value
- timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 250); //match value
- timer_isr_callback_add(TIMER_GROUP_0, TIMER_0, onTimer, NULL, 0); // add isr func
- timer_enable_intr(TIMER_GROUP_0, TIMER_0); // enable isr
- ////PINS SETUP////
- //set it as gpio
- gpio_pad_select_gpio( GPIO_NUM_2);
- gpio_pad_select_gpio( GPIO_NUM_4);
- //output
- gpio_set_direction( GPIO_NUM_2, GPIO_MODE_OUTPUT);
- gpio_set_direction( GPIO_NUM_4, GPIO_MODE_OUTPUT);
- //pullup to 3.3
- gpio_set_pull_mode( GPIO_NUM_2, GPIO_PULLUP_ONLY);
- gpio_set_pull_mode( GPIO_NUM_4, GPIO_PULLUP_ONLY);
- //out current = 40ma
- gpio_set_drive_capability( GPIO_NUM_2, GPIO_DRIVE_CAP_3);
- gpio_set_drive_capability( GPIO_NUM_4, GPIO_DRIVE_CAP_3);
- //set as high
- gpio_set_level( GPIO_NUM_2, 1); //HIGH
- gpio_set_level( GPIO_NUM_4, 1); //HIGH
- }
- void loop() {
- delay(500);
- timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 100+i); //set new match value (100 should be ~2.5uS)
- timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); //reset starting value to 0
- delay(50);
- //1st signal PULSE
- REG_WRITE(GPIO_OUT_W1TC_REG, BIT2); //GPIO2 LOW(CLEAR)
- __asm__ __volatile__ (
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- " nop\n"
- );
- REG_WRITE(GPIO_OUT_W1TS_REG, BIT2); //GPIO2 HIGH (SET)
- //start timer
- timer_start(TIMER_GROUP_0, TIMER_0);
- }
Maybe there is better peripheral to do that task?
There is so many ways it seems to do that task: with DMA, RTC, LED pwm, creating some assembly code(i am not familiar with it) that can utilize 240mhz so we can get 4.16ns step.
All those ways just overwhelms me.