Pertanyaan Protokol komunikasi point-to-point serial yang sederhana


Saya memerlukan protokol komunikasi sederhana antara dua perangkat (PC dan mikrokontroler). PC harus mengirim beberapa perintah dan parameter ke mikro. Mikro harus mengirimkan array byte (data dari sensor).

Data harus kebisingan dilindungi (selain memeriksa paritas, saya pikir saya perlu beberapa metode koreksi data lainnya).

Apakah ada solusi standar untuk melakukan ini? (Saya hanya butuh ide, bukan solusi lengkap).

P.S. Saran apa pun dihargai. P.P.S Maaf atas kesalahan tata bahasa, saya harap Anda mengerti.

Edit 1. Saya belum memutuskan apakah itu akan terjadi master / slave protokol atau kedua belah pihak dapat memulai komunikasi. PC harus tahu kapan mikro telah melakukan pekerjaan dan dapat mengirim data. Ini dapat terus polling mikro jika data sudah siap, atau mikro dapat mengirim data, ketika pekerjaan selesai. Saya tidak tahu mana yang lebih baik dan lebih sederhana.

Edit 2.  Hardware dan lapisan fisik protokol. Sejak RS-232C standar serial yang digunakan di PC, akan saya gunakan komunikasi asynchronous. Saya hanya akan menggunakan sinyal RxD, TxD, dan GND. Saya tidak dapat menggunakan kabel tambahan karena AFAIK mikrokontroler tidak mendukungnya. BTW Saya menggunakan AVR Chip ATmega128.

Jadi saya akan menggunakan baud rate tetap, 8 bit data, 2 stop bit tanpa pengecekan paritas (atau dengan?).

Protokol tautan data. Itulah yang terutama menjadi perhatian utama saya. Terima kasih telah menyarankan HDLC, PPP dan Modbus protokol. Saya akan meneliti tentang itu.


51
2018-05-02 22:45


asal


Jawaban:


Saya akan menggunakan HDLC. Saya pernah beruntung dengan itu di masa lalu. Saya akan untuk point to point serial hanya menggunakan Pembingkaian asynchronous dan lupakan semua hal kontrol lainnya karena mungkin akan berlebihan.

Selain menggunakan HDLC untuk membingkai paket. Saya memformat paket saya seperti berikut ini. Ini adalah bagaimana opsi dilewatkan menggunakan 802.11

U8 cmd;
U8 len;
u8 payload[len];

Ukuran total dari setiap paket perintah adalah len +2

Anda kemudian mendefinisikan perintah seperti

#define TRIGGER_SENSOR 0x01
#define SENSOR_RESPONSE 0x02

Keuntungan lainnya adalah Anda dapat menambahkan perintah baru dan jika Anda mendesain parser Anda dengan benar untuk mengabaikan perintah yang tidak terdefinisi maka Anda akan memiliki beberapa kompatibilitas mundur.

Jadi menyusun semua paket itu akan terlihat seperti berikut.

 // total packet length minus flags len+4
 U8 sflag;   //0x7e start of packet end of packet flag from HDLC
 U8 cmd;     //tells the other side what to do.
 U8 len;     // payload length
 U8 payload[len];  // could be zero len
 U16 crc;
 U8 eflag;   //end of frame flag

Sistem kemudian akan memonitor aliran serial untuk flag 0x7e dan ketika ada di sana Anda memeriksa panjangnya untuk melihat apakah pklen> = 4 dan pklen = len + 4 dan bahwa crc valid. Catatan jangan hanya mengandalkan crc untuk paket kecil Anda akan mendapatkan banyak false positive juga periksa panjangnya. Jika panjang atau crc tidak cocok hanya mengatur ulang panjang dan crc dan mulai dengan decoding frame baru. Jika itu adalah pertandingan kemudian salin paket ke buffer baru dan berikan ke fungsi pemrosesan perintah Anda. Selalu atur ulang panjang dan crc saat bendera diterima.

Untuk fungsi pemrosesan perintah Anda ambil cmd dan len dan kemudian gunakan saklar untuk menangani setiap jenis perintah. Saya juga mensyaratkan bahwa peristiwa tertentu mengirim respons sehingga sistem berperilaku seperti panggilan prosedur jarak jauh yang didorong oleh peristiwa.

Jadi misalnya perangkat sensor dapat memiliki pengatur waktu atau menanggapi perintah untuk mengambil pembacaan. Ini kemudian akan memformat paket dan mengirimkannya ke PC dan PC akan merespon bahwa ia menerima paket. Jika tidak maka perangkat sensor bisa mengirim ulang pada waktu habis.

Juga ketika Anda melakukan transfer jaringan Anda harus mendesainnya sebagai tumpukan jaringan seperti OSI modle sebagai Foredecker poin jangan lupa tentang hal-hal lapisan fisik. Postingan saya dengan HDLC adalah lapisan data link dan RPC dan penanganan perintah adalah Lapisan Aplikasi.


34
2018-05-03 19:08



Protokol RS232 memang rumit. Saran untuk menggunakan HDLC, adalah yang bagus, tapi itu bukan solusi keseluruhan. Ada hal-hal lain yang perlu Anda putuskan:

  • Bagaimana baud rate antara kedua perangkat ditentukan? Autobuad? Predefined, atau mengatur explicate?
  • Apakah Anda akan melakukan kontrol aliran dalam perangkat lunak atau perangkat keras atau keduanya? Perhatikan, jika Anda menggunakan kontrol aliran perangkat keras maka Anda harus pastikan, bahwa kabel dibangun dengan benar.
  • Berbicara tentang kabel, ini sangat sakit dengan RS233. Tergantung pada perangkat, Anda mungkin perlu menggunakan kabel straight through, atau kabel cross over, atau varian.
  • Menggunakan mekanisme kontrol aliran berbasis perangkat lunak dapat efektif karena memungkinkan kabel yang paling sederhana untuk digunakan - hanya tiga kabel (TX, RX, dan umum).
  • Apakah Anda memilih kata 7 atau 8 bit?
  • Paritas HW atau pengecekan kesalahan perangkat lunak.

Saya sarankan Anda pergi dengan 8 bit data, tidak ada paritas hardware, 1 stop bit, dan menggunakan kontrol aliran berbasis perangkat lunak. Anda harus menggunakan autobaud jika perangkat keras Anda mendukungnya. Jika tidak, maka autobaud sangat sulit dilakukan dalam perangkat lunak.


10
2018-05-04 21:51



Ada beberapa jawaban yang bagus di sini, berikut beberapa petunjuk yang berguna:

Bahkan jika paket Anda tidak dipisahkan waktu, byte sinkronisasi adalah cara penting untuk mengurangi jumlah tempat yang Anda perlukan untuk membuat paket dari. Perangkat Anda sering harus berurusan dengan sekelompok data sampah (yaitu akhir paket di penerbangan ketika mereka dihidupkan, atau hasil dari tabrakan perangkat keras). Tanpa byte sinkronisasi, Anda harus mencoba membuat paket dari setiap byte yang Anda terima. Sinkronisasi byte berarti bahwa hanya 1/255 byte suara acak bisa menjadi byte pertama dari paket Anda. Juga FANTASTIS saat Anda ingin mengintip protokol Anda.

Memiliki alamat di paket Anda atau bahkan hanya sedikit mengatakan master / slave atau pc / perangkat berguna ketika Anda melihat paket melalui alat snoop dari beberapa jenis atau yang lain. Anda mungkin melakukan ini dengan memiliki byte sinkronisasi yang berbeda untuk PC daripada DEVICE. Juga, ini berarti perangkat tidak akan merespon gema sendiri.

Anda mungkin ingin melihat kesalahan koreksi (seperti Hamming). Anda mengemas 8 bit data ke dalam bit yang dilindungi 12 bit. Salah satu dari 12 bit tersebut dapat dibalik dan 8 bit asli diambil. Berguna untuk penyimpanan data (digunakan pada CD) atau di mana perangkat tidak dapat mengirim ulang dengan mudah (tautan satelit, satu arah rf).

