Ви не увійшли.
Проблема з кольоровим OSD в тому, що на відміну від монохромного потрібно модулювати піднесучу кольору. Це робить апаратне рішення складнішим.
Ось є проект з розбором варіантів: https://wekaosd.home.blog (англійською).
IDE 2.x.x зберігає останні налаштування в "arduino-ide/Local Storage/leveldb/*.log" у своєму бінарному форматі.
В лінуксі ця директорія в ~/.config/
У віндовсі не знаю, мабуть у C:\Users\{username}\AppDataRoaming
Так, якщо я скопіюю ino в новий файл, то менІ потрібно в ArduinoIDE заново виставити в цьому проекті деякі параметри.
Так це не для кожного проекту окремо, це глобальні налаштування.
може є більш елегантні і до того ж безшумні рішення?
Будь-яка мікросхема-комутатор аналогового сигналу з полосою пропускання від 6.5 МГц. Це якщо з відеокамер іде композитний сигнал.
Можна і на дискретних транзисторах зробити.
Думаю точність до 50 мікросекунд буде допустима.
Враховуючи точність внутрішнього осцилятора в 10% навіть з абсолютно точним алгоритмом для 1800 мкс похибка вже може бути до 180 мкс.
Навіть не знаю як це можна зробити без pulseIn().
pulseIn() - всього лише функція бібліотеки ардуіно для вимірювання часу. А час можна вимірювати різними способами.
Здавалося б така проста задача, яка одразу в всіх працює в відеоуроках з ютубу. А на практиці не все так просто...
У відеоуроках же мабуть оригінальну ардуінівську бібліотеку використовують. А для attiny13 сторонній пекедж зі своєю бібліотекою. Хто знає, як її тестували, на якому залізі, і чи тестували взагалі. Якщо і оригінальній далеко до ідеалу, то що вже казати про сторонні.
Не зовсім зрозумів про ліміти. А таймаут на очікування початку імпульсів я ставив 25 мікросекунд. В функції pulseIn() це значення було "25000" як третій аргумент.
Один таймаут - це ліміт на час очікування початку імпульса. А можливий і такий сценарій, що імпульс почався, але залишився активним на невизначений період. У прикладі нижче при такому сценарії сигнал на виході просто залишається високим.
Один із можливих варіантів реалізації:
#include <avr/io.h>
#include <avr/power.h>
#define PIN_INPUT 3
#define PIN_OUTPUT 0
// Таймер буде налаштовано так, що переповнення відбуватиметься
// з частотою 100 кГц; один тік - 10 мкс
#define TICK_US 10
// макрос US2T() конвертує мікросекунди в тіки
#define US2T(us) ((us - 1) / TICK_US + 1)
// wait_for() очікує поки вхідний пін не опиниться в заданому стані
// повертає 1 якщо пін опинився в заданому стані
// 0 якщо сплив час очікування
// timeout задається в тіках таймера; має бути більше 0
static uint8_t wait_for(uint8_t state, uint16_t timeout)
{
TCNT0 = 0; // обнуляєм лічильник таймера
TIFR0 = _BV(OCF0A); // скидаєм флаг переповнення
TCCR0B = _BV(CS00); // запускаєм таймер з дільником 1
// чекаєм поки на вході не буде потрібний стан
// або не настане таймаут
while (((PINB & _BV(PIN_INPUT)) != 0) != state)
{
if (TIFR0 & _BV(OCF0A)) // переповнення таймера
{
TIFR0 = _BV(OCF0A); // скидаєм флаг переповнення
if (--timeout == 0) // час очікування сплив?
{ // так
TCCR0B = 0; // зупиняєм таймер
return 0;
} // ні - чекаєм далі
}
}
TCCR0B = 0; // зупиняєм таймер
return 1;
}
int main(void)
{
clock_prescale_set(clock_div_1); // вимикаєм дільник F_CPU
DDRB = _BV(PIN_OUTPUT);
// PORTB = _BV(PIN_INPUT); // внутрішня підтяжка на PIN_INPUT (якщо потрібно)
TCCR0A = _BV(WGM01); // режим CTC
OCR0A = F_CPU / (1000000ul / TICK_US) - 1; // частота переповнення таймера 100 кГц, цикл 10 мкс
for (;;)
{
// стан OFF
PORTB &= ~_BV(PIN_OUTPUT);
do {
// чекаєм на високий рівень на вході
while ((PINB & _BV(PIN_INPUT)) == 0);
// чекаєм на низький рівень на вході
// якщо високий рівень протримався довше 1800 мкс - перехід в стан ON
} while (wait_for(0, US2T(1800)));
// стан ON
PORTB |= _BV(PIN_OUTPUT);
do {
// чекаєм на низький рівень на вході
while ((PINB & _BV(PIN_INPUT)) != 0);
// чекаєм на високий рівень або таймаут 25 мс
// якщо імпульса нема довше 25 мс - перехід в стан OFF
if (!wait_for(1, US2T(25000))) {
break;
}
// чекаєм на низький рівень
// якщо високий рівень протримався більше 1200 мкс - залишаємось в стані ON
} while (!wait_for(0, US2T(1200)));
}
}
Це НЕ скетч ардуіно.
Компіляція:
avr-gcc -Wall -pedantic \
-Os -mmcu=attiny13a \
-DF_CPU=9600000ull \
-ffunction-sections -fdata-sections -flto \
-Wl,--gc-sections \
-o firmware.elf firmware.c
Прошивка:
avrdude -c usbasp -p t13a -U flash:w:firmware.elf:a
Замініть usbasp на свій програматор, якщо у вас інший.
всерівно чомусь нема ніякої реакції на PWM. Чіп аттіні прошиваю на 9.6МГц
Здається мені, вашу задачу простіше і надійніше вирішити без усяких кучерявих pulseIn(). Яка конкретно умова задачі? Із того, що зрозуміло з коду:
Якщо тривалість імпульсів більше 1800 мкс - видати на пін високий рівень.
Якщо менше 1200 мкс - видати низький рівень.
Яка необхідна точність?
Що має відбуватись, якщо імпульси перестали надходити? Який таймаут на очікування початку імпульса?
Що має відбуватись, якщо імпульс триває довше певного ліміта? Який цей ліміт?
На такий код видає помилку "'builtin_avr_cli' was not declared in this scope", хоча в коді написано саме "builtin_avr_cli();""
Якщо по-ардуінівськи, то
noInterrupts();
...
interrupts();
Або просто
cli();
...
sei();
Доречі, щодо MicroCore:
MicroCore/issues/30
MicroCore/issues/114
А який пекедж використовуєте для attiny13? MicroCore?
У них досить дивна реалізація pulseIn().
Коментар до значення що повертається:
// Convert the reading to microseconds.
return (width); // Multiply by 16
Але ж повертається просто кількість ітерацій.
Обчислення таймаута бере до уваги F_CPU, а значення що повертається - ні. Схоже, ця реалізація не розрахована на частоту, відмінну від 16 МГц.
До того ж цикл реалізований на C. Я би не покладався на те, що він завжди буде 16 тактів незалежно від версії та опцій оптимізації компілятора.
Ну і саме головне – незрозуміло чому на тестері сервомашинок чіп спрауьовує від значень 600 та 900 імпульсів, а з іншими пристроями вже не працює
Тут уже дивіться, чим відрізняється форма сигналів на піні при використанні тестера та "інших пристроїв". Осцилограф вам у поміч.
Чи є цьому якесь пояснення
Може бути декілька пояснень.
В першу чергу впевніться, що всі флаги препроцесора, компілятора і лінкера коректні. Як ви збираєте скетч, в IDE? Увімкніть "Show verbose output during compile" (чи як воно там в локалізованому варіанті) і покажіть вивод процесу збірки.
pulseIn() рахує, скільки ітерацій циклу встигає виконатись перед зміною стану піна. Звісно, при обробці переривання виконання циклу призупиняється і ітерації не рахуються. В ардуіно переривання по таймеру виникає кожні 64 * 256 = 16384 такта. Один і той же код обробника переривання на 16 МГц виконується в 1.7 рази швидше, ніж на 9.6 МГц.
В коментарі до pulseIn() пишуть:
This function performs better with short pulses in noInterrupt() context
Спробуйте вимкнути обробку переривань. Звісно, millis()/micros() в такому разі не будуть працювати правильно.
Також внутрішній RC-осциллятор без калібровки має нестабільність до 10%, на граничних значеннях це теж може впливати.
Доречі, вимкнути дільник частоти на 8 можна і програмно за допомогою clock_prescale_set(), без перешивання фʼюза.
і чи можна тепер заставити тіні працювати і з іншими пристроями окрім тестера сервомашинок?
Для точного виміру інтервалів часу я би не звʼязувався з бібліотеками ардуіно, а виміряв би таймером напряму.
Може через 54 хвилини і 37 секунд?
Щодо ефективних на малих навантаженнях перетворювачів, то існують мікросхеми, наприклад MAX17553, LTC3388, TPS6217x. Але в продажу в Україні бувають рідко. Мабуть, не користуються попитом.
Дивіться у бік тих, що застосовуються у всяких соляр-модулях, там люблять високі ККД при низьких струмах.
Але ніде немає інформації як всі ці речі ведуть себе на 20-30мА струму, всі тестують їх на пару ампер і т.п.
В даташіті на мікросхему, на якій зроблено перетворювач, дивитись графіки ККД (efficiency). Якщо нема PFM або інших методів підвищення ККД на малих навантаженнях, то буде просто низький ККД. Можливо навіть нижчий ніж у лінійного стабілізатора.
Усі куплялись однакові одною партією (в одному тубусі і послідовним серійним номером).
Тобто всі чотири транзистори однакові? Звісно, тоді не буде працювати. Подивіться на схему: в нижньому плечі Q2 і Q4 - IRF540N, це N-канальні. А у верхньому Q1 і Q3 - IRF9540N, їх P-канальні комплементарні пари.
Передивився декілька роликів та статів. Визначив що у мене N-канального типу. У всіх при тестуванні однакова інформація при відкритому ключі(подачі + на затвор) протікання відбувається із стоку->витік,
При подачі + на затвор відносно чого?
Мосфет у відкритому стані проводить в обидві сторони. У закритому стані, якщо закоротити затвор з витоком, N-канальний через вбудований діод проводить з витоку в сток. P-канальний у закритому стані проводить зі стоку у виток.
N-канальний відкривається додатньою напругою на затворі відносно витоку.
P-канальний відкривається відʼємною напругою на затворі відносно витоку.
В мостовій схемі використовуються обидва типи: P-канальні у верхньому плечі, N-канальні - у нижньому.
Можна зробити міст і на транзисторах з однаковим типом провідності, але тоді одна пара буде включена по схемі повторювачів напруги, що знизить ефективність.
Потрібно запитати 4 сервомотори.
Розрахунковий струм навантаження який?
Можу вибрати або 6 АА, або 8 ААА. Думаю або АА лужні або ААА NiMH.
Навіть не принципово, чи одноразові елементи живлення, чи перезаряджаємі?
NiMH аккуми трохи більший струм зможуть віддати. Але можуть стати теж одноразовими)
Регулятор напруги UBEC 3А 5В Vin:5.5V-26V.
Нахіба сервомотору регулятор? Знизити струм елементів живлення? Чи не краще взяти 4 лужні елементи C або D (6В) і без регулятора?
На англомовному форумі є повідомлення з описом таких же симптомів. Але там виявилось, що проблема тільки з одним конкретним екземпляром.
Пункти 2,2 та 2,4 перші 5 секунд стабільно 6,7В. Далі із-за швидкого нагріву на цих затворах показує нестабільні 1,9В - 2,5В
У верхніх плечах (Q1 і Q3) у вас точно P-канальні IRF9540N, а не N-канальні IRF540N?
АЦП не работает. По всем трём каналам выдаёт максимальное значение 1023( или 4095).
А скільки подаєте, на який пін, за якою схемою? Як читаєте?
не працює.
1. Без подачі напруги на A1, A2, B1, B2 заміряйте напругу на затворах транзисторів (тут і скрізь далі - відносно PWR_N). Має бути:
1.1. На затворах Q1 і Q3: 22 В
1.2. На затворах Q2 і Q4: 0 В
2.1. Подайте 5 В на A1. На затворі Q1 напруга має стати біля 15 В, на решті не змінитись.
2.2. Зніміть 5 В з A1 і подайте на A2. На затворі Q2 має стати біля 7 В.
2.3. Зніміть з A2 і подайте на B1. На затворі Q3 має стати 15 В.
2.4. Зніміть з B1 і подайте на B2. На затворі Q4 має стати 7 В.
Зніміть 5 В з B2.
Якщо все так, тоді наступний крок.
3.1. Підключіть резистор (будь-який 10-1000 кОм) між M+ і PWR_N. На M+ має бути 0.
3.2. Подайте 5 В на A1. На M+ має стати 22 В.
Зніміть 5 В з A1.
3.3. Підключіть цей резистор між M+ і PWR_P. На M+ має бути 22 В.
3.4. Подайте 5 В на A2. На M+ має стати 0 В.
Зніміть 5 В з A2.
3.5. Підключіть резистор між M- і PWR_N. На M- має бути 0.
3.6. Подайте 5 В на B1. На M- має стати 22 В.
Зніміть 5 В з B1.
3.7. Підключіть резистор між M- і PWR_P. На M- має бути 22 В.
3.8. Подайте 5 В на B2. На M- має стати 0 В.
Зніміть 5 В з B2 і відключіть резистор.
Якщо все так, тоді треба ще подумати.
Першу секунду після вивантаження коду через серійний монітор видає відстань,
Завжди рівно секунду чи може бути різний проміжок часу перед збоєм?
але потім починає спамити різними символами.
Якими символами? Як саме це виглядає?
На якій платі запускаєте?
void setup() { Serial.begin(115200);
Спробуйте зменшити бітрейт порта (і в Serial Monitor відповідно).
if (measure.RangeStatus != 4) { Serial.print("Відстань (мм): "); Serial.println(measure.RangeMilliMeter);
Тут бажано перевіряти measure.RangeStatus на VL53L0X_ERROR_NONE. Якщо статус не VL53L0X_ERROR_NONE, то вивести статус, наприклад, за допомогою printRangeStatus().
обмежити швидкість зміни керуючого сигнала з потенціометра
Доречі, можна спробувати обійтись і чисто хардварним рішенням - RC-ланцюжок після потенціометрів перед АЦП. Можна додати ще діод, щоб зміна "вниз" відбувалась швидше.
А зрозумів, частота аналізу виходить 300 гц.
300 Гц має бути теж цілком достатньо, період в 30 разів коротше постійної часу.
Наприклад коли відбувається розгін, то двигун теж працює на цих же 23 амперах, але це відбувається плавно, просто лампочка на момент притухає і все.
Тобто обмежити не тільки струм, а і швидкість зростання струму. І при цьому не погіршити характеристику регулятора обертів. Майже взаємовиключні вимоги.
Чи не простіше обмежити швидкість зміни керуючого сигнала з потенціометра? Якщо показання з потенціометра збільшились, на вхід регулятора подавати не повне значення одразу, а збільшувати його поступово. По суті ФНЧ. Знайти максимальний коефіцієнт, при якому просадка ще допустима, і раз на період множити на нього початкове значення від потенціометра, поки воно не досягне кінцевого значення. Якщо там значення від 0 до 4096, частота оновлення 300 Гц, а час зміни порядку секунд, то коефіцієнт буде нецілим числом зовсім трохи більше одиниці. Але арифметикою з нерухомою крапкою це реалізувати нескладно.
АЦП працює в чотирьох канальному режимі, з частотою 9мГц і DMA, в сумі виходить що кожен канал працює на частоті трохи більше ніж 2мгц, думаю цієї частоти опитування достатньо.
Я маю на увазі не частоту роботи самого АЦП, а частоту аналізу отриманного значення програмою.
Думаю що програмне опитування не працює тому, що в момент коли робиться вибірка, амплітуда сигналу на вході АЦП вже йде на спад, із за невеликої ємності конденсатора (100мкф) після діодного мосту. Вирішить це можна збільшенням ємності, але тоді втратиться швидкість реакції.
Постійна часу там - 100 мкФ * 1 кОм = 100 мс. Навіть при зникненні струму до нуля, через 1 мс (при частоті опитування 1 кГц) напруга зменшиться всього на 1%.
Виходить що двигун працює зі струмом в 5А -> змінюю оберти, відбувається різкий стрибок струму з 5А до 23А -> спрацьовує ватчдог -> струм зменшився -> знову працює регулятор з 5А. Якщо в цей момент дивитись на лампочку, то виглядає так, ніби хтось швидко клацає перемикач що вимикає світло.
Якщо при 23А лампочка моргає, то вже непорядок з проводкою. Або з лампочкою Тоді вибачте, не розумію проблему ще більше. Ви хочете обмежити швидкість обмеження струму?
пробував зчитувати струм просто з АЦП, і перевіряти чи перевищує він встановлений поріг, але добитись нормальної роботи не получилось, двигун стартував з більшим струмом ніж був встановлений поріг. З analog watchdog такого нема.
Може була недостатня частота опитування АЦП? Інших варіантів, чому би з ватчдогом працювало, а з програмним опитуванням ні, не бачу.
dimich пише:А компоненти I і D у регулятора скидаєте в 0 при його повторному увімкненні?
Ні, при повторному увімкнені регулятора удару струму немає, як і удару після розгону. Удар струму відбувається при зміні обертів змінним резистором в процесі роботи регулятора.
Тоді не дуже зрозумів, чим не влаштував варіант з обмеженням струму і підчас роботи регулятора. Змінили оберти -> струм підвищився, перевищив поріг -> спрацював ватчдог -> обмежив струм. Струм зменшився -> перемкнулись на регулятор.
Щоб запобігти занадто частим перемиканням, на регулятор перемикатись через деякий мінімальний проміжок часу та/або після зниження струму до значення трохи меншого, ніж поріг спрацювання (гістерезис).
Схематично все зроблено так.
Ага, зчитується усереднений піковий струм, що є усереднена пікова повна потужність розділити на напругу. Постійне обмеження по цьому значенню буде еквівалентне використанню двигуна меншої потужності, хіба що потужному двигуну "легше" працювати без перевищення номінального струму.
коли при роботі PID регулятора струм перевищував 23А, то регулятор відмикався а замість нього знову починався розгін, а після розгону знову вмикався PID
Тобто перевищення струму при розгоні реєструється тільки по перевищенню порового значення (analog watchdog)? А компоненти I і D у регулятора скидаєте в 0 при його повторному увімкненні? Різкий удар струму може і відбуватись через накопичену інтегральну компоненту.
Нетривіальна задачка. Для детального аналізу було би цікаво подивитись графіки зміни компонент PID, виміряного струму і вихідного значення регулятора при зміні режимів. Але це, мабуть, вже занадто.
А якщо двигун буде обертатися зі струмом більше 10А, то з виходу PID регулятора буде відніматися струм.
По суті це те, що і було запропоновано вище. Обмеження струму не є задачею PID-регулятора обертів, цим має займатись ще один окремий регулятор. В якому вигляді його оптимально реалізувати: пороговий вимикач чи пропорційний регулятор - це інше питання.
Було би корисно для розуміння намалювати повну блок-схему регулювання з усіма зворотніми звʼязками. На вході: задані оберти, наявні оберти, виміряний струм; на виході - час вмикання тиристорів відносно напівперіоду (фаза).
А як реалізовано вимір струму? Є якась пост-обробка після АЦП? Зауважте, якщо струм вимірюється без врахування фази відносно напруги, то це вимір повної потужності, а просадка відбувається в основному через активну складову. Хоча з фазовим методом можуть бути нюанси.