Есть две термопары , на них есть “шум”, соответственно необходимо усреднение. Для понимания данных во времени хочу усреднять не по количеству измерений, а за период, допустим за секунду. Вот мой вариант
void readPin_AveragePerPeriod(uint16_t period){ //среднее за период в мсек
static uint32_t timer, count; //таймер для подсчета прошла ли секунда и счетчик для подсчета количества измерений
static float avg_sum, avg; //накопительная сумма измерений и средняя
if (millis()-timer>=period){ //если прошла секунда с прошлого вывода данных
timer = millis(); //обнуляем таймер
avg = avg_sum/count; //среднее значение
Serial.println(avg);
avg_sum = 0; //обнуляем
count = 0;
}
else{ //если секунда не прошла, только обновляем переменные
count++;
avg_sum += analogRead(ValueOUT)*voltageIN/1024;
}
}
Пока брал показания с одного датчика все понятно, сейчас стал вопрос второго и не могу понять как корректно делать дальше. Проще всего сделать func1 и func2 полностью идентичные, учитывая что переменные объявлены внутри ничего и менять не нужно, но хотелось бы разобраться есть ли “правильный” способ(мне лично хотелось бы короткого и удобно читаемого варианта), к тому же есть в планах добавить еще несколько измерений. Получается что при вызове функции она считает 3 переменные и один раз в секунду выдает 4-ую. Пока склоняюсь к тому, чтобы объявить на каждый пин массив и обновлять там данные, т.е. при каждом вызове функции брать их, обрабатывать и обновлять их в массиве, а по истечении секунды выдавать среднюю. правильно ли так делать с точки зрения “основ”?
Сейчас вот попробовал так сделать и первая сложность в том, что timer разный и данные выводятся не синхронно, что не удобно для их сопоставления.
S23 а это полезная фича! я сам ее подрезал когда какой то курс проходил, и в датчиках температуры видел ее, а так же датчиках веса, не уверен что через функцию, но полезная!
не подходит, так как там порядка 6тыс измерений в секунду, можно конечно было бы уменьшить, но мне пока не ясно и вникать не охота в дельту показаний, наводки, ошибки, еще что, а так средняя по такому количеству показаний думаю нивелирует все. К тому же течение во времени не ясно, а так сохранил для всех измерений одну переменную со временем и все
мне “дешевле” хранить кумулятивную сумму и количество замеров, всего две переменные, раз в секунду считать среднюю и обнулять их
чуток ошибся, это я в начале смотрел, было 6, вывел сейчас в печать count(количество замеров) 3600. Это вроде нормально или нет? она в каждом loop же вызывается. мне пока незачем ее ограничивать
вот этот вариант, только не промышленный а бытовой котел. не пойми как работает, мозги ему лечили уже два раза и не ясно что там сделали, но что то сделали, потому как работает он не по мануалу. есть ремонтный мануал в котором описаны алгоритмы проверок при работе, но вот в ручную снять все эти показания а потом еще и пересчитать в градусы и прочее не реально. задача: снять необходимые показания для выявления какие внутренние тесты на исправность он не проходит(перечень тесов в мануале) и работает в аварийном режиме на “минималках“. т.е. есть грубые ошибки о которых он сигнализирует на панели и уходит в ошибку, а есть те что вроде и не поломка, но и на рабочий режим он не выходит.
dmitriy_8 а можно еще вопрос ?)) а зачем вы так много измеряете ?
а что будет если код большой будет скорость измерения сразу просядет ?
это все 1 вопрос!)))
Если напряжение с датчика пропорционально температуре, то нужно суммировать 64 (влезет в uint16_t) значений АЦП (для AVR), а затем переводить в температуру.
не пойму вопрос, loop запускается сама по мере выполнения прошлого цикла, вот она и измерят “сколько успевает”, самоцели нет в таком большом количестве, но и необходимости ограничивать не нахожу, по мере накопления кода будет замедляться, ну и путь. может я не понял вопрос?
// Структура для хранения состояния канала измерения
struct SensorChannel {
uint8_t pin; // пин, к которому подключен датчик
uint32_t count; // счетчик измерений за период
float sum; // сумма значений за период
float lastAverage; // последнее вычисленное среднее
// Конструктор для удобной инициализации
SensorChannel(uint8_t p) : pin(p), count(0), sum(0.0), lastAverage(0.0) {}
};
// Создаем массив датчиков
SensorChannel sensors[] = {
SensorChannel(34), // первый датчик на пине 34
SensorChannel(35) // второй датчик на пине 35
};
const int numSensors = sizeof(sensors) / sizeof(sensors[0]);
uint32_t lastPrintTime = 0; // единый таймер для всех
void setup() {
Serial.begin(115200);
}
void loop() {
// Читаем ВСЕ датчики при каждом проходе loop
for (int i = 0; i < numSensors; i++) {
float voltage = analogRead(sensors[i].pin) * voltageIN / 1024.0;
sensors[i].sum += voltage;
sensors[i].count++;
}
// Проверяем, не пора ли вывести результаты (раз в период)
if (millis() - lastPrintTime >= 1000) { // период 1000 мс
lastPrintTime = millis();
// Выводим данные всех датчиков синхронно
Serial.print("Время: "); Serial.print(millis());
for (int i = 0; i < numSensors; i++) {
if (sensors[i].count > 0) {
sensors[i].lastAverage = sensors[i].sum / sensors[i].count;
Serial.print(" | Д");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(sensors[i].lastAverage, 3);
// Сбрасываем счетчики
sensors[i].sum = 0;
sensors[i].count = 0;
}
}
Serial.println();
}
}
а еще вы тут о каких то 3600 измерениях говорите… в общем вот от ии, может пригодится
если Вы про float, то я пока перевожу в вольты: 1) могу вольтметром перепроверить правильность показаний, 2) пока не готов переводить в градусы, не всю цепь нарисовал, надо разобрать какой ток изначально в цепи и сколько сопротивления на плате, без этого не могу знать точное сопротивление на термопаре, это дело времени, но сейча не готов
В качестве эксперимента. Создай массив 3600. Заполни его данными с датчика. Посчитай среднее по 8 - 16-32-64 … 2048 точек и посмотри как меняется результат. Может оказаться что усреднение по 32 точкам достаточно и дальнейшее увеличение точек в усреднении бесполезный перевод ресурсов и времени.