#1 Re: Апаратні питання » LCD 240*128 на RA6963 підключення до ESP32-C6 » Сьогодні 11:48:07

FlintBMF пише:

Здається, там була несправність, індуктивна котушка хиталась. Для відображення пікселів потрібно було щоб між Vdd та V0 було 19,5в
А в мене було не більше +11в.

Сподіваюсь, ви вірно визначити несправність. Про всяк випадок зверну увагу, що на виході Vee напруга відʼємна відносно Vdd (плюса живлення). Тобто на Vo має бути біля -19.5 В відносно плюса живлення (Vdd). Відповідно, відносно мінуса живлення (Vss) буде приблизно -12.5 В.

#2 Re: Апаратні питання » LCD 240*128 на RA6963 підключення до ESP32-C6 » 2025-10-29 19:50:09

У U8g2 як мінімум заявлена підтримка "T6963" (хоча він T6963C), а RA6963 має бути сумісний з T6963C. Так що показуйте вашу схему підключеня та код. Код бажано мінімальний, тільки ініціалізація та відображення пари байтів пікселів.

#3 Re: Проекти » Прошу допомоги!!! » 2025-10-28 15:18:58

Yurania пише:

Відображення картинки на дисплеї з sd карти,заміна файлів по таймеру.

По суті, три окремі підзадачі:
1. Читати файлову систему на SD-карті.
2. Виводити зображення на дисплей.
3. Програвати аудіо.

Вирішіть кожну з них окремо, потім обʼєднайте. Впевнений, є купа готових бібліотек для цих задач, з прикладами.

Yurania пише:

Якщо через плату DAC декодера інтерфейса I2S PCM5102A - чи можливо вивести звук на колонку?

З даташита:

Line Level Output Down to 1KΩ

Тобто у неї ліній вихід. Для відтворення на низькоомний динамік потрібен підсилювач потужності. Якщо це якийсь готовий модуль, то підсилювач там уже може бути, а може й ні.

Yurania пише:

І як завантажити МР3 файли?

Є два варіанта: або декодувати mp3 на самому MCU та видавати PCM по I2S на DAC, або використати апаратний mp3-декодер.

Yurania пише:

1-плата UNO R3 UNO UNO R3 CH340G + чіп MEGA328P 16 МГц для Arduino UNO R3

Реалізувати декодування jpeg та mp3 на атмезі буде доволі "проблематично" hmm Крім того, у атмеги нема апаратного I2S, а емулювати програмно - воно того не варте.

Yurania пише:

3-WTV020 GPD2846A Міні-модуль MP3-плеєра

Наскільки розумію, це самодостатній модуль, який програє фрагменти тільки зі "своєї" SD-карти. Якщо вас це влаштовує, то можна і його застосувати. Тоді ніякий DAC не потрібен. Але зображення тоді доведеться зберігаті на іншій SD-карті (яка в слоті дисплея, мабуть).

Yurania пише:

4-Плата DAC декодера інтерфейса I2S PCM5102A
Підкажіть чи правильний список комплектуючих?

Якщо у вас окремий самодостатній модуль mp3-плеєра, який тільки керується з MCU, тоді DAC не потрібен. А якщо відтворення звука з MCU, тоді не потрібен модуль mp3.

#4 Re: Проекти » Прошу допомоги!!! » 2025-10-28 09:41:19

Yurania пише:

Може підкажете що для цього потрібно?

Для початку - сформулювати вимоги до виробу. Які функції мають бути реалізовані, у якому вигляді? Ніколи не користувався фоторамками, тому надалі - лише здогадки.

1. Відображення картинки на дисплеї. Зображення буде прошите разом з ПЗ? Чи має завантажуватись із зовнішнього носія, наприклад, SD-карти? Чи має завантажуватись по Wi-Fi? Єдина картинка, чи декілька, які змінюються? Який критерій зміни: по таймеру, "вручну" користувачем?

