Создание пользовательского блока из скетча(примера)
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
По многочисленным вопросам.
.
Теория
.
Довольно часто, на просторах Интернета встречаются примеры кода выполняющие ту или иную задачу и у пользователей FLProg возникает желание добавить данный функционал в свой проект в виде ПБ (Пользовательского блока).
Ничего особо сложного в этом нет. Тем более если данным блоком будете пользоваться только вы. Не надо заботится об универсальности и писать описание. Хотя последнее я бы посоветовал сделать в любом случае, ибо через полгода вы и не вспомните что это и зачем.
Прежде всего хочу сказать, что для грамотного переноса скетча (кода, примера) в блок необходимо обладать базовыми знаниями языка С++. К сожалению для русскоязычного человека к незнанию C++ зачастую накладывается и незнание английского языка, что усложняет задачу вдвойне. Дело в том, что из названия операторов и функций уже становится понятно за что примерно она отвечает.
Возьмем к примеру digitalRead(), analogRead(), digitalWrite(), analogWrite().
Все же довольно прозрачно - Цифровой, Аналоговый, Читаем, Пишем. Очевидно же, что речь идет о цифровых и аналоговых входах/выходах контроллера. Либо мы читаем пин, либо записываем на него значение.
Ориентируясь за что отвечают операторы и функции (их еще обзывают командами Arduino), достаточно просто перенести пример в блок.
Есть в среде ArduinoIDE еще и базовые, основные функции, без которых не обходится ни один скетч:
.
void setup() // установки
{
//Все что здесь, выполняется один раз при старте контроллера
}
void loop() // петля (бесконечный цикл)
{
// Все что здесь будет выполняться после setup() и бесконечно повторяться до отключения питания.
}
.
В FLProg, в базовом редакторе ПБ, для этих функций существуют соответствующие секции. .
Кроме этого есть секции
DeclareSection
Сюда заносится все то, что находится перед void setup()
А иногда и то, что после, но не входит в состав void loop() и других функций (в скетче, примере).
.
FunctionSection
Сюда заносятся прочие пользовательские функции.
.
С теорией пожалуй хватит.
Единственное, что нам еще потребуется, это Notepad++. Обязательно скачайте и установите. Это ваш первый помощник в создании и корректировке кода.
.
Практика
.
Сразу начнем с не совсем удачного примера.
.
[spoiler=Пример сетча с просторов Интернета]
int led_pin=3; // пин подключения
void setup() {
pinMode(led_pin, OUTPUT); // Инициализируем цифровой вход/выход в режиме выхода.
}
void loop() {
for (int x=0; x<3; x++) {
digitalWrite(led_pin, HIGH);// зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++) {
digitalWrite(led_pin, HIGH);// зажигаем светодиод
delay(500); // ждем 700 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++) {
digitalWrite(led_pin, HIGH);// зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(5000); // ждем 5 секунд
}
[/spoiler]
.
Самый простой способ.
Переносим код в Notepad++, изучаем его, находим void setup() и void loop().
Не забудьте выбрать Синтакс С++
.
Сразу после void setup() находим открывающую фигурную скобку { . Выделяем ее и Notepad++ показывает нам ответную закрывающую скобку } . .
Все что между этими скобками, за исключением самих скобок копируем в SetupSection. .
Точно так же поступаем и с void loop(), переносим содержимое, за исключением открывающей и закрывающей фигурных скобок в LoopSection. .
Все что у нас осталось в коде и не вошло в void setup() и void loop(), это первая строчка.
Ее мы копируем в DeclareSection. .
Не забываем вписать название блока и сохранить. .
Наш блок как бы готов.
Почему как бы? Да потому что у нашего блока не ни входов ни выходов. .
Несмотря на это, если загрузить проект в контроллер, все будет работать. На третьем пине будет генерироваться сигнал SOS - три коротких, три длинных, снова три коротких и пауза 5 секунд. И так по кругу.
.
Продолжение следует...
.
Теория
.
Довольно часто, на просторах Интернета встречаются примеры кода выполняющие ту или иную задачу и у пользователей FLProg возникает желание добавить данный функционал в свой проект в виде ПБ (Пользовательского блока).
Ничего особо сложного в этом нет. Тем более если данным блоком будете пользоваться только вы. Не надо заботится об универсальности и писать описание. Хотя последнее я бы посоветовал сделать в любом случае, ибо через полгода вы и не вспомните что это и зачем.
Прежде всего хочу сказать, что для грамотного переноса скетча (кода, примера) в блок необходимо обладать базовыми знаниями языка С++. К сожалению для русскоязычного человека к незнанию C++ зачастую накладывается и незнание английского языка, что усложняет задачу вдвойне. Дело в том, что из названия операторов и функций уже становится понятно за что примерно она отвечает.
Возьмем к примеру digitalRead(), analogRead(), digitalWrite(), analogWrite().
Все же довольно прозрачно - Цифровой, Аналоговый, Читаем, Пишем. Очевидно же, что речь идет о цифровых и аналоговых входах/выходах контроллера. Либо мы читаем пин, либо записываем на него значение.
Ориентируясь за что отвечают операторы и функции (их еще обзывают командами Arduino), достаточно просто перенести пример в блок.
Есть в среде ArduinoIDE еще и базовые, основные функции, без которых не обходится ни один скетч:
.
void setup() // установки
{
//Все что здесь, выполняется один раз при старте контроллера
}
void loop() // петля (бесконечный цикл)
{
// Все что здесь будет выполняться после setup() и бесконечно повторяться до отключения питания.
}
.
В FLProg, в базовом редакторе ПБ, для этих функций существуют соответствующие секции. .
Кроме этого есть секции
DeclareSection
Сюда заносится все то, что находится перед void setup()
А иногда и то, что после, но не входит в состав void loop() и других функций (в скетче, примере).
.
FunctionSection
Сюда заносятся прочие пользовательские функции.
.
С теорией пожалуй хватит.
Единственное, что нам еще потребуется, это Notepad++. Обязательно скачайте и установите. Это ваш первый помощник в создании и корректировке кода.
.
Практика
.
Сразу начнем с не совсем удачного примера.
.
[spoiler=Пример сетча с просторов Интернета]
int led_pin=3; // пин подключения
void setup() {
pinMode(led_pin, OUTPUT); // Инициализируем цифровой вход/выход в режиме выхода.
}
void loop() {
for (int x=0; x<3; x++) {
digitalWrite(led_pin, HIGH);// зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++) {
digitalWrite(led_pin, HIGH);// зажигаем светодиод
delay(500); // ждем 700 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++) {
digitalWrite(led_pin, HIGH);// зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(5000); // ждем 5 секунд
}
[/spoiler]
.
Самый простой способ.
Переносим код в Notepad++, изучаем его, находим void setup() и void loop().
Не забудьте выбрать Синтакс С++
.
Сразу после void setup() находим открывающую фигурную скобку { . Выделяем ее и Notepad++ показывает нам ответную закрывающую скобку } . .
Все что между этими скобками, за исключением самих скобок копируем в SetupSection. .
Точно так же поступаем и с void loop(), переносим содержимое, за исключением открывающей и закрывающей фигурных скобок в LoopSection. .
Все что у нас осталось в коде и не вошло в void setup() и void loop(), это первая строчка.
Ее мы копируем в DeclareSection. .
Не забываем вписать название блока и сохранить. .
Наш блок как бы готов.
Почему как бы? Да потому что у нашего блока не ни входов ни выходов. .
Несмотря на это, если загрузить проект в контроллер, все будет работать. На третьем пине будет генерироваться сигнал SOS - три коротких, три длинных, снова три коротких и пауза 5 секунд. И так по кругу.
.
Продолжение следует...
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Dryundel 27 сен 2021, 12:56, всего редактировалось 2 раза.
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
Продолжаем разговор...
.
Блок мы создали, он работает, но проку от него в FLProg не много, потому как повлиять на его работу мы не можем. Ни включить выключить генерацию SOS, ни изменить пин, ни задать время коротких/длинных импульсов не представляется возможным , кроме как снова лезть в редактор. Попробуем это изменить.
Наверное первое что необходимо, это включить или выключить генерацию SOS. Сделать это можно запретом или разрешением выполнения кода по какому то условию.
.
Создаем вход boolean En в соответствующей вкладке редактора.
Все созданные входы/выходы являются переменными (в базовом редакторе) и автоматически декларируются при компиляции как переменные. Дополнительно декларировать их не надо.
Далее создаем условие выполнения кода если En=1.
Можно записать так:
if (En == 1)
{
// Здесь весь код из LoopSection
}
или так, что одно и то же:
if (En)
{
// Здесь весь код из LoopSection
}
Теперь у нас появился вход En, при подаче на который логической единицы, наш первоначальный код в LoopSection будет выполняться и будет пропускаться если En=0. Как учебный пример блок работать будет.
Можете запустить и попробовать. .
Далее можно добавить в параметры время задержек.
Покажу на примере паузы между миганием.
.
Во вкладке "Параметры пользователя" создаем константу Pause и вписываем ее в соответствующие delay() Теперь у блока есть параметр "Pause", а при компиляции delay(Pause) будет заменяться на соответствующее значение. То же самое можно проделать и с другими временными параметрами.
.
Так же поступаем с выбором пина на который будет выводиться сигнал. .
Дальнейшие манипуляции с данным кодом не имеют смысла, т.к. задержки в нем основаны на delay()
Другие блоки в проекте вместе с этим работать не будут
Почему? Читайте здесь
При желании можно попробовать заменить все delay() на таймеры, однако проще будет построить такой алгоритм на других принципах.
.
Продолжение следует...
.
Блок мы создали, он работает, но проку от него в FLProg не много, потому как повлиять на его работу мы не можем. Ни включить выключить генерацию SOS, ни изменить пин, ни задать время коротких/длинных импульсов не представляется возможным , кроме как снова лезть в редактор. Попробуем это изменить.
Наверное первое что необходимо, это включить или выключить генерацию SOS. Сделать это можно запретом или разрешением выполнения кода по какому то условию.
.
Создаем вход boolean En в соответствующей вкладке редактора.
Все созданные входы/выходы являются переменными (в базовом редакторе) и автоматически декларируются при компиляции как переменные. Дополнительно декларировать их не надо.
Далее создаем условие выполнения кода если En=1.
Можно записать так:
if (En == 1)
{
// Здесь весь код из LoopSection
}
или так, что одно и то же:
if (En)
{
// Здесь весь код из LoopSection
}
Теперь у нас появился вход En, при подаче на который логической единицы, наш первоначальный код в LoopSection будет выполняться и будет пропускаться если En=0. Как учебный пример блок работать будет.
Можете запустить и попробовать. .
Далее можно добавить в параметры время задержек.
Покажу на примере паузы между миганием.
.
Во вкладке "Параметры пользователя" создаем константу Pause и вписываем ее в соответствующие delay() Теперь у блока есть параметр "Pause", а при компиляции delay(Pause) будет заменяться на соответствующее значение. То же самое можно проделать и с другими временными параметрами.
.
Так же поступаем с выбором пина на который будет выводиться сигнал. .
Дальнейшие манипуляции с данным кодом не имеют смысла, т.к. задержки в нем основаны на delay()
Другие блоки в проекте вместе с этим работать не будут
Почему? Читайте здесь
При желании можно попробовать заменить все delay() на таймеры, однако проще будет построить такой алгоритм на других принципах.
.
Продолжение следует...
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Dryundel 27 сен 2021, 12:59, всего редактировалось 5 раз.
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
Продолжение, оно же и окончание.
.
Мы рассмотрели основные принципы создания ПБ (Пользовательского Блока) из скетча. Я специально начал с не совсем удачного примера кода для начинающих. Таких примеров в сети навалом. Все они работают как отдельно взятый скетч, но не смогут работать если кроме него поместить в программу еще что то. Запомните, а лучше нацарапайте на подкорке мозга гвоздем, прописную догму:
Команда delay() - первый враг работы микроконтроллера.
Исключением может быть delay() в void setup(), когда это просто необходимо для правильной настройки подключаемых устройств.
.
Перейдем к более приближенному к реальности примеру.
Итак, вам попался какой то интересный скетч, урок, пример, видосик, функционал из которого захотелось упаковать в Пользовательский Блок. К примеру это:
[bbvideo]https://youtu.be/rIbWnB26dp0[/bbvideo]
.
На тринадцатой минуте данного ролика приводится пример не сложного кода из которого получится вполне себе функциональный ПИД регулятор. По ссылке под видео (на YouTube) находим готовый код, дабы не переписывать его руками.
https://github.com/AlexGyver/tutorials/ ... plePID.ino
[spoiler=Код по ссылке]
[/spoiler]
Внимательно изучаем код и его составляющие.
- Декларируемые переменные отсутствуют.
- В void setup() тоже пусто
- В void loop() закоментированный пример применения.
- Видим наличие пользовательской функции int computePID()
.
Вот с последнего и начнем, благо мы не рассмотрели в первом примере внесение функций в ПБ.
1. Копируем имя функции вместе с ее параметрами и добавляем эту функцию на вкладке FunctionSection, нажав на зеленый плюсик.
2. Копируем все "потроха" данной функции, которые так же ограничены фигурными скобками, и вставляем все это в поле под именем функции. (Без скобок) .
Всё, с функцией разобрались.
Возвращаемся к void loop().
Здесь мы видим функцию delay() и вспоминаем что с врагами, допустим, нужно бороться.
Еще раз, очень внимательно смотрим ролик и понимаем за что она отвечает.
Находим у того же AlexGyver как нам победить delay() и на странице https://alexgyver.ru/lessons/time/, находим вот такую конструкцию:
Это таймер, который и будет запускать нашу функцию один раз в... , а это мы будем регулировать.
Смело вставляем данный код в LoopSection, а строчку "// выполнить действие", заменяем на вызов функции из примера.
Не забываем задекларировать переменную uint32_t myTimer1, внеся ее в DeclareSektion.
Заметка: uint32_t это то же самое что unsigned long. Можно вписывать и так, проблем не будет.
.
Получилась следующая картина. .
Не забыли что время паузы вызова функции и последний параметр функции dt должны совпадать?
Не обратили внимание? Плохо!
Еще раз пересмотрите ролик.
И обратите внимание, что в одном случае это секунды, а в другом миллисекунды.
.
Теперь разбираемся с параметрами передаваемыми в функцию computePID().
Надеюсь, что вы помните за что каждый из них отвечает.
Нет!?
Еще раз внимательно смотрим ролик!
.
Вот теперь легко и не принужденно создаем у блока 6 входов.
- Уставка - Set
- Данные с датчика - Val (обратная связь)
- Kp
- Ki
- Kd
- dt
И вписываем их в соответствующие места функции. Не забываем вписать dt в двух местах, подставив в таймере к нему коэффициент 1000, т.к. там время в миллисекундах.
Получилось следующее: .
Осталось только разобраться с выходом.
Сейчас наш алгоритм сразу передает на выбранный пин значение вычисленное ПИД регулятором. Но подать это значение на нужный пин можно и средствами FLProg. Поэтому создаем выход P, а
analogWrite(pin, computePID(Val, Set, Kp, Ki, Kd, dt)); заменяем на P = computePID(Val, Set, Kp, Ki, Kd, dt);
.
Вот и всё, наш блок ПИД-регулятор готов. .
Понравилась статья?
Не ограничивайся лайками.
Помоги форуму
.
.

.
Мы рассмотрели основные принципы создания ПБ (Пользовательского Блока) из скетча. Я специально начал с не совсем удачного примера кода для начинающих. Таких примеров в сети навалом. Все они работают как отдельно взятый скетч, но не смогут работать если кроме него поместить в программу еще что то. Запомните, а лучше нацарапайте на подкорке мозга гвоздем, прописную догму:
Команда delay() - первый враг работы микроконтроллера.
Исключением может быть delay() в void setup(), когда это просто необходимо для правильной настройки подключаемых устройств.
.
Перейдем к более приближенному к реальности примеру.
Итак, вам попался какой то интересный скетч, урок, пример, видосик, функционал из которого захотелось упаковать в Пользовательский Блок. К примеру это:
[bbvideo]https://youtu.be/rIbWnB26dp0[/bbvideo]
.
На тринадцатой минуте данного ролика приводится пример не сложного кода из которого получится вполне себе функциональный ПИД регулятор. По ссылке под видео (на YouTube) находим готовый код, дабы не переписывать его руками.
https://github.com/AlexGyver/tutorials/ ... plePID.ino
[spoiler=Код по ссылке]
Код: Выделить всё
// функция ПИД регулятора
void setup() {
}
void loop() {
//analogWrite(pin, computePID(sensorRead, 30, 1.0, 2.0, 3.0, 0.02));
//delay(20);
}
// (вход, установка, п, и, д, период в секундах)
int computePID(float input, float setpoint, float kp, float ki, float kd, float dt) {
float err = setpoint - input;
static float integral = 0, prevErr = 0;
integral += err * dt;
float D = (err - prevErr) / dt;
prevErr = err;
return (err * kp + integral * ki + D * kd);
}
Внимательно изучаем код и его составляющие.
- Декларируемые переменные отсутствуют.
- В void setup() тоже пусто
- В void loop() закоментированный пример применения.
- Видим наличие пользовательской функции int computePID()
.
Вот с последнего и начнем, благо мы не рассмотрели в первом примере внесение функций в ПБ.
1. Копируем имя функции вместе с ее параметрами и добавляем эту функцию на вкладке FunctionSection, нажав на зеленый плюсик.
2. Копируем все "потроха" данной функции, которые так же ограничены фигурными скобками, и вставляем все это в поле под именем функции. (Без скобок) .
Всё, с функцией разобрались.
Возвращаемся к void loop().
Здесь мы видим функцию delay() и вспоминаем что с врагами, допустим, нужно бороться.
Еще раз, очень внимательно смотрим ролик и понимаем за что она отвечает.
Находим у того же AlexGyver как нам победить delay() и на странице https://alexgyver.ru/lessons/time/, находим вот такую конструкцию:
Код: Выделить всё
// переменная хранения времени (unsigned long)
uint32_t myTimer1;
void setup() {}
void loop() {
if (millis() - myTimer1 >= 500) { // ищем разницу (500 мс)
myTimer1 = millis(); // сброс таймера
// выполнить действие
}
}
Смело вставляем данный код в LoopSection, а строчку "// выполнить действие", заменяем на вызов функции из примера.
Не забываем задекларировать переменную uint32_t myTimer1, внеся ее в DeclareSektion.
Заметка: uint32_t это то же самое что unsigned long. Можно вписывать и так, проблем не будет.
.
Получилась следующая картина. .
Не забыли что время паузы вызова функции и последний параметр функции dt должны совпадать?
Не обратили внимание? Плохо!
Еще раз пересмотрите ролик.
И обратите внимание, что в одном случае это секунды, а в другом миллисекунды.
.
Теперь разбираемся с параметрами передаваемыми в функцию computePID().
Надеюсь, что вы помните за что каждый из них отвечает.
Нет!?
Еще раз внимательно смотрим ролик!
.
Вот теперь легко и не принужденно создаем у блока 6 входов.
- Уставка - Set
- Данные с датчика - Val (обратная связь)
- Kp
- Ki
- Kd
- dt
И вписываем их в соответствующие места функции. Не забываем вписать dt в двух местах, подставив в таймере к нему коэффициент 1000, т.к. там время в миллисекундах.
Получилось следующее: .
Осталось только разобраться с выходом.
Сейчас наш алгоритм сразу передает на выбранный пин значение вычисленное ПИД регулятором. Но подать это значение на нужный пин можно и средствами FLProg. Поэтому создаем выход P, а
analogWrite(pin, computePID(Val, Set, Kp, Ki, Kd, dt)); заменяем на P = computePID(Val, Set, Kp, Ki, Kd, dt);
.
Вот и всё, наш блок ПИД-регулятор готов. .
Понравилась статья?
Не ограничивайся лайками.
Помоги форуму
.
.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Dryundel 26 сен 2021, 12:37, всего редактировалось 7 раз.
- SergeyShikal
- Лейтенант
- Сообщения: 593
- Зарегистрирован: 30 авг 2018, 17:15
- Откуда: Иркутская область
- Имя: Сергей
- Благодарил (а): 2 раза
- Поблагодарили: 1 раз
Создание пользовательского блока из скетча(примера)
А как создать именно выход на блоке[spoiler] [/spoiler]
У вас нет необходимых прав для просмотра вложений в этом сообщении.
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
Выход содается точно так же, как и вход.Dryundel писал(а): 23 сен 2021, 12:20 Дальнейшие манипуляции с данным кодом не имеют смысла, т.к. задержки в нем основаны на delay()
Если бы не было delay(), то можно было бы создать выход "SOS" и все
digitalWrite(led_pin, HIGH); заменить на SOS = 1;
а
digitalWrite(led_pin, LOW); на SOS = 0;
и всё.
Однако такой вариант с данным кодом в блоке работать не будет.
- SergeyShikal
- Лейтенант
- Сообщения: 593
- Зарегистрирован: 30 авг 2018, 17:15
- Откуда: Иркутская область
- Имя: Сергей
- Благодарил (а): 2 раза
- Поблагодарили: 1 раз
Создание пользовательского блока из скетча(примера)
Вопрос по компиляции: при загрузке в есп-01 без настройки сети компиляция проходит и работает, если настроить модуль на вай фай то выдает ошибку[spoiler]#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
extern "C"
{
#include "user_interface.h"
}
int _resiveModeCommunication = 0;
String _resiveVariableStringCommunication;
int _resiveVariableIndexCommunication = 0;
String _resiveVariableValueCommunication;
bool En;
int led_pin=2; // пин подключения
bool ESPControllerWifiClient_status = 1;
char ESPControllerWifiAP_SSID[40] = "perviy";
char ESPControllerWifiAP_password[40] = "12345678";
bool ESPControllerWifiAP_IsNeedReconect = 0;
bool ESPControllerWifiAP_workStatus = 1;
IPAddress ESPControllerWifiAP_ip(192, 168, 1, 25);
IPAddress ESPControllerWifiAP_dns (192, 168, 1, 1);
IPAddress ESPControllerWifiAP_gateway (192, 168, 1, 1);
IPAddress ESPControllerWifiAP_subnet (255, 255, 255, 0);
uint8_t ESPControllerWifiAP_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
WiFiUDP Udp;
char _udpPacketBuffer [UDP_TX_PACKET_MAX_SIZE];
bool _RVFC1 = 0;
bool _RVFC2 = 0;
void setup()
{
pinMode(1, OUTPUT);
digitalWrite(1, 0);
WiFi.mode(WIFI_AP);
_esp8266WifiModuleApReconnect();
Udp.begin(8888);
pinMode(led_pin, OUTPUT); // Инициализируем цифровой вход/выход в режиме выхода.
}
void loop()
{
int _udpPacketSize = Udp.parsePacket();
if (_udpPacketSize)
{
Udp.read(_udpPacketBuffer, UDP_TX_PACKET_MAX_SIZE);
for(int i=0; i <= _udpPacketSize; i++)
{
_ressiveByteFromCommunication(_udpPacketBuffer);
}
}
if(ESPControllerWifiAP_IsNeedReconect)
{
_esp8266WifiModuleApReconnect();
ESPControllerWifiAP_IsNeedReconect = 0;
}
//Плата:1
En = _RVFC1;
if (en)
{
for (int x=0; x<3; x++)
{
digitalWrite(led_pin, HIGH); // зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++)
{
digitalWrite(led_pin, HIGH); // зажигаем светодиод
delay(500); // ждем 700 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++)
{
digitalWrite(led_pin, HIGH); // зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(5000); // ждем 5 секунд
digitalWrite(1, !(_RVFC2));
}
bool _isTimer(unsigned long startTime, unsigned long period)
{
unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime)
{
return (currentTime>=(startTime + period));
}
else
{
return (currentTime >=(4294967295-startTime+period));
}
}
void _ressiveByteFromCommunication(byte resiveByte)
{
if (_resiveModeCommunication==0)
{
if (resiveByte == 1)
{
_resiveModeCommunication=1;
_resiveVariableStringCommunication="";
return;
}
}
if (_resiveModeCommunication==1)
{
if((resiveByte == 1)||(resiveByte == 3)|| (resiveByte == 4))
{
_resiveModeCommunication=0;
return;
}
else
{
if(resiveByte==2)
{
_resiveModeCommunication=2;
_resiveVariableIndexCommunication=_resiveVariableStringCommunication.toInt();
_resiveVariableStringCommunication="";
return;
}
else
{
_resiveVariableStringCommunication+= char(resiveByte);
return;
}
}
}
if (_resiveModeCommunication==2)
{
if((resiveByte == 1)||(resiveByte == 2)|| (resiveByte == 4))
{
_resiveModeCommunication=0;
return;
}
else
{
if (resiveByte==3)
{
_resiveModeCommunication=3;
_resiveVariableValueCommunication =_resiveVariableStringCommunication;
_resiveVariableStringCommunication="";
return;
}
else
{
_resiveVariableStringCommunication+= char(resiveByte);
return;
}
}
}
if (_resiveModeCommunication==3)
{
if((resiveByte == 1)||(resiveByte == 2)|| (resiveByte == 3))
{
_resiveModeCommunication=0;
return;
}
else
{
if (resiveByte==4)
{
_resiveModeCommunication=0;
_fillRessiveVariableasFromCommunication();
_resiveVariableStringCommunication="";
return;
}
else
{
_resiveVariableStringCommunication+= char(resiveByte);
return;
}
}
}
}
void _fillRessiveVariableasFromCommunication()
{
long _tempId= _resiveVariableStringCommunication.toInt();
if ((_resiveVariableIndexCommunication == 1) && (_tempId == 148551769))
{
_RVFC1 = ((_resiveVariableValueCommunication).toInt());
}
if ((_resiveVariableIndexCommunication == 2) && (_tempId == 148551769))
{
_RVFC2 = ((_resiveVariableValueCommunication).toInt());
}
}
int hexStrToInt(String instring)
{
byte len = instring.length();
if (len == 0) return 0;
int result = 0;
for (byte i = 0; i < 8; i++) // только первые 8 цыфар влезуть в uint32
{
char ch = instring;
if (ch == 0) break;
result <<= 4;
if (isdigit(ch))
result = result | (ch - '0');
else result = result | (ch - 'A' + 10);
}
return result;
}
void _esp8266WifiModuleApReconnect()
{
if (_checkMacAddres(ESPControllerWifiAP_mac))
{
wifi_set_macaddr(1, const_cast<uint8*>(ESPControllerWifiAP_mac));
}
WiFi.softAPConfig(ESPControllerWifiAP_ip, ESPControllerWifiAP_gateway, ESPControllerWifiAP_subnet);
WiFi.softAP(ESPControllerWifiAP_SSID, ESPControllerWifiAP_password);
if (! (_checkMacAddres(ESPControllerWifiAP_mac)))
{
WiFi.softAPmacAddress(ESPControllerWifiAP_mac);
}
}
bool _checkMacAddres(byte array[])
{
bool result = 0;
for (byte i = 0; i < 6; i++)
{
if (array == 255)
{
return 0;
}
if (array > 0)
{
result = 1;
}
}
return result;
}
void _parseMacAddressString(String value, byte array[])
{
int index;
byte buffer[6] = {255, 255, 255, 255, 255, 255};
byte raz = 0;
String tempString;
while ((value.length() > 0) && (raz <= 6))
{
index = value.indexOf(":");
if (index == -1)
{
tempString = value;
value = "";
}
else
{
tempString = value.substring(0, index);
value = value.substring(index + 1);
}
buffer[raz] = byte(hexStrToInt(tempString));
raz++;
}
if (_checkMacAddres(buffer))
{
for (byte i = 0; i < 6; i++)
{
array = buffer;
}
}
}
bool _compareMacAddreses(byte array1[], byte array2[])
{
for (byte i = 0; i < 6; i++)
{
if (array1 != array2)
{
return 0;
}
}
return 1;
}
bool _compareMacAddresWithString(byte array[], String value)
{
byte buffer[6] = {255, 255, 255, 255, 255, 255};
_parseMacAddressString(value, buffer);
return _compareMacAddreses(array, buffer);
}
bool _checkMacAddresString(String value)
{
byte buffer[6] = {255, 255, 255, 255, 255, 255};
_parseMacAddressString(value, buffer);
return _checkMacAddres(buffer);
}
String _macAddresToString(byte array[])
{
String result = "";
String temp ="";
for (byte i = 0; i < 6; i++)
{
temp=String(array,HEX);
if (temp.length() < 2)
{
temp = String("0") + temp;
}
result = result + temp;
if (i < 5)
{
result = result + String(":");
}
}
result.toUpperCase();
return result;
}
}[/spoiler]
#include <WiFiUdp.h>
extern "C"
{
#include "user_interface.h"
}
int _resiveModeCommunication = 0;
String _resiveVariableStringCommunication;
int _resiveVariableIndexCommunication = 0;
String _resiveVariableValueCommunication;
bool En;
int led_pin=2; // пин подключения
bool ESPControllerWifiClient_status = 1;
char ESPControllerWifiAP_SSID[40] = "perviy";
char ESPControllerWifiAP_password[40] = "12345678";
bool ESPControllerWifiAP_IsNeedReconect = 0;
bool ESPControllerWifiAP_workStatus = 1;
IPAddress ESPControllerWifiAP_ip(192, 168, 1, 25);
IPAddress ESPControllerWifiAP_dns (192, 168, 1, 1);
IPAddress ESPControllerWifiAP_gateway (192, 168, 1, 1);
IPAddress ESPControllerWifiAP_subnet (255, 255, 255, 0);
uint8_t ESPControllerWifiAP_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
WiFiUDP Udp;
char _udpPacketBuffer [UDP_TX_PACKET_MAX_SIZE];
bool _RVFC1 = 0;
bool _RVFC2 = 0;
void setup()
{
pinMode(1, OUTPUT);
digitalWrite(1, 0);
WiFi.mode(WIFI_AP);
_esp8266WifiModuleApReconnect();
Udp.begin(8888);
pinMode(led_pin, OUTPUT); // Инициализируем цифровой вход/выход в режиме выхода.
}
void loop()
{
int _udpPacketSize = Udp.parsePacket();
if (_udpPacketSize)
{
Udp.read(_udpPacketBuffer, UDP_TX_PACKET_MAX_SIZE);
for(int i=0; i <= _udpPacketSize; i++)
{
_ressiveByteFromCommunication(_udpPacketBuffer);
}
}
if(ESPControllerWifiAP_IsNeedReconect)
{
_esp8266WifiModuleApReconnect();
ESPControllerWifiAP_IsNeedReconect = 0;
}
//Плата:1
En = _RVFC1;
if (en)
{
for (int x=0; x<3; x++)
{
digitalWrite(led_pin, HIGH); // зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++)
{
digitalWrite(led_pin, HIGH); // зажигаем светодиод
delay(500); // ждем 700 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(300);
for (int x=0; x<3; x++)
{
digitalWrite(led_pin, HIGH); // зажигаем светодиод
delay(250); // ждем 350 милисекунд
digitalWrite(led_pin, LOW); // выключаем светодиод
delay(100); // ждем 300 милисекунд
}
delay(5000); // ждем 5 секунд
digitalWrite(1, !(_RVFC2));
}
bool _isTimer(unsigned long startTime, unsigned long period)
{
unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime)
{
return (currentTime>=(startTime + period));
}
else
{
return (currentTime >=(4294967295-startTime+period));
}
}
void _ressiveByteFromCommunication(byte resiveByte)
{
if (_resiveModeCommunication==0)
{
if (resiveByte == 1)
{
_resiveModeCommunication=1;
_resiveVariableStringCommunication="";
return;
}
}
if (_resiveModeCommunication==1)
{
if((resiveByte == 1)||(resiveByte == 3)|| (resiveByte == 4))
{
_resiveModeCommunication=0;
return;
}
else
{
if(resiveByte==2)
{
_resiveModeCommunication=2;
_resiveVariableIndexCommunication=_resiveVariableStringCommunication.toInt();
_resiveVariableStringCommunication="";
return;
}
else
{
_resiveVariableStringCommunication+= char(resiveByte);
return;
}
}
}
if (_resiveModeCommunication==2)
{
if((resiveByte == 1)||(resiveByte == 2)|| (resiveByte == 4))
{
_resiveModeCommunication=0;
return;
}
else
{
if (resiveByte==3)
{
_resiveModeCommunication=3;
_resiveVariableValueCommunication =_resiveVariableStringCommunication;
_resiveVariableStringCommunication="";
return;
}
else
{
_resiveVariableStringCommunication+= char(resiveByte);
return;
}
}
}
if (_resiveModeCommunication==3)
{
if((resiveByte == 1)||(resiveByte == 2)|| (resiveByte == 3))
{
_resiveModeCommunication=0;
return;
}
else
{
if (resiveByte==4)
{
_resiveModeCommunication=0;
_fillRessiveVariableasFromCommunication();
_resiveVariableStringCommunication="";
return;
}
else
{
_resiveVariableStringCommunication+= char(resiveByte);
return;
}
}
}
}
void _fillRessiveVariableasFromCommunication()
{
long _tempId= _resiveVariableStringCommunication.toInt();
if ((_resiveVariableIndexCommunication == 1) && (_tempId == 148551769))
{
_RVFC1 = ((_resiveVariableValueCommunication).toInt());
}
if ((_resiveVariableIndexCommunication == 2) && (_tempId == 148551769))
{
_RVFC2 = ((_resiveVariableValueCommunication).toInt());
}
}
int hexStrToInt(String instring)
{
byte len = instring.length();
if (len == 0) return 0;
int result = 0;
for (byte i = 0; i < 8; i++) // только первые 8 цыфар влезуть в uint32
{
char ch = instring;
if (ch == 0) break;
result <<= 4;
if (isdigit(ch))
result = result | (ch - '0');
else result = result | (ch - 'A' + 10);
}
return result;
}
void _esp8266WifiModuleApReconnect()
{
if (_checkMacAddres(ESPControllerWifiAP_mac))
{
wifi_set_macaddr(1, const_cast<uint8*>(ESPControllerWifiAP_mac));
}
WiFi.softAPConfig(ESPControllerWifiAP_ip, ESPControllerWifiAP_gateway, ESPControllerWifiAP_subnet);
WiFi.softAP(ESPControllerWifiAP_SSID, ESPControllerWifiAP_password);
if (! (_checkMacAddres(ESPControllerWifiAP_mac)))
{
WiFi.softAPmacAddress(ESPControllerWifiAP_mac);
}
}
bool _checkMacAddres(byte array[])
{
bool result = 0;
for (byte i = 0; i < 6; i++)
{
if (array == 255)
{
return 0;
}
if (array > 0)
{
result = 1;
}
}
return result;
}
void _parseMacAddressString(String value, byte array[])
{
int index;
byte buffer[6] = {255, 255, 255, 255, 255, 255};
byte raz = 0;
String tempString;
while ((value.length() > 0) && (raz <= 6))
{
index = value.indexOf(":");
if (index == -1)
{
tempString = value;
value = "";
}
else
{
tempString = value.substring(0, index);
value = value.substring(index + 1);
}
buffer[raz] = byte(hexStrToInt(tempString));
raz++;
}
if (_checkMacAddres(buffer))
{
for (byte i = 0; i < 6; i++)
{
array = buffer;
}
}
}
bool _compareMacAddreses(byte array1[], byte array2[])
{
for (byte i = 0; i < 6; i++)
{
if (array1 != array2)
{
return 0;
}
}
return 1;
}
bool _compareMacAddresWithString(byte array[], String value)
{
byte buffer[6] = {255, 255, 255, 255, 255, 255};
_parseMacAddressString(value, buffer);
return _compareMacAddreses(array, buffer);
}
bool _checkMacAddresString(String value)
{
byte buffer[6] = {255, 255, 255, 255, 255, 255};
_parseMacAddressString(value, buffer);
return _checkMacAddres(buffer);
}
String _macAddresToString(byte array[])
{
String result = "";
String temp ="";
for (byte i = 0; i < 6; i++)
{
temp=String(array,HEX);
if (temp.length() < 2)
{
temp = String("0") + temp;
}
result = result + temp;
if (i < 5)
{
result = result + String(":");
}
}
result.toUpperCase();
return result;
}
}[/spoiler]
У вас нет необходимых прав для просмотра вложений в этом сообщении.
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
[ref]SergeyShikal[/ref], когда делаете блок, будьте очень внимательны с кодом.
Это раз.
Вход у Вас имеет имя "En" , а в коде Вы написали if (en)
Это разные переменные. Регистр имеет значение.
Это два.
В третьих, прежде чем делать проекты с созданным блоком, проверьте его на компиляцию.
Ну и последнее, ОНО ЖЕ ПЕРВОЕ.
Когда исправите ошибки в блоке, компиляция пройдет успешно.
Однако не забывайте.
Вы забыли про закрывающую скобку в конце.
Это раз.
Вход у Вас имеет имя "En" , а в коде Вы написали if (en)
Это разные переменные. Регистр имеет значение.
Это два.
В третьих, прежде чем делать проекты с созданным блоком, проверьте его на компиляцию.
Ну и последнее, ОНО ЖЕ ПЕРВОЕ.
Отправлено спустя 2 минуты 36 секунд:Dryundel писал(а): 23 сен 2021, 12:20 Дальнейшие манипуляции с данным кодом не имеют смысла, т.к. задержки в нем основаны на delay()
Другие блоки в проекте вместе с этим работать не будут
Почему? Читайте здесь
Когда исправите ошибки в блоке, компиляция пройдет успешно.
Однако не забывайте.
Сложите время всех delay() умножте на 3, т.к. там трехкратные циклы, и получите время одного цикла программы с этим блоком. Так понятней?
- SergeyShikal
- Лейтенант
- Сообщения: 593
- Зарегистрирован: 30 авг 2018, 17:15
- Откуда: Иркутская область
- Имя: Сергей
- Благодарил (а): 2 раза
- Поблагодарили: 1 раз
Создание пользовательского блока из скетча(примера)
Спасибо, не доглядел,вижу что тормозит при выполнении программы.Dryundel писал(а): 24 сен 2021, 12:07
Сложите время всех delay() умножте на 3, т.к. там трехкратные циклы, и получите время одного цикла программы с этим блоком. Так понятней?
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
Обновил (закончил) статью. Всем заинтересованным советую дочитать до конца.
.
Если что то еще не понятно по Редактору ПБ Code-Basic, задавайте вопросы в этой теме.
.
Если что то еще не понятно по Редактору ПБ Code-Basic, задавайте вопросы в этой теме.
Создание пользовательского блока из скетча(примера)
Слегка поправлю --- Delay() зло в цикле а вот в Setup для многих железяк просто необходим!
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
Справедливое замечание. Внес поправку в статью.Anydy писал(а): 26 сен 2021, 12:15 Слегка поправлю --- Delay() зло в цикле а вот в Setup для многих железяк просто необходим!
-
- Капитан
- Сообщения: 908
- Зарегистрирован: 04 окт 2015, 19:10
- Откуда: Новосибирск
- Имя: Павел
- Благодарил (а): 20 раз
- Поблагодарили: 22 раза
Создание пользовательского блока из скетча(примера)
И еще в функциях, особенно если они вызываются редко, и городить таймер там, порой, просто бессмысленно.Anydy писал(а): 26 сен 2021, 12:15 Delay() зло в цикле а вот в Setup для многих железяк просто необходим.
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
А вот с этим не согласен. Функция должна выполняться по возможности быстро и без задержек.Naladchik писал(а): 26 сен 2021, 12:46 И еще в функциях, особенно если они вызываются редко, и городить таймер там, порой, просто бессмысленно.
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
В шапке темы создан опрос:
Нужна ли статья про Редактор Code-Professional?
Хотелось бы понимать размер аудитории, кому это необходимо.
Прежде чем голосовать, прочитайте написанное ниже.
.
Что же такое Новый редактор ПБ Code-Professional и на сколько он хорош.
Редактор Code-Professional не хуже и не лучше Code-Basic. Он просто другой.
Code-Professional прежде всего актуален в том случае, если Вы хотите и готовы создавать пользовательские блоки для других. Под готовностью я подразумеваю то, что вы имеете базовые знания C++, четко понимаете структуру скетча Arduino, знаете что такое функции и как с ними работать, освоили работу с прерываниями, имеете представление об адресации устройств, хотя бы приблизительно ориентируетесь в разнице контроллеров на AVR, ESP, STM и т.п. Кроме этого в Code-Professional при создании блока накладывается дополнительная нагрузка по структуре и избирательности компиляции кода.
Практически всё, за исключением некоторых нюансов, можно сделать в Code-Basic. Да, не будет возможности например прятать неиспользуемые входы, выходы и параметры. Но в большинстве случаев этого и не нужно.
За то создание ПБ в Code-Basic делается на порядок проще и быстрей.
И если вы не планируете создавать ПБ для других, то наверное стоит отдать свой голос за "Интересно было бы знать".
.
Кроме всего сказанного, хотелось бы услышать мнение тех, кто уже в какой то мере освоил Редактор Code-Professional.
Как по вашему мнению, достаточно ли авторского мануала для освоения?
Если нет, то на какие возможности и принципы работы следует обратить особое внимание?
Какие моменты вызывали у вас сложности в освоении?
.
Буду очень признателен за участие.
.
Нужна ли статья про Редактор Code-Professional?
Хотелось бы понимать размер аудитории, кому это необходимо.
Прежде чем голосовать, прочитайте написанное ниже.
.
Что же такое Новый редактор ПБ Code-Professional и на сколько он хорош.
Редактор Code-Professional не хуже и не лучше Code-Basic. Он просто другой.
Code-Professional прежде всего актуален в том случае, если Вы хотите и готовы создавать пользовательские блоки для других. Под готовностью я подразумеваю то, что вы имеете базовые знания C++, четко понимаете структуру скетча Arduino, знаете что такое функции и как с ними работать, освоили работу с прерываниями, имеете представление об адресации устройств, хотя бы приблизительно ориентируетесь в разнице контроллеров на AVR, ESP, STM и т.п. Кроме этого в Code-Professional при создании блока накладывается дополнительная нагрузка по структуре и избирательности компиляции кода.
Практически всё, за исключением некоторых нюансов, можно сделать в Code-Basic. Да, не будет возможности например прятать неиспользуемые входы, выходы и параметры. Но в большинстве случаев этого и не нужно.
За то создание ПБ в Code-Basic делается на порядок проще и быстрей.
И если вы не планируете создавать ПБ для других, то наверное стоит отдать свой голос за "Интересно было бы знать".
.
Кроме всего сказанного, хотелось бы услышать мнение тех, кто уже в какой то мере освоил Редактор Code-Professional.
Как по вашему мнению, достаточно ли авторского мануала для освоения?
Если нет, то на какие возможности и принципы работы следует обратить особое внимание?
Какие моменты вызывали у вас сложности в освоении?
.
Буду очень признателен за участие.
.
- AlexCrane
- Капитан
- Сообщения: 903
- Зарегистрирован: 20 окт 2017, 13:22
- Откуда: Ульяновск
- Имя: Александр
- Поблагодарили: 12 раз
Создание пользовательского блока из скетча(примера)
Ну не скажи, сейчас самый простой блок мне проще сделать в Code-Professional...Dryundel писал(а): 27 сен 2021, 10:44 За то создание ПБ в Code-Basic делается на порядок проще и быстрей.
Самый простой метод изучения - посмотреть как делают другие.
Если не знаю, то не скажу. Если скажу, то сначала проверю...
Если нет возможности отблагодарить материально, хотя бы оцени пост....
Если нет возможности отблагодарить материально, хотя бы оцени пост....
- Dryundel
- Полковник
- Сообщения: 2405
- Зарегистрирован: 22 май 2017, 23:15
- Откуда: Ярославль
- Имя: Андрей
- Поблагодарили: 15 раз
Создание пользовательского блока из скетча(примера)
Возможно профессионал пилот истребителя то же самое может сказать любителю парапланеристу, про задачу долететь из точки в точку.AlexCrane писал(а): 27 сен 2021, 13:46 Ну не скажи, сейчас самый простой блок мне проще сделать в Code-Professional...

Но любое мнение сейчас важно. И это здорово, что откликнулись.
Было бы не плохо, если бы Вы поделились особенностями, которые актуальны на старте вхождения в Code-Professional.
На какие моменты стоило бы обратить внимание Автору для упрощения понимания процесса создания ПБ, коротенько, по вашему мнению.
-
- Полковник
- Сообщения: 3357
- Зарегистрирован: 24 дек 2016, 16:55
- Откуда: Уфа
- Имя: Айдар
- Благодарил (а): 12 раз
- Поблагодарили: 100 раз
- Контактная информация:
Создание пользовательского блока из скетча(примера)
Мне тоже нравится базовый редактор.
Создание блока на профессионале иногда получается сложнее, чем написать программу в коде
, особенно когда хочешь туда засунуть всё что возможно!
Создание блока на профессионале иногда получается сложнее, чем написать программу в коде

-
- Полковник
- Сообщения: 3992
- Зарегистрирован: 12 фев 2016, 11:40
- Откуда: Шатура
- Имя: Энвер
- Благодарил (а): 136 раз
- Поблагодарили: 148 раз
Создание пользовательского блока из скетча(примера)
Еще одно мнение - setup() само по себе зло почти всегда (если только для присвоения констант) - создает проблемы при реализации управляемого программного сброса проекта.Anydy писал(а): 26 сен 2021, 12:15 Слегка поправлю --- Delay() зло в цикле а вот в Setup для многих железяк просто необходим!
И delay() всегда зло. Иногда приходиться использовать delayMicroseconds(x), где x не более 100.
-
- Полковник
- Сообщения: 3992
- Зарегистрирован: 12 фев 2016, 11:40
- Откуда: Шатура
- Имя: Энвер
- Благодарил (а): 136 раз
- Поблагодарили: 148 раз
Создание пользовательского блока из скетча(примера)
Базовый редактор полезный инструмент. Но код из него лучше (и в некотором смысле удобнее) выносить в отдельную библиотеку.aidar_i писал(а): 27 сен 2021, 15:24 Мне тоже нравится базовый редактор.
Создание блока на профессионале иногда получается сложнее, чем написать программу в коде , особенно когда хочешь туда засунуть всё что возможно!
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость