Передача данных
- Войдите на сайт для отправки комментариев
Пнд, 30/10/2017 - 22:45
Помогите разобраться с передачей пакета данных по серийнику. Вродебы все просто, а не получается так как хочется. Вообщем идея такая, пакет состоит из символа и трех цыферек, типа (z456). Вот код:
void serialEvent()
{
char n1=0, n2=0, n3=0;
int n = Serial.available();
int sk, k=0;
for(int i=0; i < n; i++) // считываем байт из приемного буфера в переменную
{
if(i==0)
{
k = Serial.read();
Serial.println(k);
}
if(i==1)
{
n1=Serial.read();
}
if(i==2)
{
n2=Serial.read();
}
if(i==3)
{
n3=Serial.read();
}
}
Serial.flush();
//Serial.println(k);
//Serial.println(n1);
//Serial.println(n2);
//Serial.println(n3);
//Serial.println(sk);
//if(Serial.available()==0)
//{
if(k==122)
{
Serial.println(n1);
Serial.println(n2);
Serial.println(n3);
Serial.println("End");
}
//}
}
запускаю монитор ввожу пакет "z123" и... вижу обработка "z" условие выполняется, но куда делись n1,n2,n3?
И почему n1 отобразилось после закрытия условия иф?
122
End
49
Может поможет?
Особо не вникал, но мне кажется, у Вас не правильно организован прием данных. Что-то пришло в сериал, фукция вызвалась, и сразу смотрит а сколько там в сериале байт? А там только один байт пока пришел, поэтому цикл фор в вашей функции выполнится только 1 раз. А остальное Вы очищаете флашем.
Попробуйте в начало функции вставить строчку
while(Serial.available() < 4); - это не сделает код правильным, но может быть заработает, и Вы разбиретесь что к чему.
Спасибо всем за советы, прошерстил кучу информации, но "воз и ныне там". В конце концов вытянул библиотечный скетч ReadASCIIString, собрал схемку управления светодиодом, загрузил в уно и нифига не получилось (афигеть!!!) нет регулировки яркости/цвета и нет ответа на мониторе. Пробовал несколько разных плат и все повторилось(платы рабочие). Как решить эту проблему с пакетами, подскажите, может я че пропускаю, но библотека должна ведь работать(я проверял не все скетчи и ввроде все работало). И последнее, программа ардуинка версия 1,8,0.
Хм. Эк Вы мечетесь-то. А можно глянуть на полный код?
serialEvent не работает как вы ожидаете. Можете легко это проверить
Потом отправьте z123 и посмотрите что вам вернется ;)
Хотите использовать serialEvent вот почти стандартный пример из ардуино иде
Кому не нравится String можно заменить на массив. Принцип не изменится, только за указателем на элемент массива надо следить.
Добрый день. Ну посмотреть полный код... да в принципе можно, но ладно мой код не фурыкает, так ведь и библиотечный сериал(см. в предыдущем посте) также не регулирует светодиоды. А что касамо моего кода - это управление станком и связь с иполнительной платой (ардуинка уно) по серинику с ведущей платой. Одиночные команды идут без проблем, появилась необходимость немного переделать управление не одиночными коммандами а пакетом, типа код комманды + код операции + к.с. + подтвеждение. Извиняюсь за длинную писанину, станок пока работает и я пока долбаюсь с прогой(перевод на пакетный режим). Че я выяснил, массив не заполняется значениями в цикле, выводится только первая комманда а операция и т.д. все в нулях :(. Ну и последнее что хочу попробовать, это на другом компе установить идэ ардуинку и посмотрю как будет работать прошивка платы с библиотечной прогой серийника. Скачал еще новую версию 1,8,6. ардуины, может поможет. НА форуме почитал про серийник(его работу) и не видел подобной проблемы, это получается только у меня такая засада, вот досада :(
Че я выяснил, массив не заполняется значениями в цикле, выводится только первая комманда а операция и т.д. все в нулях :(. Ну и последнее что хочу попробовать, это на другом компе установить идэ ардуинку и посмотрю как будет работать прошивка платы с библиотечной прогой серийника. Скачал еще новую версию 1,8,6. ардуины, может поможет. НА форуме почитал про серийник(его работу) и не видел подобной проблемы, это получается только у меня такая засада, вот досада :(
Именно про это я Вам и говорил. И даже рассказал почему. Вы сделали то, что я советовал?
Да я проверил ваше предложение но это мало что мне дало. Собственно говоря разницы между цыклами я не увидел, не говоря уже об особенностях их применени. А Вот почему так происходит что-то я не видел вашего расказа, извините наверно слепой стал, если не трудно поясните еще раз
Так вроде пост мой никуда не удалился. Кстати, а как у Вас вызывается функция void serialEvent() ?
А мои посты видно? :)
Ребята, да в том-то и дело что и функции и текстовка прописывается (под мою задачу) в корне ничем не отличается от аналогичных и работающих. Я осмелюсь уточнить(ранее писал), залил на уно скетч из библиотеки ReadASCIIString и результат был нулевой!!! Проверил по длинне приема, пакет соответствует а вот ни регулировки светодиода ни ответа на монитор не получил. ПОучается что по иф условие не обрабатывается, т.е. код конца пакета ('\n') почемуто не нашелся(его естественно вставлял в строку). Вчера вечером повозился с ранее написанными скетчам(пакетной оправкой не занимался) и получается что проблема только с пакетами, неважно какой длинны(больше 1 байта). А байт ловит приемник без проблем. Но там нет цыклов реад, на важно каким цыклом читаем (for или while). Надо попробовать читать без них, щас проверю!
А ларчик просто открывался, переустановил ардуинку иде, все заработало. Новую 1,8,6, не ставил, просто переустановил(полностью) 1,8,0, и все! Незнаю почему мне так "повезло" что прога глюканула и довольно интересно, чуть было не полысел :(. Вообщем ребята всем спасибо за помощь.
5N62V кстати про функцию serialEvent()? Что значит как вызывается, я просто ввел это прерывание по наличию в приемном буфере чегото и все! Функция работает пока буфер не опустеет, ну а дальше уж че надо то и буду делать с полученными данными.
ну вот куски чего у меня получилось:
ну вот куски чего у меня получилось:
И что, этот код работает? - тогда ждем второй серии...
"почему было в цыкле было if (inChar == '\n')" - потому что '\n' - правильно, а 'n' - это чушь.
А мои посты видно? :)
заклятие невидимости сними с постов - будут видны.
А мои посты видно? :)
Запускаем, вводим те же z123 (не забывая в настройках монитора выбрать "Новая строка") получаем в монитор порта:
Уважаемый ТС, как смог, объяснил. У Вас та же проблема.
[
Запускаем, вводим те же z123 (не забывая в настройках монитора выбрать "Новая строка") получаем в монитор порта:
Это штатное поведение функции SerialEvent() - она вызывается на каждый приходящий символ, так и должно быть.
Я так и понял, просто эту особенность надо юзать осознанно. Лично я пятьсот раз подумаю о возможных последствиях дерганья программы по прерыванию, особенно когда loop большой и медленный. В конце-концов данные и в сериале могут полежать, никуда не денутся, пока основной цикл не проверит их наличие.
Я так и понял, просто эту особенность надо юзать осознанно. Лично я пятьсот раз подумаю о возможных последствиях дерганья программы по прерыванию, особенно когда loop большой и медленный. В конце-концов данные и в сериале могут полежать, никуда не денутся, пока основной цикл не проверит их наличие.
похоже, вы все-таки не вполне понимаете функцию SerialEvent(). Прерывания в ней не используются, иначе введением delay() вы не смогли бы изменить ее поведение.
Функция SerialEvent() тупо вызывается один раз за loop(), ее использование абсолютно равнозначно добавлению в loop() кода
if (Serial.Availiable() ) { .... }
похоже, вы все-таки не вполне понимаете функцию SerialEvent(). Прерывания в ней не используются, иначе введением delay() вы не смогли бы изменить ее поведение.
Функция SerialEvent() тупо вызывается один раз за loop(), ее использование абсолютно равнозначно добавлению в loop() кода
if (Serial.Availiable() ) { .... }
Хм. Ок. Может и так. А в каком месте loop() производится проверка if (Serial.Availiable() ) { .... }, и из чего это следует?
это следует из описания https://www.arduino.cc/en/Tutorial/SerialEvent - см вторую фразу. Проверка происходит _между_ вызовами loop().
И вот еще цитата оттуда же:
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
Если быть точнее, то вот так она вызывается:
Т.е. если у вас в loop-e будет что-то типа while(true) {if (Serial.available() ...) {...} }, то сериаливент вам не нужен в принципе. Да и вообще не особо нужен, по моему мнению. Разве что любителям хардкорного ООП-а она пригодится.
sadman41, b707 - Спасибо! Конструктивно! И с какого будуна я взял, что эта ф-ция работает по прерыванию?! :)) Где-то читал, так в памяти отложилось.
сериаливент вам не нужен в принципе. Да и вообще не особо нужен, по моему мнению. Разве что любителям хардкорного ООП-а она пригодится.
ну как сказать, я не любитель ООП, а сериал ивент использую. Она уменьшает число операторов в loop() - а сл-но, улучшает читаемость кода. На мой взгляд, ясность программы в большинстве случаев важнее. чем выигрыш десятка микросекунд.
ну как сказать, я не любитель ООП, а сериал ивент использую.
Так я вам и не запрещаю, для этого у нас Клапауций имеется.
Мне вот проще в лупе держать while, экономить микросекунды и на лету анализировать входящие данные без дополнительного складывания в буфер и повторного прохождения по нему. Каждому своё.
а я вообще в нескольких проектах обращался из лупа к сериалу только тогда, когда в нем кол-во байт приближалось к нужному, в зависимости от кол-ва байт в пачке и скорости лупа
if (Serial.available()>x)function();
Пока входящий в Serial пакет не более 16 байт - и это допустимо.