Несколько интересных и полезных библиотек

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Всем привет, решил поделиться своими библиотеками, написанными для разных проектов. Библиотеки в целом заменяют часто используемые стандартные конструкции, упрощая и ускоряя написание кода. Сразу хочу предупредить, что написаны они человеком-ардуинщиком-самоучкой, т.е. никаких ассемблеров, сплошь стандартные костыли и функции. Но всё работает, и работает отлично для моих целей и целей типичного "новичка". Актуальные версии и краткое описание методов всегда находится здесь https://github.com/AlexGyver/GyverLibs . Описание продублировано из файла .h, к каждой библиотеке идёт пачка примеров. Никаких релизов не делал, качайте всей папкой...

Что внутри:

GyverButton v2.6

Библиотека для многофункциональной отработки нажатия кнопок с Arduino. Возможности:

  • Работа с нормально замкнутыми и нормально разомкнутыми кнопками
  • Работа с подключением PULL_UP и PULL_DOWN
  • Опрос кнопки с программным антидребезгом контактов
  • Настраиваемое время антидребезга
  • Отработка нажатия, удерживания, отпускания, клика по кнопке
  • Настраиваемый таймаут удержания
  • Отработка одиночного, двойного и тройного нажатия (вынесено отдельно)
  • Отработка любого количества нажатий кнопки (функция возвращает количество нажатий)
  • Настраиваемый таймаут повторного нажатия/удержания
  • Функция изменения значения переменной с заданным шагом и заданным интервалом по времени
  • Возможность опрашивать не кнопку, а напрямую давать величину (все возможности библиотеки для матричных и резистивных клавиатур)


GyverEncoder v2.5

Библиотека для отработки энкодера с Arduino. Возможности:

  • Отработка поворота с антидребезгом
  • Отработка нажатия кнопки с антидребезгом
  • Отработка нажатия и удержания кнопки
  • Отработка "нажатого поворота"
  • Работа с двумя типами экнодеров


GyverFilters v1.3

Библиотека с некоторыми удобными фильтрами для Arduino:

  • GFilterRA - компактная альтернатива фильтра экспоненциальное бегущее среднее (Running Average)
  • GMedian3 - быстрый медианный фильтр 3-го порядка (отсекает выбросы)
  • GMedian - медианный фильтр N-го порядка. Порядок настраивается в GyverFilters.h - MEDIAN_FILTER_SIZE
  • GABfilter - альфа-бета фильтр (разновидность Калмана для одномерного случая)
  • GKalman - упрощённый Калман для одномерного случая (на мой взгляд лучший из фильтров)


GyverTimer v1.2

Компактная альтернатива конструкции таймера с millis() / micros(), обеспечивающая удобную мультизадачность на Arduino

  • Вся работа с таймером заменяется одной функцией
  • Миллисекундный и микросекундный таймер
  • Автоматический и ручной режим работы


GyverHacks v2.0

Библиотека с некоторыми удобными хаками для Arduino UNO/NANO/MINI (atmega328):

  • Быстрые аналоги стандартных функций чтения/записи
  • Изменение частоты ШИМ пинов (3, 5, 6, 9, 10, 11)
  • Установка ШИМ на пинах 9 и 10 в режим 10 бит (abalogWrite 0-1023)
  • Генерация ШИМ на ЛЮБОМ пине (частота ~150 Гц)
  • Измерение напряжения питания + калибровка константы
  • Перевод напряжения питания в проценты по графику разряда для разных типов АКБ
  • Измерение температуры ядра


GyverMotor v1.0

Библиотека для удобного управления моторчиками через драйвер полного моста для Arduino

  • Контроль скорости и направления вращения
  • Встроенный инструмент для настройки частоты ШИМ
  • Работа с 10 битным ШИМом


GyverRGB v1.6

Библиотека для удобного управления RGB светодиодами и лентами для Arduino

  • Работа в пространстве RGB
  • Работа в пространстве HSV
  • Установка цвета в формате HEX
  • 16 предустановленных цветов Доступные цвета для setHEX
    • WHITE - белый
    • SILVER - серебро
    • GRAY - серый
    • BLACK - чёрный
    • RED - красный
    • MAROON - бордовый
    • YELLOW - жёлтый
    • OLIVE - олива
    • LIME - лайм
    • GREEN - зелёный
    • AQUA - аква
    • TEAL - цвет головы утки чирка https://odesign.ru/teal-color/
    • BLUE - голубой
    • NAVY - тёмно-синий
    • PINK - розовый
    • PURPLE - пурпурный
  • Настройка полярности ШИМ
  • Функция плавной смены цвета
  • Возможность управления 6-ю RGB диодами/лентами с одной Arduino (встроенный генератор ШИМ на ВСЕХ 20 пинах atmega328)


