Как очистить Serial входящий буфер

vk007
Offline
Зарегистрирован: 16.06.2015

Вы все-таки приняли мое сообщение в свой адрес. Извините, конечно, но я действительно ни кого не имел в виду конкретно. Надо было бы все-таки разделить то сообщение на два, ну да ладно, извините еще раз. Не люблю ссориться, поэтому буду завязывать. Тем более, что мне сложно удерживать тему по курсу интересующего вопроса - "ответы" постоянно уходят с колеи, вроде бы и касаются темы, но не то, да и понять меня вы почему-то не можете, а твердо меня убеждаете, что это я не понимаю элементарного, типа того, что входящие данные в данном случае - это поток. На основании чего вы это решили? По-моему я только об этом и долблю, что нельзя сразу все одним махом принять и обработать, пока этот поток "не иссякнет". Ладно. Ограничусь тем, что есть. У меня код хоть и не по феншую и с таким ненавистным delay, но работает именно так, как мне и требовалось. С Новым годом!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vk007 пишет:

с таким ненавистным delay

Що Ви все маєте проти delay? Що за секта делэефобов?

JonHappy1
Offline
Зарегистрирован: 11.06.2018

alexpetro000 пишет:

Если хочется по-сложному, то так:

Переходим сюда:
%местокудапоставилиArduino%\Arduino\hardware\arduino\avr\cores\arduino

Открываем файл HardwareSerial.cpp
На предпоследней строке файла дописываем:

void HardwareSerial::clear()
{
	_rx_buffer_head = _rx_buffer_tail;
}

Сохраняем файл.

Открываем файл HardwareSerial.h
после public: на следующей строке пишем

virtual void clear(void);

Сохраняем.

Далее в коде можно будет использовать функцию Serial.clear(); которая очистит входной буфер

сделал так. ругается на это Serial.clear();
скопировал HardwareSerial.h/cpp  в папку с ino
стал ругаться на это
void HardwareSerial::clear()
no 'void HardwareSerial::clear()' member function declared in class 'HardwareSerial'

Zakhar1974
Offline
Зарегистрирован: 27.09.2018

JonHappy1 пишет:

alexpetro000 пишет:

Если хочется по-сложному, то так:

Переходим сюда:
%местокудапоставилиArduino%\Arduino\hardware\arduino\avr\cores\arduino

Открываем файл HardwareSerial.cpp
На предпоследней строке файла дописываем:

void HardwareSerial::clear()
{
	_rx_buffer_head = _rx_buffer_tail;
}

Сохраняем файл.

Открываем файл HardwareSerial.h
после public: на следующей строке пишем

virtual void clear(void);

Сохраняем.

Далее в коде можно будет использовать функцию Serial.clear(); которая очистит входной буфер

сделал так. ругается на это Serial.clear();
скопировал HardwareSerial.h/cpp  в папку с ino
стал ругаться на это
void HardwareSerial::clear()
no 'void HardwareSerial::clear()' member function declared in class 'HardwareSerial'

Всем привет. Огромное спасибо. Все работает.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А теперь как очистить Serial от ... спама??

kolyn
Offline
Зарегистрирован: 18.01.2019

Что-бы не плодить темы напишу сюда.

Уважаемые знаюшие, что произойдет при переполненнии  буфера Serial - перестанут приниматься последние данные или наоборот, в нем сохранятся последние, а начальные будут вытесняться?

Ардуино под рукой нет (ответы "А ты проверь" не считаются).D

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

kolyn пишет:

Что-бы не плодить темы напишу сюда.

Уважаемые знаюшие, что произойдет при переполненнии  буфера Serial - перестанут приниматься последние данные или наоборот, в нем сохранятся последние, а начальные будут вытесняться?

Ардуино под рукой нет (ответы "А ты проверь" не считаются).D

Смотрите: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial_private.h

Комментарии в строках 109-112 - есть ответ на ваш вопрос.

kolyn
Offline
Зарегистрирован: 18.01.2019

DIYMan пишет:

Смотрите: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial_private.h

Комментарии в строках 109-112 - есть ответ на ваш вопрос.

Правильно ли мы с гугельпереводчиком поняли - буфер будет заполнен первыми пришедшими, а остальные будут вычитаны и проигнорированы?

 

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

kolyn пишет:

DIYMan пишет:

Смотрите: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial_private.h

Комментарии в строках 109-112 - есть ответ на ваш вопрос.

Правильно ли мы с гугельпереводчиком поняли - буфер будет заполнен первыми пришедшими, а остальные будут вычитаны и проигнорированы?

Гугель не обманет ;)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

kolyn пишет:

Уважаемые знаюшие, что произойдет при переполненнии  буфера Serial 

