задержка без delay при входе в функцию, (возможно ли)?

sanekru
Offline
Зарегистрирован: 05.12.2017

Доброго времени!

Собственно есть код управления модемом по uart, в нем при входящей смс команде к примеру переводиться переменная float в string и отправляется в функцию отправки сообшения.

if(strstr(command, sms_temp1)){
char tmptemp[10];
char* chartemp;
float dstmp = dstemp[0];
chartemp = dtostrf(dstmp, 5, 2, tmptemp);
sendTextMessage(chartemp);

void sendTextMessage(const char* sms)
{
delay(500);
GPRS.print(send_Sms);
GPRS.print(send_NumTel);
gprsCmdAndWaitln(send_Quote);
GPRS.print(sms);
gprsCmdAndWaitln(send_Enter);
}

Собственно вопрос!

Возможно ли сделать задержку в функции по millis (без delay) и дополнительных флагов или пересматривать логику? т.е.:

void sendTextMessage(const char* sms)
{
uint32_t count = millis();
if (millis() - count > 1000){
GPRS.print(send_Sms);
GPRS.print(send_NumTel);
gprsCmdAndWaitln(send_Quote);
GPRS.print(sms);
gprsCmdAndWaitln(send_Enter);
}
}

Собственно нужно это всё чтобы сделать универсальной функцию и избавиться от delay.
Заблаговременное спасибо!

ps sorry за неформатированное сообщение, только установил firefox на ubuntu, а в нем видимо нужно доустанавливать какие то плагины и собственно форматирование текста недоступно!!!

sanekru
Offline
Зарегистрирован: 05.12.2017

Доброго времени!

Собственно есть код управления модемом по uart, в нем при входящей смс команде к примеру переводиться переменная float в string и отправляется в функцию отправки сообшения.


if(strstr(command, sms_temp1))
{
  char tmptemp[10];
  char* chartemp;
  float dstmp = dstemp[0];
  chartemp = dtostrf(dstmp, 5, 2, tmptemp);
  sendTextMessage(chartemp);
}

void sendTextMessage(const char* sms)
{
  delay(500);
  GPRS.print(send_Sms);
  GPRS.print(send_NumTel);
  gprsCmdAndWaitln(send_Quote);
  GPRS.print(sms);
  gprsCmdAndWaitln(send_Enter);
}

Собственно вопрос!

Возможно ли сделать задержку в функции по millis (без delay) и дополнительных флагов, или пересматривать логику? т.е.:

void sendTextMessage(const char* sms)
{
  uint32_t count = millis();      //что то наподобие этого
  if (millis() - count > 500)
  {
    GPRS.print(send_Sms);
    GPRS.print(send_NumTel);
    gprsCmdAndWaitln(send_Quote);
    GPRS.print(sms);
    gprsCmdAndWaitln(send_Enter);
  }
}

Собственно нужно это всё чтобы сделать универсальной функцию и избавиться от delay.
Заблаговременное спасибо!

ps получилось отформатировать

Клапауций 9999
Offline
Зарегистрирован: 27.11.2020

sanekru пишет:

Доброго времени!

Собственно есть код управления модемом по uart, в нем при входящей смс команде к примеру переводиться переменная float в string и отправляется в функцию отправки сообшения.


это типо техзадание и я в нём никак не наблюдаю необходимость задержек.

*так то оно - "да"... можно реализовать срабатывание чего-то после чего-то через определённое время, засекая время первого, вычитая текущее время и ждать пока разница не превысит требуемое для срабатывания тела условия.

!не благодари - это я от души. о_О

sadman41
Offline
Зарегистрирован: 19.10.2016

Чем функционально будет отличаться "задержка по millis" от delay()?

sanekru
Offline
Зарегистрирован: 05.12.2017

Клапауций 9999 пишет:
sanekru пишет:

Доброго времени!

Собственно есть код управления модемом по uart, в нем при входящей смс команде к примеру переводиться переменная float в string и отправляется в функцию отправки сообшения.

это типо техзадание и я в нём никак не наблюдаю необходимость задержек. *так то оно - "да"... можно реализовать срабатывание чего-то после чего-то через определённое время, засекая время первого, вычитая текущее время и ждать пока разница не превысит требуемое для срабатывания тела условия. !не благодари - это я от души. о_О

Это то понятно что можно повесить в loop sendTextMessage и при её вызове возводить флаг и millis, но получается громоздко и не универсально, а хотелось чтобы при вызове определённой функции её код выполнялся с задержкой и при этом не подвисал контроллер!

sanekru
Offline
Зарегистрирован: 05.12.2017

sadman41 пишет:
Чем функционально будет отличаться "задержка по millis" от delay()?

тем что если в loop ещё к примеру крутиться функция опроса кнопок, тогда на время delay(я) она работать не будет, пусть конечно это в реале не столь важно, т.к. это ооочень кратковркменно и не постоянно, только на время отсыла смс, но всё же считаю это костылём!

sanekru
Offline
Зарегистрирован: 05.12.2017

Клапауций 9999 пишет:
sanekru пишет:

Доброго времени!

Собственно есть код управления модемом по uart, в нем при входящей смс команде к примеру переводиться переменная float в string и отправляется в функцию отправки сообшения.

это типо техзадание и я в нём никак не наблюдаю необходимость задержек. *так то оно - "да"... можно реализовать срабатывание чего-то после чего-то через определённое время, засекая время первого, вычитая текущее время и ждать пока разница не превысит требуемое для срабатывания тела условия. !не благодари - это я от души. о_О

Просто иногда (редко), модем при отсылке пишет CMEERROR, видимо после приёма смс не успевает проглатить команду на отсылку, а с небольшой задержкой всё ОК!

sanekru
Offline
Зарегистрирован: 05.12.2017

Собственно работает всё идеально и без сбоев, просто мануал для новичков гласит что хорошая программа та, которая написана без delay!

sadman41
Offline
Зарегистрирован: 19.10.2016

sanekru пишет:

sadman41 пишет:
Чем функционально будет отличаться "задержка по millis" от delay()?

тем что если в loop ещё к примеру крутиться функция опроса кнопок, тогда на время delay(я) она работать не будет


Если использовать millis(), как вы сделали, то... Представьте, что millis() вернуло число 450. Выполнится ли условие хоть раз, даже если МК будет переходить на след. инструкцию 10мс вместо микросекунды?

b707
Offline
Зарегистрирован: 26.05.2017

sanekru пишет:

sadman41 пишет:
Чем функционально будет отличаться "задержка по millis" от delay()?

тем что если в loop ещё к примеру крутиться функция опроса кнопок, тогда на время delay(я) она работать не будет, пусть конечно это в реале не столь важно, т.к. это ооочень кратковркменно и не постоянно, только на время отсыла смс, но всё же считаю это костылём!

замените delay(500); на свою собственную функцию my_delay(500). внутри которой не просто "спите" полсекунды - а скажем проверяйте состояние кнопок

sanekru
Offline
Зарегистрирован: 05.12.2017

sadman41 пишет:
sanekru пишет:

sadman41 пишет:
Чем функционально будет отличаться "задержка по millis" от delay()?

тем что если в loop ещё к примеру крутиться функция опроса кнопок, тогда на время delay(я) она работать не будет


Если использовать millis(), как вы сделали, то... Представьте, что millis() вернуло число 450. Выполнится ли условие хоть раз, даже если МК будет переходить на след. инструкцию 10мс вместо микросекунды?

Я знаю что так будет, просто привёл как пример что возможно ли что то наподобие сделать, но логически подумав понял что тему можно закрывать, ибо функцию нужно вешать в loop и по событию возводить флаг и сбрасывать таймер чтобы она работала как я хочу, так что лучше оставлю изначально с delay, так сказать компромисс между функциональностью и простотой кода

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

Логически правильно будет ждать ответы от модема и в случае отсутствия их в течении Х времени - принимать решение о повторе операции или продолжении работы. А у вас это просто костыли.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

У Вас delay() не там стоит. Он, как я понял, нужен для того, чтобы успеть передать и обработать, и в это же время еще раз не вызвать передачу. Тогда он должен стоять после 17 строки. Его длительность надо проверять экспериментально.

В 12 строке я его присутствия не понимаю.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Вотъ

uint32_t msProc1;             // Таймер
uint32_t rep = 8000;          // Требуемая периодичность выполнения функции


void setup() {
Serial.begin(115200);
msProc1 = millis();
}

void loop() {
if (millis() - msProc1 > rep) proc1();
}


void proc1(){
static uint8_t stage = 0;
  if (stage == 0) {
    Serial.println("Stage 1");
    stage++;
    msProc1 = millis()-rep + 1000;
    return;
  }
  if (stage == 1) {
    Serial.println("Stage 2");
    stage++;
    msProc1 = millis()-rep + 2000;
    return;
  }
    if (stage == 2) {
    Serial.println("Stage 3");
    if (1==0) {stage = 0; return;}      // Если что-то пошло не так...
    stage++;
    msProc1 = millis()-rep + 500;
    return;
  }
  if (stage == 3) {
    Serial.println("Last stage");
    stage=0;
    msProc1 = millis();
    return;
  }
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

эта чо?

if (1==0) {stage = 0; return;}

Клапауций 9999
Offline
Зарегистрирован: 27.11.2020

DetSimen пишет:

эта чо?

if (1==0) {stage = 0; return;}


по крайней мере в логе ИДЕ должно было матюкнуться, что 1 никогда не станет равен 0, поэтому запись бессмысленна.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Ну господа, ну ясен пень! Это иллюстрация возможности ветвления. Заведомо ложное выражение. Но если на этом месте будет, например, проверка CRC полученных на предыдущих этапах данных, то можно не применять эти данные в последнем шаге с случае ошибки, а начать процедуру повторного их получения с шага #1 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Чо?

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

DetSimen пишет:

Чо?

Сейчас не понял вопроса 

Это просто демонстрация идеи алгоритма. Вместо (1==0) подставьте нужное условие проверки качества выполнения предыдущих шагов

А можно эту строчку вообще к хренам собачьим удалить и выполнять функцию линейно

Вот ведь докопались, изверги 

nik182
Offline
Зарегистрирован: 04.05.2015

Если так написать, компилятор просто выкинет эту строку и даже if делать не будет.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Вы сейчас все прикалываетесь? 

А если бы я написал

void func(){
тут выполняем всякую полезную х-ню
}

Вы бы тоже рассказывали, что компилятор так не может? Серьезно? 

Я четко осознаю, что компилятор не будет 1 с 0 сравнивать. Это просто заглушка для возможности организации ветвления

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Rumata пишет:

А если бы я написал

void func(){
тут выполняем всякую полезную х-ню
}

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

DetSimen пишет:

Rumata пишет:

А если бы я написал

void func(){
тут выполняем всякую полезную х-ню
}

Думаю дефайнами можно намутить))