GyverTM1637 v1.1

Бибилотека для 7 сегментного дисплея на чипе TM1637 с кучей приколюх

  • Вывод цифр массивом или прицельно
  • Вывод букв из списка доступных (листай ниже) массивом или прицельно
  • Отдельная функция вывода часов и минут (часы без нуля слева, минуты с нулём) 3 разных эффекта
  • Вывод числа от -999 до 9999 с учётом знака
  • Готовая функция бегущей строки
  • Функции смены яркости и состояния двоеточия автоматически обновляют дисплей
  • Функция обновления значения с эффектом вертикальной прокрутки
  • Функция обновления значения с эффектом скручивания (лучше один раз увидеть)


GyverPID v1.0

Библиотека классического PID регулятора для Arduino

  • Время одного расчёта около 90 мкс
  • Режим работы по величине или по её изменению (для интегрирующих процессов)
  • Возвращает результат по встроенному таймеру или в ручном режиме


GyverRelay v1.0

Библиотека классического релейного регулятора для Arduino

  • Обратная связь по скорости изменения величины
  • Настройка гистерезиса, коэффициента усиления ОС, направления регулирования
  • Возвращает результат по встроенному таймеру или в ручном режиме


GyverRTOS v1.0

Система реального времени для Arduino: максимальное энергосбережение и мультизадачность

  • Во время сна функция millis() не работает, вместо неё используется переменная mainTimer, которая автоматически увеличивается при каждом пробуждении на время сна (SLEEP_PERIOD) В ХОЛОСТОМ РЕЖИМЕ
  • Выполнение функций занимает время, поэтому ЕСЛИ ВЫПОЛНЯЕТСЯ ЗАДАЧА, время выполнения тоже автоматически суммируется в mainTimer
  • МЫ создаём несколько функций с разным периодом выполнения (задачи)
  • Настраиваем период пробуждения системы (минимально 15 мс) Далее всё автоматически:
  • Рассчитывается время до выполнения самой "ближней" задачи
  • Система периодически просыпается и считает таймеры
  • При наступлении времени выполнения ближайшей задачи, она выполняется. После этого снова выполняется расчёт времени до новой ближайшей задачи

    Как итог: Ардуино спит (в зависимости от периодов) 99.999% времени, просыпаясь только для проверки флага и расчёта таймера СМОТРИ ПРИМЕР
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Абалдеть! Ну, спасибо :)))

SLKH
Онлайн
Зарегистрирован: 17.08.2015

Спасибо!

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Попытка скомпилировать пример в IDE 1.8.5 дала следующее


Gbutton_example:5:13: error: expected ',' or '...' before numeric constant

 #define PIN 3    // кнопка подключена сюда (PIN --- КНОПКА --- GND)

             ^

sketch\GyverButton.h:27:18: note: in expansion of macro 'PIN'

  GButton(uint8_t PIN, boolean type, boolean dir); // класс кнопки, принимает PIN пин, тип type (HIGH_PULL / LOW_PULL) и направление dir (NORM_OPEN / NORM_CLOSE)

                  ^

In file included from C:\Temp\GyverLibs-master\GyverButton\examples\Gbutton_example\Gbutton_example.ino:7:0:

sketch\GyverButton.h:27:2: error: 'GButton::GButton(uint8_t)' cannot be overloaded

  GButton(uint8_t PIN, boolean type, boolean dir); // класс кнопки, принимает PIN пин, тип type (HIGH_PULL / LOW_PULL) и направление dir (NORM_OPEN / NORM_CLOSE)

  ^

sketch\GyverButton.h:25:5: error: with 'GButton::GButton(uint8_t)'

     GButton(uint8_t pin);        // класс кнопки, принимает пин

     ^

sketch\GyverButton.cpp: In constructor 'GButton::GButton(uint8_t, boolean, boolean)':

sketch\GyverButton.cpp:13:22: warning: cannot call constructor 'GButton::GButton' directly [-fpermissive]

  GButton::GButton(PIN);

                      ^

sketch\GyverButton.cpp:13:22: note: for a function-style cast, remove the redundant '::GButton'

exit status 1
expected ',' or '...' before numeric constant

Заменил PIN на _PIN_ - скомпилировалось