можно подсадить туда, в конец, exploit. 

kolyn
Offline
Зарегистрирован: 18.01.2019

DetSimen пишет:

можно подсадить туда, в конец, exploit. 

Калапуций, ты, что-ли? А че не под своим ником?;)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

по малочисленным прозьбам трудящихся, мня назначили его заместителем

renoshnik
Offline
Зарегистрирован: 11.04.2013

alexpetro000 пишет:

Если хочется по-сложному, то так:

Переходим сюда:
%местокудапоставилиArduino%\Arduino\hardware\arduino\avr\cores\arduino

Открываем файл HardwareSerial.cpp
На предпоследней строке файла дописываем:

void HardwareSerial::clear()
{
	_rx_buffer_head = _rx_buffer_tail;
}

Сохраняем файл.

Открываем файл HardwareSerial.h
после public: на следующей строке пишем

virtual void clear(void);

Сохраняем.

Далее в коде можно будет использовать функцию Serial.clear(); которая очистит входной буфер

и у меня не компилируется скетч, ругается ....  :-((

FoxJone
Offline
Зарегистрирован: 19.04.2019

Боже, кто все эти люди, которые так неистово пытаются очистить буфер UART (Serial). Зачем это им?

Почему нельзя считать с него все данные, а потом уже решить, что с ними делать? Зачем эти крайности с зачисткой? Моя не понимать....

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

FoxJone пишет:
Зачем эти крайности с зачисткой? Моя не понимать....


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

FoxJone
Offline
Зарегистрирован: 19.04.2019

Клапауций 003 пишет:
я, по причине лености, присущей всем сущностям, обладающим безграничными возможностями, не запрещаю людям заниматься крайностями

Ржу. А можно мне тоже иметь безграничные возможности и не запрещать? Хм... Попробовал и получилось! Не запретил Клапуцию удалить этот комент!

Работает!

Спасибо, Клапуций!)

nik182
Offline
Зарегистрирован: 04.05.2015

FoxJone пишет:

Ржу. А можно мне тоже иметь безграничные возможности и не запрещать? Хм... Попробовал и получилось! Не запретил Клапуцию удалить этот комент!

Работает!

Спасибо, Клапуций!)

Не, ну я понимаю, ты не Трурль что бы имя великого писать без ошибок.... 

renoshnik
Offline
Зарегистрирован: 11.04.2013

FoxJone пишет:

Боже, кто все эти люди, которые так неистово пытаются очистить буфер UART (Serial). Зачем это им?

Почему нельзя считать с него все данные, а потом уже решить, что с ними делать? Зачем эти крайности с зачисткой? Моя не понимать....

Как вариант - внешнее устройство постоянно шлет данные "сериал", а ардуина обращается для чтения в "сериал" периодически. 

Для того, чтобы читать актуальные данные, а не устаревшие желательно очистить буфер ....

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

renoshnik пишет:
Для того, чтобы читать актуальные данные, а не устаревшие желательно очистить буфер ....

что бы читать актуальные данные надо, 1- научится читать , 2 научится определять актуальные данные 3 - наконец использовать актуальные данные.  По факту что бы лечить больного надо лечить больного, а не придумывать болячки у постороннего здорового человека.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

renoshnik пишет:

Для того, чтобы читать актуальные данные, а не устаревшие желательно очистить буфер ....

????   озадачен...

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

wdrakula пишет:

renoshnik пишет:

Для того, чтобы читать актуальные данные, а не устаревшие желательно очистить буфер ....

????   озадачен...

 

Вот несколько грубый пример...

int in_buf=0;
void setup() { Serial.begin(57600); }

void serialEvent() { in_buf = Serial.read() - '0';} 

void loop() {
    if (in_buf>0)  {
	Serial.print( "читаю данные  ");    
	Serial.println(in_buf);
		in_buf=0;	}
		
   Serial.println( "мусор");	delay(5000);  

   Serial.println( "данные");	delay(2000);  
	}

 

Некое устройство постоянно шлет данные в "сериал" ...

Нужно читать данные присланные только в период "данные" ....   Если запустить этот скетч и в терминале вручную отправлять по одной цифре (как пример), то будут читаться все отправленные цифры и в "мусор" и в "данные" .

Задача в том, чтобы перед периодом "данные" очистить буфер .

 

мусор
данные
читаю данные  1
мусор
данные
читаю данные  1
мусор
данные
читаю данные  1
мусор
данные
читаю данные  2
мусор
данные
читаю данные  2
мусор
данные
мусор
данные
мусор

Вот это получается когда при появлении в терминале надписи "мусор" я три раза отправил в порт "1", а при появлении "данные" дважды отправил "2" ...