2. Відтворення аудіо. Пищання мелодії біпером? Чи повноцінне аудіо? Як і для зображення, чи буде це єдиний прошитий фрагмент, чи з файла на зовнішньому носії, чи завантажуватись по Wi-Fi? Які формати файлів та кодеків мають підтримуватись? Які критерії початку/зупинки відтворення аудіо?

Відштовхуючись від вимог уже підбирати компоненти. Контролер - на ваш смак, аби були необхідні інтерфейси (які залежать від вимог). Мабуть же, у вигляді готового модуля. Особисто я спробував би реалізувати на ESP32.
Якщо зберігання файлів на SD-карті, то очевидно, знадобиться модуль SD-карти. Для повноцінного аудіо, можливо, знадобиться окремий I2S DAC. І динамік. Буде якийсь користувацький інтейфейс? Якщо так, то знадобляться або кнопки, або тачскрін.

#5 Re: Проекти » Прошу допомоги!!! » 2025-10-27 21:31:15

Yurania пише:

допомогти розібратись з технічими питаннями

Так в чому, власне, питання? Що саме і як не працює?

#6 Re: Проекти » Прошу допомоги!!! » 2025-10-27 18:13:47

Yurania пише:

Допоможіть з реалізацією

Уточніть, будь ласка: допомогти з реалізацією - це допомогти розібратись із якимись технічними питаннями, чи виконати проект або його частину за відповідну оплату?

#7 Re: Проекти » Кухонний комбайн на базі ардуїно. Потрібна допомога. » 2025-10-05 11:21:49

В логіку коду не вчитувався, бо він сумбурний і ледь структурований. Сумнівають, що воно навіть скомпілиться. Але як мінімум, у вас неатомарні звернення до змінних, які оновлюються в обробниках переривань. ПЗ для вбудованих систем так не пишеться.
Наскільки критичний той таймінг керування симістором? 10 мкс співрозмірне з часом виконання обробників переривань. Не очікуйте, що та затримка буде завжди 10 мкс. А якщо важлива не тільки тривалість імпульсів, а й тривалість пауз між ними, то тільки analogRead() дає затримку більше 100 мкс.

#8 Re: Апаратні питання » Прокоментуйте будь ласка разводку під кварц » 2025-09-20 23:48:46

https://forum.arduino.ua/img/members/2724/2.jpg

Також 5-й пін можна підключити до землі безпосередньо на цьому ж шарі, не через перехідний отвір.

#9 Re: Апаратні питання » Прокоментуйте будь ласка разводку під кварц » 2025-09-20 20:44:08

AVR186: Best Practices for the PCB Layout of Oscillators
AVR042: AVR Hardware Design Considerations. 5 Using crystal and ceramic resonators.

khalimon пише:

прокоментуйте будь ласка розводку під кварц 8мгц + 2 конденсатори. Фото додаю

Працювати буде. Не завадило би зʼєднати корпус кварца із землею.

khalimon пише:

Треба гарна помехостійкість

Фактичну стійкість покажуть тільки випробування. На EMC впливає не лише розводка під кварц.
Якщо умови задачі дозволяють, розгляньте тактування від внутрішнього RC-осцилятора замість кварца.

#11 Re: Програмування Arduino » Регістрова змінна » 2025-09-06 16:58:24

MikeM пише:

Звичайно, обробки, швидше ніж таблична, не існує.

Та не завжди. Залежить від алгоритму та особливостей архітектури. Хоча, спеціалізовані інструкції, по суті, на таких же "таблицях" реалізовані, тільки вони містяться на самому кристалі.
Звісно, в загальному випадку нічого швидше за O(1) не існує, але в конкретних випадках бувають нюанси. В мультизадачному середовищі взагалі, ще питання, що краще: виконати кілька додаткових інструкцій, чи лазити в таблицю через спільний кеш.

MikeM пише:

Однак, не варто було одразу викладати код. JOKEERу весь кайф обламали.

Вибачте, не хотів. Здавалось очевидним. Але там є ще простір для подальшої оптимізації wink

#12 Re: Програмування Arduino » Регістрова змінна » 2025-09-06 12:00:16

dimich пише:

Звісно, BCD можна упакувати. Тоді таблиці будуть менші, але виконання трохи довшим.

А якщо правильно упакувати, то і таблиці в півтора раза менші, і виконання навіть швидше. Має вийти десь 5.5 мкс.

const uint16_t PROGMEM intr[512] = { 0x000, 0x001, ... 0x510, 0x511 };
const uint16_t PROGMEM frac[128] = { 0x000, 0x008, ... 0x984, 0x992 };
char out[6];

void convert(uint32_t n)
{
    char *dst = out;
    uint16_t d;
    d = pgm_read_word(intr + ((n >> 19) & 511));
    *dst++ = d >> 8;
    *dst++ = (d >> 4) & 0xf;
    *dst++ = d & 0xf;
    d = pgm_read_word(frac + ((n >> 12) & 127));
    *dst++ = d >> 8;
    *dst++ = (d >> 4) & 0xf;
    *dst = d & 0xf;
}

#13 Re: Програмування Arduino » Регістрова змінна » 2025-09-06 02:26:12

MikeM пише:

У 32-розрядному слові в бітах з 12 по 27 міститься двійковий код 16-розрядного числа з фіксованою крапкою. Старші 9 бітів містять цілу частину, молодші 7 бітів - дробову. Потрібно перетворити його в 6-байтовий код для відображення на екран (по одній двійково-десятковій цифрі в байті).
Задача здається нескладною, але це все треба зробити швидше, ніж за 25 мікросекунд (на 16 МГц 8-бітному Arduino).

Якщо правильно зрозумів вхідний та вихідний формати, то дві таблиці з десятковими цифрами, 3 * (512 + 128) = 1920 байт флеша. Навіть "в лоб", без низькорівневої оптимізації:

const char PROGMEM intr[512 * 3] = {
    0, 0, 0,
    0, 0, 1,
    ...
    5, 1, 0,
    5, 1, 1
}; 

const char PROGMEM frac[128 * 3] = {
    0, 0, 0, 
    0, 0, 8,
    ...
    9, 8, 4,
    9, 9, 2
};

char out[6];

void convert(uint32_t n)
{
    char *dst = out;
    const char *src = intr + 3*((n >> 19) & 511);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
    src = frac + 3*((n >> 12) & 127);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
    *dst++ = pgm_read_byte(src++);
}

виходить щось біля сотні тактів, десь 7 мкс.
Звісно, BCD можна упакувати. Тоді таблиці будуть менші, але виконання трохи довшим.

#14 Re: Програмування Arduino » Регістрова змінна » 2025-08-28 12:33:45

MikeM пише:

І ніяких бібліотек.

А SMCR, по-вашому, де визначено? wink На avr-libc і весь ардуіно фреймворк побудований, так що це як раз із бібліотекою. Тільки замість бібліотечної функції чи макроса прямий доступ до регістра. Цілком можна і так, якщо не планується компілювати для контролерів, у яких sleep modes визначаються не через SMCR.

MikeM пише:

Цікаво, що ще пару днів тому я так вже робив. Не запрацювало з-за того, що забув /n/t. Переглянувши бібліотеку зрозумів, у чому був косяк.

Дивно, бо для єдиної інструкції у виразі в asm це не має значення. А для кількох інструкцій без \n була б синтаксична помилка.

jokeer пише:

Не зрозумів роль /n/t

\n для асемблера, бо компілятор спочатку зклеює сусідні строкові літерали, потім передає асемблеру. А асемблеру потрібно розрізняти рядки з мнемоніками. Але для єдиної інструкції це не обовʼязково.
\t для краси, щоби при виводі асемблерного лістингу наступний рядок був з відступом.

#15 Re: Програмування Arduino » Регістрова змінна » 2025-08-28 05:44:59

MikeM пише:

З ваших відповідей я зрозумів, чого не вистачає. Треба зупиняти процессор!

Так. Може це не єдиний, але, мабуть, найпростіший спосіб синхронізувати виконання коду з перериванням.