Скетч использует 3234 байт (10%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 273 байт (13%) динамической памяти, оставляя 1775 байт для локальных переменных. Максимум: 2048 байт.

при этом пустой скетч компилируется

Скетч использует 444 байт (1%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.

Не многовато ли для кнопки-то?

Попробовал пример с RTOS. Результат

In file included from C:\Temp\\GyverLibs-master\GyverRTOS\examples\multitaskNew\multitaskNew.ino:1:0:

sketch\GyverRTOS.h:110:28: warning: unused parameter 'buf' [-Wunused-parameter]

 void GRTOS::wake(uint32_t* buf, uint32_t* mainTimer) {

                            ^

sketch\GyverRTOS.h: In member function 'uint32_t Gtask::tick(uint32_t*, uint32_t*)':

sketch\GyverRTOS.h:169:1: warning: no return statement in function returning non-void [-Wreturn-type]

 }

 ^

Скетч использует 2598 байт (8%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 268 байт (13%) динамической памяти, оставляя 1780 байт для локальных переменных. Максимум: 2048 байт.

Попробовал пример с таймером. Компиляция

sketch\GyverTimer.cpp: In member function 'boolean GTimer_ms::isReady()':

sketch\GyverTimer.cpp:19:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

  if ((long)millis() > _timer) {

Предположил, что для больших интервалов это не работает. Полез в код - всё ещё хуже, таймер не работает для интервалов больших, чем 65535 миллисекунд, т.к. тип переменной, задающей интервал - uint16_t.

Посмотрел код внимательнее - всё даже ещё хуже. 

Во-первых, таймер всегда врёт на миллисекунду, т.к. сравнение идёт на ">", а не на ">=". Пример:

#include "GyverTimer.h"

GTimer_ms myTimer1(100);

void setup() {
  Serial.begin(57600);
}

void loop() {
	if (myTimer1.isReady()) {
		Serial.print(millis());
		Serial.println(" - 100 ms elapsed");
	}
}

/////////////////   результат
// 101 - 100 ms elapsed
// 202 - 100 ms elapsed
// 303 - 100 ms elapsed
// 404 - 100 ms elapsed
// 505 - 100 ms elapsed
// 606 - 100 ms elapsed
// 707 - 100 ms elapsed
// 808 - 100 ms elapsed
// 909 - 100 ms elapsed
// 1010 - 100 ms elapsed
// 1111 - 100 ms elapsed
// 1212 - 100 ms elapsed
// 1313 - 100 ms elapsed
// 1414 - 100 ms elapsed
// 1515 - 100 ms elapsed
// 1616 - 100 ms elapsed
// 1717 - 100 ms elapsed
// 1818 - 100 ms elapsed
// 1920 - 100 ms elapsed
// 2021 - 100 ms elapsed
// 2122 - 100 ms elapsed
// 2223 - 100 ms elapsed
// 2324 - 100 ms elapsed
// 2425 - 100 ms elapsed
// 2526 - 100 ms elapsed
// 2627 - 100 ms elapsed
// 2728 - 100 ms elapsed
// 2829 - 100 ms elapsed

Но, это ещё не всё. Переменная _mode нигде и никак не инициализируется, а значит, если создавать экземпляр класса не статически, а динамически (на стеке или в куче), то поведение попросту непредсказуемо. Пример.

#include "GyverTimer.h"

void setup() {
  Serial.begin(57600);
}

void	myFunc() {
	char * s1 = (char *) "Stupid msg 1";
	char * s2 = (char *) "Stupid msg 2";
	String s = s1;
	s += s2;
	Serial.println(s);
}


void loop() {
	myFunc();
	GTimer_ms * myTimer1 = new GTimer_ms(100);
	while (true) {
		if (myTimer1->isReady()) {
			Serial.print(millis());
			Serial.println(" - 100 ms elapsed");
		}
	}
}

////////// результат
// Stupid msg 1Stupid msg 2
//Stupid msg 1Stupid msg 2
//101 - 100 ms elapsed
//101 - 100 ms elapsed
//101 - 100 ms elapsed
//101 - 100 ms elapsed
//104 - 100 ms elapsed
//108 - 100 ms elapsed
//112 - 100 ms elapsed
//115 - 100 ms elapsed
//119 - 100 ms elapsed
//123 - 100 ms elapsed
//126 - 100 ms elapsed
//131 - 100 ms elapsed
//135 - 100 ms elapsed
//138 - 100 ms elapsed
//142 - 100 ms elapsed
//146 - 100 ms elapsed
//149 - 100 ms elapsed
//153 - 100 ms elapsed
//157 - 100 ms elapsed
//160 - 100 ms elapsed
//164 - 100 ms elapsed
//168 - 100 ms elapsed
//172 - 100 ms elapsed
//176 - 100 ms elapsed
//180 - 100 ms elapsed
//183 - 100 ms elapsed
//187 - 100 ms elapsed
//190 - 100 ms elapsed
//194 - 100 ms elapsed
//198 - 100 ms elapsed
//201 - 100 ms elapsed
//205 - 100 ms elapsed
//209 - 100 ms elapsed
//212 - 100 ms elapsed
//217 - 100 ms elapsed
//221 - 100 ms elapsed
//224 - 100 ms elapsed
//228 - 100 ms elapsed
//232 - 100 ms elapsed
//235 - 100 ms elapsed
//239 - 100 ms elapsed
//243 - 100 ms elapsed
//246 - 100 ms elapsed
//250 - 100 ms elapsed
//254 - 100 ms elapsed
//258 - 100 ms elapsed
//262 - 100 ms elapsed
//266 - 100 ms elapsed
//269 - 100 ms elapsed
//273 - 100 ms elapsed
//276 - 100 ms elapsed
//280 - 100 ms elapsed
//284 - 100 ms elapsed
//287 - 100 ms elapsed
//291 - 100 ms elapsed
//295 - 100 ms elapsed
//299 - 100 ms elapsed
//303 - 100 ms elapsed
//307 - 100 ms elapsed
//310 - 100 ms elapsed
//314 - 100 ms elapsed
//318 - 100 ms elapsed
//321 - 100 ms elapsed
//325 - 100 ms elapsed
//329 - 100 ms elapsed
//332 - 100 ms elapsed
//336 - 100 ms elapsed
//340 - 100 ms elapsed
//344 - 100 ms elapsed
//348 - 100 ms elapsed
//352 - 100 ms elapsed
//355 - 100 ms elapsed
//359 - 100 ms elapsed
//362 - 100 ms elapsed
//366 - 100 ms elapsed
//370 - 100 ms elapsed
//373 - 100 ms elapsed
//377 - 100 ms elapsed
//381 - 100 ms elapsed
//385 - 100 ms elapsed
//389 - 100 ms elapsed
//393 - 100 ms elapsed
//396 - 100 ms elapsed
//400 - 100 ms elapsed
//404 - 100 ms elapsed
//407 - 100 ms elapsed
//411 - 100 ms elapsed
//415 - 100 ms elapsed
//418 - 100 ms elapsed
//422 - 100 ms elapsed
//427 - 100 ms elapsed
//430 - 100 ms elapsed
//434 - 100 ms elapsed
//438 - 100 ms elapsed
//441 - 100 ms elapsed
//445 - 100 ms elapsed
//448 - 100 ms elapsed
//452 - 100 ms elapsed
//456 - 100 ms elapsed
//459 - 100 ms elapsed
//463 - 100 ms elapsed
//467 - 100 ms elapsed
//471 - 100 ms elapsed
//475 - 100 ms elapsed
//479 - 100 ms elapsed
//482 - 100 ms elapsed
//486 - 100 ms elapsed
//490 - 100 ms elapsed

Стоит здесь закомментировать строку 17 - всё работает нормально (врёт на 1 мс как обычно, но работает), а вот с той строкой наблюдаем бред, который я привёл.

В общем, работа проделана большая, но, к сожалению, качество - как у большинства "суперлиб" - "Хотели, как лучше, а получилось ..."

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вот же не ленивый!

А ТС-то критики не просил. Я уже давно избегаю критиковать, когда явно не просят.

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Спасибо, поправим. Это не суперлиба, писалось для личного удобства

Во всех примерах автоматом подключается Serial, которая и жрёт. В кнопке одна переменная uint_32, остальные булин флаги

Logik
Offline
Зарегистрирован: 05.08.2014

//Библиотека для многофункциональной отработки нажатия кнопок с Arduino.

Хороше хоть Калапуций на форуме не дожил. ;)

b707
Онлайн
Зарегистрирован: 26.05.2017

Ворота пишет:

В общем, работа проделана большая, но, к сожалению, качество - как у большинства "суперлиб" - "Хотели, как лучше, а получилось ..."

Почему то желание писать библиотеки и делится ими возникает в основном у тех, кому еще рано это делать. А когда люди дорастают до нужного уровня - желание писать библиотеки для новичков почему-то пропадает :)

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Если чё, то остальные я не смотрел. Внимательно только по таймеру прошёлся. Боюсь, что в остальных тоже хватает :(

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

AlexGyver пишет:

Это не суперлиба, писалось для личного удобства

Да нет, без дураков и безо всякого стёба - масштаб проделанной работы реально впечатляет и вызывает уважение.

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Инициализировал все пустые булины, инициализацию тоже поправил где с дефайном совпасть может. На конструктивную критику не рассчитывал, но опыт рождается в исправлении своих же косяков =) так что буду рад узнать о других

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexGyver - а можно кратенько обрисовать ваш опыт в программировании вообще на Си и для МК в частности?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

AlexGyver пишет:

 так что буду рад узнать о других

как говорил наш зам декана - каждая последняя ошибка в программе является предпоследней

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Кратенько:

- Сайт https://alexgyver.ru/  там в разделе "проекты"

- Все мои проекты (включая то чего нет на сайте) также есть тут https://github.com/AlexGyver

- Ну и в формате видосов тут https://www.youtube.com/channel/UCgtAOyEQdAyjvm9ATCi_Aig

- + Этот пакет библиотек, написанных "потому что интересно и хочется упростить себе жизнь"

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Алекс, приветствую! Буду краток: сам виноват, держись ;) В том смысле - что у нас тут специфическая и открытая атмосфера, на чины и регалии - внимания ноль, всё по делу и жёстко ;)

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexGyver пишет:

Кратенько:

- Сайт https://alexgyver.ru/  там в разделе "проекты"

- Все мои проекты (включая то чего нет на сайте) также есть тут https://github.com/AlexGyver

Алекс, я же немного не об этом спрашивал. Проекты - это хорошо, но чтобы оценить их уровень, их надо серьезно разобрать. Сами по себе проекты ничего не доказывают... вон у известного ардуинщика Осипова сколько проектов на Ютубе, но все в основном либо элементарные. а как что посложнее - так косяк на косяке.

просто при всем уважении к работе, то, что Ворота вытащил из библиотеки Таймер - это полное непонимание основ работы МК, с таким уровнем библиотеки выкладывать стыдно.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Нормально все. Поменьшей мере автор библиотеки научился чему нибудь. И да некоторые ходы похожи на мои, хотя я не их первоткрыватель.  И при чем тут понимание МК. Главное понимать как можно строить большие проекты на Си в среде Ардуино.

AlexGyver
Offline
Зарегистрирован: 12.03.2017

С каких пор >= и > это основы работы МК? Даже если и так, то я ардуинщик, вообще не программист и не микроконтроллерщик, мне не стыдно

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andycat пишет:

горорил наш зам декана - каждая последняя ошибка в программе является предпоследней

Это он цитировал фундаментальный закон - "every last bug you found is actually the penultimate".

