Получить подсчет производства за текущую минуту
Я пытаюсь сделать производственный счетчик для машины. Я хочу отобразить производственный отсчет последней минуты для каждой секунды. Таким образом, дисплей должен обновляться каждую секунду и отображать реальное значение последних 60 секунд. У меня есть система для обнаружения вывода продукта в реальном времени и передачи его на Arduino с помощью цифрового входного штифта.
Я написал ниже коды и для этого. то, что я сделал, - это подсчитал выход и получил выход в секунду. Затем сохраните его в массиве в виде разделенного значения для каждой секунды. Каждую секунду массив обновлялся и добавлял новое значение для текущей секунды. Наконец, добавьте все значение счета за последние 60 секунд и выведите его как производительность текущей минуты.
Мой вопрос заключается в том, есть ли какой-нибудь простой и эффективный способ сделать это без использования нескольких переменных ?
#define countSensor 8 //вход счетного датчика
uint8_t records[60];
uint8_t countSensorState = 0;
uint8_t totalCount = 0;
uint8_t countOfLastSec = 0;
uint8_t lastCount = 0;
uint8_t lastMinCount;
uint32_t preMills = 0;
void setup() {
Serial.begin(9600);
//init sensor input pin
pinMode(countSensor, INPUT_PULLUP); //изменение в зависимости от типа датчика
//очистить случайное значение ячеек памяти
for (int i = 0; i < 60; i++) {
records[i] = 0;
}
}
void loop() {
//get count at falling edge
if (digitalRead(countSensor)^ countSensorState) {
if (!digitalRead(countSensor)) {
totalCount++;
}
countSensorState = digitalRead(countSensor);
}
//получить отсчет последней секунды
if (millis() - preMills > 1000) {
preMills = millis();
countOfLastSec = totalCount - lastCount;
lastCount = totalCount;
//запись последних 60-х отсчетов
//--сдвиг назад на секунду в массиве
for (int i = 0; i < 59; i++) {
records[i] = records[i + 1];
}
//--запись текущей секунды в массиве по 59-му индексу
records[59] = countOfLastSec;
//get last 60s count
for (int i = 0; i < 60; i++) {
lastMinCount += records[i];
}
Serial.println(lastMinCount);
}
}
@user_fs10, 👍1
Обсуждение1 ответ
Лучший ответ:
Как я уже сказал в комментарии, если вам действительно нужно вычислить эту скользящую сумму, вам абсолютно необходимо сохранить в памяти последние 60 секундных отсчетов. Тем не менее, есть несколько небольших проблем с этим кодом, для которых у меня есть несколько предложений:
Нет никакого смысла хранить
totalCount
. Вы не используете его по-настоящему, и он в конце концов переполнится.Вам не нужно явно инициализировать все глобалы до нуля, как это неявно делает среда выполнения: это требование языка.
Вы вызываете
digitalRead(countSensor)
три раза подряд. Логика подсчета ребер работает до тех пор, пока три вызова дают один и тот же результат, но это не гарантировано. Безопаснее считывать контакт только один раз за итерацию цикла.Точно так же два вызова
millis()
могут дать разные результаты, и это сделает ваши тайминги немного выключенными.Условие
millis() - preMills > 1000>
будет срабатывать только тогда, когда Прошло 1001 миллисекунда. Из-за того, какработает millis ()
, иногда вы пропустите 1001-ю миллисекунду и обработаете 1002-ю миллисекунду. Чтобы избежать накопления этих небольших временных ошибок, лучше всего обновлятьпремиллы
, всегда добавляя ровно 1000.Как указывает jsotola, вам не нужно сдвигать массив: вместо этого вы можете повторно использовать ячейку массива, которая содержит данные, которые вам больше не нужны .
Вам не нужно каждый раз выполнять всю сумму. Вместо этого можно обновить ранее вычисленную сумму, удалив количество секунд , выпадающих из текущего одноминутного окна, и добавив количество текущей секунды.
Вот моя попытка применить все вышеперечисленные предложения. Предупреждение: он не был протестирован.
const uint8_t countSensor = 8;
uint8_t record[60]; // последние 60 секунд отсчетов
uint8_t currentIndex; // текущий индекс в записи[]
uint8_t oldSensorState; // предыдущее состояние countSensor input
uint32_t previousSecond; // последний раз мы печатали minuteCount
uint8_t thisSecondCount; // количество элементов в текущем втором
uint16_t minuteCount; // количество элементов в последнюю минуту
void setup() {
Serial.begin(9600);
pinMode(countSensor, INPUT_PULLUP);
}
void loop() {
// Подсчет падающих краев.
uint8_t sensorState = digitalRead(countSensor);
if (oldSensorState == HIGH && sensorState == LOW) {
thisSecondCount++;
}
oldSensorState = sensorState;
// Обновляйте статистику каждую полную секунду.
if (millis() - previousSecond >= 1000) {
previousSecond += 1000;
// Обновите minuteCount, удалив секунду, которая падает с
// окна, и добавив ту, которая входит в окно.
minuteCount += thisSecondCount - record[currentIndex];
// Замените счетчик, который больше не нужен, на
// текущий.
record[currentIndex] = thisSecondCount;
// Начинайте отсчет новой секунды.
thisSecondCount = 0;
// Обновить текущий индекс, обернув его на 60.
if (++currentIndex >= 60) {
currentIndex = 0;
}
Serial.println(minuteCount);
}
}
- Что происходит при включении Arduino и сколько времени все это занимает?
- Пытаюсь поддерживать мой основной код в рабочем состоянии, если ввод не будет LOW в течение определенного промежутка времени
- Как использовать SPI на Arduino?
- Как справиться с rollover millis()?
- Как получить текущее время и дату в Arduino без внешнего источника?
- Как сбросить или отформатировать Arduino?
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как запустить цикл на определенное время?
Если вам действительно нужна общая сумма за последние 60 секунд, то да, вы должны сохранить этот массив. Если вы можете жить с чем-то вроде [экспоненциально взвешенной скользящей средней](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average), то необходимо сохранить только предыдущее значение среднего значения., @Edgar Bonet
вам не нужно сдвигать значения .... индексируйте массив по кругу, @jsotola
@jsotola, я не смог понять это правильно. Как я могу применить круговой массив к своему коду? Не могли бы вы дать мне измененный код..., @user_fs10
прямо сейчас вы используете цикл " для "для итерации массива с помощью указателя "i".... удалите инструкцию " для
... используйте
i++` каждую секунду вместо этого ... считайте 0 1 2.. 59 0 1 2 ...., @jsotola