Какво да изпратите през серийни портове

Съжалявам, ако това е много неясен въпрос, но изглежда не мога да го формулирам правилно, за да намеря някой друг с този проблем. Основният въпрос е, след като имате установена серийна връзка между две устройства, как използвате тази връзка за осъществяване на двупосочна комуникация?

Един пример може да помогне. Да предположим, че имате температурен сензор като вградено устройство, използващо микроконтролер и фърмуер, написан на C. Имате връзка със сериен порт от този сензор към компютър и някакъв софтуер на компютъра за взаимодействие с него, да речем C++ приложение. Разбирам как да настроя серийните портове от двете страни и да чета и записвам единични байтове данни между двете устройства. Истинският въпрос е каква конвенция използвате за комуникация между двете устройства?

Да приемем, че вашите изисквания са както следва:

1.) Трябва да можете да изпратите команда за отчитане на единична температура от вграденото устройство и да я изпратите на компютъра за целите на показването.

2.) Трябва да изпратите команди, за да накарате сензора да стартира и спре поточно предаване на температурни стойности.

3.) Имате нужда от набор от команди, за да зададете различни аспекти във фърмуера, като скорост на поточно предаване, поточно предаване при стартиране, мигащи светодиоди и т.н.

4.) Имате нужда от някаква структура, за да изпратите сложни форми на данни към компютъра, може би набор от показания за напрежение на батерията.

Начини за постигане на това

Изглежда има няколко начина, по които хората са склонни да правят това:

API за прости низове:

Най-често срещаните, от работа със сензори на трети страни, изглежда използват прост API, базиран на низове, така че командите за стартиране и спиране на потоци може да бъдат съответно "SS,1\r" и "SS,0\r". В този случай ще трябва да четете от серийния порт, докато получите знака "\r" и след това да анализирате данните, които имате, за да видите дали има команда (вляво от запетаята) и параметри (вдясно от запетаята). Това работи за сценарии от 1 до 3 по-горе, но не прави сценарий 4 много лесен.

JSON String API:

Това работи по същия начин като горното, но вместо да предавате вашите параметри като прости стойности, вие подавате JSON обекти, които могат да представляват сложни структури от данни. Следователно можете да изпратите масива от напрежения на батерията като JSON масив. Този метод изглежда покрива всички случаи на употреба 1-4 по-горе. Но JSON изпраща низове и е по-трудно да се анализира с помощта на вграден c. Това би направило чудеса за компютърната страна, която може да използва език от по-високо ниво като Java, който има библиотеки за четене на JSON данни.

API за пакетен стил:

Това е решението, което приехме, за което сега донякъде съжалявам. Това включва изпращане на структурирана пакетна конвенция от байтове за всяка част от данните, които изпращаме. Структурата на пакета е показана по-долу.

[0xFF][0xFF][ID][CMD][D0][D1][D2][D3][D4][D5][D6][D7][0xEE][0xEE][0xEE]

С тази структура изпращаме горен и долен колонтитул (0xFF и 0xEE) за проверка на пълнотата на пакета, идентификатор за изпращане на последователни пакети (за предаване на масив от данни), масив от данни, който можем да използваме за пакетиране на longs, float, int и т.н. , и команден байт (CMD), който може да се използва от устройството, за да определи как да анализира полезния товар на данните (D0-D7).

Затова питам кой е най-предпочитаният начин за комуникация през сериен порт? Има ли други начини, които пропускам? Напоследък се занимавам много с уеб разработка и изглежда, че JSON е хубава абстрактна система за предаване, но има своите ограничения, защото трябва да правите много повече анализиране на низове, което е малко сложно от страна на фърмуера.