Авторство формулировки приписывают многим (например, Дейкстре), но Кнут вроде говорил, что он точно знает, что оригинальный автор - Фредерик Брукс.

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexGyver пишет:
я ардуинщик, вообще не программист и не микроконтроллерщик, мне не стыдно

какого фига вы тогда беретесь писать библиотеки, если вы не программист?

Дайте угадаю - потому что в свое время вы с огромным трудом разобрались, как же различить одинарное и двойное нажатие кнопки - и потому решили осчастливить новичков. чтоб они так не мучались? Увы и ах - эти мучения новичкам необходимы, без них они вряд ли освоят то, что освоили вы. А не новичкам ваши библиотеки тем более не нужны, потому что в силу того, что "вы не программист" - написаны они криво, содержат кучу как мелких, так и грубых ошибок (таких как переменная типа int для миллис). занимают кучу места и требуют много лишней памяти.

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Догадки неверны, как и трактовка замечания про таймер. С кнопкой я без проблем сам разобрался и давно использую свои наработки. Переменная таймера была изначально uint32_t, как ей и нужно быть. Типом int была переменная, отвечающая за период работы таймера. И это был не косяк, а фича. Далее, не сказал бы, что библиотеки занимают много места (опять же, из того же комментария про таймер), в примере подключена Serial для отладки, которая и жрёт всё место, в самой библиотеке есть пачка булинов и один uint32_t, больше ничего. Вывод: не стоит делать выводы на основе комментариев, таки дела.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Алекс, не стоит, поверь. Вижу, что комментарии вполне по делу - тебя начинают задевать. Это значит - что ты не готов к критике, а она будет, поверь. Я тоже вот - заинтересовался, пойду, пожалуй, погляжу, что там в коде творится ;) Ведь ты берёшь на себя некоторую долю ответственности, выкладывая библиотеки, хочется тебе того, или нет.

b707
Онлайн
Зарегистрирован: 26.05.2017

ну понятно, очередная мега-библиотека, выложенная в сеть исключительно ради поднятия ЧСВ автора...

Сколько их таких уже на гитхабе, забытых через неделю после первого релиза

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Я хотел критики, но конструктивной, как у человека с ником Ворота. А не кривого пересказа его комментария с полной потерей сути

b707
Онлайн
Зарегистрирован: 26.05.2017

