Отправить последние 10 минутные данные по Bluetooth

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

Сначала я подумал, что если я сделаю массив из 20 ведер и помещу его в цикл, а затем отправлю функцию цикла на Android, это будет правильно. Но он просто отправляет мне данные о продолжении. Мне нужны только последние 10-минутные данные программы.

float sensorvalue[20];

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

    for (int i = 0; i < 20; i++) {
        pinMode(sensorvalue, OUTPUT);
    }
}

void loop()
{
    sendvalues();
    char c;

    if(Serial.available()) {
        c=Serial.read();
        if (c=='t')
            sendvalues();
    }
}

void sendvalues()
{
    for (int i=0 ; i<20 ; i++) {

        Serial.println(sensorvalue);
        sensorvalue   = analogRead(A0);
        delay(30000); //каждые 30 секунд считываются данные

        if (i>=20) {
            i=0; //сброс в начало массива, чтобы вы не пытались сохранять показания за пределами массива
        }
    }
    Serial.println("***********************************");
}

, 👍1

Обсуждение

он считывается каждые 30 секунд. я хочу отправить последние 10-минутные данные, но я не уверен, что это правильный путь..., @201

вы действительно должны отформатировать свой код ... она практически нечитабельна, @jsotola

Если вы хотите получить/отправить последние 10 минут данных, сначала вы(ваш код) должны знать, как долго будет проходить передача, а затем вы можете использовать функцию millis () или чип RTS, чтобы точно определить, когда вы хотите отправить данные. в основном таймер обратного отсчета начинается, например, с 20 минут, а когда он достигнет 10 минут, начинает отправлять данные., @ElectronSurf

Большое вам спасибо. Идея обратного отсчета звучит прекрасно, но у меня есть одна проблема. Я должен получать последние 10-минутные данные всякий раз, когда отправляю, например, "m" с моего последовательного порта., @201

ну, тогда начинайте считать всякий раз, когда вы посылаете букву "м"., @ElectronSurf

Мне не нужны живые данные, и в этом вся проблема. Мне нужны данные, которые были измерены за 10 минут до отправки команды. это либо сбивает с толку, либо я не на правильном пути..., @201


2 ответа


0

Ваш код не имеет большого смысла в том виде, в каком он написан.

Вам необходимо:

Собирайте новое значение каждые 30 секунд и сохраняйте его в массив значений, увеличивая переменную "индекс текущего значения" с каждым считыванием.

Вы хотите инициировать отправку буфера, заполненного данными, когда массив заполнен, или с помощью команды с удаленного телефона? Если вы хотите запустить отправку с телефона, что бы вы сделали, если бы не было полного буфера данных? Что бы вы сделали, если буфер заполнится, а с телефона не будет отправлена команда?

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

Если вы хотите запустить отправку с телефона, вам придется обрабатывать крайние случаи, такие как переполнение буфера или попытка отправки до того, как у вас будет полный буфер данных. Я бы предложил создать массив больше, чем вам нужно (скажем, 100 значений), сделать его кольцевым буфером (погуглите его) и непрерывно сохранять новые значения до тех пор, пока кольцевой буфер не заполнится. Если скетч получает команду "отправить", он может проверить, есть ли у него по крайней мере 20 значений в буфере, и отправить их/удалить их из буфера, если это так, или отправить обратно сообщение "недостаточно собранных данных", если нет.

,

большое вам спасибо :), @201


1

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

Вы это читали? Хорошо! Теперь ваш случай несколько особенный, поскольку вам не нужно постоянно отслеживать как указатель чтения, так и указатель записи : вам нужен только указатель записи, так как чтение происходит в одном большом пакете.

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

Есть один особый случай, о котором нужно позаботиться. Что делать, если программа получит команду для сброса данных, пока в ней хранится менее 20 показаний? Вы можете решить, что это ошибка пользователя, и программа может выдавать мусор. Однако я предлагаю, чтобы программа могла обнаружить эту ситуацию, а затем отправлять только действительные данные. Для этого ему необходимо сохранить логическую переменную, чтобы запомнить, был ли буфер заполнен или нет.

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

const uint32_t READING_PERIOD = 30000;  // one reading every 30 s
const int MAX_READINGS = 20;           // 20 readings = 10 min

int readings[MAX_READINGS];  // ring buffer
uint8_t reding_index = 0;    // next available slot
bool readings_full = false;  // did we fill the ring buffer?

static void register_reading(int value) {
    readings[reding_index] = value;
    if (++reding_index >= MAX_READINGS) {
        readings_full = true;
        reding_index = 0;
    }
}

static void dump_readings() {
    // If the buffer is full, then the next avaiable slot is the oldest
    // reading in the buffer.
    if (readings_full) {
        for (int i = reding_index; i < MAX_READINGS; i++)
            Serial.println(readings[i]);
    }
    for (int i = 0; i < reding_index; i++)
        Serial.println(readings[i]);
}

Теперь основная программа довольно проста. Вы засекаете данные, полученные с помощью техники, показанной в руководстве "Мигание без задержки". Вы не хотите использовать функцию delay (), потому что, когда программа задерживается, она не может отвечать на ваши команды. Остается последний вопрос: когда он сбрасывает данные, должен ли он забыть об этом? Другими словами, если вы дважды попросите его сбросить данные с интервалом менее 10 минут, должен ли он предоставить повторные данные во второй раз или должен предоставить только свежие данные? В приведенном ниже коде я предполагаю более поздний вариант и, таким образом, сбрасываю буфер, но в конце концов это ваш выбор:

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

void loop() {
    // Периодически проводите чтение.
    static uint32_t last_reading_time;
    if (millis() - last_reading_time >= READING_PERIOD) {
        last_reading_time += READING_PERIOD;
        register_reading(analogRead(A0));
    }

    // Сбросьте данные по команде.
    if (Serial.read() == 't') {
        dump_readings();
        reding_index = 0;       // reset the buffer
        readings_full = false;  // ditto
    }
}
,

большое вам спасибо!!!! Я застрял в этом коде навсегда... Я думаю, что это было слишком тяжело для новичка..лол, @201

Можете ли вы отредактировать свой вопрос, чтобы лучше объяснить, что вы хотите сделать?, @Duncan C