Обробник переривання не може почати виконуватись посередині 2- чи 3-тактової інструкції. А організувати цикл чи розгалуження без таких інструкцій неможливо. Щоб забезпечити незмінність затримки між виникненням запиту на переривання та виконанням коду, потрібно, щоб запит виникав, коли процесор знаходиться в режимі idle, тобто виконує інструкцію sleep.

MikeM пише:

Нове питання: як це зробити з Arduino IDE?

Що потрібно зробити, написано в даташиті, розділи 9.3 Idle Mode, 9.11.1 SMCR – Sleep Mode Control Register.
Як це можна зробити засобами avr-libc, написано в avr/sleep.h. Цей хідер для вашої версії avr-libc лежить у вас на диску в тулчейні.
Якщо коротко (по запису, не по виконанню):

// Один раз на початку:
set_sleep_mode(SLEEP_MODE_IDLE);
...
// Для входу в режим очікування:
sleep_mode();

Але це оверхед з перестраховкою. Можна простіше:

// Один раз на початку:
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
...
// Для входу в режим очікування:
sleep_cpu();

IDE тут ні до чого, код писати можна хоч у блокноті. Чи ви маєте на увазі, зробити засобами фреймворка ардуіно? По-перше, зручно використовувати 16-бітний TIMER1 в режимі CTC, бо при 16 МГц одна горизонтальна лінія відповідає циклу таймера в 508 тактів. По-друге, потрібно як мінімум вимкнути переривання від TIMER0, який ардуіно фреймворк використовує для своїх потреб.

#16 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 23:30:40

MikeM пише:

При спробі вивести 18й символ (а місце для нього є і на екрані, і на осциллограмі) таймер збивається.

Що значить "збивається"?

MikeM пише:

Таке враження, що, якщо обробка переривання не завершується за 4 мкс до наступного переривання, то це має негативний вплив.

4 мкс - це 64 такта. Спробую вгадати, ви помістили в обробник чималий шматок коду, який потребує зберігання/відновлення всіх регістрів. 32 інструкції pop по 2 такта в епілозі обробника, от вам і 4 мкс.
По-хорошому, обробник має складатись з єдиної інструкції reti: тільки розбудити процесор зі сплячки і завершитись.

Покажіть же, як ініціалізуєте таймер, що виконується в обробнику, як синхронізуєте переривання з рештою коду.

MikeM пише:

Хто-небудь може щось прояснити?

При наявній на даний момент інформації - можуть хіба що екстрасенси-телепати.

#17 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 16:54:03

jokeR пише:

Колись учили ассемблер x86, там все якось більш зрозуміло було wink

x86 CISC, регістрів менше, а інструкцій більше. А тут RISC, все навпаки smile

#18 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 14:46:00

jokeR пише:

Цікаві досліди winkЗаписуємо 0 після i14? наче в С коді не було. Чи це вже щось наступне?

Старший байт 16-бітної змінної. У автора там наче б то індекс для масиву зі шрифтом.

#19 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 12:54:35

Для демонстрації, мабуть, красивіше так:

$ avr-objdump -dzrwC --no-address --no-show-raw-insn --visualize-jumps test.o
...
<foo()>:
        lds     r24, 0x0000     ; 0x<__SREG__+0x7fffc1> R_AVR_16        serialBuf+0x1
        bst     r24, 2
        eor     r24, r24
        bld     r24, 0
        sts     0x0000, r24     ; 0x<__SREG__+0x7fffc1> R_AVR_16        i14
        sts     0x0000, r1      ; 0x<__SREG__+0x7fffc1> R_AVR_16        i14+0x1

Або просто продукувати лістинг компілятором

$ avr-g++ -mmcu=atmega328p -Os -S -o - test.cc

Але з -flto після лінковки кінцевий результат може бути зовсім іншим, так що це дуже приблизно.

#20 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 11:53:59

jokeR пише:
lds     r24, 0x0000 ; завантажили в r24 те що лежало в RAM за адресою 0х0000? serialBuf? старший байт?