DIYMan пишет:

Алекс, ты берёшь на себя некоторую долю ответственности, выкладывая библиотеки, хочется тебе того, или нет.

+100

Для себя можно писать как угодно. Но когда выкладываешь - дело другое. Не надо людей подставлять. Беря библиотеку, они рассчитвают получить полезный, детально проработанный грамотный код, а не наспех слепленную кучу глюков, на которую только убьешь время.

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

AlexGyver пишет:

это был не косяк, а фича. 

Ой, не надо! У нас тут уже есть два специалиста, у которых, что ни баг, то фича. Хватит с нас.

То, что у тебя в одних местах millis преобразуется к long, а в других таких же - нет, тоже фича? Больше похоже на поиск работающего варианта методом тыка.

Кстати, ты там окончание интервала сложением определяешь, так что, если бы ты не сделал "фичу" с шестнадцитибитным интервалом, то налетел бы на другую "фичу" - переполнение миллис. Ты в курсе что это такое?

Ты, парень убрал бы гонор, слушал бы и учился бы. Пользы больше.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Первый косяк, библиотека GyverPID:

pidTimer = (long)millis() + dt;

pidTimer при этом объявлен норм:

uint32_t pidTimer

Конструкции вида

if ((long)millis() > pidTimer)

говорят о том, что всё смешалось в доме Облонских - не надо так вольно смешивать типы переменных, иначе зачем pidTimer объявлена как uint32_t ????

Второй косяк - библиотека GyverRGВ:

#define WHITE		0xFFFFFF	// белый
#define SILVER		0xC0C0C0	// серебро
#define GRAY		0x808080	// серый
#define BLACK		0x000000	// чёрный
#define RED			0xFF0000	// красный
#define MAROON		0x800000	// бордовый
#define YELLOW		0xFFFF00	// жёлтый
#define OLIVE		0x808000	// олива
#define LIME		0x00FF00	// лайм
#define GREEN		0x008000	// зелёный
#define AQUA		0x00FFFF	// аква
#define TEAL		0x008080	// цвет головы утки чирка https://odesign.ru/teal-color/
#define BLUE		0x0000FF	// голубой
#define NAVY		0x000080	// тёмно-синий
#define PINK		0xFF00FF	// розовый
#define PURPLE		0x800080	// пурпурный

Многие юзают ту же UTFT, где определены подобные дефайны, даже с такими же именами. В результате - можно получить кучу головняков в коде. Выход - есть, естественно ;)

Там же:

for (int i = 0; i < deltaMax; i++)

при этом deltaMax - объявлена как byte. Это - классическое "comparing signed and unsigned values", неаккуратненько ;)

GyverRelay - везде проходит, чего же здесь не пройти, да:

if ((long)millis() > prevTime)

Там же:

int8_t sign(float value) {
	if (value > 0) return 1;
	else if (value == 0) return 0;
	else if (value < 0) return -1;
}

Второй 

else if (value == 0) return 0;

НИКОГДА не будет истиной, ибо - float и его представление: никогда он ТОЧНО не равен нулю.

Дальше продолжать, или не надо? Достаточно конструктивно?

AlexGyver
Offline
Зарегистрирован: 12.03.2017

В лонг преобразуем при арифметических вычислениях, работает и работало без этого. Конец интервала знаю, через 50 суток собьётся на несколько миллисекунд. Сделано во благо избавления от одного вычисления при вызове функции, раньше конец считался как в классе с микрос. Не согласен, что мой гонор не по делу

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Во, вот это конструктив, спасибо

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

AlexGyver пишет:

Во, вот это конструктив, спасибо

Ок. Класс GyverButton - Алекс, 27 (!), двадцать семь, Карл! байт переменных на один экземпляр класса кнопки - извини, но такое - категорически неприемлемо и не рекомендуется к применению, от слова "совсем". Это - само по себе, по факту двадцати семи байт, из которых большая часть в одном байте содержит только битовый флаг - очень плохо, очень.

Почитай про битовые поля, и создай вместо:

boolean isHolded_f = false, isRelease_f = false, isPress_f = false, step_flag = false, oneClick_f = false, isOne_f = false;

простую структурку, раз с битами не хочешь возиться:

#pragma pack(push,1)
typedef struct
{
	bool isHolded_f: 1;
	bool isRelease_f: 1;
	bool isPress_f: 1;
	bool step_flag: 1;
	bool oneClick_f: 1;
	bool isOne_f: 1;
	// тут другие битовые поля, там дохрена мусора ещё, который можно вынести сюда
	
} GyverButtonFlags;
#pragma pack(pop)