Nomor paket membuat hidup lebih mudah. Sebuah paket yang dikirim membawa nomor, tanggapan membawa nomor yang sama sebuah bendera yang mengatakan "respons". Ini berarti bahwa paket-paket yang tidak pernah datang (sync corruped say) mudah dideteksi oleh pengirim dan dalam mode full-duplex dengan tautan yang lambat, dua perintah dapat dikirim sebelum respon pertama diterima. Ini juga membuat analisis protokol lebih mudah (Pihak ketiga dapat memahami paket yang diterima tanpa sepengetahuan protokol yang mendasarinya)

Memiliki seorang guru tunggal adalah penyederhanaan yang luar biasa. Yang mengatakan, dalam lingkungan dupleks penuh itu tidak masalah sama sekali. Cukuplah untuk mengatakan Anda harus selalu melakukannya kecuali Anda mencoba untuk menghemat daya atau Anda melakukan sesuatu yang digerakkan di ujung perangkat (keadaan input berubah, sampel siap).


8
2018-05-03 14:02



Saran saya adalah modbus. Ini adalah protokol standar yang efisien dan mudah untuk komunikasi dengan perangkat yang memiliki sensor dan parameter (misalnya PLC). Anda bisa mendapatkan spesifikasi di http://www.modbus.org. Sudah ada sejak 1979 dan semakin populer, Anda tidak akan kesulitan menemukan contoh dan pustaka.


5
2018-05-06 02:35



Saya membaca pertanyaan ini beberapa bulan yang lalu, memiliki masalah yang persis sama, dan tidak benar-benar menemukan sesuatu yang cukup efisien untuk mikro kecil 8-bit dengan sejumlah kecil RAM. Jadi terinspirasi oleh BISA dan LIN saya membangun sesuatu untuk melakukan pekerjaan itu. Saya menyebutnya MIN (Microcontroller Interconnect Network) dan saya telah mengunggahnya ke GitHub di sini:

https://github.com/min-protocol/min

Ada dua implementasi di sana: satu di embedded C, satu dengan Python untuk PC. Ditambah sedikit program tes "hello world" di mana PC mengirim perintah dan lampu firmware menjadi LED. Saya membuat blog tentang hal ini dan menjalankannya di papan Arduino di sini:

https://kentindell.wordpress.com/2015/02/18/micrcontroller-interconnect-network-min-version-1-0/

MIN sangat sederhana. Saya memperbaiki representasi layer 0 (8 bit data, 1 stop bit, tanpa parity) tetapi membiarkan baud rate terbuka. Setiap frame dimulai dengan tiga 0xAA byte yang dalam biner adalah 1010101010, sebuah pulsetrain yang bagus untuk melakukan deteksi tingkat autobaud jika salah satu ujung ingin secara dinamis beradaptasi dengan yang lain. Frame adalah 0-15 byte muatan, dengan checksum Fletcher 16-bit serta byte kontrol dan pengenal 8-bit (untuk memberi tahu aplikasi apa yang memuat data muatan).

Protokol menggunakan isian karakter sehingga 0xAA 0xAA 0xAA selalu menunjukkan start-of-frame. Ini berarti bahwa jika perangkat keluar dari pengaturan ulang selalu sinkron dengan awal frame berikutnya (tujuan desain untuk MIN tidak pernah melewatkan frame yang tidak lengkap atau salah). Ini juga berarti tidak perlu ada batasan waktu inter-byte dan inter-frame yang spesifik. Rincian lengkap protokol ada di repo wiki GitHub.

Ada ruang untuk peningkatan di masa mendatang dengan MIN. Saya telah meninggalkan beberapa kait di sana untuk pengiriman pesan blok (4 bit dari byte kontrol disediakan) dan untuk negosiasi tingkat kemampuan yang lebih tinggi (identifier 0xFF dicadangkan) sehingga ada banyak ruang untuk menambahkan dukungan untuk fungsionalitas yang biasanya diperlukan.


