Функции Delay() и millis() не работают во внешних файлах cpp
В настоящее время я сталкиваюсь с проблемой использования функций delay() и millis() во внешнем файле cpp. Проблема в том, что когда я использовал функцию delay() в своей основной программе (имеется в виду файл .ino), она работает хорошо, но когда я вызываю ту же функцию во внешнем файле cpp, я застреваю в функции delay. Что касается настройки, файл .hpp, связанный с используемым cpp, хорошо включен в файл .ino и в Arduino librairy.h включен в мой cpp. Я также попытался заменить задержку циклом с использованием миллиса, но значение, возвращаемое миллисом, всегда равно 0. Я использую Arduino mega2560 и датчик уровня воды в следующем примере. Версия Arduino IDE 1.8.16.
Вот выдержка из моего файла ino:
#include <Arduino.h>
#include "DS3231.h"
#include "MyGardenClock.hpp"
#include "sensors.hpp"
#include <LiquidCrystal.h>
#include "Keypad.h"
#include <Wire.h>
///Time object creation
DS3231 clock; //Clock object -> contains basic Real Time Clock functions
RTCDateTime dt; //Struct from DS3231 lib - contains date and time
mG_RTC myClock; //Object that contains specific clock functions to my project like printing date and time on the lcd...
///LCD object creation
//--Pin allocation
const int rs = 2, en = 1, d4 = 4, d5 = 7, d6 = 8, d7 = 10;
//--LCD dynamic object creation
LiquidCrystal* pLCD = new LiquidCrystal(rs, en, d4, d5, d6, d7);
///Keypad parametrization and object creation
//Define col nb and row nb
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad
//Keypad dynamic object creation
Keypad* pKpd = new Keypad(makeKeymap(hexaKeys),rowPins,colPins,ROWS,COLS);
///Sensors object creation
//WaterLvl Sensors
//--Pin allocation
const int WtrLvlAnalogPin = 8; //pin used to read value from water lvl sensor
const int WtrLvlPowerPin = 35; //pin used to power the sensor before reading a value
//--WaterLvl dynamic object creation
Water_Lvl_Sensor* pWtrLvlSens = new Water_Lvl_Sensor(WtrLvlAnalogPin,WtrLvlPowerPin); //contains the delay and millis functions that don't work
/////////// TEST FUNCTIONS ///////////
void testLCD_Kpd(Keypad*,LiquidCrystal*); //test lcd and keypad
void testWtrLvlSens(Water_Lvl_Sensor*,LiquidCrystal*); //test water lvl sensor
void setup()
{
Serial.begin(9600);
pLCD->begin(16,2);
testLCD_Kpd(pKpd,pLCD);
testWtrLvlSens(pWtrLvlSens,pLCD);
}
void loop()
{
}
////////////////////// TEST FUNCTIONS ///////////////////////////
void testLCD_Kpd(Keypad* pKpd, LiquidCrystal* pLCD)
{
char test;
test ='i';
pLCD->print("Hello");
do
{
test = pKpd->waitForKey();
}while(test=='i');
pLCD->clear();
delay(3000); //This one work well
pLCD->print("test = ");
pLCD->print(test);
}
void testWtrLvlSens(Water_Lvl_Sensor* pWLS,LiquidCrystal* plcd)
{
int wtrLvl;
wtrLvl = pWLS->getCurrentWaterLvlValue();
plcd->setCursor(0,1);
plcd->print("wtrLvl = ");
plcd->print(wtrLvl);
}
Вот выдержка из моего файла cpp:
#include <Arduino.h>
#include "sensors.hpp"
/********************************************
* CLASS WATER LvL SENSOR DESCRIPTION *
********************************************/
///Constructor
//-- Assign pin number (analog & digital)
//-- Define pinMode for VCC + set to low
//-- read and store actual waterLevelValue as initial val
Water_Lvl_Sensor::Water_Lvl_Sensor(int anPinNb, int DigPinNb)
{
//Variable used for millis
unsigned long prevTime;
unsigned long currentTime;
const unsigned long delayTime = 100;
Serial.begin(9600); //to debug
//Assign analog and digital pin numbers
analogPinNumber = anPinNb;
VCC_digitalPinNumber = DigPinNb;
pinMode(VCC_digitalPinNumber, OUTPUT); //Digital pin to power the sensor
digitalWrite(VCC_digitalPinNumber,HIGH);//Turn sensor ON before reading initial value
//delay(100); //not working ???
prevTime = millis(); //get and store actual time
do
{
currentTime = millis(); //get actual time
Serial.println(currentTime); //print actual time (debug only)
}while(currentTime<(prevTime+delayTime)); //while time spent < 100
currentValue = analogRead(analogPinNumber); //read analog value
digitalWrite(VCC_digitalPinNumber,LOW); //turn sensor OFF
historyValue = currentValue; //init history val
minValue = 0; //default value - sensor dry
maxValue = 520; //default value - sensor under water
}
У кого-нибудь есть решение?
Надеюсь, я рассказал достаточно подробностей. Если нет, пожалуйста, не стесняйтесь спрашивать.
Спасибо!
@Cyril_Ram, 👍5
1 ответ
Лучший ответ:
Платформа Arduino выполняет некоторую инициализацию для вас, прежде чем перейти к настройке()
и циклу ()
, например, правильно настраивает Timer0 для миллисов()
, задержки()
и братьев и сестер. Это делается в функции main ()
, которая затем после первой инициализации вызывает setup()
и loop()
.
Но создание глобально определенных объектов (и, следовательно, выполнение их конструкторов) выполняется еще до функции main ()
. В это время ни millis()
, ни delay()
не будут работать, так как для их работы необходимо правильно настроить аппаратное время 0. Аппаратный таймер генерирует прерывания с определенной частотой, и в соответствующем ISR (Подпрограмма обслуживания прерываний) увеличивается переменная для millis ()
. Если Timer0 не настроен, его прерывание не может сработать, и, следовательно, функция millis()
останется нулевой. Таким образом, вы не можете сделать все это в конструкторе объекта, или вам всегда нужно создавать объект в setup()
или loop()
.
Именно по этой причине большинство библиотек Arduino, связанных с оборудованием, используют метод .begin()
для инициализации материалов, связанных с оборудованием. Эта функция может быть вызвана для глобального объекта в функции setup ()
, когда все остальное уже настроено правильно.
Что теперь делать? Создайте метод .begin()
для своего класса. Переместите весь код из конструктора (за исключением присвоения pin) в эту функцию .begin ()
. А затем вызовите эту функцию в setup()
.
- управление 2 датчиками и 3 насосами с помощью millis
- Использование millis вместо задержки перезагрузки реле
- Получить подсчет производства за текущую минуту
- Обновите атрибут класса с помощью attachInterrupt
- Как разделить входящую строку?
- Как использовать SPI на Arduino?
- Как справиться с rollover millis()?
- Как сбросить или отформатировать Arduino?
Большое спасибо за ваш быстрый ответ. Это действительно имеет смысл, действительно. Я внесу изменения и скажу вам, сработает ли это, но я уверен., @Cyril_Ram
Привет, Крисл, просто чтобы ты знала, что твое решение работает хорошо. Большое спасибо., @Cyril_Ram