Ок, будь по вашему, пусть будет if (false) ....

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Благородный Дон, я думаю, если бы Вы написали

if (false) {stage = 0; return;} // здесь вместо false подставить код ошибки

то эта строчка вызвала бы намного меньше вопросов.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

andriano пишет:

Благородный Дон, я думаю, если бы Вы написали

if (false) {stage = 0; return;} // здесь вместо false подставить код ошибки

то эта строчка вызвала бы намного меньше вопросов.

Согласен с Вами уважаемый сэр! Но, как же тогда срач? 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Кстати, вполне ходовым вариантом может стать проверка something.available() в этом месте. Например модем, UART или пакет NTP

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

sanekru пишет:

Просто иногда (редко), модем при отсылке пишет CMEERROR, видимо после приёма смс не успевает проглатить команду на отсылку, а с небольшой задержкой всё ОК!

Узнаю SoftSerial ))) Задержками можно подобрать более устойчивую работу, но в корне не решите проблему. Подход предложенный в #1 очень даже верный, только по мелочам ошибки count должен быть static, ну и значение ему присваивать не каждый раз, а когда проверка выполнилась.

Ну а если двигаться дальше в направлении этом то полезно делать так: все остальные места, где есть завязка по времени реализовать аналогично; значение millis передавать в функцию параметром; возвращать из функции не void а что то,  информирующее о том было ли реально выполнено в функции действие или впустую прогнали т.к. время не пришло, например true если делали что. Тогда снаружи имеем красоту

void loop()
{
 uint32_t t;
 t=millis();

 if (sendTextMessage("sms",t))  тут будем только при реальной отправке;
 if(GetButton(t)) тут будем по нажатию кнопки;
 if(receveData(d,t)) тут будем при приеме данных;
...


Очень симпатичная архитектура без делеев получается.