Программный uart + sim800l

Pavluha
Offline
Зарегистрирован: 21.08.2022

Здравствуйте. Пытаюсь оттачивать навыки постройки проектов на ардуино. На данный момент имеется связка NANO 328 + Sim800 через программный uart. Работает стабильно уже несколько дней. Но совершенству, как известно, нет предела. Есть желание оптимизировать код там, где это возможно. В голове возникла такая мысль:

1.Длина нужных в работе сообщений с порта не может превышать, условно, 100 знаков.
2. Но в связи с рекламными рассылками сообщений от оператора и с возможным спамом, иногда приходят бесполезные смс с большой длиной, как следствие- сим присылает в порт длинные ненужные сообщения, а ардуино выгружает их содержимое в переменную и тратит на это ценные ресурсы, (лишний раз фрагментируя память?).
3. Да, я знаю, что буфер порта находится в динамической памяти, но насколько я понимаю, выгружая содержимое буфера в стрингу с помощью readstring, я фактически делаю дубликат этой строки в памяти.
4. Придумалось мне попытаться игнорировать сообщения с uart длиной более 100 знаков, не выгружая их в переменную, а просто очищая буфер.

Как я это примерно представляю:

если uart.avialable возвращает более 100, то делаем не String s =uart.readString(), а делаем просто uart.readString().

Вопрос-имеет ли это смысл? А именно, вызывая readstring "вникуда", экономлю ли я ресурсы, или возврат этой функции все равно " куда-то сохраняется временно" и смысла в этом нет?

Есть еще второй костыль,очищающий uart, который я вычитал в интернете: вручную добавить в библиотеку serial метод clear(), очищающий буфер. Но тут возникает вопрос, будет ли это корректно работать в программном uart? ну и вообще, может быть я слишком заморачиваюсь, и стоит просто оставить все как есть?

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

Надеюсь, что по неопытности не вызвал раздражение у опытных программистов. Сам я в этой теме всего два месяца.

rkit
Offline
Зарегистрирован: 23.11.2016

Если тебя так волнуют стиринги, то просто не используй их.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Лично я считаю программный uart извращением и никогда его не использую, поэтому, вероятно, не все мои замечания будут справедливы для программного порта.

2. Насколько мне известно, у аппаратного uart размер буфера по умолчанию составляет 64 байта, и оперативно изменять этот размер не представляется возможным.

3. Из 2 следует, что available никогда не может вернуть число больше 64.

4. По поводу String полностью согласен с rkit.

5. Вообще, дожидаться, пока придет 100-й символ, мне кажется, неправильным. А если сообщение короче 100 символов,  следующее еще неизвестно когда будет, что так сидеть и ждать? В то же время, если сообщение и более 100 символов, то оно все равно приходит постепенно, поэтому в момент запроса из, скажем, 150 символов могло успеть приняться только 80. Т.е. ты будешь считать, что сообщение нужно читать, а это не так.

6. Мне кажется, для экономии памяти и избежания ее фрагментации лучше организовать кольцевой буфер, в который считывать по мере прихода по 1 байту и сразу анализировать содержимое. Никаких readString! Если тебя не интересуют строки длиннее 100 байт, можно сделать буфер длиной как раз 100 байт. При этом никакого дополнительного расхода памяти в процессе работы не потребуется, поэтому не будет проблем ни с нехваткой памяти, ни с ее фрагментацией.

7. Но, в принципе, если разбирать приходящие данные на лету, то даже 100-байтный буфер может оказаться избыточным.

b707
Offline
Зарегистрирован: 26.05.2017

Pavluha пишет:
Как я это примерно представляю: если uart.avialable возвращает более 100, то делаем не String s =uart.readString().

проще вычитать все символы из буфера с помощью read()

if ( uart.avialable() > 100) {
  while ( uart.avialable() ) uart.read();
}

только я сильно сомневаюсь, что uart.avialable может быть больше 100. По-моему, он показывает число принятых символов в буфере, а стандартный буфер всего 64 байта

Pavluha
Offline
Зарегистрирован: 21.08.2022

Спасибо, ребят. глупость вопроса я осознал.

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

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Тут куча примеров
https://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-n...
По поводу software serial - модем подключается к аппаратному uart, программный используется только для вывода отладочных сообщений, в готовом устройстве полностью убирается.

SAB
Offline
Зарегистрирован: 27.12.2016

Когда то давно увеличивал в библиотеке размер буфера до 200 байт, для приема QR кода (8 класс). Можно конечно было налету в массив засовывать данные, но выбирать их надо было по условию через некоторое время спустя как они залетали (а данные в буфер валятся по прерыванию) по этому происходило потеря данных(буфер работает как стек). Так что помогло только увеличение буфера.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Кольцевой буфер в сотню байт решит ваши проблемы.