ESP32 millis не работает должным образом

У меня есть программа, которая измеряет температуру каждые 30 минут и отправляет их в базу данных. Сразу после запуска программы отправляется первое измерение, однако второе (которое должно быть отправлено через 30 мин), отправляется только через 1 час. С тех пор код работает нормально. Время измеряется в миллисекундах. Однако если я установлю разницу во времени на 28 минут, то с самого начала все будет работать нормально. В чем же может быть причина? Есть ли вероятность, что он перейдет в спящий режим? Я не понимаю, почему он прекрасно работает с 28 минутами и перестает работать с 29 минутами?

Заранее спасибо!

Мой код:

if (millis() - sendDataPrevMillis > 1740000)
  {
    sendDataPrevMillis = millis();

//другой код

}

Единственная часть, которую я меняю, чтобы она работала, - это установка миллиса с 1740000 (29 минут) до 1680000 (28 минут).

, 👍0

Обсуждение

Поделитесь с нами своим кодом., @Zhelyazko Grudov

Пожалуйста, предоставьте минимальный компилируемый пример кода, который показывает вашу проблему, а не просто очень маленький фрагмент кода, @chrisl

используйте "длинный без знака" в качестве типа данных " sendDataPrevMillis`, @Juraj

Вы убедились, что millis() возвращает 0 при запуске? Для отладки вы можете распечатать начальное значение и любое следующее, если условие выполнено., @the busybee


1 ответ


-1
  1. Хотя это и не является строго обязательным, возможно, используйте круглые скобки вокруг millis() - sendDataPrevMillis для удобства чтения;
  2. Я предполагаю, что вы инициализируете sendDataPrevMillis в 0, но в первый раз, когда вы назначаете sendDataPrevMillis в millis (), пройдет некоторое время с момента вашей оценки. Таким образом, вызов millis() дважды даст разные результаты. Это делает его менее легко увидеть, что происходит.

Предложение попробовать:

long HALFHOUR = 30 * 60 * 1000L;

if ( (millis() % HALFHOUR ) == 0L ) {
    //измерить и отправить
    //....
}

Надеюсь, это поможет.

NB: % - это то, что называется "оператором по модулю", см.: https://www.geeksforgeeks.org/modulo-operator-in-c-cpp-with-examples/

,

Я не совсем понимаю, что вы имеете в виду со своим вторым пунктом. Многократный вызов millis() даст разные результаты, когда между вызовами пройдет по крайней мере одна миллисекунда. При инициализации "sendDataPrevMillis" до нуля время будет отсчитываться с момента запуска (цикл питания или сброс). Маловероятно, что код выполнялся в течение получаса до того, как был получен оператор if в первый раз. Так почему это должно иметь значение?, @chrisl

Проблема. этого, конечно, будет действительно очень мало. то, что я пытался сказать, касалось стиля: когда состояние цикла относится к фактическому прогрессирующему миллису (первый вызов) Я бы предложил хранить именно эту ценность. Назначение в пределах условия если ( (currentMillis = millis()) - sendDataPrevMillis > 1740000) { sendDataPrevMillis = текущий миллиметр; для того, чтобы это не стало немного беспорядочным, вам не кажется?, @user75521

Вы можете сделать это с назначением в условии if, но я не думаю, что это лучше читается. Хотя это субъективно. Во втором пункте вы не говорите о стиле. Как я теперь понимаю, вы говорите, что вызовы millis() в условии if и в следующем внутреннем утверждении дают разные результаты. Я так не думаю. Код работает слишком быстро для этого. Даже если код случайно попадет в точную точку, где увеличивается значение millis (), это будет означать максимальную ошибку в 1 мс. Не важно, когда в этом временном диапазоне, а также когда вы используете "millis()"., @chrisl

каковы шансы попасть в это с точностью до мс из тысяч?, @dandavis

Это имеет слишком большой потенциал, чтобы пойти не так в среде реального времени, и это не лучший код, чем тот, о котором идет речь. Кроме того, таймеры, зависящие от " millis ()", всегда должны быть "длинными без знака" (или "uint32_t")., @StarCat