diff --git a/GyverBus/GBUSmini.h b/GyverBus/GBUSmini.h new file mode 100644 index 0000000..0317824 --- /dev/null +++ b/GyverBus/GBUSmini.h @@ -0,0 +1,227 @@ +#pragma once +#include +// ******* ЛЁГКИЕ ФУНКЦИИ ОТПРАВКИ И ЧТЕНИЯ GBUS ******* +// Все функции (кроме GBUS_is_busy) блокируют выполнение кода на время приёма/отправки + +// Возвращает true, если линия занята. Таймаут GBUS_BUSY_TIMEOUT мс +bool GBUS_is_busy(byte pin); + +// Отправить сырые данные (пин, дата, размер) +// Формат посылки GBUS [суммарное количество байт, адрес получателя, адрес отправителя, ...байты даты..., CRC] +// Функция блокирующая на всё время отправки +// 640 байт (Arduino Nano), 150 байт ATtiny13 (microCore) +void GBUS_send_raw(byte pin, byte* data, byte size); + +// Отправить данные с CRC (пин, адрес получателя, адрес отправителя, дата, размер) +// Функция блокирующая на всё время отправки +// 740 байт (Arduino Nano), 230 байт ATtiny13 (microCore) +void GBUS_send_crc(byte pin, byte to, byte from, byte* data, byte size); + +// Отправить данные без CRC (пин, адрес получателя, адрес отправителя, дата, размер) +// Функция блокирующая на всё время отправки +// 700 байт (Arduino Nano), 200 байт ATtiny13 (microCore) +void GBUS_send_no_crc(byte pin, byte to, byte from, byte* data, byte size); + +// Прочитать сырые данные (пин, дата, размер) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма. +// Возвращает количество принятых байт при завершении приёма +// 520 байт (Arduino Nano), 220 байт ATtiny13 (microCore) +byte GBUS_read_raw(byte pin, byte* buf, byte size); + +// Прочитать данные с CRC (пин, наш адрес, дата, размер) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +// 650 байт (Arduino Nano), 330 байт ATtiny13 (microCore) +byte GBUS_read_crc(byte pin, byte addr, byte* buf, byte size); + +// Прочитать данные без CRC (пин, наш адрес, дата, размер) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +// 622 байт (Arduino Nano), 300 байт ATtiny13 (microCore) +byte GBUS_read_no_crc(byte pin, byte addr, byte* buf, byte size); + +// Отправить запрос (пин, адрес получателя, адрес отправителя) +// Функция блокирующая на всё время отправки +// 640 байт (Arduino Nano), 150 байт ATtiny13 (microCore) +void GBUS_send_request(byte pin, byte to, byte from); + +// Принять запрос (пин, наш адрес) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +// 540 байт (Arduino Nano), 220 байт ATtiny13 (microCore) +byte GBUS_read_request(byte pin, byte addr); + +// Отправить подтверждение (пин, адрес получателя, адрес отправителя) +// Функция блокирующая на всё время отправки +void GBUS_send_ack(byte pin, byte to, byte from); + +// Принять подтверждение (пин, наш адрес) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +byte GBUS_read_ack(byte pin, byte addr); + +// Отправить запрос и ждать подтверждения приёма, т.е. пытаться достучаться +// (пин, адрес получателя, адрес отправителя, кол-во попыток, таймаут между попытками) +// возвращает 0 при таймауте, 1 при успехе (получили ack) +// см. примеры call response _ack +byte GBUS_send_request_ack(byte pin, byte to, byte from, byte tries, int timeout); + + +// ******************************************************* +// ********************** СЕРВИС ************************* +// ******************************************************* +byte GBUS_send_request_ack(byte pin, byte to, byte from, byte tries, int timeout) { + GBUS_send_request(pin, to, from); + byte thisTry = 0; + uint32_t tmr = millis(); + while (1) { + byte addr = GBUS_read_ack(pin, from); + if (addr == to) return ACK_ONLY; + if (millis() - tmr >= timeout) { + tmr = millis(); + thisTry++; + if (thisTry >= tries) return ACK_ERROR; + GBUS_send_request(pin, to, from); + } + } + return ACK_ERROR; +} + +// ******************************************************* +bool GBUS_is_busy(byte pin) { + static uint32_t tmr; + if (digitalRead(pin)) { + if (millis() - tmr >= GBUS_BUSY_TIMEOUT) return false; + else return true; + } else { + tmr = millis(); + return true; + } +} + +// ******************************************************* +// ********************* ЧТЕНИЕ ************************** +// ******************************************************* +byte GBUS_read_raw(byte pin, byte* buf, byte size) { + int8_t bitCount = 0; // счётчик битов + byte byteCount = 0; // счётчик байтов + if (!digitalRead(pin)) { // проверяем старт бит (low) + GBUS_DELAY(GBUS_BIT_2); // ждём половину времени + if (!digitalRead(pin)) { // если всё ещё старт бит (low) + while (1) { + GBUS_DELAY(GBUS_BIT); // ждём бит + byte bit = digitalRead(pin); // читаем + if (bitCount < 8) { // передача битов даты + bitWrite(buf[byteCount], bitCount, bit); // пишем в буфер + } else if (bitCount == 8) { // стоп бит (high) + byteCount++; // счётчик собранных байтов + if (!bit) return 0; // ошибка стоп бита. Завершаем + } else if (bitCount == 9) { // старт бит (low) + if (bit) return byteCount; // не дождались старт бита. Конец приёма, возврат количества + if (byteCount >= size) return 0; // буфер переполнен. Завершаем + bitCount = -1; // костыль + } + bitCount++; // следующий бит + } + } + } + return 0; +} + +// ******************************************************* +byte GBUS_read_no_crc(byte pin, byte addr, byte* buf, byte size) { + byte buf2[size + 3]; // буфер на приём + byte bytes = GBUS_read_raw(pin, buf2, (size + 3)); // принимаем, получаем количество байт посылки + if (buf2[0] == bytes && buf2[1] == addr) { // если совпало количество байт и адрес + for (byte i = 0; i < bytes - 3; i++) buf[i] = buf2[i + 3]; // переписываем в буфер в скетче + return buf2[2]; // возвращаем адрес + } + return 0; // иначе возвращаем ошибку +} + +// ******************************************************* +byte GBUS_read_crc(byte pin, byte addr, byte* buf, byte size) { + byte buf2[size + 4]; // буфер на приём + byte bytes = GBUS_read_raw(pin, buf2, (size + 4)); // принимаем, получаем количество байт посылки + if (buf2[0] == bytes && buf2[1] == addr) { // если совпало количество байт и адрес + byte crc = 0; + for (byte i = 0; i < bytes; i++) GBUS_crc_update(crc, buf2[i]); // crc + if (crc != 0) return 0; // данные повреждены + for (byte i = 0; i < bytes - 4; i++) buf[i] = buf2[i + 3]; // переписываем в буфер в скетче + return buf2[2]; // возвращаем адрес + } + return 0; // иначе возвращаем ошибку +} + +// ******************************************************* +// структура буфера: [0, адрес получателя, адрес отправителя] +byte GBUS_read_request(byte pin, byte addr) { + byte buf[3]; + if (GBUS_read_raw(pin, buf, 3) == 3 && buf[1] == addr && buf[0] == 0) return buf[2]; + else return 0; +} + +// ******************************************************* +// структура буфера: [1, адрес получателя, адрес отправителя] +byte GBUS_read_ack(byte pin, byte addr) { + byte buf[3]; + if (GBUS_read_raw(pin, buf, 3) == 3 && buf[1] == addr && buf[0] == 1) return buf[2]; + else return 0; +} + + +// ******************************************************* +// ******************** ОТПРАВКА ************************* +// ******************************************************* +void GBUS_send_raw(byte pin, byte* buf, byte size) { + for (byte bytes = 0; bytes < size; bytes++) { + pinMode(pin, OUTPUT); // старт бит + digitalWrite(pin, 0); + GBUS_DELAY(GBUS_BIT); + for (byte bits = 0; bits < 8; bits++) { + bool bit = (buf[bytes] >> bits) & 1; // биты + pinMode(pin, !bit); + digitalWrite(pin, bit); + GBUS_DELAY(GBUS_BIT); + } + pinMode(pin, INPUT); // стоп бит + digitalWrite(pin, 1); + GBUS_DELAY(GBUS_BIT); + } + // тут пин уже автоматом INPUT_PULLUP +} + +// ******************************************************* +void GBUS_send_no_crc(byte pin, byte to, byte from, byte* data, byte size) { + byte buf[size + 3]; + buf[0] = size + 3; + buf[1] = to; + buf[2] = from; + for (byte i = 0; i < size; i++) buf[3 + i] = data[i]; + GBUS_send_raw(pin, buf, sizeof(buf)); +} + +// ******************************************************* +void GBUS_send_crc(byte pin, byte to, byte from, byte* data, byte size) { + byte buf[size + 4]; + byte crc = 0; + buf[0] = size + 4; + buf[1] = to; + buf[2] = from; + for (byte i = 0; i < size; i++) buf[3 + i] = data[i]; + for (byte i = 0; i < size + 3; i++) GBUS_crc_update(crc, buf[i]); + buf[size + 3] = crc; + GBUS_send_raw(pin, buf, sizeof(buf)); +} + +// ******************************************************* +void GBUS_send_request(byte pin, byte to, byte from) { + byte buf[3] = {0, to, from}; + GBUS_send_raw(pin, buf, sizeof(buf)); +} + +// ******************************************************* +void GBUS_send_ack(byte pin, byte to, byte from) { + byte buf[3] = {1, to, from}; + GBUS_send_raw(pin, buf, sizeof(buf)); +} \ No newline at end of file diff --git a/GyverBus/GyverBus.h b/GyverBus/GyverBus.h new file mode 100644 index 0000000..45e961b --- /dev/null +++ b/GyverBus/GyverBus.h @@ -0,0 +1,542 @@ +#pragma once +#include + +/* + GyverBus - библиотека для общения по протоколу GBUS + - Очень простой, надёжный, устойчивый к помехам и задержкам, но медленный интерфейс связи на базе UART + - Двухсторонняя связь по одному проводу + - Асинхронная отправка и чтение (на базе millis()) + - Двухсторонняя совместимость с аппаратным UART + - Возможность принимать и отправлять данные внутри сети Ардуинок + - Адресация до 254 устройств в сети (от 1 до 255) + - Всеядная функция отправки и приёма (ест переменные, структуры, массивы) + - Встроенная проверка CRC (контроль целостности) пакета данных + - Возможность отправки и чтения короткого "запроса" + - Поддерживаются все Arduino-совместимые платы + - Сама библиотека предоставляет возможности по отладке (коды ошибок) + - В примерах есть компактные варианты чтения и отправки данных, влезет даже в ATtiny +*/ + +/* + Коды статусов и ошибок (tick() и getStatus()): + 0 [GBUS_IDLE] - ожидание + 1 [TRANSMITTING] - передача + 2 [TX_OVERFLOW] - буфер переполнен + 3 [TX_COMPLETE] - передача завершена + 4 [RECEIVING] - приём + 5 [RX_ERROR] - ошибка приёма + 6 [RX_ABORT] - ошибка. Приём прерван + 7 [RX_OVERFLOW] - ошибка. Буфер или пакет переполнен + 8 [RX_ADDRESS_ERROR] - ошибка. Не наш адрес + 9 [RX_CRC_ERROR] - ошибка. Не совпадает CRC + 10 [RX_REQUEST] - успешное получение запроса + 11 [RX_COMPLETE] - успешный приём данных + 12 [RX_ACK] - успешное получение подтверждения +*/ + +/* + Инициализация: + GBus<пин, тип, crc> объект(адрес, размер буфера) + - пин: номер пина + - тип: GBUS_FULL - двухсторонняя связь (активен по умолчанию, можно не указывать) + - тип: GBUS_TX - только отправка (экономит память) + - тип: GBUS_RX - только приём (экономит память) + - crc: GBUS_CRC - с контролем целостности данных CRC (активен по умолчанию, можно не указывать) + - crc: GBUS_NO_CRC - отключить ожидание и проверку CRC + + Список методов: + tick() - отправляет и принимает данные. Вызывать хотя бы каждую миллисекунду. Возвращает коды статусов, тип GBUSstatus (enum) + getStatus() - возвращает коды статусов (такие же как tick()), тип GBUSstatus (enum) + + sendData(адрес, дата) - вводит данные на отправку по адресу получателя. Принимает любй тип данных (переменные, массивы, структуры). Отправка начнётся автоматически после "освобождения" линии + gotData() - вернёт true, если новый пакет данных принят без ошибок. Сам сбрасывается в false + readData(дата) - выводит данные из внутреннего буфера в указанную "переменную" (переменные, массивы, структуры) + + sendRequest(адрес) - отправить "запрос" по адресу получателя + gotRequest() - вернёт true, если на наш адрес пришёл запрос. Сам сбрасывается в false. Адрес отправителя можно узнать в getTXaddress() + + getTXaddress() - возвращает адрес отправителя с последнего успешного получения данных или запроса + isBusy() - возвращает true, если линия занята. Возвращает false, если с момента последнего общения по линии прошло GBUS_BUSY_TIMEOUT миллисекунд + + sendAck(адрес) - отправляет ack (ответ на запрос) по адресу + gotAck() - вернёт true, если на наш адрес пришёл ack (ответ на запрос). Сам сбрасывается в false. Адрес отправителя можно узнать в getTXaddress() + + sendRequestAck(адрес, кол-во попыток, таймаут) - отправляет реквест на адрес. + Ждёт ответ (ack или data), если не дожидается в теч. таймаута - отправляет ещё раз. + Если количество попыток превышено - возвращает ACK_ERROR (0 ноль). + Если принят ack - возвращает ACK_ONLY (1 единица) + Если принята дата - возвращает ACK_DATA (2 два) + ФУНКЦИЯ БЛОКИРУЮЩАЯ + Смотри примеры call_response_tx_ack и call_response_rx_ack + + sendRaw(байтовый массив, размер) - отправит сырые байты (без протокола) по шине. Смотри примеры в папке raw + gotRaw() - вернёт true, были приняты какие-то данные (приём завершён успешно). Сам сбрасывается в false. + rawSize() - вернёт количество принятых байт (последний успешный приём). Иначе вернёт 0 + + buffer - можно обращаться как к массиву. Встроенный буфер библиотеки +*/ + +/* + Интерфейс: UART. start бит 0, stop бит 1. Кодирование даты: HIGH - 0x1, LOW - 0x0 + + 1 _______ ___ ___ ______ ___ .........._________ + |___| |______| |___| |___| |___| конец передачи + 0 start 0 1 2 3 4 5 6 7 stop start stop + + Протокол: + Дата + CRC [суммарное количество байт, адрес получателя, адрес отправителя, ...байты даты..., crc] + Дата без CRC [суммарное количество байт, адрес получателя, адрес отправителя, ...байты даты...] + Запрос (request) [0, адрес получателя, адрес отправителя] + Подтверждение (ack) [1, адрес получателя, адрес отправителя] +*/ + +// НАСТРОЙКИ +#define GBUS_SPEED 300 // скорость (BAUD) +#define DEBUG_CODES // закомментируй, чтобы сэкономить 160 байт =) + +// КОНСТАНТЫ +#define GBUS_RX 0 +#define GBUS_TX 1 +#define GBUS_FULL 2 +#define GBUS_NO_CRC 0 +#define GBUS_CRC 1 +#define ACK_ERROR 0 +#define ACK_ONLY 1 +#define ACK_DATA 2 + +// ЗАМЕТКИ +// Отключение DEBUG_CODES экономит ~160 байт Flash +// Отключение CRC экономит 50-70 байт Flash +// GBUS_RX вместо GBUS_FULL экономит 432 байт Flash +// GBUS_TX вместо GBUS_FULL экономит 930 байт Flash +// Смотри GBUSmini.h, там куча простых лёгких функций отправки и чтения + +#if (GBUS_SPEED > 200) +#define GBUS_DELAY(x) delayMicroseconds(x) +#define GBUS_BIT (1000000UL / GBUS_SPEED) +#define GBUS_TIME micros +#else +#define GBUS_DELAY(x) delay(x) +#define GBUS_BIT (1000UL / GBUS_SPEED) +#define GBUS_TIME millis +#endif + +#define GBUS_BIT_2 (GBUS_BIT >> 1) +#define GBUS_BUSY_TIMEOUT 50 + +#ifdef DEBUG_CODES +#define _set_status_code(x) _status = (x) +#else +#define GBUSstatus int +#define _set_status_code(x) +#endif + +#ifdef DEBUG_CODES +enum GBUSstatus { + GBUS_IDLE, + TRANSMITTING, + TX_OVERFLOW, + TX_COMPLETE, + RECEIVING, + RX_ERROR, + RX_ABORT, + RX_OVERFLOW, + RX_ADDRESS_ERROR, + RX_CRC_ERROR, + RX_REQUEST, + RX_COMPLETE, + RX_ACK, +}; +#endif + +void GBUS_crc_update(uint8_t &crc, uint8_t data); + +template +class GBus { +public: + enum TX_stage { + TX_IDLE, + TX_START, + TX_SENDING, + TX_FINISH, + }; + enum RX_stage { + RX_IDLE, + RX_START, + RX_READING, + RX_FINISH, + }; + + GBus(byte addr, byte bufSize) + : _bufSize(bufSize + (_CRC ? 4 : 3)), _addr(addr) { + buffer = malloc(_bufSize); + memset(buffer, 0, _bufSize); + pinMode(_PIN, INPUT_PULLUP); + } + + ~GBus() { + free(buffer); + } + + GBUSstatus tick() { + if (_role == GBUS_RX) { // приёмник + if (_ROLE == GBUS_RX || _ROLE == GBUS_FULL) { // компилятор вырежет при выбранной роли + byte bit = digitalRead(_PIN); + switch(_rxstage) { + case RX_IDLE: + if (!bit) { + _tmr = GBUS_TIME(); + _rxstage = RX_START; + } + break; + + case RX_START: + if (GBUS_TIME() - _tmr >= GBUS_BIT_2) { + if (!bit) { + _rxstage = RX_READING; + _set_status_code(RECEIVING); + _bitCount = 0; + _byteCount = 0; + _crc = 0; + _readFlag = false; + _ackFlag = false; + _requestFlag = false; + _rawFlag = false; + _rawSize = 0; + _tmr = GBUS_TIME(); + } else { + _rxstage = RX_FINISH; + _set_status_code(RX_ERROR); + } + } + break; + + case RX_READING: + if (GBUS_TIME() - _tmr >= GBUS_BIT) { + _tmr += GBUS_BIT; + _lastPulse = millis(); + + if (_bitCount < 8) { // передача битов даты + bitWrite(buffer[_byteCount], _bitCount, bit); // пишем в буфер + } else if (_bitCount == 8) { // стоп бит (high) + if (!bit) { // ошибка стоп бита. Завершаем + _rxstage = RX_FINISH; + _set_status_code(RX_ERROR); + return _status; + } + if (_CRC) GBUS_crc_update(_crc, buffer[_byteCount]); + _byteCount++; // счётчик собранных байтов + } else if (_bitCount == 9) { // старт бит (low) + if (bit) { // не дождались нового старт бита. Конец приёма? + _rawFlag = true; + _rawSize = _byteCount; + _txAddress = buffer[2]; + if (buffer[1] != _addr) { // адрес не совпал + _rxstage = RX_FINISH; + _set_status_code(RX_ADDRESS_ERROR); + return _status; + } + if (_byteCount == 3 && buffer[0] == 0) { // реквест + _rxstage = RX_FINISH; + _set_status_code(RX_REQUEST); + _requestFlag = true; + return _status; + } + if (_byteCount == 3 && buffer[0] == 1) { // подтверждение + _rxstage = RX_FINISH; + _set_status_code(RX_ACK); + _ackFlag = true; + return _status; + } + if (_byteCount < buffer[0]) { // передача прервана + _rxstage = RX_FINISH; + _set_status_code(RX_ABORTED); + return _status; + } + if (_CRC) { + if (_crc != 0) { // не совпал CRC + _rxstage = RX_FINISH; + _set_status_code(RX_CRC_ERROR); + return _status; + } + } + + // данные приняты + _readFlag = true; + _set_status_code(RX_COMPLETE); + _rxstage = RX_FINISH; + return _status; + } + if (_byteCount > 2) { // мин. размер пакета + if (_byteCount > _bufSize || // буфер переполнен или + _byteCount >= buffer[0]) { // пакет переполнен. Завершаем + _rxstage = RX_FINISH; + _set_status_code(RX_OVERFLOW); + } + } + _bitCount = -1; // костыль + } + _bitCount++; // следующий бит + } + break; + + case RX_FINISH: + _rxstage = RX_IDLE; + _set_status_code(GBUS_IDLE); + break; + } + } + } else { // передатчик + if (_ROLE == GBUS_TX || _ROLE == GBUS_FULL) { // компилятор вырежет при выбранной роли + switch(_txstage) { + case TX_IDLE: + break; + + case TX_START: + if (!isBusy()) { + _txstage = TX_SENDING; + _bitCount = -1; + _byteCount = 0; + _set_status_code(TRANSMITTING); + _tmr = GBUS_TIME() - GBUS_BIT; + } + break; + + case TX_SENDING: + if (GBUS_TIME() - _tmr >= GBUS_BIT) { + _tmr += GBUS_BIT; + if (_bitCount == -1) { + pinMode(_PIN, OUTPUT); + digitalWrite(_PIN, 0); + } + else if (_bitCount < 8) { + bool bit = (buffer[_byteCount] >> _bitCount) & 1; + digitalWrite(_PIN, bit); + pinMode(_PIN, !bit); + } + else if (_bitCount == 8) { + digitalWrite(_PIN, 1); + _byteCount++; + if (_byteCount == _txSize) { + pinMode(_PIN, INPUT_PULLUP); + _txstage = TX_FINISH; + _set_status_code(TX_COMPLETE); + _lastPulse = millis(); + } + _bitCount = -2; + } + _bitCount++; + } + break; + + case TX_FINISH: + if (_ROLE == GBUS_FULL) _role = GBUS_RX; + _set_status_code(GBUS_IDLE); + _txstage = TX_IDLE; + break; + } + } + } + return _status; + } + + GBUSstatus getStatus() {return _status;} + + bool gotData() { + bool temp = _readFlag; + _readFlag = false; + return temp; + } + + byte getTXaddress() {return _txAddress;} + + bool isBusy() { + return !(GBUS_TIME() - _lastPulse > GBUS_BUSY_TIMEOUT); + } + + void sendRequest(byte addr) { + if (_ROLE == GBUS_TX || _ROLE == GBUS_FULL) { + buffer[0] = 0; // размер даты (0-запрос) + buffer[1] = addr; // адрес приёмника + buffer[2] = _addr; // адрес передатчика (наш) + _txstage = TX_START; // флаг на передачу + _role = GBUS_TX; // теперь ты отправитель + _txSize = 3; // отправляем 3 байта + } + } + + bool gotRequest() { + bool temp = _requestFlag; + _requestFlag = false; + return temp; + } + + void sendAck(byte addr) { + if (_ROLE == GBUS_TX || _ROLE == GBUS_FULL) { + buffer[0] = 1; // размер даты (1-ack) + buffer[1] = addr; // адрес приёмника + buffer[2] = _addr; // адрес передатчика (наш) + _txstage = TX_START; // флаг на передачу + _role = GBUS_TX; // теперь ты отправитель + _txSize = 3; // отправляем 3 байта + } + } + + bool gotAck() { + bool temp = _ackFlag; + _ackFlag = false; + return temp; + } + + byte sendRequestAck(byte addr, byte tries, int timeout) { + if (_ROLE == GBUS_TX || _ROLE == GBUS_FULL) { + sendRequest(addr); + while (tick() == GBUS_IDLE); // ждём таймаут + while (tick() != TX_COMPLETE); // ждём отправку + byte thisTry = 0; + uint32_t tmr = GBUS_TIME(); + while (1) { + tick(); // принимаем или отправляем + if (gotData()) return ACK_DATA; // приняли дату + if (gotAck()) return ACK_ONLY; // приняли ответ + if (GBUS_TIME() - tmr >= timeout) { // таймаут + tmr = GBUS_TIME(); + thisTry++; + if (thisTry >= tries) return ACK_ERROR; // превышено количество попыток + sendRequest(addr); // снова шлём запрос + } + } + } + return ACK_ERROR; + } + + void sendRaw(byte* data, byte size) { + if (_ROLE == GBUS_TX || _ROLE == GBUS_FULL) { + byte i = 0; + for (; i < min(size, _bufSize); i++) buffer[i] = data[i]; + _txSize = i; + _txstage = TX_START; // флаг на начало передачи + _role = GBUS_TX; // теперь мы отправитель + } + } + bool gotRaw() { + bool temp = _rawFlag; + _rawFlag = false; + return temp; + } + byte rawSize() {return _rawSize;} + + template + void sendData(byte addr, T &data) { + if (_ROLE == GBUS_TX || _ROLE == GBUS_FULL) { + buffer[0] = sizeof(T) + _bufOffset; // размер пакета + if (buffer[0] > _bufSize) { // переполним буфер + _txstage = TX_FINISH; + _set_status_code(TX_OVERFLOW); + return; + } + buffer[1] = addr; // адрес приёмника + buffer[2] = _addr; // адрес передатчика (наш) + const uint8_t *ptr = (const uint8_t*) &data; + for (uint16_t i = 0; i < sizeof(T); i++) { + buffer[i + 3] = *ptr++; + } + + // crc + if (_CRC) { + _crc = 0; + for (byte i = 0; i < sizeof(T) + 3; i++) GBUS_crc_update(_crc, buffer[i]); + buffer[sizeof(T) + 3] = _crc; + } + _txSize = sizeof(T) + _bufOffset; + _txstage = TX_START; // флаг на начало передачи + _role = GBUS_TX; // теперь мы отправитель + } + } + + template + void readData(T &data) { + uint8_t *ptr = (uint8_t*) &data; + for (uint16_t i = 0; i < sizeof(T); i++) { + *ptr++ = buffer[i + 3]; + } + } + + byte *buffer; + +private: + const int _bufSize; + int8_t _bitCount = 0; + byte _txSize = 0, _byteCount = 0;; + uint32_t _tmr; + uint32_t _lastPulse; + byte _txAddress; + byte _addr; + byte _bufOffset = _CRC ? 4 : 3; + + byte _role = GBUS_RX; + TX_stage _txstage = TX_IDLE; + RX_stage _rxstage = RX_IDLE; + +#ifdef DEBUG_CODES + GBUSstatus _status = GBUS_IDLE; +#else + int _status = 0; +#endif + + bool _readFlag = false; + bool _requestFlag = false; + bool _ackFlag = false; + bool _rawFlag = false; + byte _rawSize = 0; + byte _crc = 0; +}; + +// =============== УТИЛИТЫ =============== +// пакуем любой тип данных в байтовый буфер +template +void packDataBytes(byte *buffer, T &data) { + const uint8_t *ptr = (const uint8_t*) &data; + for (uint16_t i = 0; i < sizeof(T); i++) { + buffer[i] = *ptr++; + } +} + +// распаковываем из байтового буфера обратно +template +void unpackDataBytes(byte *buffer, T &data) { + uint8_t *ptr = (uint8_t*) &data; + for (uint16_t i = 0; i < sizeof(T); i++) { + *ptr++ = buffer[i]; + } +} + +// расчёт CRC +void GBUS_crc_update(uint8_t &crc, uint8_t data) { +#if defined (__AVR__) + // резкий алгоритм для AVR + uint8_t counter; + uint8_t buffer; + asm volatile ( + "EOR %[crc_out], %[data_in] \n\t" + "LDI %[counter], 8 \n\t" + "LDI %[buffer], 0x8C \n\t" + "_loop_start_%=: \n\t" + "LSR %[crc_out] \n\t" + "BRCC _loop_end_%= \n\t" + "EOR %[crc_out], %[buffer] \n\t" + "_loop_end_%=: \n\t" + "DEC %[counter] \n\t" + "BRNE _loop_start_%=" + : [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer) + : [crc_in]"0" (crc), [data_in]"r" (data) + ); +#else + // обычный для всех + uint8_t i = 8; + while (i--) { + crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1); + data >>= 1; + } +#endif +} \ No newline at end of file diff --git a/GyverBus/examples/GBUS/GBus_demo/GBus_demo.ino b/GyverBus/examples/GBUS/GBus_demo/GBus_demo.ino new file mode 100644 index 0000000..2336b7a --- /dev/null +++ b/GyverBus/examples/GBUS/GBus_demo/GBus_demo.ino @@ -0,0 +1,61 @@ +// тест отправки и получения на одной ардуине +// перемычка между D2 и D3 + +#include "GyverBus.h" + +GBus<2, GBUS_FULL> tx(1, 10); // пин 2, адрес 1, буфер 10 байт +GBus<3, GBUS_FULL> rx(2, 10); // пин 3, адрес 2, буфер 10 байт + +// при создании объекта можно указать: +// GBus<пин, GBUS_FULL> - двухсторонняя связь +// GBus<пин, GBUS_TX> - только отправка (экономит память) +// GBus<пин, GBUS_RX> - только приём (экономит память) + +// второй параметр - CRC +// GBus - отключить ожидание и проверку CRC +// по умолчанию CRC включен + +// например структура для отправки +struct myStruct { + byte val_b; + int val_i; + float val_f; +}; +myStruct tx_data; + +void setup() { + Serial.begin(9600); + + // заполняем + tx_data.val_b = 123; + tx_data.val_i = -23456; + tx_data.val_f = 3.14; +} + +void loop() { + rx.tick(); + tx.tick(); + + // успешный приём + if (rx.gotData()) { + // приёмная структура + myStruct rx_data; + + // читаем в неё + rx.readData(rx_data); + + // выводим проверяем + Serial.println(rx_data.val_b); + Serial.println(rx_data.val_i); + Serial.println(rx_data.val_f); + Serial.println(); + } + + // отправляем каждые 2 секунды + static uint32_t tmr; + if (millis() - tmr >= 2000) { + tmr = millis(); + // отправляем на адрес 2 + tx.sendData(2, tx_data); + } +} diff --git a/GyverBus/examples/GBUS/GBus_read/GBus_read.ino b/GyverBus/examples/GBUS/GBus_read/GBus_read.ino new file mode 100644 index 0000000..c6e59d3 --- /dev/null +++ b/GyverBus/examples/GBUS/GBus_read/GBus_read.ino @@ -0,0 +1,22 @@ +// простой пример приёма (вотправляет пример GBus_send) +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// пин 4, адрес 3, приёмник на 15 байт +GBus rx(RX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + if (rx.gotData()) { + int rec; + rx.readData(rec); + Serial.println(rec); + } +} diff --git a/GyverBus/examples/GBUS/GBus_request/GBus_request.ino b/GyverBus/examples/GBUS/GBus_request/GBus_request.ino new file mode 100644 index 0000000..d093381 --- /dev/null +++ b/GyverBus/examples/GBUS/GBus_request/GBus_request.ino @@ -0,0 +1,30 @@ +// тест реквеста на одной ардуине +// перемычка между D2 и D3 + +#include "GyverBus.h" + +GBus<2, GBUS_FULL> tx(1, 10); // пин 2, адрес 1, буфер 10 байт +GBus<3, GBUS_FULL> rx(2, 10); // пин 3, адрес 2, буфер 10 байт + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + tx.tick(); + + // получили запрос + if (rx.gotRequest()) { + Serial.print("request from "); + Serial.print(rx.getTXaddress()); + Serial.println(); + } + + static uint32_t tmr; + if (millis() - tmr > 2000) { + tmr = millis(); + // отправляем запрос на адрес 2 + tx.sendRequest(2); + } +} diff --git a/GyverBus/examples/GBUS/GBus_send/GBus_send.ino b/GyverBus/examples/GBUS/GBus_send/GBus_send.ino new file mode 100644 index 0000000..2460d41 --- /dev/null +++ b/GyverBus/examples/GBUS/GBus_send/GBus_send.ino @@ -0,0 +1,26 @@ +// простой пример отправки (принимает пример GBus_read) +#include "GyverBus.h" + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +// пин 4, адрес 1, буфер на 15 байт +GBus tx(TX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +// данные +int data = 12345; + +void loop() { + if (tx.tick() == TX_COMPLETE) Serial.println("transmitted"); + + static uint32_t tmr; + if (millis() - tmr >= 1000) { + tmr = millis(); + tx.sendData(RX_ADDR, data); + } +} diff --git a/GyverBus/examples/GBUS/GBus_status/GBus_status.ino b/GyverBus/examples/GBUS/GBus_status/GBus_status.ino new file mode 100644 index 0000000..4139571 --- /dev/null +++ b/GyverBus/examples/GBUS/GBus_status/GBus_status.ino @@ -0,0 +1,18 @@ +// простой пример приёма для simple_send и raw_send +#include "GyverBus.h" + +// пин 4, адрес 1, приёмник на 15 байт +GBus<4, GBUS_FULL, GBUS_CRC> rx(1, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + static byte lastStatus = 0; + byte status = rx.tick(); + if (lastStatus != status) { + Serial.println(status); + lastStatus = status; + } +} diff --git a/GyverBus/examples/GBUS/Serial/read/serial_read/serial_read.ino b/GyverBus/examples/GBUS/Serial/read/serial_read/serial_read.ino new file mode 100644 index 0000000..60c8714 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/read/serial_read/serial_read.ino @@ -0,0 +1,27 @@ +// принимаем пакет и выводим на дисплей, адрес отправителя отдельно +// readBytes - блокирующая функция! +// отправляет serial_read_send +// у этой ардуины провод подключен к пину RX (пин 0) + +#include +LiquidCrystal_I2C lcd(0x27, 16, 2); + +void setup() { + Serial.begin(300); + Serial.setTimeout(100); + lcd.init(); + lcd.backlight(); +} + +byte buf[10]; +void loop() { + if (Serial.readBytes(buf, 6)) { + lcd.clear(); + lcd.home(); + lcd.print("tx: "); + lcd.print(buf[2]); + lcd.setCursor(0, 1); + int val = buf[3] | (buf[4] << 8); + lcd.print(val); + } +} diff --git a/GyverBus/examples/GBUS/Serial/read/serial_read_send/serial_read_send.ino b/GyverBus/examples/GBUS/Serial/read/serial_read_send/serial_read_send.ino new file mode 100644 index 0000000..e97f7a9 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/read/serial_read_send/serial_read_send.ino @@ -0,0 +1,27 @@ +// простой пример отправки (принимает пример serial_read) +#include "GyverBus.h" + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +// пин 4, адрес 1, буфер на 15 байт +GBus tx(TX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +// данные +int data = 0; + +void loop() { + if (tx.tick() == TX_COMPLETE) Serial.println("transmitted"); + + static uint32_t tmr; + if (millis() - tmr >= 1000) { + tmr = millis(); + data += 50; + tx.sendData(RX_ADDR, data); + } +} diff --git a/GyverBus/examples/GBUS/Serial/send/serial_send/serial_send.ino b/GyverBus/examples/GBUS/Serial/send/serial_send/serial_send.ino new file mode 100644 index 0000000..83b9d21 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/send/serial_send/serial_send.ino @@ -0,0 +1,17 @@ +// отправляем данные через аппаратный UART +// принимает пример serial_send_read +// у этой ардуины провод подключен к пину TX (пин 1) + +#define RX_ADDR 3 // адрес приёмника + +void setup() { + Serial.begin(300); // скорость настраиваем как в GBUS! +} + +void loop() { + Serial.write(4); // количество байт + Serial.write(RX_ADDR); // отправляем на адрес приёмника + Serial.write(5); // допустим наш адрес 5 + Serial.write(123); // дата + delay(1000); +} diff --git a/GyverBus/examples/GBUS/Serial/send/serial_send_2/serial_send_2.ino b/GyverBus/examples/GBUS/Serial/send/serial_send_2/serial_send_2.ino new file mode 100644 index 0000000..4dc2740 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/send/serial_send_2/serial_send_2.ino @@ -0,0 +1,24 @@ +// более интересный пример +// отправляем данные через аппаратный UART +// принимает пример serial_send_read_2 +// у этой ардуины провод подключен к пину TX (пин 1) + +#define RX_ADDR 3 // адрес приёмника + +byte buff[1 + 3]; // буфер отправки (1 байт данных + 3 сервис без CRC) + +void setup() { + Serial.begin(300); // скорость настраиваем как в GBUS! + // заполняем буфер + buff[0] = 4; // количество байт в пакете + buff[1] = RX_ADDR; // адрес получателя + buff[2] = 5; // адрес отправителя (пусть 5) +} + +byte val = 0; +void loop() { + val++; + buff[3] = val; // отправляем val + Serial.write(buff, sizeof(buff)); // запускаем + delay(1000); +} diff --git a/GyverBus/examples/GBUS/Serial/send/serial_send_3/serial_send_3.ino b/GyverBus/examples/GBUS/Serial/send/serial_send_3/serial_send_3.ino new file mode 100644 index 0000000..f9c3c2b --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/send/serial_send_3/serial_send_3.ino @@ -0,0 +1,48 @@ +// более интересный пример +// отправляем данные через аппаратный UART +// ОТПРАВЛЯЕМ СТРУКТУРУ ПО СЕРИАЛ =) +// принимает пример serial_send_read_3 +// у этой ардуины провод подключен к пину TX (пин 1) + +#define RX_ADDR 3 // адрес приёмника + +// структура включает первые три байта протокола GBUS +struct myStruct { + byte amount; + byte rxaddr; + byte txaddr; + byte val_b; + int val_i; + float val_f; +}; +myStruct tx_data; + +byte buff[sizeof(tx_data)]; // буфер отправки + +// подключаем либу для pack функции +#include "GyverBus.h" + +void setup() { + Serial.begin(300); // скорость настраиваем как в GBUS! + + // заполняем буфер, первые три байта по протоколу + tx_data.amount = sizeof(tx_data); + tx_data.rxaddr = RX_ADDR; + tx_data.txaddr = 5; // наш адрес 5 например + + // заполняем дату + tx_data.val_b = 123; + tx_data.val_i = -23456; + tx_data.val_f = 3.14; + + // пакуем структуру в байтовый буфер + packDataBytes(buff, tx_data); +} + +void loop() { + // serial write заполняет буфер на отправку по uart + // то есть вызов не блокирующий, данные будут отправлены + // полностью асинхронно + Serial.write(buff, sizeof(buff)); // запускаем + delay(2000); +} diff --git a/GyverBus/examples/GBUS/Serial/send/serial_send_read/serial_send_read.ino b/GyverBus/examples/GBUS/Serial/send/serial_send_read/serial_send_read.ino new file mode 100644 index 0000000..509ad11 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/send/serial_send_read/serial_send_read.ino @@ -0,0 +1,23 @@ +// принимаем данные из примера serial_send_read +// у этой ардуины провод подключен к пину RX_PIN +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// пин 4, адрес 3, приёмник на 15 байт +GBus rx(RX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + if (rx.gotData()) { + byte in; + rx.readData(in); + Serial.println(in); + } +} diff --git a/GyverBus/examples/GBUS/Serial/send/serial_send_read_2/serial_send_read_2.ino b/GyverBus/examples/GBUS/Serial/send/serial_send_read_2/serial_send_read_2.ino new file mode 100644 index 0000000..66be431 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/send/serial_send_read_2/serial_send_read_2.ino @@ -0,0 +1,26 @@ +// более интересный пример +// принимаем данные из примера serial_send_read_2 +// у этой ардуины провод подключен к пину RX_PIN +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// пин 4, адрес 3, приёмник на 15 байт +GBus rx(RX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + if (rx.gotData()) { + // выводим проверяем + byte in; + rx.readData(in); + Serial.print(in); + Serial.println(); + } +} diff --git a/GyverBus/examples/GBUS/Serial/send/serial_send_read_3/serial_send_read_3.ino b/GyverBus/examples/GBUS/Serial/send/serial_send_read_3/serial_send_read_3.ino new file mode 100644 index 0000000..88c07e6 --- /dev/null +++ b/GyverBus/examples/GBUS/Serial/send/serial_send_read_3/serial_send_read_3.ino @@ -0,0 +1,39 @@ +// более интересный пример +// принимаем данные из примера serial_send_read_3 +// у этой ардуины провод подключен к пину RX_PIN +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// пин 4, адрес 3, приёмник на 15 байт +GBus rx(RX_ADDR, 15); + +// та же структура, но БЕЗ ПЕРВЫХ ТРЁХ БАЙТОВ!!! +struct myStruct { + byte val_b; + int val_i; + float val_f; +}; +myStruct rx_data; + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + if (rx.gotData()) { + // читаем (служебные байты автоматически отбросятся) + rx.readData(rx_data); + + // выводим дату + Serial.println(rx_data.val_b); + Serial.println(rx_data.val_i); + Serial.println(rx_data.val_f); + Serial.print("from address: "); + Serial.println(rx.getTXaddress()); + Serial.println(); + } +} diff --git a/GyverBus/examples/GBUS/call_response/call_response_rx/call_response_rx.ino b/GyverBus/examples/GBUS/call_response/call_response_rx/call_response_rx.ino new file mode 100644 index 0000000..351a5e1 --- /dev/null +++ b/GyverBus/examples/GBUS/call_response/call_response_rx/call_response_rx.ino @@ -0,0 +1,32 @@ +// принимаем запрос и отправляем в ответ данные с АЦП +// парный пример - call_response_rx + +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +GBus rx(RX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + // приняли запрос + if (rx.gotRequest()) { + Serial.print("request from "); + Serial.print(rx.getTXaddress()); + Serial.println(); + + // прочитали аналог + int val = analogRead(0); + Serial.print("sending "); + Serial.println(val); + + // отправили обратно + rx.sendData(rx.getTXaddress(), val); + } +} diff --git a/GyverBus/examples/GBUS/call_response/call_response_tx/call_response_tx.ino b/GyverBus/examples/GBUS/call_response/call_response_tx/call_response_tx.ino new file mode 100644 index 0000000..e655d85 --- /dev/null +++ b/GyverBus/examples/GBUS/call_response/call_response_tx/call_response_tx.ino @@ -0,0 +1,36 @@ +// отправляем запрос и в ответ ждём данные, т.е. +// отправитель работает на отправку, потом на приём +// парный пример - call_response_tx + +#include "GyverBus.h" + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +GBus tx(TX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + tx.tick(); + + // отправляем запрос на RX_ADDR каждые три секунды + static uint32_t tmr; + if (millis() - tmr > 3000) { + tmr = millis(); + tx.sendRequest(RX_ADDR); + Serial.println("send request"); + } + + // если нам что-то отправили + if (tx.gotData()) { + int data; + // читаем и выводим + tx.readData(data); + Serial.print("received "); + Serial.println(data); + } +} diff --git a/GyverBus/examples/GBUS/call_response_ack/call_response_rx_ack/call_response_rx_ack.ino b/GyverBus/examples/GBUS/call_response_ack/call_response_rx_ack/call_response_rx_ack.ino new file mode 100644 index 0000000..33e5667 --- /dev/null +++ b/GyverBus/examples/GBUS/call_response_ack/call_response_rx_ack/call_response_rx_ack.ino @@ -0,0 +1,34 @@ +// принимаем запрос и отправляем в ответ данные с АЦП или ack +// парный пример - call_response_rx_ack + +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// работает как отправитель и приёмник!! GBUS_FULL +GBus rx(RX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + // приняли запрос request + if (rx.gotRequest()) { + Serial.print("ack from "); + Serial.print(rx.getTXaddress()); + Serial.println(); + + // прочитали аналог + int val = analogRead(0); + Serial.print("sending "); + Serial.println(val); + + // отправили обратно + rx.sendData(rx.getTXaddress(), val); // отправить дату + //rx.sendAck(rx.getTXaddress()); // отправить в ответ ack + } +} diff --git a/GyverBus/examples/GBUS/call_response_ack/call_response_tx_ack/call_response_tx_ack.ino b/GyverBus/examples/GBUS/call_response_ack/call_response_tx_ack/call_response_tx_ack.ino new file mode 100644 index 0000000..63e56a1 --- /dev/null +++ b/GyverBus/examples/GBUS/call_response_ack/call_response_tx_ack/call_response_tx_ack.ino @@ -0,0 +1,47 @@ +// отправляем запрос и в ответ ждём данные или подтверждение ack +// пытаемся отправить несколько раз и ждём таймаут +// парный пример - call_response_tx_ack + +#include "GyverBus.h" + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +// работает как отправитель и приёмник!! GBUS_FULL +GBus tx(TX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + // отправляем запрос на RX_ADDR каждые три секунды + static uint32_t tmr; + if (millis() - tmr > 3000) { + // отправить запрос и ждать подтверждения + // (адрес, количество попыток, таймаут между ними) + byte state = tx.sendRequestAck(RX_ADDR, 3, 1000); + switch (state) { + case ACK_ERROR: Serial.println("ack error"); + break; + case ACK_ONLY: Serial.println("got ack"); + break; + case ACK_DATA: Serial.print("got data: "); + int val; + tx.readData(val); + Serial.println(val); + break; + } + tmr = millis(); + } + + /*// если нам что-то отправили + if (tx.gotData()) { + int data; + // читаем и выводим + tx.readData(data); + Serial.print("received "); + Serial.println(data); + }*/ +} diff --git a/GyverBus/examples/GBUS/raw/GBus_read_raw/GBus_read_raw.ino b/GyverBus/examples/GBUS/raw/GBus_read_raw/GBus_read_raw.ino new file mode 100644 index 0000000..2ad0c4d --- /dev/null +++ b/GyverBus/examples/GBUS/raw/GBus_read_raw/GBus_read_raw.ino @@ -0,0 +1,24 @@ +// простой пример приёма сырых данных по шине +#include "GyverBus.h" + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// пин 4, адрес 3, приёмник на 15 байт +GBus rx(RX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +void loop() { + rx.tick(); + + if (rx.gotRaw()) { + for (byte i = 0; i < rx.rawSize(); i++) { + Serial.print(rx.buffer[i]); + Serial.print(','); + } + Serial.println(); + } +} diff --git a/GyverBus/examples/GBUS/raw/GBus_send_raw/GBus_send_raw.ino b/GyverBus/examples/GBUS/raw/GBus_send_raw/GBus_send_raw.ino new file mode 100644 index 0000000..77dde99 --- /dev/null +++ b/GyverBus/examples/GBUS/raw/GBus_send_raw/GBus_send_raw.ino @@ -0,0 +1,26 @@ +// простой пример отправки сырых данных по шине +#include "GyverBus.h" + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +// пин 4, адрес 1, буфер на 15 байт +GBus tx(TX_ADDR, 15); + +void setup() { + Serial.begin(9600); +} + +// данные +byte data[] = {12, 34, 56}; + +void loop() { + if (tx.tick() == TX_COMPLETE) Serial.println("transmitted"); + + static uint32_t tmr; + if (millis() - tmr >= 1000) { + tmr = millis(); + tx.sendRaw(data, sizeof(data)); + } +} diff --git a/GyverBus/examples/GBUSmini/busy/busy.ino b/GyverBus/examples/GBUSmini/busy/busy.ino new file mode 100644 index 0000000..a9c0d9a --- /dev/null +++ b/GyverBus/examples/GBUSmini/busy/busy.ino @@ -0,0 +1,24 @@ +// периодично шлём свои данные. Шлём только тогда, когда линия не занята + +#define BUS_PIN 4 // пин +#define TX_ADDR 5 // наш адрес (мы отправитель) +#define RX_ADDR 3 // адрес приёмника + +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +void setup() { +} + +byte data[1] = {0}; +void loop() { + // тупо ждём, пока линия освободится + while(GBUS_is_busy(BUS_PIN)); + + GBUS_send_no_crc(BUS_PIN, RX_ADDR, TX_ADDR, data, sizeof(data)); + data[0]++; + delay(2000); + + // либо используем так + // if (!GBUS_is_busy(BUS_PIN)) GBUS_send_no_crc(BUS_PIN, RX_ADDR, TX_ADDR, data, sizeof(data)); + // т.е. если линия свободна - отправить +} diff --git a/GyverBus/examples/GBUSmini/call response/simple_call_response_rx/simple_call_response_rx.ino b/GyverBus/examples/GBUSmini/call response/simple_call_response_rx/simple_call_response_rx.ino new file mode 100644 index 0000000..4991025 --- /dev/null +++ b/GyverBus/examples/GBUSmini/call response/simple_call_response_rx/simple_call_response_rx.ino @@ -0,0 +1,32 @@ +// принимаем запрос и отправляем в ответ данные с АЦП + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +void setup() { + Serial.begin(9600); +} + +void loop() { + // ждём приём на адрес RX_ADDR, т.е. наш адрес RX_ADDR + byte txaddr = GBUS_read_request(RX_PIN, RX_ADDR); + if (txaddr) { + // если успешно приняли + // например читаем АЦП + int val = analogRead(0); + + Serial.print("sending "); + Serial.println(val); + + // разбиваем на байты + byte b1 = lowByte(val); + byte b2 = highByte(val); + byte buf[] = {b1, b2}; + + // отправляем обратно (по txaddr) + // с нашего адреса (RX_ADDR) + // c контролем целостности данных + GBUS_send_crc(RX_PIN, txaddr, RX_ADDR, buf, sizeof(buf)); + } +} diff --git a/GyverBus/examples/GBUSmini/call response/simple_call_response_tx/simple_call_response_tx.ino b/GyverBus/examples/GBUSmini/call response/simple_call_response_tx/simple_call_response_tx.ino new file mode 100644 index 0000000..5ad92fa --- /dev/null +++ b/GyverBus/examples/GBUSmini/call response/simple_call_response_tx/simple_call_response_tx.ino @@ -0,0 +1,28 @@ +// отправляем запрос и в ответ ждём данные с АЦП + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +byte buf[2]; + +void setup() { + Serial.begin(9600); +} + +void loop() { + // отправляем запрос каждые три секунды + static uint32_t tmr; + if (millis() - tmr > 3000) { + tmr = millis(); + GBUS_send_request(TX_PIN, RX_ADDR, TX_ADDR); + } + + if (GBUS_read_crc(TX_PIN, TX_ADDR, buf, sizeof(buf))) { + // склеиваем байты обратно в инт + int val = buf[0] | (buf[1] << 8); + Serial.print("received "); + Serial.println(val); + } +} diff --git a/GyverBus/examples/GBUSmini/call response_ack/simple_call_response_rx/simple_call_response_rx.ino b/GyverBus/examples/GBUSmini/call response_ack/simple_call_response_rx/simple_call_response_rx.ino new file mode 100644 index 0000000..e519c49 --- /dev/null +++ b/GyverBus/examples/GBUSmini/call response_ack/simple_call_response_rx/simple_call_response_rx.ino @@ -0,0 +1,19 @@ +// принимаем запрос и отправляем в ответ данные с АЦП + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +void setup() { + Serial.begin(9600); +} + +void loop() { + // ждём приём на адрес RX_ADDR, т.е. наш адрес RX_ADDR + byte txaddr = GBUS_read_request(RX_PIN, RX_ADDR); + if (txaddr) { + Serial.print("got request from "); + Serial.println(txaddr); + GBUS_send_ack(RX_PIN, txaddr, RX_ADDR); + } +} diff --git a/GyverBus/examples/GBUSmini/call response_ack/simple_call_response_tx/simple_call_response_tx.ino b/GyverBus/examples/GBUSmini/call response_ack/simple_call_response_tx/simple_call_response_tx.ino new file mode 100644 index 0000000..386d03c --- /dev/null +++ b/GyverBus/examples/GBUSmini/call response_ack/simple_call_response_tx/simple_call_response_tx.ino @@ -0,0 +1,25 @@ +// отправляем запрос с подтверждением + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +void setup() { + Serial.begin(9600); +} + +void loop() { + // отправляем запрос каждые три секунды + static uint32_t tmr; + if (millis() - tmr > 3000) { + tmr = millis(); + // отправлять запросы и ждать подтверждения приёма, т.е. пытаться достучаться + // (пин, адрес получателя, адрес отправителя, кол-во попыток, таймаут между попытками) + if (GBUS_send_request_ack(TX_PIN, RX_ADDR, TX_ADDR, 3, 500)) { + Serial.println("got ack"); + } else { + Serial.println("error"); + } + } +} diff --git a/GyverBus/examples/GBUSmini/pack data/packData_mini_read_crc/packData_mini_read_crc.ino b/GyverBus/examples/GBUSmini/pack data/packData_mini_read_crc/packData_mini_read_crc.ino new file mode 100644 index 0000000..527ec78 --- /dev/null +++ b/GyverBus/examples/GBUSmini/pack data/packData_mini_read_crc/packData_mini_read_crc.ino @@ -0,0 +1,35 @@ +// принимаем и распаковываем отправленные в примере packData_mini_send_crc данные + +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +// структура для приёма +struct myStruct { + byte val_b; + int val_i; + float val_f; +}; +myStruct rxData; // приёмная структура +byte buffer[sizeof(rxData)]; // приёмный буфер + +void setup() { + Serial.begin(9600); + + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(RX_PIN, INPUT_PULLUP); +} + +void loop() { + if (GBUS_read_crc(RX_PIN, RX_ADDR, buffer, sizeof(buffer))) { + // если успешно приняли, распаковываем + unpackDataBytes(buffer, rxData); + + // выводим проверяем + Serial.println(rxData.val_b); + Serial.println(rxData.val_i); + Serial.println(rxData.val_f); + Serial.println(); + } +} diff --git a/GyverBus/examples/GBUSmini/pack data/packData_mini_send_crc/packData_mini_send_crc.ino b/GyverBus/examples/GBUSmini/pack data/packData_mini_send_crc/packData_mini_send_crc.ino new file mode 100644 index 0000000..fe4999c --- /dev/null +++ b/GyverBus/examples/GBUSmini/pack data/packData_mini_send_crc/packData_mini_send_crc.ino @@ -0,0 +1,36 @@ +// пакуем данные любого типа (например, структура) в буфер и отправляем +// принимаем и распаковываем в примере packData_mini_read_crc + +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +// структура для отправки +struct myStruct { + byte val_b; + int val_i; + float val_f; +}; +myStruct txData; // отправная структура +byte buffer[sizeof(txData)]; // отправной буфер + +void setup() { + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(TX_PIN, INPUT_PULLUP); + + // заполняем структуру + txData.val_b = 123; + txData.val_i = -23456; + txData.val_f = 3.14; + + // пакуем структуру в буфер + packDataBytes(buffer, txData); +} + +void loop() { + // пин, адрес получателя, адрес отправителя, дата, размер + GBUS_send_crc(TX_PIN, RX_ADDR, TX_ADDR, buffer, sizeof(buffer)); + delay(2000); +} diff --git a/GyverBus/examples/GBUSmini/raw/gbus_mini_read_raw/gbus_mini_read_raw.ino b/GyverBus/examples/GBUSmini/raw/gbus_mini_read_raw/gbus_mini_read_raw.ino new file mode 100644 index 0000000..7aa4617 --- /dev/null +++ b/GyverBus/examples/GBUSmini/raw/gbus_mini_read_raw/gbus_mini_read_raw.ino @@ -0,0 +1,25 @@ +// простой пример приёма сырых данных и их разбор вручную +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define RX_PIN 4 // пин +byte data[10]; // приёмный буфер (байты) +// МИНИМУМ НА 4 БАЙТА БОЛЬШЕ, ЧЕМ ОЖИДАЕМАЯ ДАТА + +void setup() { + Serial.begin(9600); + + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(RX_PIN, INPUT_PULLUP); +} + +void loop() { + // ждём приём + if (GBUS_read_raw(RX_PIN, data, sizeof(data))) { + // если успешно приняли, выводим + for (byte i = 0; i < sizeof(data); i++) { + Serial.print(data[i]); + Serial.print(", "); + } + Serial.println(); + } +} diff --git a/GyverBus/examples/GBUSmini/raw/gbus_mini_send_raw/gbus_mini_send_raw.ino b/GyverBus/examples/GBUSmini/raw/gbus_mini_send_raw/gbus_mini_send_raw.ino new file mode 100644 index 0000000..6a973b6 --- /dev/null +++ b/GyverBus/examples/GBUSmini/raw/gbus_mini_send_raw/gbus_mini_send_raw.ino @@ -0,0 +1,17 @@ +// простая функция отправки по GBUS с контролем целостности данных +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define TX_PIN 4 // пин + +void setup() { + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(TX_PIN, INPUT_PULLUP); +} + +// отправляемая дата (байты) +byte data[] = {12, 34, 56}; + +void loop() { + GBUS_send_raw(TX_PIN, data, sizeof(data)); + delay(1000); +} diff --git a/GyverBus/examples/GBUSmini/request/gbus_mini_read_request/gbus_mini_read_request.ino b/GyverBus/examples/GBUSmini/request/gbus_mini_read_request/gbus_mini_read_request.ino new file mode 100644 index 0000000..c944e54 --- /dev/null +++ b/GyverBus/examples/GBUSmini/request/gbus_mini_read_request/gbus_mini_read_request.ino @@ -0,0 +1,21 @@ +// простой пример приёма сырых данных и их разбор вручную +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес + +void setup() { + Serial.begin(9600); + + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(RX_PIN, INPUT_PULLUP); +} + +void loop() { + // ждём приём, ловим адрес + byte txaddr = GBUS_read_request(RX_PIN, RX_ADDR); + if (txaddr) { + Serial.print("Request from "); + Serial.println(txaddr); + } +} diff --git a/GyverBus/examples/GBUSmini/request/gbus_mini_send_request/gbus_mini_send_request.ino b/GyverBus/examples/GBUSmini/request/gbus_mini_send_request/gbus_mini_send_request.ino new file mode 100644 index 0000000..69c42ff --- /dev/null +++ b/GyverBus/examples/GBUSmini/request/gbus_mini_send_request/gbus_mini_send_request.ino @@ -0,0 +1,20 @@ +// простая функция отправки по GBUS с контролем целостности данных +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +void setup() { + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(TX_PIN, INPUT_PULLUP); +} + +// отправляемая дата (байты) +byte data[] = {12, 34, 56}; + +void loop() { + // пин, адрес получателя, адрес отправителя, дата, размер + GBUS_send_request(TX_PIN, RX_ADDR, TX_ADDR); + delay(1000); +} diff --git a/GyverBus/examples/GBUSmini/with crc/gbus_mini_read_crc/gbus_mini_read_crc.ino b/GyverBus/examples/GBUSmini/with crc/gbus_mini_read_crc/gbus_mini_read_crc.ino new file mode 100644 index 0000000..6609e1c --- /dev/null +++ b/GyverBus/examples/GBUSmini/with crc/gbus_mini_read_crc/gbus_mini_read_crc.ino @@ -0,0 +1,25 @@ +// простой пример приёма сырых данных и их разбор вручную +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес +byte data[6]; // приёмный буфер (байты) + +void setup() { + Serial.begin(9600); + + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(RX_PIN, INPUT_PULLUP); +} + +void loop() { + // ждём приём, если функция вернула отличное от 0 значение + if (GBUS_read_crc(RX_PIN, RX_ADDR, data, sizeof(data))) { + // если успешно приняли + for (byte i = 0; i < sizeof(data); i++) { + Serial.print(data[i]); + Serial.print(", "); + } + Serial.println(); + } +} diff --git a/GyverBus/examples/GBUSmini/with crc/gbus_mini_send_crc/gbus_mini_send_crc.ino b/GyverBus/examples/GBUSmini/with crc/gbus_mini_send_crc/gbus_mini_send_crc.ino new file mode 100644 index 0000000..3c7f805 --- /dev/null +++ b/GyverBus/examples/GBUSmini/with crc/gbus_mini_send_crc/gbus_mini_send_crc.ino @@ -0,0 +1,20 @@ +// простая функция отправки по GBUS с контролем целостности данных +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +void setup() { + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(TX_PIN, INPUT_PULLUP); +} + +// отправляемая дата (байты) +byte data[] = {12, 34, 56}; + +void loop() { + // пин, адрес получателя, адрес отправителя, дата, размер + GBUS_send_crc(TX_PIN, RX_ADDR, TX_ADDR, data, sizeof(data)); + delay(1000); +} diff --git a/GyverBus/examples/GBUSmini/without crc/gbus_mini_read_no_crc/gbus_mini_read_no_crc.ino b/GyverBus/examples/GBUSmini/without crc/gbus_mini_read_no_crc/gbus_mini_read_no_crc.ino new file mode 100644 index 0000000..024a5ed --- /dev/null +++ b/GyverBus/examples/GBUSmini/without crc/gbus_mini_read_no_crc/gbus_mini_read_no_crc.ino @@ -0,0 +1,27 @@ +// простой пример приёма сырых данных и их разбор вручную +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define RX_PIN 4 // пин +#define RX_ADDR 3 // наш адрес +byte data[6]; // приёмный буфер (байты) + +void setup() { + Serial.begin(9600); + + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(RX_PIN, INPUT_PULLUP); +} + +void loop() { + // ждём приём, ловим адрес + byte txaddr = GBUS_read_no_crc(RX_PIN, RX_ADDR, data, sizeof(data)); + if (txaddr) { + // если успешно приняли + for (byte i = 0; i < sizeof(data); i++) { + Serial.print(data[i]); + Serial.print(", "); + } + Serial.print(" from address "); + Serial.println(txaddr); + } +} diff --git a/GyverBus/examples/GBUSmini/without crc/gbus_mini_send_no_crc/gbus_mini_send_no_crc.ino b/GyverBus/examples/GBUSmini/without crc/gbus_mini_send_no_crc/gbus_mini_send_no_crc.ino new file mode 100644 index 0000000..8198c55 --- /dev/null +++ b/GyverBus/examples/GBUSmini/without crc/gbus_mini_send_no_crc/gbus_mini_send_no_crc.ino @@ -0,0 +1,20 @@ +// простая функция отправки по GBUS с контролем целостности данных +#include "GBUSmini.h" // мини-библиотека с лёгкими функциями + +#define TX_PIN 4 // пин +#define RX_ADDR 3 // адрес приёмника +#define TX_ADDR 5 // наш адрес + +void setup() { + // ПИН ОБЯЗАТЕЛЬНО PULLUP!!!111 + pinMode(TX_PIN, INPUT_PULLUP); +} + +// отправляемая дата (байты) +byte data[] = {12, 34, 56}; + +void loop() { + // пин, адрес получателя, адрес отправителя, дата, размер + GBUS_send_no_crc(TX_PIN, RX_ADDR, TX_ADDR, data, sizeof(data)); + delay(1000); +} diff --git "a/GyverBus/examples/\320\262\321\201\320\265 \320\277\321\200\320\270\320\274\320\265\321\200\321\213 \321\201\320\276\320\262\320\274\320\265\321\201\321\202\320\270\320\274\321\213 \320\264\321\200\321\203\320\263 \321\201 \320\264\321\200\321\203\320\263\320\276\320\274.txt" "b/GyverBus/examples/\320\262\321\201\320\265 \320\277\321\200\320\270\320\274\320\265\321\200\321\213 \321\201\320\276\320\262\320\274\320\265\321\201\321\202\320\270\320\274\321\213 \320\264\321\200\321\203\320\263 \321\201 \320\264\321\200\321\203\320\263\320\276\320\274.txt" new file mode 100644 index 0000000..e69de29 diff --git a/GyverBus/keywords.txt b/GyverBus/keywords.txt new file mode 100644 index 0000000..b308254 --- /dev/null +++ b/GyverBus/keywords.txt @@ -0,0 +1,73 @@ +####################################### +# Syntax Coloring Map For GyverBus +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +GyverBus KEYWORD1 +GBus KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +tick KEYWORD2 +getStatus KEYWORD2 +gotData KEYWORD2 +getTXaddress KEYWORD2 +isBusy KEYWORD2 +sendData KEYWORD2 +readData KEYWORD2 +sendRaw KEYWORD2 +sendRequest KEYWORD2 +gotRequest KEYWORD2 +gotRaw KEYWORD2 +rawSize KEYWORD2 + +sendAck KEYWORD2 +gotAck KEYWORD2 +sendRequestAck KEYWORD2 + +GBUS_is_busy KEYWORD2 +GBUS_send_raw KEYWORD2 +GBUS_send_crc KEYWORD2 +GBUS_send_no_crc KEYWORD2 +GBUS_read_raw KEYWORD2 +GBUS_read_crc KEYWORD2 +GBUS_read_no_crc KEYWORD2 +GBUS_send_request KEYWORD2 +GBUS_read_request KEYWORD2 +GBUS_send_ack KEYWORD2 +GBUS_read_ack KEYWORD2 +GBUS_send_request_ack KEYWORD2 + +GBUS_crc_update KEYWORD2 +packDataBytes KEYWORD2 +unpackDataBytes KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +GBUS_IDLE LITERAL1 +TRANSMITTING LITERAL1 +TX_OVERFLOW LITERAL1 +TX_COMPLETE LITERAL1 +RECEIVING LITERAL1 +RX_ERROR LITERAL1 +RX_ABORT LITERAL1 +RX_OVERFLOW LITERAL1 +RX_ADDRESS_ERROR LITERAL1 +RX_CRC_ERROR LITERAL1 +RX_REQUEST LITERAL1 +RX_COMPLETE LITERAL1 +RX_ACK LITERAL1 + +ACK_ERROR LITERAL1 +ACK_ONLY LITERAL1 +ACK_DATA LITERAL1 + +GBUS_RX LITERAL1 +GBUS_TX LITERAL1 +GBUS_FULL LITERAL1 +GBUS_NO_CRC LITERAL1 +GBUS_CRC LITERAL1 \ No newline at end of file diff --git a/GyverBus/library.properties b/GyverBus/library.properties new file mode 100644 index 0000000..9ea9f1e --- /dev/null +++ b/GyverBus/library.properties @@ -0,0 +1,9 @@ +name=GyverBus +version=1.0 +author=AlexGyver +maintainer=AlexGyver +sentence=Communicating by GBUS interface +paragraph=GBUS is very simple and reliable one-wire interface for transmitting and receiving data +category=Communication +url=https://github.com/AlexGyver/GyverLibs +architectures=* \ No newline at end of file diff --git a/README.md b/README.md index 88c34c7..cc47cad 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ## Написанные с нуля/модифицированные библиотеки для Arduino [![AlexGyver YouTube](http://alexgyver.ru/git_banner.jpg)](https://www.youtube.com/channel/UCgtAOyEQdAyjvm9ATCi_Aig?sub_confirmation=1) > Внимание! Библиотеки написаны ютубером-ардуинщиком, возможна высокая концентрация костылей и стандартных подходов. Но всё работает замечательно! +![Logo](/logos/libs.png) ## Содержание ### Железки * [GyverButton](#GyverButton) - расширенный контроль кнопкой @@ -12,6 +13,7 @@ * [GyverRGB](#GyverRGB) - управление RGB светодиодами и лентами * [GyverTM1637](#GyverTM1637) - управление дисплеем на TM1637 * [ServoSmooth](#ServoSmooth) - плавное управление сервоприводами +* [GyverBus](#GyverBus) - связь Ардуинок по одному проводу ### Периферия МК * [directADC](#directADC) - расширенный контроль АЦП и компаратора @@ -43,6 +45,141 @@ * [microDS18B20](#microDS18B20) - микро библиотека для работы с датчиком температуры ds18b20 * [GyverUART](#GyverUART) - облегчённый и ускоренный Serial * [minimLibs](#minimLibs) - набор классов для работы с железками +--- + + +### GyverBus v1.0 [СКАЧАТЬ](https://github.com/AlexGyver/GyverLibs/releases/download/GyverBus/GyverBus.zip), [ДОКУМЕНТАЦИЯ](https://alexgyver.ru/gyverbus/) +GyverBus - библиотека для общения по протоколу GBUS +- Очень простой, надёжный, устойчивый к помехам и задержкам, но медленный интерфейс связи на базе UART +- Двухсторонняя связь по одному проводу +- Асинхронная отправка и чтение (на базе millis()) +- Двухсторонняя совместимость с аппаратным UART +- Возможность принимать и отправлять данные внутри сети Ардуинок +- Адресация до 254 устройств в сети (от 1 до 255) +- Всеядная функция отправки и приёма (ест переменные, структуры, массивы) +- Встроенная проверка CRC (контроль целостности) пакета данных +- Возможность отправки и чтения короткого "запроса" +- Поддерживаются все Arduino-совместимые платы +- Сама библиотека предоставляет возможности по отладке (коды ошибок) + - В примерах есть компактные варианты чтения и отправки данных, влезет даже в ATtiny + +#### Методы и функции библиотеки +
+РАЗВЕРНУТЬ +

