mcpwm_sync_example.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* MCPWM sync example
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. /*
  8. * This example will show you how to use capture function to read HC-SR04 sonar sensor.
  9. */
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include "freertos/queue.h"
  13. #include "esp_rom_gpio.h"
  14. #include "soc/mcpwm_periph.h"
  15. #include "hal/gpio_hal.h"
  16. #include "esp_log.h"
  17. #include "esp_check.h"
  18. #include "soc/rtc.h"
  19. #include "driver/mcpwm.h"
  20. const static char *TAG = "sync_example";
  21. #define TARGET_MCPWM_UNIT MCPWM_UNIT_0
  22. #define TIMER0_OUTPUT_GPIO GPIO_NUM_16
  23. #define TIMER1_OUTPUT_GPIO GPIO_NUM_17
  24. #define TIMER2_OUTPUT_GPIO GPIO_NUM_18
  25. #define SIMU_GPIO_SYNC_SOURCE_GPIO GPIO_NUM_21
  26. #define SIMU_GPIO_SYNC_SIMULATE_GPIO GPIO_NUM_19
  27. void app_main(void) {
  28. ESP_LOGI(TAG, "MCPWM sync example");
  29. // init MCPWM: 10% duty cycle on all three timers in MCPWM unit 0 (currently not synchronous)
  30. mcpwm_config_t pwm_config = {
  31. .frequency = 1000,
  32. .cmpr_a = 10,
  33. .cmpr_b = 0,
  34. .counter_mode = MCPWM_UP_COUNTER,
  35. .duty_mode = MCPWM_DUTY_MODE_0,
  36. };
  37. ESP_ERROR_CHECK(mcpwm_init(TARGET_MCPWM_UNIT, MCPWM_TIMER_0, &pwm_config));
  38. ESP_ERROR_CHECK(mcpwm_init(TARGET_MCPWM_UNIT, MCPWM_TIMER_1, &pwm_config));
  39. ESP_ERROR_CHECK(mcpwm_init(TARGET_MCPWM_UNIT, MCPWM_TIMER_2, &pwm_config));
  40. // bind output to GPIO
  41. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
  42. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
  43. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
  44. ESP_LOGI(TAG, "PWM started, not synchronized");
  45. vTaskDelay(pdMS_TO_TICKS(1000));
  46. // temporarily disable GPIO output, by binding to GenBs which have 0 output
  47. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0B, TIMER0_OUTPUT_GPIO));
  48. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1B, TIMER1_OUTPUT_GPIO));
  49. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2B, TIMER2_OUTPUT_GPIO));
  50. vTaskDelay(pdMS_TO_TICKS(2000));
  51. ESP_LOGI(TAG, "Sync timers with GPIO approach");
  52. // first configure sync source
  53. mcpwm_sync_config_t sync_conf = {
  54. .sync_sig = MCPWM_SELECT_GPIO_SYNC0,
  55. .timer_val = 0,
  56. .count_direction = MCPWM_TIMER_DIRECTION_UP,
  57. };
  58. ESP_ERROR_CHECK(mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_0, &sync_conf));
  59. ESP_ERROR_CHECK(mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_1, &sync_conf));
  60. ESP_ERROR_CHECK(mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_2, &sync_conf));
  61. // then configure GPIO
  62. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM_SYNC_0, SIMU_GPIO_SYNC_SOURCE_GPIO));
  63. gpio_config_t io_conf = {};
  64. io_conf.intr_type = GPIO_INTR_DISABLE;
  65. io_conf.mode = GPIO_MODE_OUTPUT;
  66. io_conf.pin_bit_mask = BIT64(SIMU_GPIO_SYNC_SIMULATE_GPIO);
  67. io_conf.pull_down_en = 0;
  68. io_conf.pull_up_en = 0;
  69. ESP_ERROR_CHECK(gpio_config(&io_conf));
  70. ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 0));
  71. ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 1));
  72. // wait for at least one TEP
  73. vTaskDelay(pdMS_TO_TICKS(10));
  74. // re-enable GPIO output, to see the result
  75. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
  76. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
  77. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
  78. ESP_LOGI(TAG, "Output should already be synchronized");
  79. vTaskDelay(pdMS_TO_TICKS(1000));
  80. // stop and restart timers to mess them
  81. ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_2));
  82. ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_1));
  83. ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_0));
  84. vTaskDelay(pdMS_TO_TICKS(2000));
  85. ESP_ERROR_CHECK(mcpwm_start(TARGET_MCPWM_UNIT, MCPWM_TIMER_0));
  86. ESP_ERROR_CHECK(mcpwm_start(TARGET_MCPWM_UNIT, MCPWM_TIMER_1));
  87. ESP_ERROR_CHECK(mcpwm_start(TARGET_MCPWM_UNIT, MCPWM_TIMER_2));
  88. ESP_LOGI(TAG, "force synchronous lost");
  89. vTaskDelay(pdMS_TO_TICKS(1000));
  90. // temporarily disable GPIO output, by binding to GenBs which have 0 output
  91. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0B, TIMER0_OUTPUT_GPIO));
  92. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1B, TIMER1_OUTPUT_GPIO));
  93. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2B, TIMER2_OUTPUT_GPIO));
  94. vTaskDelay(pdMS_TO_TICKS(2000));
  95. #ifdef SOC_MCPWM_SWSYNC_CAN_PROPAGATE
  96. // use the trick that only available on esp32s3
  97. mcpwm_set_timer_sync_output(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_SWSYNC_SOURCE_SYNCIN);
  98. sync_conf.sync_sig = MCPWM_SELECT_TIMER0_SYNC;
  99. mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_0, &sync_conf);
  100. mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_1, &sync_conf);
  101. mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_2, &sync_conf);
  102. // then send soft sync event to timer0
  103. mcpwm_timer_trigger_soft_sync(MCPWM_UNIT_0, MCPWM_TIMER_0);
  104. // re-enable GPIO output
  105. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
  106. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
  107. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
  108. ESP_LOGI(TAG, "Output should already be synchronized on esp32s3");
  109. vTaskDelay(pdMS_TO_TICKS(1000));
  110. #endif
  111. // temporarily disable GPIO output, by binding to GenBs which have 0 output
  112. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0B, TIMER0_OUTPUT_GPIO));
  113. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1B, TIMER1_OUTPUT_GPIO));
  114. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2B, TIMER2_OUTPUT_GPIO));
  115. vTaskDelay(pdMS_TO_TICKS(2000));
  116. // create phase between each timer.
  117. // for this case all timers has 10% of period phase between each other
  118. sync_conf.sync_sig = MCPWM_SELECT_GPIO_SYNC0;
  119. sync_conf.timer_val = 0; // no phase applied
  120. mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_0, &sync_conf);
  121. sync_conf.timer_val = 900; // fill the counter with 90.0% of period will cause next pulse being delayed 10% period
  122. mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_1, &sync_conf);
  123. sync_conf.timer_val = 800; // fill the counter with 80.0% of period will cause next pulse being delayed 20% period
  124. mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_2, &sync_conf);
  125. // trigger positive edge
  126. ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 0));
  127. ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 1));
  128. // wait for at least one TEP
  129. vTaskDelay(pdMS_TO_TICKS(10));
  130. // re-enable GPIO output, to see the result
  131. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
  132. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
  133. ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
  134. ESP_LOGI(TAG, "Each output pulse should be placed with 10 percents of period");
  135. vTaskDelay(pdMS_TO_TICKS(1000));
  136. ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_2));
  137. ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_1));
  138. ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_0));
  139. }