person JBausmer    schedule 05.09.2013    source източник
comment
Какво не е наред с подхода, който сте използвали, освен че е патентован? Какво имаш предвид под предпочитан? Има малки, надеждни парсери за JSON, които можете да използвате на вградено устройство: zserge.bitbucket.org/jsmn .html   -  person Robert Harvey    schedule 05.09.2013
comment
Повечето JSON се използват в мрежа, където текстът на JSON съобщението е обвит в пакет(и) и се сумира с контролна сума и се проверява, за да е сигурно, че ще стигне до мястото, където го изпращате. Не е гарантирано правилно предаване на необработените серийни байтове. (Обикновено грешките са 1 или повече бита в последователност. Може би някои цели байтове.) Трябва да направите нещо, за да проверите целостта на съобщението и да проверите дали това, което изпращате, действително е попаднало там. Това, което използвате, трябва да направи това.   -  person Lee Meador    schedule 05.09.2013
comment
От една страна, ограничава използването до 256 типа команди. За да избегнем това, ние нарушихме нашата конвенция за изпращане на данни и команди в единични пакети. Сега изпращаме пакет, чиито данни задават идентификатора на параметъра, който искаме да зададем, и отделен пакет, който изпраща стойността, на която да зададем този параметър. В известен смисъл има внедрено състояние в нашата система за доставка, фърмуерът трябва да запомни ID в RAM, докато получи данните, за да зададе този параметър. Използваме 2 пакета, където използвахме 1, което прави повредата по-вероятна. Под предпочитан имам предвид със сигурност някой друг да има по-добър начин за изпращане и анализ на структурирани данни.   -  person JBausmer    schedule 05.09.2013
comment
какво ще кажете за json-rpc, който се занимава както с изпращане, така и с получаване-ack? и също е често срещан метод.   -  person Lao Shaw    schedule 07.07.2017


Отговори (2)


Най-големият проблем тук е, че липсват стандарти. Почти всеки внедрява свой собствен протокол за ограничаващи устройства или когато става въпрос за транспортиране на ниско ниво като UART / серийна линия. Но с нарастващата тенденция на IoT това се надяваме да започне да се променя.

Моля, разгледайте SLIP и SLIPMUX за изпращане на пакетно ориентирани протоколи по серийна линия.

Без значение дали изпращате JSON, XML или нещо друго, най-вероятно се нуждаете от някакъв стоп флаг, за да прекратите вашите съобщения. Често \n се използва за четливост в комбинация с ASCII кодирано съдържание, но това не е най-доброто за двоично кодирана машинна комуникация 2.

SlipMux е обратно съвместим със SLIP (за IPv4 и IPv6 пакети), но също така поддържа нови типове съобщения като CoAP и диагностични (четими от човека) съобщения. Можете просто да внедрите свои собствени типове пакети като съобщения „JSON“ или „XML“.

Като протокол мога да препоръчам CoAP в комбинация със SlipMux. CoAP е много подобен на HTTP, но много по-лек и по този начин лесен за работа за повечето разработчици.

person Tarion    schedule 24.01.2017

Форматът на двоичен пакет е привлекателен поради своята очевидна простота и ефективност. Освен това някои комуникационни връзки вече изпращат данни като пакети с фиксиран размер (USB, TCP/IP, файлови системи и т.н.), но ако трябваше да го направя по различен начин, не бих продължил по този начин отново поради следните недостатъци:

  • не се чете от хора (освен ако не искате да объркате нещата и да защитите протокола си :-) )
  • зависимост от компютърната архитектура: помислете за проблемите с endianity
  • зависимости от инструменталната верига: напр., как компилаторът X пакетира структури от данни спрямо компилатор Y?
  • зависимости на връзката: ако връзката се промени, какво става, ако има странно съвпадение между размера на пакета на протокола и размера на новия пакет на връзката?

JSON би бил моят начин сега: ASCII предаванията на данни са по-малко ефективни от двоичните предавания, но неговото удобство и преносимост компенсират това, освен ако приложението няма сериозно ограничение на честотната лента. Аз лично написах JSON парсер за Arduino Uno платка и той работи в по-малко от 2 kb RAM за данни, включително системен стек. Добре, може да се задуши при дълбоко вложени JSON предавания, но беше достатъчно добър, за да премахне ключови елементи от туит пакет в Twitter и доказа, че може да работи на малки системи.

Ив Макдоналд

person user2918341    schedule 25.10.2013