5
2018-05-02 22:59



Berikut ini protokol alternatif:

u8  Sync          // A constant value which always marks the start of a packet
u16 Length        // Number of bytes in payload
u8  Data[Length]  // The payload
u16 Crc           // CRC

Gunakan RS232 / UART, karena PC (port serial) dan prosesor (UART) sudah dapat menangani itu dengan rewel minimum (hanya perlu MAX232 chip atau serupa untuk melakukan pergantian tingkat).

Dan menggunakan RS232 / UART, Anda tidak perlu khawatir tentang master / slave jika tidak relevan. Kontrol aliran tersedia jika diperlukan.

Perangkat lunak PC yang disarankan: baik tulis sendiri, atau Docklight untuk pemantauan dan kontrol sederhana (versi evaluasi gratis).

Untuk pengecekan kesalahan yang lebih besar, yang paling sederhana adalah pengecekan paritas, atau jika Anda membutuhkan sesuatu yang lebih kuat, mungkin pengkodean konvolusional.

Bagaimanapun, apa pun yang Anda lakukan: tetap sederhana!

EDIT: Menggunakan RS232 dengan PC bahkan lebih mudah daripada sebelumnya, karena Anda sekarang bisa mendapatkan konverter USB ke RS232 / TTL. Salah satu ujungnya masuk ke soket USB PC Anda, dan muncul sebagai port serial biasa; yang lain keluar ke 5 V atau 3,3 V sinyal yang dapat dihubungkan langsung ke prosesor Anda, tanpa memerlukan pemindahan tingkat.

Kami telah menggunakan TTL-232R-3V3 dari FDTI Chip, yang berfungsi sempurna untuk aplikasi semacam ini.


3



Satu-satunya saran saya adalah jika Anda memerlukan suara-tahan Anda mungkin ingin menggunakan RS-422/485 full-duplex. Anda dapat menggunakan IC yang serupa ini di sisi AVR, maka RS-232-> RS-422 konverter pada sisi PC seperti 485PTBR di sini. Jika Anda dapat menemukan atau membuat kabel berpelindung (dua pasang berpelindung berpilin) ​​maka Anda akan memiliki lebih banyak perlindungan. Dan semua ini tidak terlihat oleh mikro dan PC - tidak ada perubahan perangkat lunak.

Apa pun yang Anda lakukan memastikan bahwa Anda menggunakan sistem full-duplex dan pastikan garis baca / tulis diaktifkan ditegaskan pada IC.


2



Anda dapat melihat Telemetry dan implementasi desktop terkait dengan python Pytelemetry

Fitur utama

Ini adalah sebuah Protokol berbasis PubSub, tetapi tidak seperti MQTT itu adalah protokol point-to-point, tidak ada broker.

Seperti halnya protokol pubsub, Anda bisa menerbitkan dari satu ujung ke a topic dan diberi tahu di ujung lain tentang topik itu.

Di sisi yang melekat, penerbitan ke suatu topik sesederhana:

publish("someTopic","someMessage")

Untuk angka:

publish_f32("foo",1.23e-4)
publish_u32("bar",56789)

Cara mengirim variabel ini mungkin tampak terbatas, tetapi tonggak berikutnya bermaksud untuk menambahkan makna tambahan ke parsing topik dengan melakukan hal-hal seperti ini:

// Add an indexing meaning to the topic
publish("foo:1",45) // foo with index = 1
publish("foo:2",56) // foo with index = 2

// Add a grouping meaning to the topic
publish("bar/foo",67) // foo is under group 'bar'

// Combine
publish("bar/foo:45",54)

Ini bagus jika Anda perlu mengirim array, struktur data yang kompleks, dll.

Juga, pola PubSub sangat bagus karena fleksibilitasnya. Anda dapat membangun aplikasi master / slave, perangkat ke perangkat, dll.

Perpustakaan C GitHub version

Perpustakaan C sangat sederhana untuk ditambahkan pada perangkat baru apa pun selama Anda memiliki pustaka UART yang layak di atasnya.