Це дизасемблинг обʼєктного файлу (.o) до релокації, в ньому всі адреси нульові. При лінковці вже лінкер підставить потрібні адреси. Там буде адреса другого байта

jokeR пише:
sts     0x0000, r24 ; зберігаємо 0/1 в 0х0000? назад в serialBuf?

Нє, там буде інша адреса. Тут має бути зрозуміліше: https://godbolt.org/z/zKqrK7szG

jokeR пише:
sts     0x0000, r1  ; а що в r1??

За конвенцією в r1 завжди нуль. Саме тому після інструкцій mul, а також в преамбулі ISR компілятор його обнуляє. Є сумніви щодо доцільності такого рішення, але вже так.

jokeR пише:

А що робить lds-sts - незрозуміло.

Просто завантажує (Load Direct from Data Space) та вивантажує (Store Direct to Data Space) значення регістрів з/в памʼять. Так, в нерелокованому коді нульові адреси збивають з пантелику.

#21 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 08:31:53

Цікаво, що навіть GCC 15.1.0 такий фрагмент:

i14 = (serialBuf & 0x400) == 0 ? 0 : 1;

компілює в короткий 9-тактовий код, а еквівалентний йому

i14 = (serialBuf & 0x400) ? 1 : 0;

в довгий, схожий на той що генерує 7.3.0.

#22 Re: Програмування Arduino » Регістрова змінна » 2025-08-27 05:48:03

MikeM пише:

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

  if((serialBuf & 0x200) == 0) {i15 = 0;} else {i15 = 1; __asm__("nopnt");}
  if((serialBuf & 0x400) == 0) {i14 = 0; __asm__("nopnt""nopnt""nopnt");} else {i14 = 1;} 

Час виконання кожного з рядків стабільний, незалежно від значення serialBuf. Але для досягнення такої стабільності треба додавати різну кількість NOPів і, що ще цікавіше, в різні гілки.

По-хорошому, такі фрагменти потрібно одразу писати на асемблері, чи на вбудованому, чи в окремому файлі. Воно-то можна зкомпонувати вирази мовою високого рівня і підібрати необхідну кількість нопів. Але при подальших змінах в коді, чи при компіляції іншою версією, або з іншими опціями згенерований код може стати іншим, і все попливе.

Наприклад, такий код (еквівалентний рядку вашого):

uint32_t serialBuf;
uint16_t i14;

__attribute__((naked)) void foo()
{
    i14 = ((serialBuf & 0x400) == 0) ? 0 : 1;
}

Або, те ж саме:

i14 = !!(serialBuf & 0x400);

GCC версії 15.1.0 з опціями "-mmcu=atmega328p -Os" компілює в

00000000 <_Z3foov>:
   0:   80 91 00 00     lds     r24, 0x0000     ; 0x800000 <__SREG__+0x7fffc1>
   4:   82 fb           bst     r24, 2
   6:   88 27           eor     r24, r24
   8:   80 f9           bld     r24, 0
   a:   80 93 00 00     sts     0x0000, r24     ; 0x800000 <__SREG__+0x7fffc1>
   e:   10 92 00 00     sts     0x0000, r1      ; 0x800000 <__SREG__+0x7fffc1>

9 тактів, ніякої залежності від значень.

А GCC версія 7.3.0 з ардуінівського тулчейна з тими ж опціями компілює в

00000000 <_Z3foov>:
   0:   80 91 00 00     lds     r24, 0x0000     ; 0x800000 <__SREG__+0x7fffc1>
   4:   90 91 00 00     lds     r25, 0x0000     ; 0x800000 <__SREG__+0x7fffc1>
   8:   a0 91 00 00     lds     r26, 0x0000     ; 0x800000 <__SREG__+0x7fffc1>
   c:   b0 91 00 00     lds     r27, 0x0000     ; 0x800000 <__SREG__+0x7fffc1>
  10:   2a e0           ldi     r18, 0x0A       ; 10
  12:   b6 95           lsr     r27
  14:   a7 95           ror     r26
  16:   97 95           ror     r25
  18:   87 95           ror     r24
  1a:   2a 95           dec     r18
  1c:   01 f4           brne    .+0             ; 0x1e <_Z3foov+0x1e>
  1e:   81 70           andi    r24, 0x01       ; 1
  20:   99 27           eor     r25, r25
  22:   90 93 00 00     sts     0x0000, r25     ; 0x800000 <__SREG__+0x7fffc1>
  26:   80 93 00 00     sts     0x0000, r24     ; 0x800000 <__SREG__+0x7fffc1>

