Запись потока данных в массив
- Войдите на сайт для отправки комментариев
Чт, 27/06/2013 - 19:10
Здравствуйте ! Подскажите пожалуйста как организовать запись потока данных от датчика расстояния в массив? ДАнные от датчика растояния сыпятся по 10 значений в секундцу, вот мне надо чтобы в массив записывались все показания датчика за каждую секунду. Дело в том, что на датчике иногда проскакивают неадекватные значения, чтобы их фильтровать я хочу писать каждую секунду данные в массив, и каждую же секунду высчитывать среднее значение из всех записанных значений с массиве. По моим предположениям неадекватные значения в таком случае сильного возмущения не принесут.
Всем спасибо !
хммм... ну если предположим что есть 9 значений в районе 10 и одно НЕАДЕКВАТНОЕ в районе 1000... то среднее у вас получится 109... будет похоже на среднюю зарплату в России.. президент ей доволен, а большинство народу таких денег никогда не видело... Вы не родственики с президентом случайно? а то образ мышления у вас похож :)
Да, я троюродный отец матери сына бабушки мамы сестры путина, все верно друг мой!
Как бы то ни было, вы можете подсказать как записывать данные каждую 1/10 секунды в массив ?
и где тут поиск ? я первый раз на этом форуме.
опрашивайте датчик каждуй 0.1с, проверяйте на адекватность полученные данные и пишите в массив.... ваш кэп :)
нужно подругому искать ошибочные значения. если только одно ошибочное то можно смотреть по 3 значения и если ошибка - делить разницу между крайними на 2. Ошибку искать как - разница между 1 и 2 больше разницы между крайними(1 и 3) в 3 раза.
Вобщем надо пример показаний с ошибками, чтобы придумать фильтр для них.
вот пример :
датчик показывает расстояние до кресла :
50
51
50
50
52
51
97
49
51
50
Видим цифру 97 - результат того что кресло чуть повернули и сигнал исказился там отразился от плутона туда сюда, пришло большое значение.
дело в том что кресло может быть на расстоянии и 1 метр и 3 метра тоесть задавать какие то условия не получится, ибо в разное время кресло может быть в разном удалении.
Если бы была возможность каждое значение записывать в переменную, то переменные бы можно было сравнивать, и скажем если одна отличается от предыдущей на допустим более чем 30% то приравнивать её к предыдущей. Но и здесь, подскажите, как записывать данные из потока в переменные ?
flaot buf[100]; int pos = 0; void loop() { buf[pos++] = analogRead(1); delay(100); if(pos == 99) pos = 0; }буду пробовать, спасибо :) здесь я насколько понимаю данные пишутся каждую милисикунду с аналогово ввхода ?
давайте тогда двинемся в глубь идеи... я вижу как бы несколько вопросов..
1.зачем мы опрашиваем датчик 10 раз в секунду? мы что мчимся со страшной скоростью и нам грозит опасность столкновения и десятая доля секунды играет роль?
2. а будем ли мы успевать опрашивать датчик 10 раз в секунду, когда код разрастется в процесе обработки?
3. NeiroN вам уже описал алгоритм вычисления неправильных данных
1. предполагается использовать датчик в полете, поэтому условно да, нужна реакция.
2. Честно скажу - не знаю пока еще.
3.Да, я ему написал что с записью значений из потока в переменные у меня тоже нелады.
Можно упростить, допустим 5 значений в секунду, как записывать значения в пять переменных, при чем так, чтобы они сменялись поочередно ?
float buf[3]; void loop() { if(i == 3) { i=0; float d1; float d2; d1 = buf[2]-buf[0]; d2 = abs(buf[0]-buf[1]); if(d2 > abs(d1)*3){ buf[1] = buf[0]+d1/2; } Serial.println(buf[0]); Serial.println(buf[1]); Serial.println(buf[2]); } buf[i] = analogRead(); i++; }Сбасибо, буду пробовать!
в первом приблежинии вот что получается. почему то в массив не попадают переменные.
http://vk.com/doc433721_198466807?hash=32f37a24ba43a3af14&dl=0797049695558e4998
distance_sm это переменная, которая и есть поток. значения в окошке 3 - это три сантиметра. нули это данные из массива
обявление и установку переменной надо вынести за цикл, чтобы оно не сбрасывало значения. проверяйте код пошагово - с пониманием для чего нужна каждая строка.
Все сводится к фильтру калмана.
Товарищи, кто-нибудь занимался фильтрованием сигналов ? Я из любопытства спрашиваю, ничего объяснять мне не надо :)
Я в подобной ситуации (датчик расстояния) воспользовался функцией отсюда : http://playground.arduino.cc/Main/DigitalSmooth
"A digital smoothing filter for smoothing sensor jitter
This filter accepts one new piece of data each time through a loop, which the
filter inputs into a rolling array, replacing the oldest data with the latest reading.
The array is then transferred to another array, and that array is sorted from low to high.
Then the highest and lowest %15 of samples are thrown out. The remaining data is averaged
and the result is returned."
Добрый день. Извиняюсь за может не столь интересный вопрос, но столкнулся с проблемой можно сказать на прямом месте.
Создаю CW ключ морзе с памятью. Есть массив в который записывается нажатия 1й или 2й кнопки (1 или 2), и по задумке после 10ти нажатий эта последовательность символов улетает в EEPROM в определённую ячейку.
Вопросик:
Массив работает, но при каждой интерации цикла for записывается новая цифра, а надо чтоб сразу 10ть символов улетела в память.
(примерто такого вида нужно EEPROM.writeLong(addrEeprom, 1212121211;) а к сожелению записывается последняя цифра массива "1")
Как правильно организовать запись массива в память?
Заранее благодарю!
#include <EEPROMex.h> #include "Arduino.h" word addrEeprom = 6; unsigned long buf[10]; #define KLUCH_TOCHKA A3 //PB4 точка #define KLUCH_TERE A4 //PB5 тере void setup() { unsigned long output = EEPROM.readLong(addrEeprom); //смотрим что записали Serial.print(output); Serial.println(); } void loop() { //определяем что нажали if((analogRead(KLUCH_TOCHKA)/4 > 250) && (analogRead(KLUCH_TERE)/4 <= 0)){ //нажали на точку delay(100); tmp_Tochka_Tere_int = 1; // в переменную указываем что нажали на точку } if((analogRead(KLUCH_TERE) > 250) && (analogRead(KLUCH_TOCHKA) <= 0)){ //нажали на тере delay(100); tmp_Tochka_Tere_int = 2; // в переменную указываем что нажали на тере } if(tmp_Tochka_Tere_int != 0){ //если что-то нажали точку или тере то в массиве записываем это buf[schetchik++] = tmp_Tochka_Tere_int; //прибавляем счётчик при каждом нажатии точки или тере if(schetchik == maxSimvol){ //считаем, когда максимум то записываем набранное for(int b=0; b < 10; b++){ EEPROM.writeLong(addrEeprom, buf[b]); //пишем код tone(BEEP_Pin, BEEP_Tone, 100); //пикаем после записи //Serial.println(int(buf[b])); } schetchik = 0; } } tmp_Tochka_Tere_int = 0; //обнуляем переменную }https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B4%D0%B8%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%84%D0%B8%D0%BB%D1%8C%D1%82%D1%80
Вот здесь алгоритм обработки именно для таких случаев.
А здесь даже реализация на Си есть http://chipenable.ru/index.php/embedded-programming/item/203-mediannyy-filtr.html
Хм... Изучив код примера.... Немного не понял... А причём тут МЕДИАННЫЙ ФИЛЬТР? Если вопрос идет о том как записать массив не с помощью последовательных интераций (может и так), а как-то иначе, чтоб EEPROM записал сразу 10 цифр а не перебирал, выбрав только одну....?
Дело в том, что на датчике иногда проскакивают неадекватные значения, чтобы их фильтровать я хочу писать каждую секунду данные в массив, и каждую же секунду высчитывать среднее значение из всех записанных значений с массиве. По моим предположениям неадекватные значения в таком случае сильного возмущения не принесут.
Медианный фильтр убирает неадекватные значения. Это его предназначение. После него простого бегушего среднего будет достаточно для адекватного значения.
А как же быть с моим вопросом, неужели никто не подскажет..?
Все! Разобрался сам, просёрфив не одну тонну интернета.
Вот может кому и пригодится, к примеру таким искателям как я. Использовал стандартную библиотеку :#include <EEPROMex.h>
Приведён пример на все случаи жизни:
/* * EEPROMEx * * Demonstrates reading, writing and updating data in the EEPROM * to the computer. * This example code is in the public domain. */ #include <EEPROMex.h> #include "Arduino.h" void issuedAdresses(); void readAndWriteByte(); void readAndWriteInt(); void readAndWriteLong(); void readAndWriteFloat(); void updateAndReadDouble(); void writeAndReadCharArray(); void writeAndReadByteArray(); void waitUntilReady(); void errorChecking(int adress); void setup(); void loop(); const int maxAllowedWrites = 80; const int memBase = 350; int addressByte; int addressInt; int addressLong; int addressFloat; int addressDouble; int addressByteArray; int addressCharArray; void issuedAdresses() { Serial.println("-----------------------------------"); Serial.println("Following adresses have been issued"); Serial.println("-----------------------------------"); Serial.println("adress \t\t size"); Serial.print(addressByte); Serial.print(" \t\t "); Serial.print(sizeof(byte)); Serial.println(" (byte)"); Serial.print(addressInt); Serial.print(" \t\t "); Serial.print(sizeof(int)); Serial.println(" (int)"); Serial.print(addressLong); Serial.print(" \t\t "); Serial.print(sizeof(long)); Serial.println(" (long)"); Serial.print(addressFloat); Serial.print(" \t\t "); Serial.print(sizeof(float)); Serial.println(" (float)"); Serial.print(addressDouble); Serial.print(" \t\t "); Serial.print(sizeof(double)); Serial.println(" (double)"); Serial.print(addressByteArray); Serial.print(" \t\t "); Serial.print(sizeof(byte)*7); Serial.println(" (array of 7 bytes)"); Serial.print(addressCharArray); Serial.print(" \t\t "); Serial.print(sizeof(char)*7); Serial.println(" (array of 7 chars)"); } // Test reading and writing byte to EEPROM void readAndWriteByte() { Serial.println("---------------------------"); Serial.println("storing and retreiving byte"); Serial.println("---------------------------"); byte input = 120; byte output = 0; EEPROM.write(addressByte,input); // same function as writeByte output = EEPROM.read(addressByte); // same function as readByte Serial.print("adress: "); Serial.println(addressByte); Serial.print("input: "); Serial.println(input); Serial.print("output: "); Serial.println(output); Serial.println(""); } // Test reading and writing int to EEPROM void readAndWriteInt() { Serial.println("--------------------------"); Serial.println("writing and retreiving int"); Serial.println("--------------------------"); int input = 30000; int output = 0; EEPROM.writeInt(addressInt,input); output = EEPROM.readInt(addressInt); Serial.print("adress: "); Serial.println(addressInt); Serial.print("input: "); Serial.println(input); Serial.print("output: "); Serial.println(output); Serial.println(""); } // Test reading and writing long to EEPROM void readAndWriteLong() { Serial.println("----------------------------"); Serial.println("writing and retreiving Long"); Serial.println("----------------------------"); long input = 200000000; long output = 0; EEPROM.writeLong(addressLong,input); output = EEPROM.readLong(addressLong); Serial.print("adress: "); Serial.println(addressLong); Serial.print("input: "); Serial.println(input); Serial.print("output: "); Serial.println(output); Serial.println(""); } // Test reading and writing float to EEPROM void readAndWriteFloat() { Serial.println("----------------------------"); Serial.println("writing and retreiving float"); Serial.println("----------------------------"); double input = 1010102.50; double output = 0.0; EEPROM.writeFloat(addressFloat,input); output = EEPROM.readFloat(addressFloat); Serial.print("adress: "); Serial.println(addressFloat); Serial.print("input: "); Serial.println(input); Serial.print("output: "); Serial.println(output); Serial.println(""); } // Test reading and updating double to EEPROM void updateAndReadDouble() { Serial.println("------------------------------"); Serial.println("updating and retreiving double"); Serial.println("------------------------------"); double input = 1000002.50; double output = 0.0; EEPROM.updateDouble(addressDouble,input); output = EEPROM.readDouble(addressDouble); Serial.print("adress: "); Serial.println(addressDouble); Serial.print("input: "); Serial.println(input); Serial.print("output: "); Serial.println(output); Serial.println(""); } // Test reading and updating a string (char array) to EEPROM void writeAndReadCharArray() { Serial.println("---------------------------------"); Serial.println("writing and reading a char array"); Serial.println("---------------------------------"); char input[] = "Arduino"; char output[] = " "; EEPROM.writeBlock<char>(addressCharArray, input, 7); EEPROM.readBlock<char>(addressCharArray, output, 7); Serial.print("adress: "); Serial.println(addressCharArray); Serial.print("input: "); Serial.println(input); Serial.print("output: "); Serial.println(output); Serial.println(""); } void writeAndReadByteArray() { Serial.println("---------------------------------"); Serial.println("updating and reading a byte array"); Serial.println("---------------------------------"); int itemsInArray = 7; byte initial[] = {1, 0, 4, 0, 16, 0 , 64 }; byte input[] = {1, 2, 4, 8, 16, 32, 64 }; byte output[sizeof(input)]; EEPROM.writeBlock<byte>(addressByteArray, initial, itemsInArray); int writtenBytes = EEPROM.updateBlock<byte>(addressByteArray, input, itemsInArray); EEPROM.readBlock<byte>(addressByteArray, output, itemsInArray); Serial.print("input: "); for(int i=0;i<itemsInArray;i++) { Serial.print(input[i]); } Serial.println(""); Serial.print("output: "); for(int i=0;i<itemsInArray;i++) { Serial.print(output[i]); } Serial.println(""); Serial.print("Total of written bytes by update: "); Serial.println(writtenBytes); Serial.println(""); } // Check how much time until EEPROM ready to be accessed void waitUntilReady() { Serial.println("-----------------------------------------------------"); Serial.println("Check how much time until EEPROM ready to be accessed"); Serial.println("-----------------------------------------------------"); int startMillis; int endMillis; int waitMillis; // Write byte.. startMillis = millis(); EEPROM.writeByte(addressByte,16); endMillis = millis(); // .. and wait for ready waitMillis = 0; while (!EEPROM.isReady()) { delay(1); waitMillis++; } Serial.print("Time to write 1 byte (ms) : "); Serial.println(endMillis-startMillis); Serial.print("Recovery time after writing byte (ms) : "); Serial.println(waitMillis); // Write long .. startMillis = millis(); EEPROM.writeLong(addressLong,106); endMillis = millis(); // .. and wait for ready waitMillis = 0; while (!EEPROM.isReady()) { delay(1); waitMillis++; } Serial.print("Time to write Long (4 bytes) (ms) : "); Serial.println(endMillis-startMillis); Serial.print("Recovery time after writing long (ms) : "); Serial.println(waitMillis); // Read long .. startMillis = millis(); EEPROM.readLong(addressLong); endMillis = millis(); // .. and wait for ready waitMillis = 0; while (!EEPROM.isReady()) { delay(1); waitMillis++; } Serial.print("Time to read Long (4 bytes) (ms) : "); Serial.println(endMillis-startMillis); Serial.print("Recovery time after reading long (ms) : "); Serial.println(waitMillis); // Write times arrays int itemsInArray = 7; byte array7[] = {64, 32, 16, 8 , 4 , 2 , 1 }; byte arraydif7[] = {1 , 2 , 4 , 8 , 16, 32, 64}; byte arrayDif3[] = {1 , 0 , 4 , 0 , 16, 0 , 64}; byte output[sizeof(array7)]; // Time to write 7 byte array startMillis = millis(); EEPROM.writeBlock<byte>(addressByteArray, array7, itemsInArray); endMillis = millis(); Serial.print("Time to write 7 byte array (ms) : "); Serial.println(endMillis-startMillis); // Time to update 7 byte array with 7 new values startMillis = millis(); EEPROM.updateBlock<byte>(addressByteArray, arraydif7, itemsInArray); endMillis = millis(); Serial.print("Time to update 7 byte array with 7 new values (ms): "); Serial.println(endMillis-startMillis); // Time to update 7 byte array with 3 new values startMillis = millis(); EEPROM.updateBlock<byte>(addressByteArray, arrayDif3, itemsInArray); endMillis = millis(); Serial.print("Time to update 7 byte array with 3 new values (ms): "); Serial.println(endMillis-startMillis); // Time to read 7 byte array startMillis = millis(); EEPROM.readBlock<byte>(addressByteArray, output, itemsInArray); endMillis = millis(); Serial.print("Time to read 7 byte array (ms) : "); Serial.println(endMillis-startMillis); } // Check if we get errors when writing too much or out of bounds void errorChecking(int adress) { Serial.println("-------------------------------------------------------------"); Serial.println("Check if we get errors when writing too much or out of bounds"); Serial.println("-------------------------------------------------------------"); // Be sure that _EEPROMEX_DEBUG is enabled Serial.println("Write outside of EEPROM memory"); EEPROM.writeLong(EEPROMSizeUno+10,1000); Serial.println(); Serial.println("Trying to exceed number of writes"); for(int i=1;i<=20; i++) { if (!EEPROM.writeLong(adress,1000)) { return; } } Serial.println(); } void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } // start reading from position memBase (address 0) of the EEPROM. Set maximumSize to EEPROMSizeUno // Writes before membase or beyond EEPROMSizeUno will only give errors when _EEPROMEX_DEBUG is set EEPROM.setMemPool(memBase, EEPROMSizeUno); // Set maximum allowed writes to maxAllowedWrites. // More writes will only give errors when _EEPROMEX_DEBUG is set EEPROM.setMaxAllowedWrites(maxAllowedWrites); delay(100); Serial.println(""); // Always get the adresses first and in the same order addressByte = EEPROM.getAddress(sizeof(byte)); addressInt = EEPROM.getAddress(sizeof(int)); addressLong = EEPROM.getAddress(sizeof(long)); addressFloat = EEPROM.getAddress(sizeof(float)); addressDouble = EEPROM.getAddress(sizeof(double)); addressByteArray = EEPROM.getAddress(sizeof(byte)*7); addressCharArray = EEPROM.getAddress(sizeof(char)*7); // Show adresses that have been issued issuedAdresses(); // Read and write different data primitives readAndWriteByte(); readAndWriteInt(); readAndWriteLong(); readAndWriteFloat(); updateAndReadDouble(); // Read and write different data arrays writeAndReadCharArray(); writeAndReadByteArray(); // Test EEPROM access time waitUntilReady(); // Test error checking errorChecking(addressLong); } void loop() { // Nothing to do during loop }