Вопрос чайника по самописным функциям
- Войдите на сайт для отправки комментариев
Не могу понять как правильно написать функцию...
Вот код, который работает как задумано, печатает в порт раз в n секунд что-то:
unsigned long Time = 0; void setup() { Serial.begin(9600); } void Timer(); void loop() { Timer(1000); } void Timer(int millisec) { if(millis() - Time > millisec){ Serial.println(1); Time = millis(); } }
Но когда я хочу вызвать эту функцию другой функцией, например Run(), не понимаю как надо изменить Timer, какого типа его сделать и что он должен возвращать, и должен ли, чтобы внутри Run() она адекватно отрабатывала. Затык в функции bool Timer(int millisec). Если сделать return true до Time = millis();, то таймер никогда не обновится, и всегда будет true, а если наоборот, то тоже самое. В любом случае, первый попавшийся return завершает функцию. А хочется сделать полноценную функцию, чтобы она как delay() работала, только не блокировала всю программу, а через нужный промежуток времени возвращала что-либо.
unsigned long Time = 0; void setup() { Serial.begin(9600); } bool Timer(); void Run(); void loop() { Run(); } bool Timer(int millisec) { if(millis() - Time > millisec){ Time = millis(); return true; } } void Run(){ if(Timer(1000) == true) { Serial.println(1); } }
Если функция должна что-то возвратить, то ей это необходимо делать всегда. А у Вас только в одном случае происходит возврат true.
Параметр функции точно должен быть int?
Параметр может быть любой, вплоть до возможных 32 бит, это же таймер. Так что может и int может быть мало.
Не очень понял, что значит "необходимо делать всегда". Функция отсчитала время и вернула true. А как можно сделать иначе?
В любом другом случае она должна возвращать false...
Вот например, аналогичный вариант. Куда воткнуть здесь Time = millis() внутри функции byte Timer(), чтобы чередовались return 1 и return 2?
только оно не будет чередоваться
Это смотря с каким параметором вызвать ...
только оно не будет чередоваться
Вот и я об этом. Я не понимаю как сделать в данном случае смену состояния. И даже если просто нужно чтобы функция отработала через несколько секунд, как сделать так, чтобы ее можно было вызывать многократно в разных местах с разными параметрами?
Не очень понял, что значит "необходимо делать всегда". Функция отсчитала время и вернула true. А как можно сделать иначе?
похоже вы не понимаете, как работает ваша функция. Слова "отсчитала время и вернула true" были бы уместны, если бы функция запускалась, ждала 1000мс и потом возвращала true. Но на самом деле все работает совсем не так - за время 1 сек loop() успевает запустить вашу функцию десяток тысяч раз и каждый раз она должна что-то возвращать - а в вашем коде этого нет.
И по этой же причине новый вариант, возвращающий "1" и "2" - не будет их "чередовать". Функция будет возвращать несколько тысяч "двоек" на одну "единицу"
Вот и я об этом. Я не понимаю как сделать в данном случае смену состояния.
я думаю, вы другого не понимаете - не понимаете в принципе, как работают таймеры на миллис. А смена состояния тут получается автоматически - об этом переживать не стоит.
Крайняя выдаёт двойки и иногда (раз в заданное время единичку).
Конкретно эту фунцию сложно вызывать из разных мест с разными параметрами - так как она привязана к одной и той же
unsigned
long
Time
Не очень понял, что значит "необходимо делать всегда". Функция отсчитала время и вернула true. А как можно сделать иначе?
похоже вы не понимаете, как работает ваша функция. Слова "отсчитала время и вернула true" были бы уместны, если бы функция запускалась, ждала 1000мс и потом возвращала true. Но на самом деле все работает совсем не так - за время 1 сек loop() успевает запустить вашу функцию десяток тысяч раз и каждый раз она должна что-то возвращать - а в вашем коде этого нет.
И по этой же причине новый вариант, возвращающий "1" и "2" - не будет их "чередовать". Функция будет возвращать несколько тысяч "двоек" на одну "единицу"
Это я уже все понял экспериментальным путем, и только после этого создал эту тему. Даже читал книгу по С++ )) Кстати, здесь на сайте, сказано про return, что он завершает функцию и выходит из нее. Это в случае, если return "пустой"?
Конкретно эту фунцию сложно вызывать из разных мест с разными параметрами - так как она привязана к одной и той же
unsigned
long
Time
Ну почему, при условии того, что новый вызов делается только после окончания периода прежнего - можно вызывать сколько угодно раз.
Крайняя выдаёт двойки и иногда (раз в заданное время единичку).
Конкретно эту фунцию сложно вызывать из разных мест с разными параметрами - так как она привязана к одной и той же
unsigned
long
Time
То что видно в мониторе порта, это сначала единички, а потом уже бесконечные двойки..
Нужно создавать в самой функции
unsigned
long
Time
?Нужно создавать в самой функции
unsigned
long
Time
?нет, это не поможет.
Можно описать эту функцию как класс - и на каждый период создавать свой экземпляр - только непонятно, нафига такие сложности...
Конкретно эту фунцию сложно вызывать из разных мест с разными параметрами - так как она привязана к одной и той же
unsigned
long
Time
Ну почему, при условии того, что новый вызов делается только после окончания периода прежнего - можно вызывать сколько угодно раз.
А это как? Можно пример?
Нужно создавать в самой функции
unsigned
long
Time
?нет, это не поможет.
Можно описать эту функцию как класс - и на каждый период создавать свой экземпляр - только непонятно, нафига такие сложности...
Вот я так и думал. Чтобы не писать везде, где нужен таймер, вычисления из миллиса. Просто написал функцию, указал параметры и она работает.
Нужно создавать в самой функции
unsigned
long
Time
?Нельзя - она уничтожится вместе выходом из фунции.
Если нужны работающие одновременно такого плана функции, то они должны опираться каждая на свою опорную переменную. Ну или в вызов функции передавать ещё и указатель на опорную переменную.
Вот я так и думал. Чтобы не писать везде, где нужен таймер, вычисления из миллиса.
по мне так "вычисления из миллиса" проще, я никакими библиотеками таймеров не пользуюсь
Вот я так и думал. Чтобы не писать везде, где нужен таймер, вычисления из миллиса.
по мне так "вычисления из миллиса" проще, я никакими библиотеками таймеров не пользуюсь
Я понимаю что проще, но так не интересно. ))) Значит пойду объекты и классы изучать ))
только непонятно, нафига такие сложности...
упаси нас бог это узнать ...
Я понимаю что проще, но так не интересно. ))) Значит пойду объекты и классы изучать ))
вы бы для начала хотя бы на С программировать научились, а то ведь ни о функциях, ни о циклах, ни о переменных ничего не знаете. С таким "багажом знаний" изучать классы бессмысленно.
ТС не ищет простых путей ...
Человек велосипед изобретает, а вы тут набросились - злые дядьки. ))
с треугольными колесами ...
freeman86,
Если функция должна что-то возвратить, то ей это необходимо делать всегда.
что значит "необходимо делать всегда". Функция отсчитала время и вернула true. А как можно сделать иначе?
В любом другом случае она должна возвращать false...
Это именно то, о чём говорится в анекдоте про программиста, который на ночь ставил на прикроватную тумбочку стакан с водой на случай, если захочется пить и пустой стакан - на случай, если пить не захочется.
Непрограммисты этоЙ шутки не понимают.
Параметр может быть любой, вплоть до возможных 32 бит, это же таймер. Так что может и int может быть мало.
Поэтому я и интересуюсь - сознательно ли применён int. signed int и unsigned int, например, занимают по 2 байта, но крайние значения у них несколько разные, если так можно выразиться.
Следите за руками, упрощённо объясняю:
Вызов функции - это, для МК, переход с текущего адреса A по некоему адресу B в перечне выполняемых команд. Return - это, после выполнения всего, что находится в функции, возврат неизвестно откуда (B+9000, например) на адрес A+1. Если вызываемая функция не является void, то логично предположить, что результатом её работы можно пользоваться. Для этого, после возврата на адрес A+1, в ячейке X должно находиться некоторое значение - результат работы (то, что происходит при return 1 или return 89).
В Вашем случае в ячейку X заносится true только в одном случае - когда условие внутри функции истинно. А если оно не истинно? Правильно - ничего не заносится. Т.е. после возврата из функции в X может лежать старое true, может случайно занесённое false. Результат в любом случае непредсказуем. А Вы на этот результат начинаете опираться в следующих вычислениях и получаете барабан из "Поля чудес".
Теперь подумайте, как нужно действовать, чтобы в X при завершении функции всегда что-то попадало.
Вот я так и думал. Чтобы не писать везде, где нужен таймер, вычисления из миллиса. Просто написал функцию, указал параметры и она работает.
[/quote]
Похоже Вам надо чтото такое
Красивая функция. Ее можно в дребезгах использовать?
Да. Я использую.
Большое спасибо за полезные советы и помощь! :)
boolean my_pausa(unsigned
long
time,
byte
nomer)
//time-время задержки, nomer-номер таймера
11
{
12
bool
x = 0;
13
if
(fl_pause[nomer] == 0)currentPause[nomer] = millis(), fl_pause[nomer] = 1;
14
if
(millis() - currentPause[nomer] >= time) x = 1, fl_pause[nomer] = 0;
15
return
x;
16
}
Объясните, зачем в этой функции(выше написана в скетче) обязательно нужно использовать флаг состояния в 13 строчке? Почему без него не будет работать? Заходим в функцию, устанавливаем Х = 0, запоминаем время в currentPause, а ниже уже проверка на время таймера. Почему обязательно нужен флаг состояния?
Не нужен, только там где x=1 вместо флаг=0 пишем currentPause=millis()
Bозник еще один. Почему нельзя просто вернуть единицу: return 1; а нужно именно присваивать значение переменной и уже ее возвращать return x; ? Если делать так return 1; функция работает как если бы не было отсчета времени.
Потому что х изначально =0. И функция в основном этот ноль и возвращает. Единицу возвращает только когда таймер заканчивается (когда заходит в иф). Можно.обойтись без переменной х. Два раза написать return. В ифе return 1. После ифа return 0.