Запуск нескольких функций с использованием millis

Я писал код для измерения прихода и исчезновения цифрового сигнала (ВКЛ и ВЫКЛ соответственно). Я выполнил часть расчета времени простоя одной системы (разница во времени между включением и выключением системы), но когда я не могу масштабироваться до нескольких систем, когда я пытаюсь скопировать тот же код, который работал выше. Поэтому было бы полезно, если бы кто-нибудь мог дать некоторое представление о том, как это можно сделать, плюс объяснение кода помогло бы.

Мой код:

unsigned long a=0, b=0, difference;  
void setup()   
{    
  Serial.begin(9600);  
  pinMode(2, INPUT);  
  Serial.print("start");  
  Serial.print(",");  
  Serial.print("stop");  
  Serial.print(",");  
  Serial.print("minutes");  
  Serial.print(",");  
  Serial.println("seconds");  
}

void loop()   
{  
 //задержка(1000);
 int A = digitalRead(2);  
 if(A == LOW)  
 {  
  b = millis();  
 }  
 if(A == HIGH)  
  {  
     a = millis();  
     display_output();  
   }  
 delay(3000);  
}  
void display_output()  
{  
 int minutes, seconds, sec;  
 difference = a - b;  
 seconds = int(difference/1000);  
 if(seconds >= 60)  
 {  
  //сек = секунды;
  seconds = seconds%60;  
  minutes = minutes+1;  
 }  
 //минуты = int(секунд/60);
 Serial.print((a/1000)+1);  
 Serial.print(",");  
 Serial.print((b/1000)+1);  
 Serial.print(",");  
// Serial.print(разница);
 //Serial.print(",");
 Serial.print(minutes);  
 Serial.print(",");  
 Serial.println(seconds);  
 //Serial.println(",");
}  

, 👍0

Обсуждение

Вопрос не очень ясен. Вы пытаетесь измерить время между двумя событиями во времени? Что вы подразумеваете под «масштабированием до нескольких систем»? Прерывания — это еще один способ измерения изменения логического состояния сигнала., @MichaelT

Да, я измеряю разницу во времени между моментом, когда на Ардуино приходит сигнал от моей машины, и моментом, когда сигнал прекращается. У меня есть несколько машин, работающих одновременно на разных этапах, и мне нужно сделать проект о том, как часто и как долго машины не работают. Я программировал для одной машины, и она работала нормально, но когда я пытаюсь запрограммировать для двух или более машин (обратите внимание, что две машины могут одновременно выйти из строя с некоторой ошибкой), я получаю случайное значение., @Rajesh Anand10


1 ответ


1

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

 int A = digitalRead(2);
 if(A == LOW)  
 {  
  b = millis();  
 }

Здесь вы проверяете состояние вывода. Если это LOW, вы берете рекорд того времени. Это не верно. То, что вы хотите записать, это время при котором входные данные падают, а не когда они LOW. Это называется обнаружением изменения состояния. Чтобы реализовать вам нужно сравнить состояние контакта, которое вы только что прочитали, с предыдущее состояние. Правильное условие: «если вывод был HIGH». в последний раз я читал это и теперь НИЗКИЙ”:

// Глобальная переменная:
int pin_state = HIGH;

// Внутри цикла():
int new_pin_state = digitalRead(2);
if (pin_state == HIGH && new_pin_state == LOW) {  // он только что упал
    time_of_fall = millis();
    pin_state = new_pin_state;
}

Обратите внимание: предполагается, что состояние по умолчанию — HIGH. Если штифт оказывается LOW при включении питания, тогда код будет считать это просто упал при запуске программы.

Далее вам необходимо удалить из вашего кода все вхождения delay(). Это только сделает ваше время неверным. На данный момент у вас есть неблокирующий код, который можно легко адаптировать для обработки множественного ввода каналы.

Затем вам необходимо определить переменные, специфичные для канала, и иметь версию каждой переменной для каждого канала (здесь могут быть полезны массивы). Тогда вашему коду нужно будет только перебирать массивы.

Вместо использования кратных массивов вы можете сделать код чище, группировка всех данных, относящихся к конкретному каналу, в единую структуру данных:

struct Channel {
    byte pin;
    byte state;
    unsigned long fell, rose;  // времена падения и подъема
};

Таким образом, вы можете создать единый массив, содержащий все данные для всех каналы:

const int CHANNEL_COUNT = 5;

Channel channels[CHANNEL_COUNT] = {
    { 2, HIGH, 0, 0 },
    { 3, HIGH, 0, 0 },
    { 4, HIGH, 0, 0 },
    { 5, HIGH, 0, 0 },
    { 6, HIGH, 0, 0 }
};

Теперь код становится довольно простым: вы просто проходите по массиву и обрабатывать один канал за раз:

void setup()
{
    for (int i = 0; i < CHANNEL_COUNT; ++i) {
        pinMode(channels[i].pin, INPUT);
    }
    Serial.begin(9600);
    Serial.println("pin,fell,rose,low time");
}

void loop()
{
    for (int i = 0; i < CHANNEL_COUNT; ++i) {
        Channel &c = channels[i];
        byte new_state = digitalRead(c.pin);
        if (c.state == HIGH && new_state == LOW) {  // ввод упал
            c.fell = millis();
        }
        else if (c.state == LOW && new_state == HIGH) {  // входной сигнал вырос
            c.rose = millis();
            display_channel(c);
        }
        c.state = new_state;
    }
}

Функция display_channel() оставлена читателю в качестве упражнения. ;-) (подсказка: прототип должен быть void display_channel(const Channel &c);, чтобы избежать излишнее копирование структуры данных.

Следующим шагом в модульности кода будет изменение структуры Channel. в класс с подходящим конструктором и создайте display_channel() метод этого класса.

,

А как насчет ссылки на пример обнаружения изменения состояния? https://www.arduino.cc/en/Tutorial/StateChangeDetection, @Jot

Этот код выглядит аккуратно, и я обязательно попробую его использовать. Я мало что знаю о конструкторах и структурных вещах. Узнаю об этом. Я использовал задержку в своей программе, чтобы не иметь слишком много точек данных, и вместо этого будет достаточно данных раз в две или три секунды, плюс это не критичное по времени приложение, поэтому я не знаю, является ли использование функции миллис излишним для мое заявление. Однако, спасибо :), @Rajesh Anand10

@Jot: Хорошая идея. Я добавил ссылку., @Edgar Bonet

@RajeshAnand10: 1. Изучение объектно-ориентированного программирования (классы с конструкторами и методами) полезно, но вы можете жить без него для таких простых проектов, как этот. 2. delay() был полезен в вашей предыдущей версии _только_ потому, что вы неправильно поняли логику. Если вы правильно обнаружите изменения состояния, это не принесет никакой пользы. 3. Что вы подразумеваете под «излишним убийством»? Считаете ли вы, что Millis() более тяжелый метод, чем Delay()? Это не. Для вашей конкретной проблемы это подходящий инструмент для работы., @Edgar Bonet