не может вернуть значение с float из функции

Я хочу установить 2-секундную задержку для считывания температуры, но задержка millis() не применяется.

#include <OneWire.h>
#include <LiquidCrystal_I2C.h>
#include <DS3231.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

Time t;
LiquidCrystal_I2C lcd(0x27, 16, 2);
DS3231  rtc(SDA, SCL);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

const int OnHour = 23;
const int OnMin = 42;
const int checkTemp = 2000;
const int checkTempinterval = 0;

void setup() {
  Serial.begin(115200);
  pinMode(3, OUTPUT);
  lcd.begin();
  lcd.backlight();
  rtc.begin();
}
void loop() {
  t = rtc.getTime();
  float testTemp;
  testTemp = temperature();
  lcd.setCursor(0,0);
  lcd.print(testTemp);
  lcd.print("   ");
  lcd.print(rtc.getTimeStr());
  lcd.setCursor(0,1);
  lcd.print(rtc.getDOWStr());
  lcd.print("   ");
  lcd.print(rtc.getDateStr());
  if(testTemp >= 28){
    digitalWrite(3,HIGH);
  }else{
    digitalWrite(3,LOW);
  }
// if(t.hour == OnHour && t.min == OnMin){
// цифровая запись(3,ВЫСОКИЙ);
// }еще{
// цифровая запись(3,НИЗКИЙ);
// }
}
float temperature(){
  unsigned long currenttime = millis();
  if(currenttime - checkTempinterval >= checkTemp){
  sensors.requestTemperatures();
  float testTemp = sensors.getTempCByIndex(0);
  currenttime = checkTempinterval;
  return testTemp;
  }
}

, 👍1

Обсуждение

Во-первых, не все пути выполнения возвращают значение, во-вторых, почему вы делаете: currenttime = checkTempinterval;, это бессмысленно, так как после возврата оно больше не будет существовать., @KIIV

В вашем примере кода нет ничего под названием «мини»., @st2000

@KIIV, поэтому я не могу вернуть значение из sensor.getTempCByIndex(0);? он читает температуру, но задержка не применяется..., @ElectronSurf

Вы можете, но код не делает этого в случае, если условие if не выполняется., @KIIV

@KIIV, так какое решение?, @ElectronSurf

Удалите все это и начните с нуля. Включить все предупреждения! Не используйте никаких ветвей в Temperature(), возможно, даже забудьте о функциях, пока вы не поймете концепцию локальных переменных, их область действия и существование. Просто используйте задержку (2000), прочитайте rtc, запросите температуру, распечатайте результаты, @KIIV

это вопрос, и, любезно ответив на него, вы можете помочь мне «понять концепцию локальных переменных», и я не хочу использовать задержку!, @ElectronSurf

Также спрашивали здесь: https://forum.arduino.cc/index.php?topic=621590.0, @Jot

@Jot "Детективное достижение разблокировано"!, @ElectronSurf

Тем более в чем вопрос? Я не вижу ни одного., @MichaelT


2 ответа


Лучший ответ:

3

Я вижу 2 проблемы с вашим кодом:

  1. Возврат значения из функции: Если вы хотите вернуть значение из функции, вы должны убедиться, что в любом случае return x выполняется внутри функции в функции temperature(), которая у вас сейчас есть, если это оператор if:

    if(currenttime - checkTempinterval >= checkTemp){
    

    Внутри него находится единственный оператор return. Это означает, что если функция вызывается до следующего времени измерения, она ничего не вернет. Обычно компилятор выдает вам как минимум предупреждение об этом (возможно, вам нужно включить предупреждения в настройках Arduino IDE).

    Здесь вы также должны подумать о том, что вы хотите вернуть, если никакое измерение фактически не выполнялось. Вы хотите вернуть значение ошибки (например, -300; значение ошибки не должно находиться в допустимых данных)? Затем сделайте это после оператора if. Или вы хотите, чтобы он просто возвращал последнее измеренное значение? Затем объявите переменную (либо в глобальной области видимости, то есть вне какой-либо функции, либо в локальной области видимости, то есть внутри функции, но статической, что означает, что значение будет сохраняться между выполнениями функций). Сохраните измеренные температуры в эту переменную и верните ее после оператора if.

    Если вы это сделаете, подумайте, что это значит для остального кода. Например, если вы возвращаете значение ошибки, в настоящее время оно также будет отображаться вашим кодом.

  2. Правильное выполнение кода millis(): что вы делаете неправильно, так это то, что вы обновляете неправильную переменную внутри if заявление. В настоящее время вы записываете значение checkTempinterval (которое является временем последнего измерения) в переменную currenttime. Переменная currenttime была объявлена локально (то есть внутри функции) с помощью

    unsigned long currenttime = millis();
    

    Локальные переменные присутствуют только во время выполнения функции, в которой они объявлены. Когда микроконтроллер выполняет оператор return, он отбрасывает все локальные переменные, освобождая ОЗУ для другие переменные. Это означает, что в настоящее время вы сохраняете значение внутри переменной, которое удаляется сразу после него.

    На самом деле вы хотели сделать наоборот:

    checkTempinterval = currenttime;
    

    checkTempinterval — это глобальная переменная. Он будет оставаться в оперативной памяти в течение всего выполнения программы. Поскольку он содержит время последнего измерения, вы записываете в него текущее время при измерении.

    Очень важно: в настоящее время checkTempinterval определяется как const int, что означает постоянное целое число. Эта переменная не должна быть постоянной, так как мы хотим изменить значение (обновить время последнего измерения). Также вы не должны использовать здесь int, потому что диапазон его значений доходит только до 32767, что составляет 32 секунды при использовании с millis(). После этого он переполнится до отрицательных значений. Лучше использовать тип возвращаемого значения millis(): unsigned long. Он имеет 4 байта (вместо 2 байтов ints) и переполнится только через 49 дней. Если вы используете этот тип переменной только для вещей с millis(), даже это переполнение не будет проблемой.

,

1

Вы можете использовать функцию millis() для создания "таймера", который будет получать показания датчика каждые 2 секунды. Скетч BlinkWithoutDelay.ino должен поставляться с Arduino IDE, но если его нет, его можно найти здесь: BlinkWithoutDelay.

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

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

// Сохраняем последний раз, когда вы проверяли датчик.
unsigned long previousMillis = 0;

// интервал проверки датчика (миллисекунды)
const long interval = 2000;

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

void loop() {
  // здесь вы бы разместили код, который должен выполняться все время.

  // Получить текущее время.
  unsigned long currentMillis = millis();

  // Проверяем, не пора ли проверить показания датчика.
  if (currentMillis - previousMillis >= interval) {
    // сохранить последний раз, когда вы проверяли датчик.
    previousMillis = currentMillis;

    // Здесь вы добавляете код, который проверяет датчик.

    // Тестовый вывод.
    Serial.println("Checking Sensor");
  }
}
,