ESP32 обновление ledсSetup .... ledcFade

D В проекте нужно подключить 4 сервомотора (0-180 градусов).

PWM управление.

Частота 50 Гц. Длительность импульса 500 мкс - 0 градусов, 2500 мкс - 180 градусов.

Посмотрел готовые библиотеки. Но ни одна не захотела работать. Ошибка на отсутствие функции ledсSetup. Изучая вопрос нашел информацию на гитхабе, что в новом ядре esp32 core эту функцию исключили. Вместо нее теперь ledсAttach.

Листая дальше увидел интересную функцию -

bool ledcFade(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms);

Из описания понял, что это функция, которая не тратит процессорное время и может плавно менять скважность выходного сигнала. Посмотрел в примерах. Нашел использование в примерах. Но ни один пример не заработал.

сталкивался ли кто с этой функцией? Как ее правильно использовать? И как понимать, что она не тратит процессорное время? В примере используется прерывание.

какой-то вы невезучий…
Ни одна библиотека, ни один пример не хочут работать для вас…

Первый подход к был в начале апреля. И примеры из библиотек прекрасно работали. Но позже видимо прошло обновление и ряд функций изменили. На текущий момент реализовал без использования ledcFade()

Но очень чешется испытать новые возможности.

у вас какая-то странная логика. Если в результате обновления функция более недоступна - то какие же это “новые” возможности? Это старые… то есть, точнее, устаревшие.

Хотя я думаю что вы что-то напутали. В ЕСП32 главное правило всегда запускать примеры именно от той версии пакета, которая у вас установлена. Не пытатесь искать примеры в интернете - они почти наверяняка не подойдут.

Какую плату выбираете при компиляции скетча? Какая версия поддержки ЕСП32 стоит?

Migration from 2.x to 3.0

Пример с fade компилируется. Но работает не верно.

Из примеров:

/* LEDC Fade Arduino Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)
   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <Arduino.h>

// use 12 bit precision for LEDC timer
#define LEDC_TIMER_12_BIT 12

// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ 50

// fade LED PIN (replace with LED_BUILTIN constant for built-in LED)
#define LED_PIN 27

// define starting duty, target duty and maximum fade time
#define LEDC_START_DUTY  (0)
#define LEDC_TARGET_DUTY (4095)
#define LEDC_FADE_TIME   (3000)

bool fade_ended = false;  // status of LED fade
bool fade_in = true;

void ARDUINO_ISR_ATTR LED_FADE_ISR() {
  fade_ended = true;
}

void setup() {
  // Initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  // Setup timer with given frequency, resolution and attach it to a led pin with auto-selected channel
  ledcAttach(LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);

  // Setup and start fade on led (duty from 0 to 4095)
  ledcFade(LED_PIN, LEDC_START_DUTY, LEDC_TARGET_DUTY, LEDC_FADE_TIME);
  Serial.println("LED Fade on started.");

  // Wait for fade to end
  delay(LEDC_FADE_TIME);

  // Setup and start fade off led and use ISR (duty from 4095 to 0)
  ledcFadeWithInterrupt(LED_PIN, LEDC_TARGET_DUTY, LEDC_START_DUTY, LEDC_FADE_TIME, LED_FADE_ISR);
  Serial.println("LED Fade off started.");
}

void loop() {
  // Check if fade_ended flag was set to true in ISR
  if (fade_ended) {
    Serial.println("LED fade ended");
    fade_ended = false;

    // Check what fade should be started next
    if (fade_in) {
      ledcFadeWithInterrupt(LED_PIN, LEDC_START_DUTY, LEDC_TARGET_DUTY, LEDC_FADE_TIME, LED_FADE_ISR);
      Serial.println("LED Fade in started.");
      fade_in = false;
    } else {
      ledcFadeWithInterrupt(LED_PIN, LEDC_TARGET_DUTY, LEDC_START_DUTY, LEDC_FADE_TIME, LED_FADE_ISR);
      Serial.println("LED Fade out started.");
      fade_in = true;
    }
  }
}

Вот этот код из примера компилируется.

Но в Serial не успевает ни чего вывести. Контроллер перегружается постоянно.

если бездумно не менять этот параметр, а воспользоваться калькулятором, то всё работает правильно )))

Можно подробнее?

LEDC_BASE_FREQ нельзя задать 50 Гц?

Но для моторов нужна частота именно 50 Гц

Громкий крик “выпиющего” …и пустыни тут у меня есть, правда далеко, больше 100 км.

Какого хрена люди идут на форум к живым собеседникам с подобной хернёй? Добрые заокеанские и даже некоторые российские дядечки сжигают мегаватты электричества в датацентрах и запускают там Большие Языковые Модели! У многих из них можно получить подробнейшие ответы на подобные вопросы совершенно задарма.
Так какого же хрена спрашивать подобное? Для вопроса о параметрах ШИМ и совместимости библиотек реально нужен живой человек? Для чего?
Живые люди хотят спокойно рилсы смотреть, с котиками и сиськами, а не вот это вот всё!

Вопрос на засыпку - пример из библиотеки, как он есть ( то есть с тем значением ШИМ, что задано в примере) - работает?
Если пример с базовой частотой работает, а с 50 Гц нет - значит менять на 50 Гц нельзя.

поищи на форуме, я выкладывал расчеты по всем частотам

исправь, я не жадный:

// use 12 bit precision for LEDC timer

#define LEDC_TIMER_12_BIT 16

// use 5000 Hz as a LEDC base frequency

#define LEDC_BASE_FREQ 50

На ESP32 все функции связанные с ledc работают аппаратно, не используя CPU. Это так потому, что в ESP32 есть специальный блок, называется LED Controller, который делает все сам.

Библиотека, еще одна, вам не нужна. Она уже у вас есть, называется Arduino Core.

Порядок действий в Arduino такой (включить\выключить):

// Выключаем LEDC на пине. Включаем пин в режим "Simple GPIO, OUTPUT"
  pinMode(pin, OUTPUT);
  if (ledcAttach(pin, frequency, resolution)) {
      if (ledcWrite(pin, duty_abs)) {   // <-- установка DUTY вручную

или

// Выключаем LEDC на пине. Включаем пин в режим "Simple GPIO, OUTPUT"
pinMode(pin, OUTPUT);

// Если частота ненулевая  
  if (freq) {
    // Если приаттачился пин
    if (ledcAttach(pin, freq, resolution)) {
      // Если запустился Fade
      if (ledcFade(pin, start_duty, target_duty, max_fade_time_ms)) {
          // Ура, получилось!
      }
    }
   }

Более сложную логику можно городить, если использовать

bool ledcFadeWithInterrupt(uint8_t pin, uint32_t start_duty, uint32_t target_duty, int max_fade_time_ms, void (*userFunc)(void));```

Если частота у вас одинаковая везде, то вам доступно от 8 до 16 каналов (в зависимости от проца).

Если вам нужна разная частота , то вместо ledcAttach надо использовать ledcAttachChannel(), в котором нужно вручную указывать ledc channel. Это номер, от 0 до 7 или от 0 до 15. У соседних каналов не может быть разная частота: каналы 0 и 1 работают на одной частоте, так же, как каналы 2 и 3, или 6 и 7.

Параметр resolution оставьте равным 10: это даст и плавный fade и не даст сильных ограничени по частоте (чем выше частота LEDC тем меньшее разрешение можно использовать для DUTY.) Значение 10 это 1024 градаций DUTY

Покажите настройки проекта в Arduino IDE. Скорее всего неправильно указан размер флешки.

Перезагружается у вас все потому, что Task Watchdog перезагружает систему.

Можете временно заткнуть этот watchdog, чтобы посмотреть, загрузится ли:

esp_task_wdt_deinit();

Но скорее всего не загрузится. Я не вижу debug сообщений дальше bootloaderа, а это означает, что скетч даже не стартанул. Загрузчик облажался. Такое бывает если параметры проекта не соответствуют реальному железу

я не смотрел его скетч внимательно, но была зависимость частоты от разрешения
09:38:43.226 → E (12) ledc: requested frequency 50 and duty resolution 8 can not be achieved, try reducing freq_hz or duty_resolution. div_param=0

Я , честно говоря, уже дано не задаю резолюшн вручную, я делаю так:

if ((resolution = ledc_find_suitable_duty_resolution(ledc_clock, freq)) != 0) {
  // Ура, нашли разрешение соответствующее нашей частоте.
}

Странно это все. На 50 Hz должно работать 8 бит (пины 2 и 4 соединены перемычкой):slight_smile:

Я, впрочем, выбираю 14 бит

esp32#>pwm 2 50

% Selected duty cycle resolution is 14 bits, LEDC channel is 0

[91383621][E][esp32-hal-ledc.c:463] ledcDetach(): pin 2 is not attached to LEDC
[91383621][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type GPIO (1) successfully set to 0x420c69e0
[91383622][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 2 successfully set to type GPIO (1) with bus 0x3
[91383622][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type LEDC (9) successfully set to 0x42014ecc
[91383623][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 2 successfully set to type INIT (0) with bus 0x0
[91383623][D][esp32-hal-ledc.c:53] find_matching_timer(): Searching for timer with freq=50, resolution=14
[91383624][D][esp32-hal-ledc.c:69] find_matching_timer(): No matching timer found for freq=50, resolution=14
[91383624][D][esp32-hal-ledc.c:97] find_free_timer(): Found free timer 0
[91383624][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 2 successfully set to type LEDC (9) with bus 0x3fcec374
[91383625][I][esp32-hal-ledc.c:288] ledcAttachChannel(): LEDC attached to pin 2 (channel 0, resolution 14)

% PWM on pin#2, 50 Hz (50% duty cycle, channel#0) is enabled

esp32#>
esp32#>count 4

% ⌚ Counting pulses on GPIO4...(press <Enter> to abort)
% 50 pulses in approx. 1000 ms (49 Hz, 0 IRQs)

esp32#>

Я тут с LittleFS подвис, пока разобрался, что IDE 2.3.6 лезло в CORE ESP8266 и оттуда брало программу для загрузки, ну а там естественно была, что с ограничением на длину имени файла в 32 знака (с расширением) )))

Кстати, перечитывая свою тему наткнулся на список частот, обязан был твой скетч работать при 12 бит разрешении, а я тут на тебя наехал )))

Но esp32 об этом не знает. Вернул частоту 50к. Так же происходит перезагрузка. Нужно попробовать на другом МК.

там 5 к было, не суть, я попробовал и на просто ESP32 и на ESP32S3 не перезагружается

У вас до загрузки даже не доходит дело. Виснет где-то в районе бутлоадера. Попробуйте стереть весь флеш перед прошивкой.

Проверьте размер флеша в настройках Arduino IDE:

Ну и поставьте Core Debug Level => Verbose. Если ваш скетч начнет загружаться - вы увидите текст на экране.