+Смотри примеры в папке examples! + +```C + ==================== GyverBus.h ==================== + Инициализация: + GBus<пин, тип, crc> объект(адрес, размер буфера) + - пин: номер пина + - тип: GBUS_FULL - двухсторонняя связь (активен по умолчанию, можно не указывать) + - тип: GBUS_TX - только отправка (экономит память) + - тип: GBUS_RX - только приём (экономит память) + - crc: GBUS_CRC - с контролем целостности данных CRC (активен по умолчанию, можно не указывать) + - crc: GBUS_NO_CRC - отключить ожидание и проверку CRC + + Список методов: + tick() - отправляет и принимает данные. Вызывать хотя бы каждую миллисекунду. Возвращает коды статусов, тип GBUSstatus (enum) + getStatus() - возвращает коды статусов (такие же как tick()), тип GBUSstatus (enum) + + sendData(адрес, дата) - вводит данные на отправку по адресу получателя. Принимает любй тип данных (переменные, массивы, структуры). Отправка начнётся автоматически после "освобождения" линии + gotData() - вернёт true, если новый пакет данных принят без ошибок. Сам сбрасывается в false + readData(дата) - выводит данные из внутреннего буфера в указанную "переменную" (переменные, массивы, структуры) + + sendRequest(адрес) - отправить "запрос" по адресу получателя + gotRequest() - вернёт true, если на наш адрес пришёл запрос. Сам сбрасывается в false. Адрес отправителя можно узнать в getTXaddress() + + getTXaddress() - возвращает адрес отправителя с последнего успешного получения данных или запроса + isBusy() - возвращает true, если линия занята. Возвращает false, если с момента последнего общения по линии прошло GBUS_BUSY_TIMEOUT миллисекунд + + sendAck(адрес) - отправляет ack (ответ на запрос) по адресу + gotAck() - вернёт true, если на наш адрес пришёл ack (ответ на запрос). Сам сбрасывается в false. Адрес отправителя можно узнать в getTXaddress() + + sendRequestAck(адрес, кол-во попыток, таймаут) - отправляет реквест на адрес. + Ждёт ответ (ack или data), если не дожидается в теч. таймаута - отправляет ещё раз. + Если количество попыток превышено - возвращает ACK_ERROR (0 ноль). + Если принят ack - возвращает ACK_ONLY (1 единица) + Если принята дата - возвращает ACK_DATA (2 два) + ФУНКЦИЯ БЛОКИРУЮЩАЯ + Смотри примеры call_response_tx_ack и call_response_rx_ack + + sendRaw(байтовый массив, размер) - отправит сырые байты (без протокола) по шине. Смотри примеры в папке raw + gotRaw() - вернёт true, были приняты какие-то данные (приём завершён успешно). Сам сбрасывается в false. + rawSize() - вернёт количество принятых байт (последний успешный приём). Иначе вернёт 0 + + buffer - можно обращаться как к массиву. Встроенный буфер библиотеки + + ==================== GBUSmini.h ==================== + // Все функции (кроме GBUS_is_busy) блокируют выполнение кода на время приёма/отправки + +// Возвращает true, если линия занята. Таймаут GBUS_BUSY_TIMEOUT мс +bool GBUS_is_busy(byte pin); + +// Отправить сырые данные (пин, дата, размер) +// Формат посылки GBUS [суммарное количество байт, адрес получателя, адрес отправителя, ...байты даты..., CRC] +// Функция блокирующая на всё время отправки +// 640 байт (Arduino Nano), 150 байт ATtiny13 (microCore) +void GBUS_send_raw(byte pin, byte* data, byte size); + +// Отправить данные с CRC (пин, адрес получателя, адрес отправителя, дата, размер) +// Функция блокирующая на всё время отправки +// 740 байт (Arduino Nano), 230 байт ATtiny13 (microCore) +void GBUS_send_crc(byte pin, byte to, byte from, byte* data, byte size); + +// Отправить данные без CRC (пин, адрес получателя, адрес отправителя, дата, размер) +// Функция блокирующая на всё время отправки +// 700 байт (Arduino Nano), 200 байт ATtiny13 (microCore) +void GBUS_send_no_crc(byte pin, byte to, byte from, byte* data, byte size); + +// Прочитать сырые данные (пин, дата, размер) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма. +// Возвращает количество принятых байт при завершении приёма +// 520 байт (Arduino Nano), 220 байт ATtiny13 (microCore) +byte GBUS_read_raw(byte pin, byte* buf, byte size); + +// Прочитать данные с CRC (пин, наш адрес, дата, размер) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +// 650 байт (Arduino Nano), 330 байт ATtiny13 (microCore) +byte GBUS_read_crc(byte pin, byte addr, byte* buf, byte size); + +// Прочитать данные без CRC (пин, наш адрес, дата, размер) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +// 622 байт (Arduino Nano), 300 байт ATtiny13 (microCore) +byte GBUS_read_no_crc(byte pin, byte addr, byte* buf, byte size); + +// Отправить запрос (пин, адрес получателя, адрес отправителя) +// Функция блокирующая на всё время отправки +// 640 байт (Arduino Nano), 150 байт ATtiny13 (microCore) +void GBUS_send_request(byte pin, byte to, byte from); + +// Принять запрос (пин, наш адрес) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +// 540 байт (Arduino Nano), 220 байт ATtiny13 (microCore) +byte GBUS_read_request(byte pin, byte addr); + +// Отправить подтверждение (пин, адрес получателя, адрес отправителя) +// Функция блокирующая на всё время отправки +void GBUS_send_ack(byte pin, byte to, byte from); + +// Принять подтверждение (пин, наш адрес) +// Вызывать как можно чаще, чтобы не пропустить. Функция блокирующая на всё время приёма +// Возвращает адрес отправителя при успешном завершении приёма. При ошибке возвращает 0 +byte GBUS_read_ack(byte pin, byte addr); + +// Отправить запрос и ждать подтверждения приёма, т.е. пытаться достучаться +// (пин, адрес получателя, адрес отправителя, кол-во попыток, таймаут между попытками) +// возвращает 0 при таймауте, 1 при успехе (получили ack) +// см. примеры call response _ack +byte GBUS_send_request_ack(byte pin, byte to, byte from, byte tries, int timeout); +``` +

