Возникли проблемы с массивом

У меня возникла проблема, в которой я не могу разобраться. Я пытаюсь сохранить в массиве данные датчиков за несколько минут (считываемые каждые 5 секунд), чтобы через одну минуту у меня было 12 значений.

Я хочу сохранить в массиве 12 значений, поэтому мне нужно продолжать перемещать все значения в нем на один индекс вниз за каждое новое значение, достигающее индекса [0], чтобы гарантировать, что время жизни каждого чтения в массиве составляет 60 секунд. Вот мой код:

void add_readings_to_averages() {
  // На этом этапе я перемещаю значения вниз по массиву, чтобы освободить место в начале.
  for (int a = 11; a >= 0; a--) {
    Serial.print("The value at temperature_c_minute_avg[");
    Serial.print(a);
    Serial.print("] is ");
    Serial.print(temperature_c_minute_avg[a]);
    Serial.println();
    if (a == 11) {
      Serial.println("At 12 so need to overwrite this value");
    }

    if (a <= 10) {
      Serial.print("a is ");
      Serial.println(a);
      temperature_c_minute_avg[a] = temperature_c_minute_avg[a + 1];  // Это перемещает каждую запись на один индекс вниз в массиве, создавая пустое пространство в индексе [0]
    }

    if (a == 0) {
      temperature_c_minute_avg[a] = temperature_c;
    }
  }

Во время инициализации я загрузил в свой массив фиктивные данные, чтобы видеть, что происходит. Первый запуск отображается так, как и следовало ожидать.

The value at temperature_c_minute_avg[11] is 120.00
At 12 so need to overwrite this value
The value at temperature_c_minute_avg[10] is 110.00
a is 10
The value at temperature_c_minute_avg[9] is 100.00
a is 9
The value at temperature_c_minute_avg[8] is 90.00
a is 8
The value at temperature_c_minute_avg[7] is 80.00
a is 7
The value at temperature_c_minute_avg[6] is 70.00
a is 6
The value at temperature_c_minute_avg[5] is 60.00
a is 5
The value at temperature_c_minute_avg[4] is 50.00
a is 4
The value at temperature_c_minute_avg[3] is 40.00
a is 3
The value at temperature_c_minute_avg[2] is 30.00
a is 2
The value at temperature_c_minute_avg[1] is 20.00
a is 1
The value at temperature_c_minute_avg[0] is 10.00
a is 0
2018/11/2 11:4:39  -  Running for a total of 0 hours 0 minutes and 7         seconds

Но во второй раз при выполнении loop() мой массив уничтожается.

The value at temperature_c_minute_avg[11] is 120.00
At 12 so need to overwrite this value
The value at temperature_c_minute_avg[10] is 120.00
a is 10
The value at temperature_c_minute_avg[9] is 120.00
a is 9
The value at temperature_c_minute_avg[8] is 120.00
a is 8
The value at temperature_c_minute_avg[7] is 120.00
a is 7
The value at temperature_c_minute_avg[6] is 120.00
a is 6
The value at temperature_c_minute_avg[5] is 120.00
a is 5
The value at temperature_c_minute_avg[4] is 120.00
a is 4
The value at temperature_c_minute_avg[3] is 120.00
a is 3
The value at temperature_c_minute_avg[2] is 120.00
a is 2
The value at temperature_c_minute_avg[1] is 120.00
a is 1
The value at temperature_c_minute_avg[0] is 0.00
a is 0
2018/11/2 11:4:44  -  Running for a total of 0 hours 0 minutes and 12     seconds

Весь массив был перезаписан последним значением, а новое значение не было добавлено. Сам массив настроен как глобальная переменная. Инициализация вверху.

float temperature_c_minute_avg[12] = {10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,110.0,120.0};

Что мне здесь не хватает? Я смотрел на это некоторое время, но впервые пытаюсь использовать массив Arduino, поэтому могу полностью поверить, что проблема в PBKAC! :)

, 👍2

Обсуждение

Я голосую за то, чтобы оставить этот вопрос открытым. Согласно этой странице: https://arduino.stackexchange.com/help/on-topic, «По теме» включает «Конкретные вопросы о платах Arduino, коде…»., @VE7JRO


3 ответа


0

В блоке if (a <= 10) вы находитесь внутри цикла for, который уменьшается и заменяет каждое значение значением внутри index+1. Это означает, что, спускаясь по индексам, вы несете с собой 11-е значение индекса. Вот как это происходит без переменных (позвольте мне сократить имя переменной до t):

t[10] = t[11];
t[9] = t[10];
t[8] = t[9];

И так далее. Все, что было в a[11], перетаскивается через каждую из переменных нижних индексов.

