Semua perangkat mikrokontroler saya yang berkomunikasi dengan PC melalui UART menggunakan string ASCII untuk mengirim perintah dan menerima data (seperti yang diterapkan dalam Arduino). Itulah yang saya pelajari ketika saya mulai menggali ke dalam elektronik dan saya selalu merasa mengirim string kosong sudah cukup. Namun saya perhatikan bahwa sebagian besar perangkat yang saya temui menggunakan protokol biner canggih yang mencakup kode fungsi, alamat, dan pengecekan kesalahan CRC.
Kapan komunikasi dasar ASCII dapat diterima dan kapan saya harus mempertimbangkan sesuatu yang lebih maju, seperti Modbus? Apakah perangkat komersial menggunakan ASCII seperti itu? Industri?
microcontroller
serial
communication
uart
protocol
Saya tidak tahu apa yang saya lakukan
sumber
sumber
Jawaban:
ASCII dan CRC tidak saling eksklusif. ASCII adalah penyandian, dan CRC untuk pengecekan kesalahan.
APA SAJA dapat dikirim sebagai ASCII. Kami orang tua tentu ingat UUEncoding, yang mengubah apa pun menjadi string ASCII.
A) Bagi saya, biasanya masalah kecepatan dan efisiensi. Mengirim nomor 32-bit besar oleh ASCII dapat memakan waktu lama, tetapi hanya perlu 4 byte untuk mengirimkannya sebagai biner melalui protokol serial.
B) Mengirim ANGKA melalui ASCII berarti Anda harus mengonversi nomor tersebut ke ASCII, yang merupakan langkah ekstra yang jelas (ini adalah bagian dari apa yang dilakukan "printf").
Jika Anda entah bagaimana kehilangan tempat Anda, mengacaukan, kehilangan format, mendapatkan endian yang salah, dll, protokol komunikasi biner pasti dapat mengacaukan. Jika Anda mengirim ASCII, akan lebih mudah untuk pulih dari kekacauan hanya dengan masuk dan MELIHAT aliran data.
sumber
Berikut ini beberapa pemikiran tentang hal itu:
sumber
Pada tingkat paling sederhana, Anda bisa mengatakan protokol komunikasi sederhana memiliki tiga lapisan: fisik, transportasi, dan aplikasi. (Ada model dengan lebih banyak seperti OSI dengan 7 atau TCP / IP dengan 4. Jumlah lapisan tidak terlalu penting dalam konteks pertanyaan ini.)
Lapisan aplikasi adalah lapisan yang Anda tangani langsung dalam kode Anda, dan fokus pertanyaan. Sejauh menyangkut lapisan transport, byte yang Anda lewati di send_data hanyalah pola biner, tetapi Anda dapat menafsirkannya dalam kode aplikasi Anda sebagai huruf 'A'. Perhitungan CRC atau checksum akan sama terlepas dari apakah Anda menganggap byte sebagai 'A,' 0x41, atau 0b01000001.
Lapisan transport adalah level paket, di mana Anda memiliki header pesan Anda, dan pengecekan kesalahan, apakah itu CRC atau checksum dasar. Dalam konteks firmware, Anda mungkin memiliki fungsi seperti send_data, tempat Anda mengirimkan byte untuk dikirimkan. Di dalam fungsi itu dimasukkan ke dalam paket yang mengatakan, "Hei ini adalah pesan normal, memerlukan pengakuan, dan checksumnya adalah 0x47, waktu saat ini adalah X." Paket ini dikirim melalui lapisan fisik ke node penerima.
Lapisan fisik adalah tempat elektronik dan antarmuka didefinisikan: konektor, level tegangan, timing, dll. Lapisan ini dapat berkisar dari beberapa jejak yang menjalankan sinyal TTL untuk UART dasar pada PCB, hingga pasangan diferensial sepenuhnya terisolasi seperti pada beberapa Implementasi BISA .
Pada node penerima, paket masuk pada lapisan fisik, dibongkar pada lapisan transport, dan kemudian pola biner Anda tersedia untuk lapisan aplikasi. Terserah lapisan aplikasi simpul penerima untuk mengetahui apakah pola itu harus ditafsirkan sebagai 'A,' 0x41, atau 0b01000001, dan apa yang harus dilakukan dengannya.
Kesimpulannya, mengirimkan karakter ASCII cukup banyak dapat diterima jika itu yang diperlukan oleh aplikasi. Yang penting adalah memahami skema komunikasi Anda, dan memasukkan mekanisme pengecekan kesalahan.
sumber
Poin yang belum disebutkan adalah bahwa apakah seseorang menggunakan ASCII atau protokol biner, mengirimkan karakter rub-out sebelum setiap paket akan memastikan bahwa bahkan jika noise garis atau kesalahan pembingkaian muncul sebelum dimulainya paket, semua karakter setelah digosok out akan dibingkai dengan benar tanpa adanya kebisingan lebih lanjut. Jika tidak, jika seseorang mengirim paket secara terus menerus dan tidak menyertakan karakter apa pun yang dijamin untuk mencapai sinkronisasi ulang, mungkin saja satu kesalahan dapat merusak semua yang terjadi hingga jeda transmisi berikutnya. Karakter 0xFF bagus karena menjamin bahwa setiap penerima akan dapat melakukan sinkronisasi ulang pada karakter berikut.
(*) 0xFF - disebut rub-out karena seseorang yang mengetik karakter yang salah saat mengetik data ke pita kertas dapat menekan tombol "step tape backward" dan menekan rub-out untuk mengganti karakter yang dilubangi dengan 0xFF, yang akan diabaikan oleh sebagian besar penerima).
sumber
Salah satu keuntungan mengirim string ASCII adalah bahwa kode kontrol kemudian dapat digunakan untuk memberi sinyal awal / akhir pesan. misalnya STX (char 2) dan ETX (char 3) dapat menandakan mulai transmisi dan transmisi akhir. Atau Anda dapat menambahkan umpan garis sederhana untuk menandai akhir transmisi.
Saat mengirim data biner, ini menjadi lebih rumit karena tidak ada pola bit tertentu yang dapat dicadangkan untuk kode kontrol (tanpa overhead atau kompleksitas tambahan) karena byte data yang valid mungkin memiliki pola yang sama.
sumber
ASCII baik-baik saja, saya menggunakannya di hampir semua proyek. Itu membuat debugging lebih mudah untuk memantau port, dan itu hanya akan menjadi masalah jika ada banyak data untuk dikirim.
Bonus lain, saya menggunakan perangkat radio serial untuk mendapatkan pesan di antara arduinos, dan saya bisa menggunakan monitor serial yang terhubung ke laptop saya dan menyuntikkan pesan untuk membuat hal-hal tertentu terjadi. Bagus untuk pengujian.
Selain itu, mengirimkan hal-hal sebagai biner bukan tidak mungkin untuk di-debug dan tergantung pada alat Anda, Anda dapat memiliki biner yang diekstraksi dan dikonversi menjadi sesuatu yang dapat dibaca manusia. Atau jika Anda tahu apa yang Anda cari, Anda dapat secara visual memeriksa datastream dan mengenali nilai-nilai di mana mereka seharusnya dan kesalahan menemukan cara itu, meskipun, tidak begitu mudah. yaitu, Anda akan mengenali pola byte dan mengenali nilai yang diharapkan
sumber
Alih-alih Modbus pertimbangkan HDLC . Anda mendapatkan deteksi kesalahan (yang penting pada saluran serial berisik). Sinkronisasi kuat, melarikan diri kuat.
Saya telah menggunakan HDLC di jaringan RS-485 tanpa masalah dan PPP juga menggunakannya.
sumber
ASCII atas UART adalah yang paling populer sebagian karena:
Itu dapat dibaca manusia saat debugging (saya belum melihat penganalisa logika yang tidak mendekode ASCII).
Ini sangat mudah diimplementasikan, Anda punya tabel ASCII melalui google cepat yang terstandarisasi dengan baik.
Ini telah membangun sinkronisasi dengan bit start / stop.
Hampir seluruh dunia hobbyst telah mengatur dirinya sendiri dengan ASCII melalui serial, jadi setiap metode baru harus berurusan dengan itu, dan itu tidak mudah dengan cara apa pun.
Kemudian Anda masuk ke situasi ketika Anda mulai mengirim pengkodean tertentu, seperti mengirim representasi dalam memori float dibandingkan dengan mengkonversi float ke ASCII, mengirimkannya melalui serial yang bisa lebih dari 4 byte, dan kemudian mengubahnya kembali ke representasi dalam memori pada host. Sebagai gantinya, Anda hanya mengirim representasi 4 byte setiap waktu. Tentu, Anda dapat mulai menangani pengodean sendiri, tetapi kemudian Anda perlu mengatur tag awal / akhir, pesanan, dll.
Sebaliknya, hal-hal seperti Protobuf dapat digunakan. Ini sebenarnya digunakan dalam proyek yang saya kerjakan dan itu sangat bermanfaat, itu pesan panjang variabel, menangani endian untuk Anda, dan beberapa fitur keren lainnya. Ukuran kode juga tidak terlalu besar, dan Anda dapat menentukan semuanya untuk dialokasikan secara statis saat startup. Anda harus melempar checksum sendiri, jika Anda membutuhkannya.
sumber