Serial read
- Войдите на сайт для отправки комментариев
Чт, 14/03/2013 - 21:19
Пытаюсь передать инфу с ардуино, ничего не получается(((
В конце концов начал посылать с ардуино "123" , но все равно процессинг выдает другие числа, причем не рандомно а с особой последовательностью
Processing:
import processing.serial.*; Serial myPort; // Create object from Serial class int val; // Data received from the serial port void setup() { String portName = Serial.list()[0]; myPort = new Serial(this, "COM3", 9600); } void draw() { val = myPort.read(); println(val); }
Display 0 does not exist, using the default display instead.
Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
-1
-1
0
0
0
0
0
0
0
0
0
0
0
49
242
-1
-1
-1
-1
-1
-1
-1
-1
-1
165
17
144
138
88
90
12
74
196
165
17
144
138
88
90
12
74
196
165
17
144
138
88
90
12
74
196
165
17
144
138
88
90
12
74
196
165
17
144
138
88
90
12
74
196
165
17
144
138
Serial::available() \ Language (API) \ Processing 2+
>В конце концов начал посылать с ардуино "123"
Не предполагайте телепатов. Как показывает опыт это можно сделать десятками неправильных способов.
P.S. Логи тоже можно вставлять как код.
Arduino
Processing
LOG
Windows 8, arduino ide 1.5.2, processing 1.5.1
Ну вот, так гораздо лучше :) Теперь хоть что-то осмысленное можно сказать ;)
Вначале нужно понять "в чем проблема", а потом уже будем думать "что с этим делать".
Проблема в следующем:
Кратко: из ардуины вы шлете ТЕКСТОВУЮ СТРОКУ, а читаете как бинарный поток.
Подробней: ардуина и комп между собой могу обмениватся данными. весь обмен данных состоит из байтов. А вот какой смысл вкладывается в этим байты - решают передающай и принимающий скетч/программа. Один из наиболее распространенных "смыслов" - это когда каждый байт означает "код символа". Номер значка в шрифте который можно нарисовать на экране. Соотвествие кодов и символов можно посмотреть, к примеру тат http://www.asciitable.com/
Терминальный программы (и ардуиновский Serial Monitor в частности) именно такой "смысл" и вкладывают в байты. Например если из Serial пришел байт со значением 65, то он нарисует на экране букву 'A'. Когда вы в коде пишите Serial.print("ABC"); то ардуина шлет три байта: 65,66,67, а уж сериал монитор выводить их именно как буквы. (и сериал монтор, к сожалению, умеют только так интерпретировать/показывать входящую информацию. показать именно "занчение байтов" - он не умеет. нужно другие программы для этого брать).
Теперь смотри что шлеты вы. Serial.println(1232); Что он делает? Для начала преобразую ваше число в строку. Из 1232 сделает "1232". То есть строку состоящуюи из СИМВОЛОВ '1','2','3','2' . А коды этих символов (см. табличку по ссылке) - 49,50,51,50
После чего, так как вы использовали println, а не print - добавить к ним еще два "спец символа", с кодами 13 (возврат каретки) и 10 (перевод строки). Итого ардуина "выплюнет" следующую серию байтов
49,50,51,50,13,10
Упс. Правда похоже на числа которые у вас были? А все потому что Serial.read читает именно цифровое значение байта. Ничего не зная код символа это или что-то другое. Что потом делать с этим значением - это уже ваша забота. Например вы можете отнять от полученных символов 48 (это код нуля) и получите числовые значения 1,2,3,4, а потом "собрать" их в одно число. 1*1000+2*100+3*10+4=1234. Вообщем занятся конвертацией строки в int. (почитайте доку, 99% что у процессинга уже есть готовая функция для подобного. как нибудь parseInt или int.Parse будет называтся).
Вообщем "шо делать?". Тут сильно зависит от того что вы потом собираетесь делать с этими принятыми числами. Просто "выводить пользователю" или "использовать для каких-то вычислений".
Вы должны решить, в каком виде будут общатся между собой Arduino и Processing. В текстовом (что-бы вам удобно было читать в Serial мониторе) или в бинарном (компьютерном языке).
Если вы выбираете текстовое решение - то в процессинге вам нужно читать именно строки, потом конвертировать их числовые занчение, потом делать с ними какие-то вычисление. Все данные будут идти по цепочке число->строка->передача на комп->чтение строки->парсинг в число.
Если вы во главу угла ставите "удобство программы" - можно выбросить промежуточный "человекочитаемый" вариант (в Serial мониторе все будет выглядить как кракозяблы).
Простейшей реализацией "бинарного протокола" будет если вы на ардуине будете делать не Serial.print, а Serial.write. write - не делает никаких конвертаций в строку. Если вы написали Serial.print(5); - то он пошет КОД СИМВОЛА ПЯТЕРКА, то биш 53. А Serial.write(5) пошелт байт со значением 5-ть. И Serial.read() на процессинге вычитает именно 5-ть. Вообщем что послали - то и получили. Никаких промежуточныйх конвертаций.
Но... одно но. write/read оперируют одним байтом за раз. То есть Serial.write(245) вы можете послать. А Serial.write(300) - уже нет. Не влазит число в байт.... но это уже другая история. Вначале попруйбет с малыми числами (от 0 до 255).
Большое спасибо!) Теперь я понимаю как это работает)
Но вместе с этим у меня возникает новый вопрос.
Почему все работает иначе на этом видео http://youtu.be/1TvNU2vxX2Q
А с чего вы взяли что "работает иначе"? Все ровно как я и описывал. ЧИТАЮТ СТРОКУ, потом конвертят ее в число
Вы должны решить, в каком виде будут общатся между собой Arduino и Processing. В текстовом (что-бы вам удобно было читать в Serial мониторе) или в бинарном (компьютерном языке).
Они решили "в текстовом виде гонять данные".
Важно что-бы и отправлялось и читалось в однаковом формате. Тогда будет работает. Они шлют в виде строк и читают в виде строк. Поэтому у них работает.
А вы слали строки, а читали как бинарные байты.
Поэтому у вас есть два варианта - либо начинать слать тоже бинарно (замена print на write), либо меня на стороне компа - начинать читать строки (как они делали).
Вообщем приемник и предатчик должны говорить на одном языке. У вас - разнобой. Кого менять что-бы "языки совпали" - сторону ардуины или сторону процессинга - вам решать.
Насколько я помню, пробовал сделать как у них и результат был тот же, в любом случае попробую еще. А в чем именно различие их приема инфы от( строчного) от того как у меня(бинарного)?
В том что в одному случае поступающие из serial значения интерпретируются как байты-значения, отдельные, а во втором вычитывается сразу множество байтов (у них - пока не попадется символ новой строки) и интепретируются как коды символов.
Вообщем представте, кто-то позвонил вам и сказал: "48,49,50"
Вы записали все эти три числа, но не знаете связаны они между собой и что вообще означают.
А теперь вам сказали, что "сейчас тебе позвонят и продиктуют шифрограмму. расшифруешь ее с помощью asci таблицы" то что получится - это какое-то число.
Вам звонят и диктуют "48,49,50,конец связи". Вы берете таблицу и переводите в символы, у вас выходит строка "123". Теперь вы берете кого-нибудь грамотного, кто умеет читать и спрашивает "что тут написанно?", он вам говорит "число 123".
Это как работает "текстовый вариант".
Бинарный: вам говорят, счас принесут бандерольку (один байт). в ней будут камушки. сколько камушков - это и есть код от сейфа. Тут в окно влетает коробка. Вы заглядываете в нее - видите 123 камушка. Ну и все. Вы знаете сразу "ЧИСЛО".
Большое спасибо))) Разобрался, все работает)
Ребят подскажите плис! Принимаю информация в таком виде:
(Отправлена при помощи Serial.print с контроллера)
28EFEDA803000074 Temp C: 25.00
285C1CA9030000CE Temp C: 25.00
28EFEDA803000074 Temp C: 25.00
285C1CA9030000CE Temp C: 25.00
с помощью processing:
while (myPort.available() > 0) {
myString = myPort.readStringUntil(lf);
if (myString != null) {
println(myString);
Теперь вопрос. Мне необходимо вывести на экран значение Temp C: 25.00 для устройства 28EFEDA803000074.
Как это сделать? т.е. мне необходимо вывести string значение для строки, начинающейся на 28EFEDA803000074.
Если прописать:
text(myString); то выводится все подряд т.е., как я понял, необходимо в text задать какоето условие....
В программировании я начинающий, так что вопрос может и глупый...
Для первого датчика что-то вроде:
Для второго - аналогично.
О функции strstr читаем, например, здесь.
Матюгается на
if (strstr(myString,"28EFEDA803000074")!=NULL)
Говорит - The function strstr(String, String) does not exist. Короче не поддерживается...:(
так это непосредственно processing? Ака жаба?
Ну, тогда попробуйте
Подробнее читать здесь.
Процессинг...
Теперь он пишет NullPointerException
Уже близко.....выдает какую-то ерунду:
Щас мозг закипит....
C этим кое-как справился. Появился другой вопрос.
Как убрать из строки вот это 28EFEDA803000074?
C этим кое-как справился. Появился другой вопрос.
Как убрать из строки вот это 28EFEDA803000074?
Вывод подстроки начиная с "Temp" (соответственно, без "28EFEDA803000074"):
Позволю себе самоцитирование:
Подробнее читать здесь.
Огромное спасибо!!! Все заработало так, как и должно работать!
Еще один глупый вопрос, если не побьете.
Как теперь всю эту канитель в integer преобразовать?
где s - подстрока, содержащая цифири.
Опять же, подробнее - тут (в Интернете).
Да я в программировании туп как пробка! Мой стаж программирования составляет неделю, поэтому для меня
описание в интернете не о чем, мне нужен конкретный пример, только так что то становится понятно.
Короче что то я ни так делаю.....
Результат:
Пробовал даже так:
Результат тот же....
indexOf() - если прочитать описание по приведенной мной ссылке - возвращает позицию первого символа искомой подстроки, то есть в вашем случае позицию символа 'T'. А вам надо знать позицию первой цифры.
Которая стоит где?
Правильно - вслед за двоеточием и пробелом. То есть на 7 символов (длина строки "Temp C:") дальше уже упомянутого 'T'.
Теперь - в качестве упражнения - попробуйте догадаться, как нужно изменить вышеприведенный оператор. Знаний в программировании здесь в общем-то не требуется - простой арифметики достаточно.
Блин, дак как указать..., ... можно было так " " но в строке дво пробела т.е. это равносильно что " Temp C:"
"Temp C:" +7 ?
Даже 3 пробела..
Добрался до цифр:
Ошибка выскакивает та-же...
Блин, дак как указать..., ... можно было так " " но в строке дво пробела т.е. это равносильно что " Temp C:"
"Temp C:" +7 ?
А вот так пробовали:
а еще лучше вот так (естественно, с соответствующими объявлениями переменных):
По крайней мере будет видно, из-за чего выскакивает ошибка.
1. Тоже самое.
2.
В таком виде бежит что то вроде:
Так в строке 4-ре, вы опять выводите переменную idx, а не подстроку которую вы выделили str. Наверное print(str) лучше покажет что же именно вы "выкусили" :)
Кстати, еще и
Можно сделать, что-бы четче видеть что именно мы пытаемся разобрать на части. Может там внутри лежит не то что мы думаем.
Еще есть подозрение на то что parseInt ожидает разделителем целой/дробной части не точку, а запятую... но это потом проверив. Вначале - выведите inString и str и покажите тут.
Кстати, еще и
Можно сделать, что-бы четче видеть что именно мы пытаемся разобрать на части. Может там внутри лежит не то что мы думаем.
А
где вывод?
Мы увидители что именно мы пытаемся разобрать, но не увидели - какой-же именно кусок вы выкусили для кормления parseInt
>Еще есть подозрение на то что parseInt ожидает разделителем целой/дробной части не точк
Проморгал слона в гостинной. parseInt вообще не ждет что там будут какие-то разделители. Откуда дробная часть у целого числа?
Если у нас число может быть дробным, то навреное что-то типа parseFloat/parseDouble будет более подходящим. У нас же температура может быть не только целыми числами. И val, тогда тоже должна не Int-том быть, а соотвествующим типом.
Ребят огромное Вам спасибо!!! Все заработало в лучшем виде!!!
Возникла проблемка, как проверить доступность нужного порта? Листинг портов строит список без учёта занят/свободен. Необходимо получать сообщение о занятости порта (на данный момент занятость порта другим приложением приводит к ошибке библиотеки).
Самый "лобовой вариант", обернуть попытку открытия порта в try-catch блок.
тогда помощь далее нужна, взял пример по функции
по строкам 11-12 сразу вопрос, если файл есть, но пустой, все как описано работает. А вот если файла нет совсем, то ошибка снова на строке 10 и её не перехватывает (условие перехвата другое должно быть?). А строка 12 вообще непонятно что такое, вроде как печататься что то куда то должно, однако видимых результатов нигде нет.
Попробуй не IOException а Exception ловить
Хм.. Поймалось.. Спасибо. На первое время такого варианта отлова ошибок мне за глаза хватит.
ловя Exception ты поймаешь все ошшибки
Это я уже потестил, попихал туда разные косяки. Относительно ошибок ком-порта оно и не важно. Нет чтения данных, нет нормальной работы. Приложение можно закрывать записав ошибку в лог или вынуждать пользователя менять настройки если они доступны для изменения через само приложение (чего я не планирую, все вынесено в *.ini и только)
Приложение можно закрывать записав ошибку в лог или вынуждать пользователя менять настройки
Можно изанчально пробежатся по всему списку портов и посмотреть кто открывается, а кто нет. И пользователю давать список уже "живых портов".
Собственно сама ArduinoIDE, по крайней мере в старых версиях, именно так и делала. Поэтому и были жалобы типа "долго дуплит когда открываю меню tools" если в системе много ком-портов (всякий телефонный софт любит заводить с десяток портов).