Задача в том чтобы избавиться от данных которые приходят в период "мусор"...

 

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

renoshnik пишет:
Задача в том чтобы избавиться от данных которые приходят в период "мусор"...

есть такое понятие хидер и тег , голова и хвост сообщения. Разумеется между ними находится сообщение.Ну а остальное мусор.  #сообщение1\nмусор#сообщение2\nмусор  и да периодически надо извлекать данные и потом отправлять уже по этому принципу.  Это вроде стандартное решение, только почему-то прошло мимо вас.

Densl
Offline
Зарегистрирован: 28.11.2018

А буфер от мусора очищается холостым чтением. Но это уже после того как вы прочли свое сообщение.
While(Serial.available()){ Serial.read()}

sadman41
Онлайн
Зарегистрирован: 19.10.2016

И, если в буфер постоянно что-то валит, то так всю жись и будем "отчищать Serial".

Densl
Offline
Зарегистрирован: 28.11.2018

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

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Почему и кому не должно? Наличие канала обмена всегда подразумевает вероятность, что туда приходят данные, не спрашивая можно уже или ещё нет.

renoshnik
Offline
Зарегистрирован: 11.04.2013

qwone пишет:

renoshnik пишет:
Задача в том чтобы избавиться от данных которые приходят в период "мусор"...

есть такое понятие хидер и тег , голова и хвост сообщения. Разумеется между ними находится сообщение.Ну а остальное мусор.  #сообщение1\nмусор#сообщение2\nмусор  и да периодически надо извлекать данные и потом отправлять уже по этому принципу.  Это вроде стандартное решение, только почему-то прошло мимо вас.

Про голову и хвост я знаю. Но вопрос совсем в другом.

Видимо я не совсем корректно выбрал названия, правильнее вместо "мусор" было бы написать "устаревшие данные".

По стандартным решениям вопросов нет, но иногда приходят НЕ стандартные.

Например внешнее устройство (в работу которого я не могу вмешиваться) отправляет в "сериал" информацию  один раз в секунду.

Контроллеру нужны эти значения один раз в минуту.

Вот и получается, что за это время в буфере скапливается очередь устаревших значений ....

 

Densl
Offline
Зарегистрирован: 28.11.2018

Ну все может быть. Также есть вероятность принять мусор за сообщение.

FoxJone
Offline
Зарегистрирован: 19.04.2019

renoshnik пишет:

Например внешнее устройство (в работу которого я не могу вмешиваться) отправляет в "сериал" информацию  один раз в секунду.

Контроллеру нужны эти значения один раз в минуту.

Вот и получается, что за это время в буфере скапливается очередь устаревших значений ....

 


Что мешает контроллеру считывать данные раз в секунду, а использовать только последнее значение раз в минуту?

renoshnik
Offline
Зарегистрирован: 11.04.2013

FoxJone пишет:
renoshnik пишет:

 

Например внешнее устройство (в работу которого я не могу вмешиваться) отправляет в "сериал" информацию  один раз в секунду.

Контроллеру нужны эти значения один раз в минуту.

Вот и получается, что за это время в буфере скапливается очередь устаревших значений ....

 

Что мешает контроллеру считывать данные раз в секунду, а использовать только последнее значение раз в минуту?

Что-то мешает...

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

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

то милис переполнится, то буфер вовремя не очистится и в конце концов скетч не зальется. Но думаю вера она опиум для народа.

Densl
Offline
Зарегистрирован: 28.11.2018

renoshnik пишет:

FoxJone пишет:
renoshnik пишет:

 

Например внешнее устройство (в работу которого я не могу вмешиваться) отправляет в "сериал" информацию  один раз в секунду.

Контроллеру нужны эти значения один раз в минуту.

Вот и получается, что за это время в буфере скапливается очередь устаревших значений ....

 

Что мешает контроллеру считывать данные раз в секунду, а использовать только последнее значение раз в минуту?

Что-то мешает...

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

 


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

nik182
Offline
Зарегистрирован: 04.05.2015

Точно кольцевой? Не нашёл в справочнике такой информации, только длину 64 байта.

Densl
Offline
Зарегистрирован: 28.11.2018

nik182 пишет:

Точно кольцевой? Не нашёл в справочнике такой информации, только длину 64 байта.


Мне кажется там FIFO должен быть. Это не кольцевой тогда? Но все равно он очищается для новых данных.

renoshnik
Offline
Зарегистрирован: 11.04.2013

qwone пишет:

то милис переполнится, то буфер вовремя не очистится и в конце концов скетч не зальется. Но думаю вера она опиум для народа.

спасибо.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Densl пишет:
Это не кольцевой тогда?