Anda hanya perlu instanciate struktur data yang disebut TM_transport (didefinisikan oleh Telemetry), dan menetapkan 4 pointer fungsi read  readable  write  writeable.

// your device's uart library function signatures (usually you already have them)
int32_t read(void * buf, uint32_t sizeToRead);
int32_t readable();
int32_t write(void * buf, uint32_t sizeToWrite);
int32_t writeable();

Untuk menggunakan Telemetri, Anda hanya perlu menambahkan kode berikut

// At the beginning of main function, this is the ONLY code you have to add to support a new device with telemetry
TM_transport transport;
transport.read = read;
transport.write = write;
transport.readable = readable;
transport.writeable = writeable;

// Init telemetry with the transport structure
init_telemetry(&transport);  

// and you're good to start publishing
publish_i32("foobar",...

Perpustakaan Python PyPI version

Di sisi desktop, ada pytelemetrymodul yang mengimplementasikan protokol.

Jika Anda tahu python, kode berikut terhubung ke port serial, menerbitkan sekali pada topik foo, cetak semua topik yang diterima selama 3 detik kemudian berakhir.

import runner
import pytelemetry.pytelemetry as tm
import pytelemetry.transports.serialtransport as transports
import time

transport = transports.SerialTransport()
telemetry = tm.pytelemetry(transport)
app = runner.Runner(transport,telemetry)

def printer(topic, data):
    print(topic," : ", data)

options = dict()
options['port'] = "COM20"
options['baudrate'] = 9600

app.connect(options)

telemetry.subscribe(None, printer)
telemetry.publish('bar',1354,'int32')
time.sleep(3)

app.terminate()

Jika Anda tidak tahu python, Anda dapat menggunakan antarmuka baris perintah

Pytelemetry CLI PyPI version

Baris perintah dapat dimulai dengan

pytlm

Maka kamu bisa connect, ls(daftar) topik yang diterima, print data yang diterima pada suatu topik, pub(terbitkan) pada suatu topik, atau buka a plot pada suatu topik untuk menampilkan data yang diterima secara real-time

enter image description here

enter image description here


2



Mengenai pemeriksaan paritas (seperti muncul beberapa kali di sini):

Mereka kebanyakan tidak berguna. Jika Anda khawatir bahwa satu bit dapat diubah karena kesalahan, maka sangat mungkin bahwa bit kedua juga dapat berubah dan Anda akan mendapatkan false positive dari cek paritas.

Gunakan sesuatu yang ringan seperti CRC16 dengan tabel pencarian - itu dapat dihitung sebagai setiap byte diterima dan pada dasarnya hanya sebuah XOR. Saran Steve Melnikoff sangat bagus untuk mikro kecil.

Saya juga menyarankan untuk mentransmisikan data yang dapat dibaca manusia, daripada biner mentah (jika kinerja bukan prioritas pertama Anda). Ini akan membuat debugging dan log file jauh lebih menyenangkan.


1



Anda tidak secara spesifik menentukan bagaimana mikrokontroler berperilaku, tetapi apakah semua yang ditransmisikan dari mikro menjadi respons langsung terhadap perintah dari PC? Jika dilakukan maka sepertinya Anda dapat menggunakan protokol master / slave dari beberapa jenis (ini biasanya akan menjadi solusi yang paling sederhana). Jika kedua belah pihak dapat memulai komunikasi, Anda memerlukan protokol lapisan data tautan yang lebih umum. HDLC adalah protokol klasik untuk ini. Meskipun protokol penuh mungkin adalah berlebihan untuk kebutuhan Anda, Anda bisa misalnya setidaknya menggunakan format frame yang sama. Anda mungkin juga melihat PPP untuk melihat apakah ada bagian yang berguna.


0



mungkin pertanyaan ini bisa benar-benar bodoh tetapi ada yang menganggap penggunaan salah satunya X / Y / Z MODEM protokol?

Manfaat utama menggunakan salah satu protokol di atas adalah ketersediaan implementasi siap pakai dalam berbagai lingkungan pemrograman.


0