#851 Re: Програмування Arduino » ищу того кто поможет допилить скетч » 2023-12-11 23:01:14

Є код, не спаплюжений автоперекладачем?

В цьому "коді", як можна зрозуміти, налаштування кожного таймера зберігається в EEPROM у такому форматі:

#байта   значення
   0     активний/неактивний
   1     година увімкнення
   2     хвилина увімкнення
   3     година вимкнення
   4     хвилина вимкнення
   5     номер канала
   6     рівень сигнала
   7     бітова маска днів тижня

Тобто час задається дискретно по хвилинах.
Щоб зробити по секундах, можна доповнити структуру ще двома полями: секунда увімкнення і секунда вимкнення. Тоді в обчисленні часу замість

timeTimerStart = (uint32_t)funcReadTimer(i, 1) * 3600 + funcReadTimer(i, 2) * 60;
timeTimerStop = (uint32_t)funcReadTimer(i, 3) * 3600 + funcReadTimer(i, 4) * 60; 

буде щось типу

timeTimerStart = (uint32_t)funcReadTimer(i, 1) * 3600 + funcReadTimer(i, 2) * 60 + funcReadTimer(i, 8);
timeTimerStop = (uint32_t)funcReadTimer(i, 3) * 3600 + funcReadTimer(i, 4) * 60 + funcReadTimer(i, 9);

Тоді структура займатиме 10 байт замість 8-ми, тому потрібно змінити індексування EEPROM:

uint8_t funcReadTimer(uint8_t i, uint8_t j) {
  return EEPROM[i * 10 + j];
}
...
void funcSaveTimer(uint8_t i, uint8_t j, uint8_t k) {
  EEPROM[i * 10 + j] = k;
}

і решту коду, де очікується 8-байтова структура. Відповідно зміниться і кількість доступних таймерів з "кількість байт EEPROM/8" на "кількість байт EEPROM/10".
Також знадобиться додати установку секунд в UI.

Якщо буде достатньо дискретності в 2 секунди (тобто тільки 0, 2, 4, .. 58 секунд), то можна упакувати поле часу в ті ж два байта і обійтись без зміни розміру структури: 5 біт на години, 6 біт на хвилини і 5 біт на секунди. Або зберігати час просто як кількість 2-секундних інтервалів від початку доби.

UPD: ще, щоб не змінювати розмір структури, але отримати дискретність в 1 секунду, можна використати біти з нульового байта структури і упакувати додаткові біти секунд у нього.

#852 Re: Програмування Arduino » Проблема з Serial » 2023-12-09 16:29:10

В чому полягає питання? Звідки -38?
Ви вводите два символи: '3' і перевод строки з кодом 10. 10 - 48 (код символу '0') = -38.

#853 Re: Програмування Arduino » передача данных по GPRS » 2023-12-08 20:19:27

Що вже працює і на якому етапі перестає?
GSM-модуль реєструється в мережі? Отримує IP-адресу?
Вдається встановити TCP-зʼєднання хоч з яким-небудь сервером, без передачі даних? Наприклад, з будь-яким працюючим web-сервером на порт 443?
Ваш хост, який ви плануєте використовувати в ролі сервера, має глобальну (білу) IP-адресу? Якщо ні, то прокиньте порт на свій хост на роутері. Спробуйте встановити зʼєднання з девайса на вашу глобальну адресу і цей порт. У wireshark маєте побачити хоча би спробу TCP зʼєднання (SYN-пакет). Потім запустіть той же socat, чи netcat, чи що там є під вашу операційну систему.

#854 Re: Програмування Arduino » Проблема з #include <OneWire.h> » 2023-12-02 20:19:51

linaya пише:

шлях до бібліотек я вставляла в c_cpp_properties.json, який я скинула вище

Налаштування в c_cpp_properties.json впливають на збірку вбудованими в VSCode засобами та на IntelliSense. На збірку проекту зі стороннім Makefile вони не впливають.