Нет. FIFO буфер может быть или не быть кольцевым. С фифошностью это не связано.

Densl пишет:
Но все равно он очищается для новых данных.

Можете привести пример скетча, где это было бы явно видно?

nik182
Offline
Зарегистрирован: 04.05.2015

Собственно вот процедура приема символа

void HardwareSerial::_rx_complete_irq(void)
{
  if (bit_is_clear(*_ucsra, UPE0)) {
    // No Parity error, read byte and store it in the buffer if there is
    // room
    unsigned char c = *_udr;
    rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;

    // if we should be storing the received character into the location
    // just before the tail (meaning that the head would advance to the
    // current location of the tail), we're about to overflow the buffer
    // and so we don't write the character or advance the head.
    if (i != _rx_buffer_tail) {
      _rx_buffer[_rx_buffer_head] = c;
      _rx_buffer_head = i;
    }
  } else {
    // Parity error, read byte but discard it
    *_udr;
  };
} 

Насколько хватает моего английского написано что если достигли конца буфера просто отбрасываем символ чтобы не переполнить буфер. Никакого кольцевого. Переполнили - всё. Больше приёма нет, пока не почистим. И соответственно, чтобы однозначно почистить буфер перед приёмом нужной информации достаточно

  // clear any received data
  _rx_buffer_head = _rx_buffer_tail; 

 

Densl
Offline
Зарегистрирован: 28.11.2018

ЕвгенийП пишет:

Densl пишет:
Это не кольцевой тогда?

Нет. FIFO буфер может быть или не быть кольцевым. С фифошностью это не связано.

Densl пишет:
Но все равно он очищается для новых данных.

Можете привести пример скетча, где это было бы явно видно?


Фифошнлсть это же организация на уровне регистров МК. Я туда лазить не пробовал ещё.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Densl пишет:
Фифошнлсть это же организация на уровне регистров МК.

Фифошность - это организация данных на уровне идеи (карандаша и бумаги). Она не имеет никакого отношения ни к регистрам, ни к МК, и делается абсолютно одинаково хоть МК-61, хоть на Summit'е

Densl пишет:
Я туда лазить не пробовал ещё.

Ну, так либо полезьте, либо не делайте заявлений о том, что там что-то "всё равно очищается".

Densl
Offline
Зарегистрирован: 28.11.2018

nik182 пишет:

Собственно вот процедура приема символа

void HardwareSerial::_rx_complete_irq(void)
{
  if (bit_is_clear(*_ucsra, UPE0)) {
    // No Parity error, read byte and store it in the buffer if there is
    // room
    unsigned char c = *_udr;
    rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;

    // if we should be storing the received character into the location
    // just before the tail (meaning that the head would advance to the
    // current location of the tail), we're about to overflow the buffer
    // and so we don't write the character or advance the head.
    if (i != _rx_buffer_tail) {
      _rx_buffer[_rx_buffer_head] = c;
      _rx_buffer_head = i;
    }
  } else {
    // Parity error, read byte but discard it
    *_udr;
  };
} 

Насколько хватает моего английского написано что если достигли конца буфера просто отбрасываем символ чтобы не переполнить буфер. Никакого кольцевого. Переполнили - всё. Больше приёма нет, пока не почистим. И соответственно, чтобы однозначно почистить буфер перед приёмом нужной информации достаточно

  // clear any received data
  _rx_buffer_head = _rx_buffer_tail; 

 


Не думал что такой тут буфер приема символов. Нужно писать свой - кольцевой, а то этот неудобный.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так он и здесь кольцевой. А какой же он тут? Кольцевой, но с контролем переполнения.

Если Вы и впрямь решили написать "затирающий", то должен предупредить - это не так просто, как может показаться.

Надеюсь, Вы знаете, что делаете.

Densl
Offline
Зарегистрирован: 28.11.2018

ЕвгенийП пишет:

Так он и здесь кольцевой. А какой же он тут? Кольцевой, но с контролем переполнения.

Если Вы и впрямь решили написать "затирающий", то должен предупредить - это не так просто, как может показаться.

Надеюсь, Вы знаете, что делаете.


Я подумал у кольцевого переполнение никогда не наступает.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

С чего бы? Ну вот он заполнился. Что делать? Есть варианты: тереть старое или выбрасывать вновь пришедшее. И чем тут "кольцевость" мешает? Хоть так, хоть так можно делать.

nik182
Offline
Зарегистрирован: 04.05.2015

Densl пишет:
Не думал что такой тут буфер приема символов. Нужно писать свой - кольцевой, а то этот неудобный.

А ты всегда в форум пишешь то что думаешь? Не пробовал сначала посмотреть, разобраться, а потом писать?