+
+ --- diff --git a/logos/accelMotor.png b/logos/accelMotor.png new file mode 100644 index 0000000..caa1140 Binary files /dev/null and b/logos/accelMotor.png differ diff --git a/logos/adclogo.png b/logos/adclogo.png new file mode 100644 index 0000000..ac81660 Binary files /dev/null and b/logos/adclogo.png differ diff --git a/logos/bme280.png b/logos/bme280.png new file mode 100644 index 0000000..63aeeeb Binary files /dev/null and b/logos/bme280.png differ diff --git a/logos/btnLogo.png b/logos/btnLogo.png new file mode 100644 index 0000000..6365d93 Binary files /dev/null and b/logos/btnLogo.png differ diff --git a/logos/buildLogo.png b/logos/buildLogo.png new file mode 100644 index 0000000..d5a67e2 Binary files /dev/null and b/logos/buildLogo.png differ diff --git a/logos/busLogo.png b/logos/busLogo.png new file mode 100644 index 0000000..e0c00f2 Binary files /dev/null and b/logos/busLogo.png differ diff --git a/logos/direcrtimersLogo.png b/logos/direcrtimersLogo.png new file mode 100644 index 0000000..26d579e Binary files /dev/null and b/logos/direcrtimersLogo.png differ diff --git a/logos/ds18b20Logo.png b/logos/ds18b20Logo.png new file mode 100644 index 0000000..305510d Binary files /dev/null and b/logos/ds18b20Logo.png differ diff --git a/logos/ds3231logo.png b/logos/ds3231logo.png new file mode 100644 index 0000000..ab724b2 Binary files /dev/null and b/logos/ds3231logo.png differ diff --git a/logos/encLogo.png b/logos/encLogo.png new file mode 100644 index 0000000..8d20f5d Binary files /dev/null and b/logos/encLogo.png differ diff --git a/logos/filLogo.png b/logos/filLogo.png new file mode 100644 index 0000000..96643dd Binary files /dev/null and b/logos/filLogo.png differ diff --git a/logos/gtimer.png b/logos/gtimer.png new file mode 100644 index 0000000..bdd8526 Binary files /dev/null and b/logos/gtimer.png differ diff --git a/logos/gtimer012.png b/logos/gtimer012.png new file mode 100644 index 0000000..bdc2b7d Binary files /dev/null and b/logos/gtimer012.png differ diff --git a/logos/hacksLogo.png b/logos/hacksLogo.png new file mode 100644 index 0000000..2bb71a1 Binary files /dev/null and b/logos/hacksLogo.png differ diff --git a/logos/lcdLogo.png b/logos/lcdLogo.png new file mode 100644 index 0000000..ad6cc75 Binary files /dev/null and b/logos/lcdLogo.png differ diff --git a/logos/libs.png b/logos/libs.png new file mode 100644 index 0000000..6665ac6 Binary files /dev/null and b/logos/libs.png differ diff --git a/logos/microLED.png b/logos/microLED.png new file mode 100644 index 0000000..2588d2d Binary files /dev/null and b/logos/microLED.png differ diff --git a/logos/motorLogo.png b/logos/motorLogo.png new file mode 100644 index 0000000..d9d3c41 Binary files /dev/null and b/logos/motorLogo.png differ diff --git a/logos/oledLogo.png b/logos/oledLogo.png new file mode 100644 index 0000000..86d0940 Binary files /dev/null and b/logos/oledLogo.png differ diff --git a/logos/pidLogo.png b/logos/pidLogo.png new file mode 100644 index 0000000..59ea2c7 Binary files /dev/null and b/logos/pidLogo.png differ diff --git a/logos/power.png b/logos/power.png new file mode 100644 index 0000000..6227ba6 Binary files /dev/null and b/logos/power.png differ diff --git a/logos/pwmLogo.png b/logos/pwmLogo.png new file mode 100644 index 0000000..8ba5533 Binary files /dev/null and b/logos/pwmLogo.png differ diff --git a/logos/pwmrelay.png b/logos/pwmrelay.png new file mode 100644 index 0000000..ee4838b Binary files /dev/null and b/logos/pwmrelay.png differ diff --git a/logos/relayLogo.png b/logos/relayLogo.png new file mode 100644 index 0000000..c83ed52 Binary files /dev/null and b/logos/relayLogo.png differ diff --git a/logos/rgbLogo.png b/logos/rgbLogo.png new file mode 100644 index 0000000..40c17f1 Binary files /dev/null and b/logos/rgbLogo.png differ diff --git a/logos/rtoslogo.png b/logos/rtoslogo.png new file mode 100644 index 0000000..587c701 Binary files /dev/null and b/logos/rtoslogo.png differ diff --git a/logos/servoLogo.png b/logos/servoLogo.png new file mode 100644 index 0000000..f56d0fb Binary files /dev/null and b/logos/servoLogo.png differ diff --git a/logos/stepperLogo.jpg b/logos/stepperLogo.jpg new file mode 100644 index 0000000..54a7b38 Binary files /dev/null and b/logos/stepperLogo.jpg differ diff --git a/logos/stepperLogo.png b/logos/stepperLogo.png new file mode 100644 index 0000000..577947d Binary files /dev/null and b/logos/stepperLogo.png differ diff --git a/logos/timerslogo.png b/logos/timerslogo.png new file mode 100644 index 0000000..bdfda18 Binary files /dev/null and b/logos/timerslogo.png differ diff --git a/logos/tm1637.png b/logos/tm1637.png new file mode 100644 index 0000000..5c0272d Binary files /dev/null and b/logos/tm1637.png differ diff --git a/logos/uartLogo.png b/logos/uartLogo.png new file mode 100644 index 0000000..be17b2d Binary files /dev/null and b/logos/uartLogo.png differ diff --git a/logos/wdtLogo.png b/logos/wdtLogo.png new file mode 100644 index 0000000..ecb7e19 Binary files /dev/null and b/logos/wdtLogo.png differ diff --git a/logos/wirelogo.png b/logos/wirelogo.png new file mode 100644 index 0000000..4986a2a Binary files /dev/null and b/logos/wirelogo.png differ