oscillator.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "oscillator.h"
  2. #include <driver/ledc.h>
  3. #include <esp_timer.h>
  4. #include <algorithm>
  5. #include <cmath>
  6. static const char* TAG = "Oscillator";
  7. extern unsigned long IRAM_ATTR millis();
  8. static ledc_channel_t next_free_channel = LEDC_CHANNEL_0;
  9. Oscillator::Oscillator(int trim) {
  10. trim_ = trim;
  11. diff_limit_ = 0;
  12. is_attached_ = false;
  13. sampling_period_ = 30;
  14. period_ = 2000;
  15. number_samples_ = period_ / sampling_period_;
  16. inc_ = 2 * M_PI / number_samples_;
  17. amplitude_ = 45;
  18. phase_ = 0;
  19. phase0_ = 0;
  20. offset_ = 0;
  21. stop_ = false;
  22. rev_ = false;
  23. pos_ = 90;
  24. previous_millis_ = 0;
  25. }
  26. Oscillator::~Oscillator() {
  27. Detach();
  28. }
  29. uint32_t Oscillator::AngleToCompare(int angle) {
  30. return (angle - SERVO_MIN_DEGREE) * (SERVO_MAX_PULSEWIDTH_US - SERVO_MIN_PULSEWIDTH_US) /
  31. (SERVO_MAX_DEGREE - SERVO_MIN_DEGREE) +
  32. SERVO_MIN_PULSEWIDTH_US;
  33. }
  34. bool Oscillator::NextSample() {
  35. current_millis_ = millis();
  36. if (current_millis_ - previous_millis_ > sampling_period_) {
  37. previous_millis_ = current_millis_;
  38. return true;
  39. }
  40. return false;
  41. }
  42. void Oscillator::Attach(int pin, bool rev) {
  43. if (is_attached_) {
  44. Detach();
  45. }
  46. pin_ = pin;
  47. rev_ = rev;
  48. ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_LOW_SPEED_MODE,
  49. .duty_resolution = LEDC_TIMER_13_BIT,
  50. .timer_num = LEDC_TIMER_1,
  51. .freq_hz = 50,
  52. .clk_cfg = LEDC_AUTO_CLK};
  53. ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
  54. static int last_channel = 0;
  55. last_channel = (last_channel + 1) % 7 + 1;
  56. ledc_channel_ = (ledc_channel_t)last_channel;
  57. ledc_channel_config_t ledc_channel = {.gpio_num = pin_,
  58. .speed_mode = LEDC_LOW_SPEED_MODE,
  59. .channel = ledc_channel_,
  60. .intr_type = LEDC_INTR_DISABLE,
  61. .timer_sel = LEDC_TIMER_1,
  62. .duty = 0,
  63. .hpoint = 0};
  64. ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
  65. ledc_speed_mode_ = LEDC_LOW_SPEED_MODE;
  66. // pos_ = 90;
  67. // Write(pos_);
  68. previous_servo_command_millis_ = millis();
  69. is_attached_ = true;
  70. }
  71. void Oscillator::Detach() {
  72. if (!is_attached_)
  73. return;
  74. ESP_ERROR_CHECK(ledc_stop(ledc_speed_mode_, ledc_channel_, 0));
  75. is_attached_ = false;
  76. }
  77. void Oscillator::SetT(unsigned int T) {
  78. period_ = T;
  79. number_samples_ = period_ / sampling_period_;
  80. inc_ = 2 * M_PI / number_samples_;
  81. }
  82. void Oscillator::SetPosition(int position) {
  83. Write(position);
  84. }
  85. void Oscillator::Refresh() {
  86. if (NextSample()) {
  87. if (!stop_) {
  88. int pos = std::round(amplitude_ * std::sin(phase_ + phase0_) + offset_);
  89. if (rev_)
  90. pos = -pos;
  91. Write(pos + 90);
  92. }
  93. phase_ = phase_ + inc_;
  94. }
  95. }
  96. void Oscillator::Write(int position) {
  97. if (!is_attached_)
  98. return;
  99. long currentMillis = millis();
  100. if (diff_limit_ > 0) {
  101. int limit = std::max(
  102. 1, (((int)(currentMillis - previous_servo_command_millis_)) * diff_limit_) / 1000);
  103. if (abs(position - pos_) > limit) {
  104. pos_ += position < pos_ ? -limit : limit;
  105. } else {
  106. pos_ = position;
  107. }
  108. } else {
  109. pos_ = position;
  110. }
  111. previous_servo_command_millis_ = currentMillis;
  112. int angle = pos_ + trim_;
  113. angle = std::min(std::max(angle, 0), 180);
  114. uint32_t duty = (uint32_t)(((angle / 180.0) * 2.0 + 0.5) * 8191 / 20.0);
  115. ESP_ERROR_CHECK(ledc_set_duty(ledc_speed_mode_, ledc_channel_, duty));
  116. ESP_ERROR_CHECK(ledc_update_duty(ledc_speed_mode_, ledc_channel_));
  117. }