Ви не увійшли.
По перше, енкодер хоч і оптичний, але тригерів Шмідта всередині немає.
Тригери Шмітта є на GPIO пінах атмеги. Гістерезис десь 100 мВ при 5 В Vcc.
Для компенсації кривих фронтів є таке рішення
При правильній реалізації ніякої "компенсації кривих фронтів" не потрібно.
Ось приклад для 4-квадрантного енкодера, конечний автомат - LUT з 32 елементів:
class encoder
{
uint8_t state { 0 };
static inline const uint8_t table[] = {
// in: ab aB Ab AB
0b000'01, 0b001'01, 0b010'01, 0b011'01, // 000 ab
0b000'01, 0b001'01, 0b010'01, 0b110'01, // 001 aB
0b000'01, 0b001'01, 0b010'01, 0b111'01, // 010 Ab
0b000'01, 0b001'01, 0b010'01, 0b011'01, // 011 AB
0b000'00, 0b001'01, 0b100'01, 0b110'01, // 100 Ab_b
0b000'10, 0b101'01, 0b010'01, 0b111'01, // 101 aB_a
0b000'01, 0b001'01, 0b100'01, 0b110'01, // 110 AB_b
0b000'01, 0b101'01, 0b010'01, 0b111'01, // 111 AB_a
};
public:
int8_t update(uint8_t in)
{
uint8_t act = table[state | in];
state = act & 0b111'00;
return 1 - (act & 0b000'11);
}
};На вході update() два молодших біта - стани ліній A та B. На виході: -1, 0 або +1.
Лічильник клацає по фронту і спаду кожної фази, тобто в 4 рази швидше - це треба врахувати.
t = 1 / (rpm_max * 60 * ppr * 4)
Це дасть мінімальний час між фронтами. А там уже дивіться, чи забезпечить потрібний таймінг та чи інша реалізація.
Всі зовнішні interrupts, доступні для Atmega328, зайняті.
Не до будь-якої ноги можна підключити енкодер.
У атмеги є Pin Change Interrupt на всі GPIO ноги.
У деяких інших контролерів (STM32, CH32) у таймера-лічильника є спеціальний режим для енкодера.
Колись давно я записав на Arduino Uno r3 keyestudio скетч, щоб цю ардуінку визначало як клавіатуру
Записували ж мабуть у допоміжну atmega16u, яка виконувала функцію USB-UART адаптера. Тепер вона вже не адаптер, а інший пристрій.
Що саме і як ви туди записували?
Прошити скетч у "центральну" атмегу можна декількома способами.
Як уже зазначили, можна підключити ISP-програматор і прошивати.
Якщо у "центральної" атмеги звичайний бутлоадер, що з працює по UART, і є доступ до його пінів RX/TX, то можна підключити до них зовнішній USB-UART адаптер і прошивати.
Гадаю, можна підключитись ISP-програматором і до тієї допоміжної атмеги, і залити туди оригінальну прошивку USB-UART адаптера "як було". А може на ній вже є якийсь свій бутлоадер, який активується сигналами на пінах. Потрібно знати, що там було, і що ви туди залили.
Всередині контроллера - схема на компараторі; на одному вході пилообразна напруга, на іншому - напруга з потенціометра; просто і безхитрісно.
Цікаво. Ну хоч не на 555 таймері ![]()
І само собою, захотілось прикрутити замість потенціометра ардуїнку
Чи не простіше взагалі відімкнути той генератор пили з компаратором, а мостом керувати з ардуінки напряму?
2 канала - 24 вольта петля(пасив) і 4_20ма до 200мв прямий(актив)
Щось не дуже прояснили. Вам трансміттер для струмової петлі потрібен?
XTR117 (і загалом 4-20mA signal conditioners).
AD693
Можна і на дискретних компонентах: операційник, транзистор, кілька резисторів.
Loop-Powered 4mA to 20mA Transmitter Circuit
Convert 1V to 5V Signal to 4mA to 20mA Output
Introduction to 4-20mA Current Loop Transmitters cтр.14
oled -3 key-щоб бачити що виходить
Передавач окремо, джерело сигналу окремо. Якщо аналоговий потрібен, то з ардуіни його потрібно чимось формувати. Це або зовнішній DAC, або ШІМ. Якщо дискретний, mark/space/idle - можна двома GPIO пінами обійтись (навіть одним, якщо дуже треба).
Потрібен Задатчик тока 4-20ma на ардуіно
Хтось таке робив?
Робив, тільки без ардуіно. LM317 - 1 шт, резистор на 62 Ом - 1 шт, потенціометр 270 Ом - 1 шт.
Чи вам треба з електронним керуванням? Який діапазон вихідної напруги?
Не тримає температуру , пригає на 5-10 градусів.
Як саме пригає?
Виведіть та збережіть діагностику: Input, Output та Setpoint для того канала, який налаштовуєте. Покажіть її тут. Бажано побудувати графік - по ньому буде видно, що там відбувається.
Якщо утворюються автоколивання, то або перерегуляція - завеликі коефіцієнти P або I, або недостатнє демпферування - замалий коефіцієнт D. Ще може бути завеликий період циклу, але у вас 250 мс - для нагрівача має бути ок.
Я так поняв проблема в PID коефіціентах.Вже 6 годин махаюсь і поки ніяк
У вас, наскільки бачу, коефіцієнти прямо в скетчі захардкоджені? І кожний раз перезбираєте і прошиваєте? Звісно, так підбирати - велика морока.
Перепишіть скетч, щоб задавати коефіцієнти з компа. Тоді підбирайте класичними методами.
Оффтопік порада.
if(Time>TimePidWork+250){- ніколи не порівнюйте беззнакові таймпоінти без врахування переповнення типів. Або порівнюйте беззнакові тривалості, або зберігайте таймпоінти як числа зі знаком. Але коректне перетворення беззнакових типів у знакові в C++ не зовсім тривіальне, так що краще просто порівнюйте тривалість від початкового таймпоінта до поточного із константою.
Звісно, в цьому конкретному випадку це не критичний баг, але корисно мати звичку писати код без помилок.
А так?
Так уже краще. ChatGPT вчиться? ![]()
додати кондюк 0.1 мкФ на землю (A → GND)
З підтяжкою 10 кОм такий конденсатор утворюватиме ФНЧ з частотою зрізу 160 Гц. А з вбудованою - десь 60-70 Гц. На 300 об/хв може ще не впливатиме, але якщо більше - вже не годиться.
Щоб позбутись "брудних" фронтів (якщо вони там дійсно є і заважають), можна просто рахувати по обом фронтам фази A скільки раз фаза B змінила значення на протилежне від попереднього.
либа от Paul Stoffregen
нюанс-либа рахує x4-10 P/R → 40 імпульсів/оберт
То вже якесь збочення.
Тобто варто взяти 32 розрядний проц - і можна за атомарність не паритись?
Якщо атомарність доступа до слова цієї розрядності гарантується апаратно, то для одиничного запису чи читання - так, можна не паритись. Лише впевнитись, що змінна розміщується з необхідним вирівнюванням (зазвичай це також гарантується). Але на деяких архітектурах може довестись паритись із реордерінгом інструкцій та memory барʼєрами, а іноді і з інвалідацією кеша ![]()
А при read/modify/write все одно потрібна синхронізація.
В цьому скетчі вже баги.
1. 16-бітна змінна pulses змінюється в ISR, а читається неатомарно.
2.
if (pulses != last) {
...
Serial.println(pulses);
last = pulses;Тут race condition. При всіх трьох зчитуваннях pulses може мати три різні значення.
Можливо, проблема саме в цьому енкодері?
Можливо. Але дуже малоймовірно. Також можливо, що проблема десь у зʼєднаннях, платі чи контролері. Це теж малоймовірно.
Майже впевнений, що проблема в коді, а коду ми не бачили.
Напишіть програму, що пише стан входів у Serial. Повільно обертайте енкодер і перевірте, чи бачите очікуваний квадратурний сигнал.
Якщо все ок, напишіть мінімальну програму, яка обчислює швидкість обертів і видає результат в Serial. Якщо працює не так як очікується, то показуйте код.
Мені потрібне точне регулювання обертів
Точне - це яке в цифрах?
При інтервалі в 1 секунду з PPR 10 точність виміру не перевищуватиме 5-6 об/хв. При 30 об/хв це 20%.
А точність регулювання, навіть при ідеально підібраних коефіцієнтах PID, залежатиме як від точності виміру, так і від властивостей керованої системи: потужності двигуна, характеристики навантаження.
Ви можете лише визначити, що відхилення поточної швидкості від цільової перевищує заданий поріг.
а 2000 обертів у автора atmega не потягнула.
Не дивно, з енкодером на 2000 PPR. Якщо іншого нема, а треба оберти в секунду при обертанні в один бік на такій швидкості, то можна тільки фазу Z читати. Тоді 1 PPR виходить, можна рахувати хоч мільйон об/хв.
А ще у атмеги є input capture, якщо програмної швидкодії недостатньо.
https://forum.arduino.ua/img/members/3885/Omron-E6B2_CWZ6C.zip
В цій імплементації зміна стану відбувається лише по одному фронту однієї фази. Такий метод в більшості випадків нормально працює при постійному обертанні вала. Але на граничних умовах - наприклад, покачування вала в обидва боки - будуть хибні спрацювання.
Повноцінний конечний автомат квадратурного енкодера виглядає десь так:
що досить просто реалізується за допомогою таблиці переходів.
2. Енкодер на валу двигуна підраховує кількість імпульсів за заданий інтервал часу.
Який діапазон швидкостей обертання?
на один механічний оберт вала енкодера Omron E6B2-CWZ6C щоразу видає нове значення.
Енкодер не видає значення, енкодер видає сигнали. Як ви їх обробляєте?
Мені ідея з динамічним створенням об'єктів категорично не подобається.
Ми навіть не знаєм, як там той обʼєкт створюється. Код же не показали.
Я взагалі не розумію, навіщо бібліотека заради десятка рядків коду.
Тут і невикористані піни бажано конфігурувати в детермінований стан чи вимикати digital input. Це одна з перших речей, з якою знайомляться при навчанні програмуванню МК. Але культура ардуіно цього не виховує.
Немає жодних активних та пасивних елементів – є тільки кабелі. На малюнку зрізаний приклад з'єднань: А0 - А1 це приклад робочого ланцюга, в момент виміру ємності цей ланцюг розірваний перемикачем
Щось все одно не дуже ясно. Бачу три перемикачі 4P1T і один 2P1T. Але 4P мають ще одне положення, у якому повзунок "висить у повітрі"?
і вимір (у цьому випадку) виконується між А0 - А2 і А1 - А2
Тобто при такому положенні перемикачів як на малюнку:
вимір №1: outPin=A0, inPin=A2 (ємність між повзунками верхнього і нижнього перемикачів)
вимір №2: outPin=A1, inPin=A2 (ємність між провідником від A1, що йде до одного з контактів верхнього перемикача, і повзунком нижнього перемикача)
?
(другий кінець від А2, в момент виміру теж нікуди не підключений).
По малюнку він підключений до повзунка перемикача. Повзунок може мати помітний ємносний звʼязок з контактами, в залежності від конструкції.
І якщо замір першої пари відповідає, то на другій парі – рандом.
А якщо потім знову перша пара?
Після деструкції обʼєкта CapacitorLite перед створенням нового ви переводите outPin у його початковий стан - floating input?
Спробуйте перед аимірюванням перевести всі піни в output і вивести на них 0.
В конструкторі CapacitorLite вони уже переводяться в output з низьким рівнем. Але при створенні нового обʼєкта з іншим значенням outPin, попередній залишається в output. inPin, наскільки розумію, в даному випадку залишається тим же.
Автор стверджує, що при першому вимірі наче все ок, а після якихось там перекомутацій стає не ок. Спочатку треба зрозуміти, що там куди комутується, щоб пояснити таку поведінку. А потім уже можна думати, як позбутись небажаних ефектів.
[телепат mode on]
Якщо там залишається якась заряджена ємность, то розряджати примусово. Але якщо там паразитне живлення через діод всередині корпуса компонента, чи якісь інші напівпровідники, то такий метод виміру взагалі не працюватиме. Таку лінію потрібно вимірювати напругою до 100 мВ, як це робиться у внутрішньосхемних тестерах ємності. А якщо там якісь конденсатори MLCC, то у них мало того що ємність змінюється в кілька разів в залежності від напруги, так і ефект памʼяті може проявлятись.
[телепат mode off]
Взагалі, виглядає як проблема XY.
Вимірюється ємність того, що підключено до вивода на момент виміру. Це кабелі різних типів, які запитані тільки з плати, до якої підключені.
Покажіть схему, бо за словесним описом нічого не зрозуміло. І вкажіть, в якому порядку що комутується при вимірах.
Уточню ще той аспект, що в момент вимірювання кабель з одного боку підключений до виведення плати, а з іншого боку - висить у повітрі.
Якщо поряд з провідником є інші провідники, то звісно, і вони самі впливають на результат, і те, що до них підключене.
до платы, через перемикачи пiд'єднано багато кабелiв, рiзного типу (що мають рiзну ємкiсть). Плата надсилає мiкросикунднi 0 та считує цi iмпульси (при пiдтянутiй 1)
1-wire?
Показником сicтеми є ємкiсть у окремий вiдлiк часу.
Так ємність чого ви вимірюєте? Ємність шини, разом з пристроями, що з неї і живляться?
Але якщо цей блок з'єднань був задіяний в інших режимах роботи плати
Що за блок? З чого він складається, як підʼєднаний, що на нього подається в "інших режимах"?
Цей метод виміру ємності базується на тому факті, що напруга на конденсаторі прямо пропорційна заряду і обернено пропорційна його ємності. Так як послідовно зʼєднані конденсатори отримують однаковий заряд, то знаючи ємність одного можна обчислити ємність другого. В ролі конденсатора з відомою ємністю виступає розподілена ємність. Ніяких блоків у цьому методі не передбачено.
Менi потрiбна можливiсть приведення будьяких з'єднань до загального рiвня, незалежно вiд початкового стану к схемi.
Калібрування. Це ж було вже.
Як перед вимiром нівелювати різноспрямовані заряди ємностей, щоб отримати адекватний показник (пропорцiйний)?
Там перед вимірюванням обидва піни сконфігуровані на вихід з низьким рівнем. Заряд між піном і землею - нуль, між піном і живленням - напруга живлення, помножена на розподілену ємність ємність шини живлення, яку для джерела напруги можна вважати нескінченною. При перемиканні піна у високий рівень в будь-якому разі буде заряджатись як вимірювана ємність, так і розподілена.
Прошу тих, хто у темі, дати пояснення: які плюси має такий підхід?
Плюси: одночасний доступ до декількох бітів у межах однієї GPIO банки; на деяких контролерах можливіть атомарного toggle; зазвичай трохи швидше, трохи менше розмір коду.
Мінуси: не кросплатформно.
На скільки швидше виконується операція?
На якому контроллері, з яким фреймворком?
Реалізуйте обидва варіанти, заміряйте швидкість або проаналізуйте асемблерний код.
І чи варто взагалі використати такий підхід?
Іноді варто, іноді ні. Залежить від задачі.
Який є простий спосіб "скидання" всіляких зарядів до заданого виводу (виводам), щоб вимірювана величина ємності відповідала дійсності?
Щоб вимірювана величина відповідала дійсності, проводять калібровку, і враховують паразитні ємності при обчисленні актуального значення з виміряних величин.
Є декілька методів вимірювання ємності. Ви який збираєтесь використовувати?
https://forum.arduino.ua/img/members/4196/123.rar скетч
Це код, згенерований FLProg. Він не призначений для читання та редагування людиною. Змінювати потрібно в оригінальному .flp файлі, а не в генерованому проміжному коді.
А враховуючи географію розташування видавця того FLProg, сто раз подумайте, чи варто ним користуватись.
Звісно, якщо у когось багато вільного часу та натхнення, можна реверс-інженерити і розібратись, які змінні там за що відповідають. Але куди простіше написати таку ж функціональність з нуля.
посилання та скетч прикріпив
Це посилання на відео. Покажіть сам скетч, щоб не доводилось колупатись в якихось незрозумілих архівах на гугл драйв з корявим кодуванням імен файлів.