Ви не увійшли.
Документ, что прилагается не от него, от похожего
А він точно з керуванням по послідовному протоколу?
На сайті виробника по назві DM0900 знаходиться два серво:
DM0900 10.5KG Digital Metal Gear Servo
Digital Metal Gear Servo DM0900
Обидва з PWM-керуванням. У маркетологів PWM також вважається "digital"
Може в описі товару тупо переплутали, написавши про послідовну шину. Таке буває.
Так, програма у вас видає Dynamixel Protocol 1.0.
Ще є Protocol 2.0. А на сторінці товару посилання на даташит для A1-16, де протокол схожий, але несумісний ні з Dynamixel 1.0, ні з 2.0. Кожен виробник модифікує протокол як хоче, аби було несумісно з продукцією конкурентів.
Готового решения сразу не нашел )
Теоретично, якщо зі сторони серво відкритий колектор з підтяжкою, то одного діода Шотткі з серво на TX має бути достатньо. Принаймні debugWIRE для AVRок у мене так працює без проблем.
Але мені все ж здається, що там не послідовний протокол, а звичайний PWM.
Доречі, в прошивці для Attiny не бачу конфігурування CLKPR. Якщо Attiny працює від внутрішнього осциллятора на 9.6 МГц і фʼюз CKDIV8 не скинуто, то його тактова частота - 1.2 МГц. Один такт - це біля 10% від такту для 115200 бод. Далеко не всякий UART буде нормально працювати при такій похибці.
Неделю не могу подружить сервопривод с компом.
Покажіть cхему підключення і код керування. Чи відповідає servo ID в коді дійсному ідентифікатору серво? Покажіть дамп трафіку пакетів. Чи видає серво підтвердження прийому пакетів? Чи пробували різні бодрейти UART: 9600, 19200, 57600, 115200?
Мне просто нужно что-бы схема могла включить и выключить +12v.
Явних помилок не бачу, має працювати. Постійна часу R3 * ємність затвор-виток суттєво менша періоду PWM PCA9685PW, так що ок.
D3 - защитный диод
Ага, якщо передбачається індуктивне навантаження, тоді ок. Хіба що зверніть увагу на відвід тепла, бо при великих струмах і середньому заповненні PWM діод може грітись.
Компілюєте і прошиваєте з arduino IDE? Чи правильно вибрана плата, і особливо частота кварца? Замініть myservo.write() на блимання світлодіодом, перевірте, чи правильно працює delay() взагалі.
Якщо є осциллограф, подивіться, що за сигнал іде з керуючого вивода з ардуіни.
Чи не підключено занадто довгими проводами? Спробуйте підключити якомога коротшими.
Чи буде моя схема коректною для керування PWM сигналом?
На схемі VCC 12V між діодом і стоком мосфета - помилка? Що за GND зверху? Для чого діод?
Наскільки мені відомо, у вентиляторах з PWM-керування керуючий сигнал подається на затвор вбудованого мосфета, який вже підтягнутий до живлення. Тобто достатньо просто замикати вивід PWM на землю. Теоретично одного біполярного транзистора має бути достатньо. Для інверсного керування (нуль - повна потужність) - по схемі з загальним еміттером, для прямого - з загальною базою, підтягнутою до живлення керуючої схеми.
Але ж нам не відомо, яка саме внутрішня схема вашого вентилятора. Поміряйте, чи є там підтягуючий резистор між входами PWM і 12V? Якщо є, то чи зупиняється вентилятор при замиканні PWM на землю?
Керування ШІМ та бездротова передача - різні задачі, хоча і можуть бути вирішені одним апаратним засобом.
Які вимоги до частоти і розрядності ШІМ, кількість каналів? Що є джерелом керуючого сигналу?
Протокол бездротової передачі також обирається в залежності від вимог: дальність, діапазон частот, надійність, споживання енергії.
Одним із варіантів може бути пара ESP8266 або ESP32: один в режимі WiFi Access Point, другий в режимі WiFi Station. Трохи надмірно для такої задачі, але просто в реалізації.
Інший варіант: окремо безпровідна передача, наприклад радіомодулі UART, і окремо будь-який мікроконтроллер з UART і ШІМ для виконавчої сторони і з UART і необхідним вхідним інтерфейсом для контролюючої.
Один із найпростіших, мабуть, варіантів:
constexpr byte PIN_BUZZER { 3 };
constexpr byte PIN_BUTTON { 12 };
constexpr byte debounce_ms { 50 };
void setup() {
pinMode(PIN_BUTTON, INPUT_PULLUP);
}
void loop() {
constexpr unsigned int freq[] = { 14000, 15000, 16000, 17000 };
byte idx = 0;
for (;;) {
tone(PIN_BUZZER, freq[idx]);
unsigned long start_ms = millis();
do {
if (digitalRead(PIN_BUTTON) == LOW) {
start_ms = millis();
continue;
}
} while ((millis() - start_ms) < debounce_ms);
while (digitalRead(PIN_BUTTON) == HIGH) {};
if (++idx >= sizeof(freq)/sizeof(*freq)) {
idx = 0;
}
}
}
Припускається, що випромінювач звуку підключений до піна 3, кнопка до піна 12 і замикається на землю.
В такій реалізації процесор постійно споживає струм в активному режимі. Якщо потрібна економія споживання при автономному живленні, необхідно задіяти функції енергозбеження і переривання.
Як на активному зуммері можна отримати різні тони (ноти)?
Хе, слушне зауваження. Мені спочатку здалося, що під активним мається на увазі - з вбудованим буферним каскадом.
Якщо ж під активним мається на увазі - з автогенерацією (а судячи по маркуванню на фото, так і є), то звісно що ніяк. Хіба що змінюючи напругу живлення можна отримати якусь непередбачувану невеличку девіацію частоти
Є код, не спаплюжений автоперекладачем?
В цьому "коді", як можна зрозуміти, налаштування кожного таймера зберігається в 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 секунду, можна використати біти з нульового байта структури і упакувати додаткові біти секунд у нього.
В чому полягає питання? Звідки -38?
Ви вводите два символи: '3' і перевод строки з кодом 10. 10 - 48 (код символу '0') = -38.
Що вже працює і на якому етапі перестає?
GSM-модуль реєструється в мережі? Отримує IP-адресу?
Вдається встановити TCP-зʼєднання хоч з яким-небудь сервером, без передачі даних? Наприклад, з будь-яким працюючим web-сервером на порт 443?
Ваш хост, який ви плануєте використовувати в ролі сервера, має глобальну (білу) IP-адресу? Якщо ні, то прокиньте порт на свій хост на роутері. Спробуйте встановити зʼєднання з девайса на вашу глобальну адресу і цей порт. У wireshark маєте побачити хоча би спробу TCP зʼєднання (SYN-пакет). Потім запустіть той же socat, чи netcat, чи що там є під вашу операційну систему.
шлях до бібліотек я вставляла в c_cpp_properties.json, який я скинула вище
Налаштування в c_cpp_properties.json впливають на збірку вбудованими в VSCode засобами та на IntelliSense. На збірку проекту зі стороннім Makefile вони не впливають.
Ваш Makefile не підходить для збірки ардуіно-скетчів. Як мінімум, він компілює проект на C, а скетчі пишуться на C++. Проблему з #include <OneWire.h> можна вирішити, додавши "INCLUDE += -I<шлях_до_хідера>". Але це вам не допоможе, тому що бібліотеку потрібно ще теж скомпілювати і прилінкувати. В принципі, і ваш Makefile можна адаптувати для компіляції C++, компіляції бібліотеки і лінковки з нею. Але простіше буде, як порадили вище, взяти готове рішення у вигляді arduino-mk.
З якою із частин яка конкретно проблема?
Будь-яку задачу, складнішу за блимання єдиним світлодіодом, декомпонуйте на простіші підзадачі і вирішуйте їх послідовно.
Спочатку реалізуйте індикацію, просто відображення довільних цифр.
Потім реалізуйте взаємодію з мікросхемою годинника по I²C, відображайте поточний час.
Далі реалізуйте обробку натиснення кнопок і перемикання внутрішнього стану. Меню - це класичний скінченний автомат, ознайомтесь із теорією автоматів.
Поступово доповнюйте функціонал, але беріться за наступну функцію після того як попередні вже працюють.
За яким протоколом "сайт" очікує дані? "Сирий" TCP чи UDP? HTTP GET/PUT/POST? В якому форматі мають бути дані?
Прімітивний TCP сервер можна запустити за допомогою
$ socat TCP-LISTEN:8080 -
Звісно, хост, на якому запускається сервер, має бути доступний з GPRS-мережі.
Відслідковувати трафік можна, наприклад, за допомогою wireshark.
Існують різні методи. Можна відтворювати 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(¬e, 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