Ви не увійшли.
До речі, а що взагалі не так з тою лібою servo з професійної точки зору? Всередині наче нормально, підтримується купа процесорів. Якщо робити руками - вийде таке саме.
Ну я так розумію там відтворюється якийсь проект від Алекса Гувера. Краще тоді з мінімальними змінами. У нього, судячи з каментів в коді, теж на 8 мгц щось не так.
Та там не зрозуміло, які коментарі від Гувера, а які вже від автора топіка. Якщо оригінальний код - це ось цей, то там ніякого Servo взагалі нема.
(А тут тема перейшла на нову сторінку, то того повідомлення з кодом вже не видно навіть в режимі редагування)
Ну я так розумію там відтворюється якийсь проект від Алекса Гувера. Краще тоді з мінімальними змінами. У нього, судячи з каментів в коді, теж на 8 мгц щось не так.
"56 кроків", 40% і т.д. влаштовує не дуже
Ну у вас декілька варіантів:
1. Розібратись, чому не працює зі "стандартною" Servo. Мені не вдалося відтворити ту поведінку, що ви описуєте: імпульси йдуть чітко з періодом 20 мс і очікуваною тривалістю. Значить, або ми запускаємо різний код (чи скомпільований з різними налаштуваннями), або не враховуєм якісь умови відтворення, або ви невірно описали поведінку.
Яка інформація потрібна для подальшого аналізу - вказано в попередніх повідомленнях.
2. Реалізовувати поетапно те ж саме, що робить Servo (апдейт OCR в обробнику переривання), і дивитись, на якому етапі перестає працювати. Тоді стане зрозуміло, і чому перестає, і чи можна це побороти.
3. Оптимізувати ваш варіант із відліком інтервалів по перериванню, а не по значенню TCNT. При грамотній реалізації обробник можна вмістити в декілька десятків тактів, на 8 мегагерцах де дасть роздільну здатність у порядка 200-300 кроків. Але у вас же там ще nRF24 планується, чи не так? Будуть ще переривання і затримки від SPI. Як воно із вашим кодом взаємно впливатиме - передбачити складно. Можливо, доведеться також оптимізувати і SPI.
4. Обрати іншу апаратну платформу, яка краще підходить для цієї задачі. Он пишуть, у ESP32 аж 16 апаратних jitter-free каналів PWM. Можливо, варто розглянути інший драйвер BLDC, який керується іншим способом. Якось не дуже раціонально перетворювати цифрове значення у сервоподібну PWM, яка потім драйвером перетворюється на іншу PWM вже для двигунів.
Зазвичай спочатку формулюється задача, аналізуються необхідні ресурси, вже потім обирається залізо для реалізації. А ви штучно створили собі обмеження і намагаєтесь їх героїчно подолати.
Ну ніт так ніт ![]()
Можна ще плату з lgt328 взяти - китайська ардуїна, краща за оригінальну ![]()
Ну можна в 16 мгц платі ldo перепаяти на 3.3в
Не можна. Для 16 МГц потрібно живлення не нижче 4.5 В. Див. Figure 28-1 на стр. 260 даташиту.
Ну можна в 16 мгц платі ldo перепаяти на 3.3в, 3 грн ціна питання.
Можна взяти stm32 blue pill , чи rp2040, чи esp32 - arduino сумісні, але мегагерців більше.
Можна взагалі ще один стабілізітор допаяти. І узгодження рівнів на резисторах, це буде швидше ніж вирішувати невідому проблему незрозумілими способами.
Ну якщо без велосипеда ніяк - винайдіть свою реалізацію servo. Це нескладно, таймер генерує interrupt, в кожному interrupt таймер перепрограмується на наступний інтервал часу, якщо на словах. і логічні рівні перемикати в залежності ві того який інтервал спрацював.
№18 По кварц не скажу, занадто дрібний
Там же Atmega328P в TQFP корпусі? Подивіться оцилом на XTAL2 (8-й пін).
але при переносі коду на плату 16 МГц частота подвоюється, відповідно встановлено 8 МГц...
При переносі скомпільованого коду чи при компіляції коду під 16 МГц плату?
Всі таймінги в одиницях часу (мілі- та мікросекунди) спираються на значення макроса F_CPU, що передається під час компіляції. Яке значення передається у вас?
Так що з вашим кодом, що з стандартною біліотекою Servo є проблеми з синхронізацією
Втретє кажу: виставте часовий масштаб, щоб було видно багато імпульсів. 100 мс на поділку, наприклад. І покажіть разом із сигналом від сервотестера.
№18 По кварц не скажу, занадто дрібний, але при переносі коду на плату 16 МГц частота подвоюється, відповідно встановлено 8 МГц...
Так що з вашим кодом, що з стандартною біліотекою Servo є проблеми з синхронізацією, якщо осцилограф поганий то проблеми з синхронізацією мали бути і при виконані мого коду...
"56 кроків", 40% і т.д. влаштовує не дуже, основний цикл виконується лише з частотою 30 Гц, занадто повільно, а ще 100% будуть доповнення...
№20 digitalwrite виконуються 8 раз за цикл, а 6 операторів "if" - 500 раз, багато виграю часу?
Сенс простий - напруга живлення 3,3 вольта, один стабілізатор і для Ардуіни, і для nRF24L01...
Можна, тільки я не програміст, а Ардуіну більшь-меньшь нормально знаю...
№21 Щось подібне вже почав писати, але прикладів з поясненнями нема, так що "Винайдення велосипеда"...
Або взяти чи зробити плату на якій воно точно працюватиме.
замість digitalwrite пишіть в регістр напряму. Можна на асемблері
Там можна після завершення останнього імпульса заряджати таймер одразу на початок наступного цикла. Бо майже 90% викликів ISR іде вхолосту. Зручніше це, мабуть, буде в режимі FastPWM замість CTC.
Або використати один компаратор для 20 мс циклу, а другий для відмірювання інтервалів дригання пінами.
І якщо піни обрати з однієї банки, то й виставляти їх одночасно однією інструкцією.
Непахане поле для оптимізації.
Не люблю ютуб-проекти.. 1 листок схеми займає 20 хвилин відео про тяжке життя
Це щось від Алекса Гувера? ![]()
Осцилограф - г%%но, стверджую як власник
Складно добитись синхронізації, але таки спробуйте. Hold натисніть.
Може щось з частотами - це можливо якщо в налаштуваннях Arduino IDE вибрати трохи не ту плату - за що я його не люблю. В Platformio є спосіб вказати частоту резонатора. F_OSC при компіляції чому у вас дорівнює?
Якщо ваш варіант з 40% ресурсу влаштовує - саме час тактоложества; замість digitalwrite пишіть в регістр напряму. Можна на асемблері ![]()
Можна також припустити що у вас щось не те з платою чи резонатором на ній. Є інший екземпляр? Взагалі не бачу смислу упарюватись саме в pro mini. Є 100500 контроллерів, і швидших, і дешевших.
При спробі завантажити код виходить якась ху.....
А, побачив пости з кодом при редагуванні повідомлення. Не відображається, бо там в коментарях посилання на ютуб.
Те що генерує ваша
Ваш код
Код, що я запостив, на початку setup() понижує тактову частоту вдвічі, щоб на 16-мегагерцовій платі працювало як на 8-мегагерцовій. Тому коли запускаєте на 8-мегагерцовій, інтервали будуть збільшені вдвічі. А по суті це те ж саме що "Стандартна Servo".
Але на фото масштаб 20 мс/, між імпульсами виходить 80 мс, тобто збільшені в 4 рази чомусь.
У вас там часом не 4 МГц резонатор? Чи може не ту частоту обираєте при збірці?
Чим взагалі збираєте? Покажіть, які опції передаються компілятору.
А так, на фото інтервали-то рівні. На відео - таке враження, що осцил просто не може засинхронізуватись. Зменшіть часовий масштаб, щоб з десяток імпульсів було видно.
Стандартна Servo
Знову ж таки, осцил не синхронізується.
Таке враження, що імпульси від ардуіни йдуть з набагато меншою частотою ніж від сервотестера.
Покажіть у меншому масштабі.
Моя, сжера 40% ресурсу
частота виклику 25 кГц...
Тобто гранулярність 40 мкс. Для діапазона 160-2400 мкс виходть 56 кроків. Якщо цього достатньо, то чому б і ні?
Прожерливий код який формує суму стабільну осцилограму - частота виклику 25 кГц...
ISR(TIMER1_COMPA_vect)
{
Time = Time+1;
if (Time==1) {
// Высокий уровень выставляется на всех выходах одновременно
digitalWrite(2, HIGH); // Установка на выводе 2 высокого уровня, начало формирования импульса
digitalWrite(4, HIGH); // Установка на выводе 4 высокого уровня, начало формирования импульса
digitalWrite(7, HIGH); // Установка на выводе 7 высокого уровня, начало формирования импульса
digitalWrite(8, HIGH); // Установка на выводе 8 высокого уровня, начало формирования импульса
}
// Низкий уровень выставляется для каждого вывода индивидуально в зависимости от величины управляющего сигнала
if (Time==PD_2) {digitalWrite(2, LOW);} // Установка на выводе 2 низкого уровня, конец формирования импульса
if (Time==PD_4) {digitalWrite(4, LOW);} // Установка на выводе 4 низкого уровня, конец формирования импульса
if (Time==PD_7) {digitalWrite(7, LOW);} // Установка на выводе 7 низкого уровня, конец формирования импульса
if (Time==PB_0) {digitalWrite(8, LOW);} // Установка на выводе 8 низкого уровня, конец формирования импульса
if (Time==500) {
Time = 0; // Формирование паузы и обнуление переменой Time
}
}