Я настоятельно рекомендую пойти наоборот: либо с вашим циклом, либо с тем, каким образом вы передаете данные. Например (продолжая имя массива t):

for (int i = 11; i >=0; i--) {
    if (i > 0)
        t[i] = t[i-1]; // сдвигаем данные с индекса 10->11, 9->10 и т.д.
}
t[0] = arbitrary_data; // заполняем новое «пустое» пространство

Или, если вы все еще хотите поместить новые данные в индекс 11:

for (int i = 0; i <= 11; i++) {
    if (i < 11)
        t[i] = t[i+1]; // сдвигаем данные с индекса 1->0, 2->1 и т.д.
}
t[i] = arbitrary_data; // заполняем новое «пустое» пространство

Это мое решение для вашего текущего метода управления данными. В другом ответе предлагался кольцевой буфер, в котором вы просто отслеживаете, какие данные изменяются за раз, и это гораздо более эффективно.

,

2

Ваша проблема связана с программированием на языке C и не имеет никакого отношения конкретно к Arduino. Вам следует изучить, как реализовать циклический буфер. Вы не хотите перемещать значения внутри массива, а просто увеличиваете значения индекса массива. Сохраните два значения индекса: одно из текущей позиции индекса (место, где будет размещено следующее записанное значение), а другое из числа записанных значений. В конечном итоге количество записанных значений будет равно максимальному размеру массива, и будет увеличиваться только позиция индекса. Когда индекс массива превышает максимальный размер массива, он возвращается к 0.

,

Ребята, спасибо за помощь. Чтобы решить эту проблему, я пошел по пути кольцевого буфера., @Craig


0

Чтобы расширить ответ Джеффа Вахауса, быстрый поиск в Google выявляет несколько библиотек кольцевых буферов для Arduino. Я скачал первый в списке, github rlogiacco CircularBuffer, и сделал простой скетч, чтобы проверить некоторые его функции.

#include <CircularBuffer.h>

CircularBuffer<unsigned int, 12> buffer;

byte counter = 0;

void setup(){
  Serial.begin(9600);
}

void loop(){

  // Добавляем следующее чтение в «голову» буфера.
  buffer.unshift(counter);

  // Моделирование данных датчиков.
  counter += 10;
  if(counter > 254){counter = 1;}

  // Неразрушающее чтение. Дает вам последнее сохраненное показание.
  if(!buffer.isEmpty()){
    Serial.println(buffer.first());
  }

  delay(500);
}

Используя функцию unshift(), вы можете многократно добавлять данные в начало буфера, и он автоматически «забудет» последний элемент в буфере, как только он заполнится. Я использую функцию first(), чтобы увидеть, что находится в первой ячейке буфера (последнее чтение). Если вы хотите получить все сохраненные показания, вы можете использовать функцию shift() и перебирать элементы в буфере, пока он не станет пустым. В эту библиотеку включено множество функций для взаимодействия с буфером, например, isEmpty(), isFull(), size() , available(), capacity(), clear().

ИЗМЕНИТЬ

Вы также можете использовать массив для хранения показаний. Взгляните на результат этого скетча.

byte arrayIndex = 0;
const byte arraySize = 12;
float temperature_c_minute_avg[arraySize] = {0.0};

// Имитация данных датчика.
float counter = 10.0;

void setup(){
  Serial.begin(9600);
}

void loop(){

  // Добавляем чтение в массив.
  temperature_c_minute_avg[arrayIndex] = counter;

  // Тестовый вывод: распечатываем содержимое массива.
  Serial.print("Array index = ");
  Serial.println(arrayIndex);
  for(byte i = 0; i < arraySize; i++){
    Serial.print("temperature_c_minute_avg[");
    Serial.print(i);
    Serial.print("] = ");
    Serial.println(temperature_c_minute_avg[i]);
  }
  Serial.println();

  // Обновляем индекс массива.
  arrayIndex++;
  if(arrayIndex > (arraySize - 1)){arrayIndex = 0;}

  // Имитация данных датчика.
  counter += 10.0;
  if(counter > 2400.0){counter = 0.0;}
  delay(1000);

}

Сразу после добавления показания в массив оно становится «последним показанием». Его индекс будет temperature_c_mine_avg[arrayIndex], пока вы не обновите индекс массива в конце loop(). Чтобы получить все показания из массива, вы можете использовать цикл for, который выполняется 12 раз, как указано в переменной arraySize, и начинается с arrayIndex. Вы можете уменьшить arrayIndex в цикле for. Имейте в виду, что вы не можете использовать отрицательные числа для доступа к индексу массива, поэтому вам придется сбросить индекс в цикле for до arraySize - 1, прежде чем он станет отрицательным.

,