Ваш Makefile не підходить для збірки ардуіно-скетчів. Як мінімум, він компілює проект на C, а скетчі пишуться на C++. Проблему з #include <OneWire.h> можна вирішити, додавши "INCLUDE += -I<шлях_до_хідера>". Але це вам не допоможе, тому що бібліотеку потрібно ще теж скомпілювати і прилінкувати. В принципі, і ваш Makefile можна адаптувати для компіляції C++, компіляції бібліотеки і лінковки з нею. Але простіше буде, як порадили вище, взяти готове рішення у вигляді arduino-mk.

#855 Re: Програмування Arduino » Софт для газорозрядного годинника в середовищі Ардуїно. » 2023-12-02 12:12:11

З якою із частин яка конкретно проблема?
Будь-яку задачу, складнішу за блимання єдиним світлодіодом, декомпонуйте на простіші підзадачі і вирішуйте їх послідовно.
Спочатку реалізуйте індикацію, просто відображення довільних цифр.
Потім реалізуйте взаємодію з мікросхемою годинника по I²C, відображайте поточний час.
Далі реалізуйте обробку натиснення кнопок і перемикання внутрішнього стану. Меню - це класичний скінченний автомат, ознайомтесь із теорією автоматів.
Поступово доповнюйте функціонал, але беріться за наступну функцію після того як попередні вже працюють.

#856 Re: Програмування Arduino » передача данных по GPRS » 2023-12-01 19:12:19

За яким протоколом "сайт" очікує дані? "Сирий" TCP чи UDP? HTTP GET/PUT/POST? В якому форматі мають бути дані?
Прімітивний TCP сервер можна запустити за допомогою

$ socat TCP-LISTEN:8080 -

Звісно, хост, на якому запускається сервер, має бути доступний з GPRS-мережі.
Відслідковувати трафік можна, наприклад, за допомогою wireshark.

#857 Re: Програмування Arduino » Збір інформації для своїх мелодій,активний зуммер. » 2023-12-01 18:25:54

Існують різні методи. Можна відтворювати PCM-кодований сигнал за допомогою ШІМ або зовнішнього DAC. Але при розрядності 8 біт і частоті дискретизації 8 кГц 1 секунда звуку займатиме 8 кб. На Atmega328p без зовнішньої EEPROM влізе не більше 4 секунд, а там ще код і бутлоадер. Якщо знизити розрядність до 4 біт, то влізе вдвічі більше, але якість буде гіршою.

Одноголосну мелодію можна відтворити "цифровим" методом, генеруючи прямокутний сигнал. tone()/delay() - це найпростіший спосіб.

#define PIN_BUZZER  3

void setup() {
  pinMode(PIN_BUZZER, OUTPUT);
}

struct note {
  uint16_t frequency;
  uint16_t duration;
};

static const PROGMEM note notes[] = {
  { 293, 240 },
  { 329, 240 },
  { 349, 240 },
  { 392, 240 },
  { 329, 480 },
  { 261, 240 },
  { 293, 720 }
};

void loop() {
  for (auto *p = notes; p < notes + sizeof(notes)/sizeof(*notes); ++p) {
    note note;
    memcpy_P(&note, p, sizeof(note));
    if (note.frequency) {
      tone(PIN_BUZZER, note.frequency);
    } else {
      noTone(PIN_BUZZER);
    }
    delay(note.duration);
  }
  noTone(PIN_BUZZER);

  for (;;) {}
}

Порахувати частоту ноти можна за формулою f=F*2^(n/12), де F - частота базової ноти, n - кількість напівтонів від базової ноти. Додатні значення - вверх, від'ємні - вниз. Зазвичай за базову ноту беруть "ля" першої октави, і її частоту - 440 Гц, але це не обовʼязково.

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

Можна поєднати відтворення окремих нот з ШІМ і отримати щось схоже на поліфонію. Для апаратного ШІМ в ардуіно скоріш за все доведеться використовувати TIM1 або TIM2, тому що TIM0 ардуіно використовує для своїх потреб.
Вибір оптимального метода залежить від конкретних вимог і можливостей заліза.

UPD: перемикати пін в OUTPUT не потрібно, tone() це робить сама: Tone.cpp:255

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