Потом в классе вместо кучи переменных пишешь:

GyverButtonFlags flags;

ну и где надо - проверяешь:

if(flags.isHolded_f) {...}

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

AlexGyver пишет:

В лонг преобразуем при арифметических вычислениях, работает и работало без этого. Конец интервала знаю, через 50 суток собьётся на несколько миллисекунд. Сделано во благо избавления от одного вычисления при вызове функции, раньше конец считался как в классе с микрос. Не согласен, что мой гонор не по делу

Понятно.

Ну, на "не согласен", и суда нет.

DIYMan, у нас кажется новый архат растёт? Вроде всё также - любой косяк - фича, готов убить программу ради экономии одного вычитания. Или мне показалось? 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

AlexGyver пишет:

В лонг преобразуем при арифметических вычислениях, работает и работало без этого. Конец интервала знаю, через 50 суток собьётся на несколько миллисекунд. Сделано во благо избавления от одного вычисления при вызове функции, раньше конец считался как в классе с микрос. Не согласен, что мой гонор не по делу

Не надо там ничего преобразовывать, более того - то, что ты делаешь, в корне неверно. Просто надо почитать про беззнаковую арифметику и начать измерять прошедшие интервалы правильно - и волосы будут мягкими и шелковистыми. Вот так - неправильно:

uint16_t interval = 12000;

uint32_t start = millis();

....

if( millis() >= (start + interval)) {...}

А вот так - правильно:

uint16_t interval = 12000;

uint32_t start = millis();

if(millis() - start >= interval) {...}

Как видишь - ни одного кастования в long, с потерей половины размерности в диапазоне положительных чисел ;)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кончайте травить пацана. Вон сколько всего перелопатил, старается. Лучше шефство возьмите, потычьте носом в стол, да научите чему-нибудь.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ворота пишет:

DIYMan, у нас кажется новый архат растёт? Вроде всё также - любой косяк - фича, готов убить программу ради экономии одного вычитания. Или мне показалось? 

Да не, Алекс вроде норм парень, во всяком случае - заочно: горит, интересуется, видосы пилит. Тут главное, с его стороны - не упорствовать, а просто попытаться прислушаться. И его желание поделиться накопленным - тоже понятно, и даже где-то близко. Просто у нас тут атмосфера такая - критическая, о чём я Алекса предупреждал ;)

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Вот такая работа с интервалом была изначально. Но. С пути меня сбил какой то умник, сказал что тут "лишнее вычитание". Таки дела!

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ЕвгенийП пишет:

Кончайте травить пацана. Вон сколько всего перелопатил, старается. Лучше шефство возьмите, потычьте носом в стол, да научите чему-нибудь.

Так вроде как раз стараюсь не травить - а показать тонкие места, которые в серьёзном проекте могут вылезти боком и попить немало крови. ЧЯДНТ?

igor12
igor12 аватар
Offline
Зарегистрирован: 10.01.2018

Реально Ворота всё по делу сказал и указал. Остальные начали обсуждать личность "библиотекаря", что ему стОит делать, а чего не стОит.

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Я в критических атмосферах с кучей хейта и десятками писем на мыло вращаюсь очень много, для нашего интернета это обычное дело.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Так ТС же объяснил, что он как раз вот это вычитание экономил!

DIYMan пишет:

if(millis() - start >= interval) {...}

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Ворота пишет:

Так ТС же объяснил, что он как раз вот это вычитание экономил!

DIYMan пишет:

if(millis() - start >= interval) {...}

Меня науськали более опытные. Но это не точно (про опытность)

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ЕвгенийП пишет:

потычьте носом в стол, да научите чему-нибудь.

А мы чо делаем? :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так оно и видно :)

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

AlexGyver пишет:

Вот такая работа с интервалом была изначально. Но. С пути меня сбил какой то умник, сказал что тут "лишнее вычитание". Таки дела!

Алекс, умников тоже надо слушать с оглядкой. Я тебе не зря пишу "почитай про беззнаковую арифметику" ;) Тогда сам поймёшь, что проблемы переполнения, заворачивания через пуп земли, необходимости кастовать в другой тип - у беззнаковых типов нет, от слова "вообще": просто надо понимать, как арифметические операции работают с беззнаковыми переменными и какой результат при этом получается. И пусть тебя не смущает тот факт, что беззнаковая переменная может достичь своего максимального значения и начаться, грубо говоря, с нуля - с правильно применёнными арифметическими операциями - всё будет ок. Проще говоря: отнимая одну беззнаковую переменную от другой (при этом неважно, какая из них какой больше) - на выходе мы получим ПРАВИЛЬНОЕ беззнаковое число, содержащее разницу двух значений. А будешь прибавлять к беззнаковому интервал - рискуешь попасть на переполнение, со всеми вытекающими - а зачем насильственный секс там, где без него можно обойтись, правда?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

