Счет времени с использованием миллисекунд
Я пытаюсь написать код, в котором фоторезисторы (a или b) воспринимают мигание света, а светодиоды (k и d) — одновременно с этим миганием. И я хочу, чтобы когда оба фоторезистора почувствуют темноту более 3 секунд, светодиоды загорятся и останутся, пока один из них снова не загорится. Но я не могу понять, в какой части я должен поставить счетчик времени в миллисекундах?
int k = 2;
int d = 3;
int fk = A0;
int fd = A1;
int a = 0;
int b = 0;
void setup() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
Serial.begin(9600);
}
void loop()
{
a = analogRead (fk);
b = analogRead (fd);
while (a < 1000 && b < 1000)
{
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
a = analogRead (fk);
b = analogRead (fd);
}
if (a > 1000)
digitalWrite(2, HIGH);
else
digitalWrite(2, LOW);
if (b > 1000)
digitalWrite(3, HIGH);
else
digitalWrite(3, LOW);
}
3 ответа
Миллис измеряет время. Вы можете сохранить эту меру и сравнить ее позже. Я не знаю, что в вашем коде представляет собой ощущение темноты/света в вашем коде (резисторы могут использоваться для повышения или понижения измеренного входа в зависимости от вашей схемы), поэтому вам придется работать следующим образом, заменяя вещи в < ;>
unsigned long lastlight;
void loop()
{
if (<isLitSensorA>) lastlight = millis();
if (<isLitSensorB>) lastlight = millis();
if(millis() - lastlight > 3000){ //3 секунды с момента lastlight
<LightsAlwaysOn>
}
else{
<BlinkWithLights>
}
}
Это один из тех случаев, когда решение состоит в том, чтобы просто реализовать конечный автомат. Рассмотрим конечный автомат с этими тремя состояния:
СВЕТ
: свет был обнаружен хотя бы одним из датчиков, Светодиоды следуют за датчиками света.SHORT_DARK
: ни один датчик не видит свет, оба светодиода не горятLONG_DARK
: прошло не менее трех секунд с тех пор, как ни один датчик увидел свет, оба светодиода горят.
Переходы между этими состояниями можно изобразить следующим образом. диаграмма состояний:
где «обнаружена темнота» означает, что ни один датчик не видит свет, а «свет обнаружен» означает, что по крайней мере один датчик видит свет.
Как правило, рекомендуется всегда рисовать диаграмму состояний прежде чем вы начнете писать код. Как только вы убедитесь, что ваша диаграмма описывает желаемое поведение, почти тривиально перевести его в код. Вот как я бы это закодировал:
void loop()
{
bool light_k = analogRead(IN_K) >= 1000;
bool light_d = analogRead(IN_D) >= 1000;
static enum { LIGHT, SHORT_DARK, LONG_DARK } state;
static uint32_t darkness_start;
switch (state) {
case LIGHT:
digitalWrite(OUT_K, light_k ? HIGH : LOW);
digitalWrite(OUT_D, light_d ? HIGH : LOW);
if (!light_k && !light_d) {
darkness_start = millis();
state = SHORT_DARK;
}
break;
case SHORT_DARK:
if (light_k || light_d) {
state = LIGHT;
} else if (millis() - darkness_start >= 3000) {
digitalWrite(OUT_K, HIGH);
digitalWrite(OUT_D, HIGH);
state = LONG_DARK;
}
break;
case LONG_DARK:
if (light_k || light_d) {
state = LIGHT;
}
break;
}
}
Вот более элегантный способ сделать это. Эта программа не требует, чтобы вы действительно считали, когда было темно, вместо этого она просто запоминает время, когда в последний раз видела свет (как поэтично ;). Я также добавил некоторые комментарии к коду.
// Все переменные
int k = 2; // светодиод 1
int d = 3; // светодиод 2
int fk = A0; // фоторезистор 1
int fd = A1; // фоторезистор 2
int lastLight = 0;
// Настраиваем светодиоды
void setup() {
pinMode(k, OUTPUT);
pinMode(d, OUTPUT);
}
void loop()
{
// Проверяем фоторезисторы
int a = analogRead (fk);
int b = analogRead (fd);
if (a > 1000 || b > 1000)
{
// Включаем светодиоды, если один фоторезистор чувствует свет
digitalWrite(k, HIGH);
digitalWrite(d, HIGH);
// Также установить время, когда в последний раз было светло, на текущее время
lastLight = millis();
}
else if (abs(millis() - lastLight) > 3000)
{
// Включаем светодиоды, если темно более 3 секунд (то есть 3000 миллисекунд)
digitalWrite(k, HIGH);
digitalWrite(d, HIGH);
}
else
{
// Выключаем светодиоды
digitalWrite(k, LOW);
digitalWrite(d, LOW);
}
}
По поводу «if (lastLight < millis() - 3000)
»: здесь у вас есть ошибка с пролонгацией миллисекунд. Его можно каким-то образом смягчить с помощью if (millis() - lastLight > 3000)
, но он все равно потерпит неудачу, если он останется темным дольше, чем период ролловера. Добавление lastLight = millis() - 9000
в if или какую-либо переменную состояния может это исправить., @Edgar Bonet
Хороший вопрос, я обновил ответ, чтобы он соответствовал этому. Однако использование if (millis() - lastLight > 3000)
этого не изменит. Вы можете обойти эту проблему, используя абсолютное значение разницы (таким образом светодиоды остаются темными, даже если происходит переключение). Я не понимаю вашего предложения на тот случай, если темнота остается дольше 49,5 дней., @LukasFun
abs()
не поможет, но вы должны сделать lastLight
unsigned long
. См. [Переполнение millis()... это плохо?](https://www.gammon.com.au/millis) и [Как я могу справиться с переполнением millis()?](https://arduino.stackexchange .com/q/12587). Если темнота остается дольше 49,7 дней, millis()
будет очень близка к lastLight
, и этот код выключит светодиоды. Этого не произойдет, если вы неоднократно меняете lastLight
, чтобы оставаться на несколько секунд позади millis()
., @Edgar Bonet
- Кнопка переключения переключает между операторами обращения с разблокированием кнопки
- Как запустить 4 светодиода последовательно на основе кнопочного входа?
- Как установить таймеры, используя миллисекунды на 3 датчиках PIR?
- Схемы мигания светодиодов с несколькими светодиодами с помощью millis() без использования Delay()
- Игнорирование первого высокого выходного сигнала датчика
- Считайть конкретный диапазон выходных данных как 1 единичный выходной сигнал
- Фоторезисторы не пропускают входной сигнал на светодиоды
- Проблема Fader OOP
Вы сказали фоторезисторы и мигающие огни?? Имейте в виду, что фоторезисторы имеют нечетную валентную зону. В частности, фоторезисторы будут проводить ток при включении света и будут продолжать проводить ток после того, как свет погаснет, возможно, на секунду или более. Поэтому, если ваши огни мигают достаточно быстро, вы никогда не обнаружите, что огни гаснут с помощью фоторезисторов., @st2000
Блинки идут с интервалом в 1 секунду, я уже проверял, все работает, я просто застрял с этим таймингом., @Ieva Kriščiūnaitė
Какой тип света вы мигаете, чтобы активировать фоторезисторы?, @VE7JRO