Дивіться дизассемблером, що генерується в кожному окремому випадку. Контекст виклику також істотно впливає на результат.
Можна за допомогою "avr-objdump -dz firmware.elf". Якщо збираєте власним Makefile, то генерацію асемблерного лістингу автоматизувати просто. В platformio також можна.
Опцією -S можна тимчасово вказати компілятору, щоб замість обʼєктного продукував асемблерний файл і на тому зупинявся.
Можна зберігати проміжні результати компіляції опцією -save-temps.
Для швидкого аналізу коду, що генерується, можна користустуватись godbolt.org. Тільки avr-gcc 7.3.0 чомусь там не знайшов.
Також майте на увазі, що link time optimization (опція -flto) може кардинально змінити код в результуючому .elf порівняно з тим, що в обʼєктному файлі. Тому кінцевий результат потрібно дивитись objdump'ом на .elf.

MikeM пише:

Звичайно, можна попередньо розібрати слово по байтах, але на це витрачається неприпустимо багато часу.

По суті, на обробку даних у вас є тільки час вертикального зворотнього "ходу променю".
Якщо горизонтальна синхронізація (HSync) генерується апаратно таймером по Output Compare Match, то це безперервний інтервал в 1.4 мс, тобто більше 22000 тактів. Плюс декілька десятків тактів під час кожного горизонтального синхроімпульсу та back porch.
Якщо HSync програмна на GPIO, то цей інтервал потрібно розбивати на безперервні фрагменти не більше як десь по 450 тактів.

#23 Re: Програмування Arduino » Регістрова змінна » 2025-08-24 20:07:25

jokeer пише:

Можливо компілятор і сам здогадатися розгорнути цикл,  без підказок.

З дефолтовим -Os навряд чи.

#24 Re: Програмування Arduino » Регістрова змінна » 2025-08-24 19:56:32

MikeM пише:
dimich пише:

#pragma GCC unroll 25

Нічого не змінюється, включно з розміром скомпільованого файлу.

Дивно. Ви ж це безпосередньо перед циклом "for" написали, а не десь на початку?
А, мабуть ви користуєтесь ардуінівським тулчейном з GCC 7.3.0. Ця прагма зʼявилась в GCC 8.
Просто я собі для platformio зробив пакунок atmelavr, який використовує avr-gcc, встановлений в системі (на даний момент 15.1.0), а не з їхнього репозиторію, який вони самі тягнуть з ардуїнівського з версією GCC часів Давньої Греції. Тоді вибачаюсь, не подумав перед тим як радити, що у людей це може не працювати.

#25 Re: Програмування Arduino » Регістрова змінна » 2025-08-24 19:28:36

MikeM пише:

При формуванні порожнього екранного рядка визначаються 25 символів, які будуть відображатися в наступних N рядках і в змінні і0 ... і24 записуються стартові адреси описів відповідних символів в кодовій таблиці.

А, здається, зрозумів. Ви тримаєте таблицю заздалегідь порахованих зміщень. Ну, можна й так, якщо ресурсу вистачає. У мене був символьний буфер на весь екран, здається 25x8.5 при шрифті 8x14, і коди символів з нього вибирались на кожній ітерації.

MikeM пише:

Хвіст, що може тягнутися за символом враховано. Останній біт завжди нульовий

Якщо тільки цифри, то можна було б зробити ширину символа 4 пікселя. Тоді в рядок в два рази більше влізе. Та й висоту не обовʼязково кратну 8. Ну то таке, вам постановка задачі та пріорітети фіч видніше.

Підвал форуму