igor12 пишет:

Реально Ворота всё по делу сказал и указал. Остальные начали обсуждать личность "библиотекаря", что ему стОит делать, а чего не стОит.

И я - тоже? Ткни пальцем, где я личность обсуждал? Чисто ради справедливости.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexGyver пишет:

Меня науськали более опытные. Но это не точно (про опытность)

Вы не там ищете эффективность.

Экономия на одном сложении иногда, крайне редко, бывает нужна и оправдана, напрмер, при работев прерыванияхи или при точном тайминге, но это реально редко. В большинстве же реальных программ гораздо большую экономию можно получить за счёт грамотной организации и проектирования. Вы постулат Вульфа знаете?

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Про переполнение таймера я экспериментировал с искусственной функцией миллис, все косяки вроде прощупал вручную. По теории ничего не знаю, так как не было на неё времени. Только практика! 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexGyver пишет:

Про переполнение таймера я экспериментировал с искусственной функцией миллис, 

Гораздо логичнее экпериментировать с реальной, просто начальным значением ей задать не 0, а что-нибудь близкое к переполнению.

А про теорию - это зря.

Но постулат Вульфа - не теория - это жизненное наблюдение. Вот здесь он у меня эпиграфом взят, почитайте.

AlexGyver
Offline
Зарегистрирован: 12.03.2017

Спасибо, изучу. Не думал, что можно функции миллис что то задать! Arduino reference такому не учит.

С булинами сделал как показали, давно искал удобный аналог ручной компановке битов в один булин... а оно и не нужно оказалось

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexGyver пишет:

Не думал, что можно функции миллис что то задать! 

Ну, а чего нельзя-то? Вот здесь у меня эта техника используется. смотрите.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Проделана большая работа, но достаточно грязно. Впрочем, Вам тут уже указали на некоторые несуразности. Пересмотрите весь остальной код на подобные моменты. А в ,целом, мой совет: не принимайте близко к сердцу местные советы и тем более "наезды" и переходы на личность. Большая часть (практически все кто тут отметился) из них, ничего не писали тут самостоятельно! Поищите поиском, ничего кроме стеба толком и не найдете.

В Wiring принят достаточно сомнительный способ сквозной целочисленной нумерации пинов. Сомнительный потому что микроконтроллер (каждый!) это несколько специализированное устройство и каждый его вывод имеет свои "спец. функции", у некоторых что-то, куда-то можно "переназначить", но и только. Такой подход позволяет реализовывать "эмуляции" спец.функций ногодрыгами с превращением камня в нечто непотребное (ибо эмуляция), для каких-то задач это прокатывает, но только для "каких-то". А поскольку Ардуино как проект исключительно для обучения, то эти задачи тут составляют 80%. Проблема в том, что достаточно много людей пытаются применять "это" в практической работе МК.

Попробуйте, во-первых, представить "пин" как 2 байта: "порт" и "смещение". Это несколько увеличивает занимаемую память, но как показал мой опыт МЕНЬШЕ чем таблицы преобразования от Wiring в типовых (моих) применениях, но зато существенно улучшает реализацию большинства типовых функций базовой библиотеки, в т.ч. написание разных реализаций для "спец. функций" выводов.

Во-вторых, учитывая что порты 8-и битные (смещение занимает 3 бита) и портов меньше 16 (4бита) даже у Меги 2560 попробуйте реализовать однобайтовую нумерацию .. оно окажется несколько медленнее, но зато потребует меньшего места в ОЗУ под нумерацию пинов.

И ещё: такие вещи как билиотека Serial должно выкидывать и замещать своей, взяв за основу релиз из того же Cyberlib для УНО. Расписать остальные функции согласно даташиту - не проблема, в т.ч. и под "упрощенный RTOS" или "Автоматное, событийное"  программирование. Также как и релиз остальных аппаратных интерфейсов I2C, SPI .. ничего супер сложного в них нет.

Дерзайте! :)

P.S. и меньше оглядывайтесь на "типовые библиотеки". Они по большей части (%90 не меньше) писаны такими вот дилетантами-советчиками и подлежат выбросу "не глядя". :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ну и ещё: http://easyelectronics.ru/rabota-s-portami-vvoda-vyvoda-mikrokontrollero... и гитхаб автора https://github.com/KonstantinChizhov/AvrProjects думаю будет полезно ознакомиться в плане иных вариантов реализаций..