Ви не увійшли.
Тепер, коли буду щось писати в сторінку, то теж, в підрахунок CRC включати байти команди та адреса, я правильно розумію?
Треба дивитися даташит, шукаєте там Memory function flow chart, вам спочатку потрібна буде команда OFh для запису в скретчпад, бачите там "Master RX CRC16 of Command, Address, Data" - це значить, що потрібно включати, наступною командою 55h потрібно скопіювати скретчпад в сторінку.
Я б ось це
#define inBit1Wire(inBit)
LineWire =0; delay_us( 8);
LineWire =1; delay_us( 1);
inBit =LineWire; delay_us(40);
LineWire =1; delay_us(90);
змінив на таке
#define inBit1Wire(inBit)
LineWire =0; delay_us( 8);
LineWire =1; delay_us(11);
inBit =LineWire; delay_us(30);
LineWire =1; delay_us(90);
бо лінія може не встигнути піднятись за 1мкс
Приблизно так (псевдокод):
write_0 {
bus_low
delay 59
bus_hiz
delay 11
}
write_1_read {
bus_low
delay 10
bus_hiz
delay 5
r = bus_read
delay 55
return r
}
У вас трохи неправильні таймінги. Відправка нуля - це ~59мкс нуль на шині і не менше 1мкс одиниця, відправка одиниці - 5..10мкс нуль і ~55мкс одиниця. Слейв робить зчитування шини через 30-35мкс після падаючого фронту (тобто десь посередині) і визначає, там передали 0 чи 1. А якщо слейв хоче передати нуль, то він по падаючому фронту замикає шину на землю на 30-40мкс, тобто мастер повинен робити зчитування десь посередині - приблизно на 15..20й мікросекунді.
Це штатний режим роботи, при напрузі зовнішнього живлення <~4.5V (VCC або паразитного через DQ), лічильник вимикає 1-wire інтерфейс але продовжує рахувати імпульси. Пов'язано це з тим, що споживання лічильника йде з трьох джерел - з батарейки, з VCC, з DQ - кожне через діод, яка напруга більша, звідти і споживання, коли зовнішнє живлення (VCC, DQ) лічильник вважає низьким, то щоб менше споживати від батарейки, він вимикає інтерфейсну частину. Тобто VCC або DQ має бути >4.5V, про це сказано в характеристиках пристрою, що VCC і DQ мають бути в межах 4.5 .. 5.5V.
При паразитному живленні струм споживання йде через резистор підтяжки і напруга DQ, звичайно, просідає. При підтяжці 1кОм можна заживити 1, максимум 2 лічильники (я не робив детальних досліджень). Мінімум, що допускає специфікація 1-wire це підтяжка 500 Ом.
Для вашого прикладу на фото:
#include <stdio.h>
#include <stdint.h>
uint16_t crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
for (i = 0; i < 8; ++i) {
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
return crc;
}
int main()
{
uint8_t buf[45] = {
0xa5, 0xc0, 0x01, // READMEMCOUNTER, address
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xbb,0x00,0x00,0x60,0x00,0xed,0x00,0x41,
0x31,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0xe3, 0x1b
};
uint16_t crc;
int i;
crc = 0;
for (i = 0; i < 43; i++)
crc = crc16_update(crc, buf[i]);
printf("crc = 0x%02x 0x%02xn", (uint8_t)~(crc & 0xff), (uint8_t)~(crc >> 8));
crc = 0;
for (i = 0; i < 45; i++)
crc = crc16_update(crc, buf[i]);
if (crc == 0xb001)
printf("crc okn");
else
printf("crc errorn");
}
Вивід:
crc = 0xe3 0x1b
crc ok
Ось вам приклад, щоб розібратися:
#include <stdio.h>
#include <stdint.h>
uint16_t crc16_update(uint16_t crc, uint8_t a)
{
int i;
crc ^= a;
for (i = 0; i < 8; ++i) {
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
return crc;
}
int main()
{
uint8_t buf[10] = {11, 12, 13, 14, 15, 16, 17, 18};
uint16_t crc;
int i;
/* додавання crc до повідомлення */
crc = 0;
for (i = 0; i < 8; i++)
crc = crc16_update(crc, buf[i]);
buf[i++] = ~(crc & 0xff);
buf[i++] = ~(crc >> 8);
/* перевірка повідомлення з crc */
crc = 0;
for (i = 0; i < 10; i++)
crc = crc16_update(crc, buf[i]);
if (crc == 0xb001)
printf("crc okn");
else
printf("crc errorn");
}
Перевіряти контрольну суму можна тим же способом, що і заповнювали, або використати властивість, що контрольна сума повідомлення разом його інвертованою контрольною сумою завжди буде 0xb001.
Звичайно crc16_update() можна оптимізувати, наприклад, як у вашому прикладі з oddparity.
Зверніть увагу, що в ds2423 при першому читанні сторінки контрольна сума обчислюється не лише над даними, чотирма нульовими байтами і чотирма байтами лічильника, але ще спочатку і над самою командою (0xa5) і двома байтами адреси (а для наступних сторінок, якщо читаємо далі підряд, вже лише над всіма байтами сторінки, 4 нульовими байтами і 4 байтами лічильника). Також не обов'язково вичитувати всі 32 байти сторінки, якщо потрібен лише лічильник, можна почати з останнього байту сторінки, ось тут приклад, як найпростіше прочитати лише байти лічильника.
Подивіться Модуль розширення портів з інтерфейсом 1-wire, в ньому є функція відстеження стану порта, призначена для побудови охоронної системи, може це саме те, що вам потрібно. 1-wire дозволяє почепити на одну шину безліч таких модулів, використавши лише один пін мікроконтролера для керування всіми ними. Або 1-wire можна підключити напряму до лінукс, для роботи з такими модулями є драйвер.
а також щоби ця частота була на виходах 26 та 36, як відомо, tone() може працювати одночасно тільки на одному порті, тому треба зробти якесь швидке перекидання чи якийсь інший фокус, щоби вона була на цих двух портах.
припаяйте перемичку
GmmC пише:можливо одночасно буде реалізувати також шім по двух чи одному каналу?
На одному таймері з довільною частотою два канала не вийде: у таймера два регістра-компаратора, і один із них використовується або як один із каналів ШІМ, або для керування частотою.
Подивіться режими, коли верхня межа лічильника задається регістром ICR, тоді обидва регістри-компаратори доступні для ШІМ.
Частоту і коефіцієнт заповнення ШІМ на AVR не вийде встановлювати абсолютно довільно, лише ось такі дискретні значення:
Частота: f=16MHz/N, де N=1..65536
Коеф.заповнення: d=n/N, де N - те ж саме, яке використано для підбору частоти, n=0..N
analogWrite(PIN_RELAY, 0);
Якщо я не помиляюсь, дана команда увімкне ШІМ з коефіцієнтом заповнення 1/256 (а параметр 255 дасть коефіцієнт заповнення 256/256 - завжди на одиничку більше, тобто за допомогою analogWrite неможливо отримати коефіцієнт заповнення 0/256)
Як можна з Вами зв'язатись
Зліва під аватаркою натискаєте на "E-mail" і відправляєте повідомлення.
pinMode(3, INPUT);
замініть на
pinMode(3, INPUT_PULLUP);
Якщо після цього і з тестером перестане працювати, значить спрацьовувало від наводок.
Як Вам радив dimich, виконуйте pulseIn() при вимкнених перериваннях
__builtin_avr_cli();
ch3 = pulseIn(3, HIGH, timeout);
__builtin_avr_sei();
Але прикрий момент у тому, що з іншими пристроями, які генерують ШІМ сигнал аттіні знов не працює, навіть з такими налаштуваннями зчитування сигналу.
Чи є цьому якесь пояснення і чи можна тепер заставити тіні працювати і з іншими пристроями окрім тестера сервомашинок?
А Ви з піном не помилилися? Бо пін в високоімпедансному стані і від наводок щось зловить.
Подавайте PWM на серву, але якщо дуже хочеться і є зайві гроші, звертайтесь, напишу Вам PWM->PDM конвертер.
В мене драйвер 3.5.2019.1, спробую останній 3.6.2021.12
У мене також версія 3.5.2019.1, але ніяких проблем немає, перемичку не використовую. Проблема, мабуть, в чомусь іншому.
Добрий день. Скажіть чи працює avrdude на windows 10?
У мене віндовс 10 і на ній працює. Драйвер USB-UART CH340 версії 3.5.2019.1
Можливо знадобиться такий лайфхак, коли будете використовувати avrdude з ключиком "-c avrisp"
Конденсатор (між RST і GND, або RST і VCC) чи перемичка (між RST і VCC) використовуються як лайфхак, якщо драйвер USB-UART (CH340) неправильно керує сигналом DTR, в мене в віндовс 10 з цим проблем немає, в лінуксі пробема зникла коли перейшов на ядро 5.4.х (на 4.х ще була така проблема).
Honey, людина просила простий приклад. Хоча ваш код і виконує його забаганку, але навряд чи він розбереться у ньому.
В шести рядках (куди ж вже простіший код?) має розібратися. Там та ж ідея "інтерпретатора", яку щойно докладно "для домогосподарок" розписав dimich. (dimich, респект!)
#define LED_PIN 13
#define LED_ON HIGH
#define LED_OFF LOW
short durations[] = {
// state 0
1000, -1, // always OFF (loop)
// state 2 (SOS)
100, // initial delay
// loop start
500, 500, 500, 500, 500, 1500, // ON/OFF durations
1500, 500, 1500, 500, 1500, 1500,
500, 500, 500, 500, 500, 2000,
-18, // goto 18 steps back == loop start
// state 22
0,
1000, 500, 1000, 500, 1000, 500+5000,
2000, 5000, 2000, 5000+10000,
500, 1500, 1000, 2000,
-14, // Чєрєз пять мінут наступаєт зіма
};
byte state = 22; // state = 2 for SOS
unsigned long start_time = 0;
void setup(void) {
pinMode(LED_PIN, OUTPUT);
}
void loop(void) {
digitalWrite(LED_PIN, (state & 1) ? LED_ON : LED_OFF);
unsigned long cur_time = millis();
if (cur_time - start_time >= durations[state]) {
if (durations[++state] < 0)
state += durations[state];
start_time = cur_time;
}
}
А думав що тут той самий принцип як і заливкою через usb, якщо заливаємо hex без бутлоадеру, то при перепрошивці бутлоадер не чіпається. А тут виявляється що потрібно заливати hex з назвою ....ino.with_bootloader.hex або прошивати бутлоадер при потребі окремо?
В бутлоадері запрограмовано, щоб він сам себе не затирав.
В avrdude просто вказуєте підряд обидві прошивки: -U flash:w:optiboot_atmega328.hex:i -U flash:w:myfirmware.hex:i
І ще тоді запитання: при наявності бутлоадера і залочці через lock bit через бутлоадер можно прошивку зляти? В гуглі одні пишуть так, інші пишуть ні
Прошивка сама себе може читати і при бажанні кудись відправити. Можна захистити від читання код бутлоадера з коду користувача - це може бути дійсно корисно. Можна навпаки - код користувача від бутлоадера (мабуть, це мали на увазі ті, хто писав що можна захистити), але це створить лише незручності, бо бутлоадер не зможе перевіряти те, що записав, а скинути лок можна лише стиранням всього флеш через ISP, програмно ніяк.
Доречі "відключити бутлоадер" і "затерти бутлоадер" це не одне й те ж, затертий бутлоадер все одно буде виконуватись, але оскільки в ньому порожні команди, то керування врешті передасться на прошивку користувача, а ці кілька десятків зайвих мікросекунд Ви не помітите.
Ще одне таке питання: після залочки (біт FC) на нано пропадає можливість запису прошивки через usb, процес просто висить.
Через arduinoISP прошивається. Це так і має бути?Зашив прошивку через arduinoISP, біт скинувся на FF, але через usb вже не прошивається. Хоча юсб працює, через serial я отримую данні з прошивки
Коли Ви записуєте прошивку в ціль, то затирається бутлоадер.
Подивіться інструкцію, там є приклади, як відновити бутлоадер.