# সিরিয়াল কম্যুনিকেশন (সংক্ষেপ)

গত দুই পর্বে আমরা অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং সম্পর্কে হালকা পাতলা ধারণা লাভ করেছিলাম। আজকের বিষয়বস্তু হল সিরিয়াল কম্যুনিকেশন।

## যা যা লাগবে:

* `Arduino Board (Uno / Mega 2560)`
* `Arduino IDE` (-\_-)
* `Usb Cable`
* `Computer` (duh!)

## সিরিয়াল কম্যুনিকেশন (Serial Communication):

![alt text](https://dlnmh9ip6v2uc.cloudfront.net/assets/2/5/c/4/5/50e1ce8bce395fb62b000000.png)

সিরিয়াল কম্যুনিকেশন হল এমন একটি ব্যবস্থা যার মাধ্যমে আপনি আপনার প্রিয় বোর্ডের সাথে কথা বলতে পারেন। লিটারেলি কথা? না ঠিক তা নয়, আপনি কিছু ডেটা পাঠাবেন সে সেটাকে প্রসেস করবে তারপর সেও কিছু তথ্য পাঠাবেন সেটা আবার আপনি দেখতে পারবেন কিংবা প্রসেস করতে পারবেন। অনেকটা কথা বলার মতই শুধু ভাষাটা হল `0` আর `1`। আর এই কথা বলার জন্য আপনার অবশ্যই আরেকটা ডিভাইস দরকার যার সাথে আর্ডুইনো কানেক্টেড থাকতে পারবে এবং তার পাঠানো ডেটা সে বুঝবে।

সিরিয়াল কম্যুনিকেশন একটা মাধ্যম মাত্র। আরও অনেক ধরণের কম্যুনিকেশন সিস্টেম আছে, আর্ডুইনোতেই; কিন্তু সেগুলো আলোচনা করার সময় এখনো আসে নি। এই কোর্সে যতটুকু দরকার সেটুকুই শুধু “সংক্ষিপ্ত সংস্করণ” – এ থাকবে, যাতে জিনিসটা একঘেয়ে না হয় ও যতটা আলোচনা করা হয় ততটুকুই ভালভাবে শিখতে পারেন।

আমরা যখন আর্ডুইনো বোর্ড কনফিগার করছিলাম তখন দেখেছি সেটা একটা `COM Port` এ সংযুক্ত থাকে, যেমন `COM3, COM14` ইত্যাদি। এই পোর্টকে আমরা দরজাও বলতে পারি। যে দরজা দিয়ে ডেটা যাওয়া আসা করে। আমরা যে কোড আপ্লোড করি, চিন্তা করুন তো, কীভাবে আপ্লোড হয়? হ্যাঁ, সিরিয়াল কম্যুনিকেশনের মাধ্যমে, কম্পাইল্ড `.hex` ফাইলটা বিভিন্ন প্রসেসের মধ্য দিয়ে চিপে প্রবেশ করে। আর্ডুইনোর ক্ষেত্রে সিরিয়াল কম্যুনিকেশন এ সাহায্য করার জন্য `ATmega16u2` কিংবা `ATmega8u2` চিপটি কাজ করে। এখানে আরও অনেক জটিল ব্যাপার স্যাপার আছে।

তাহলে বুঝলাম ডেটা পাঠানোর একটা টার্ম হল `Serial`! কিন্তু ডেটা ট্রান্সফার কীভাবে হচ্ছে?

এই প্রশ্নের উত্তর দিতে গেলে আমাদের আরেকটু জ্ঞানলাভ করতে হবে। `Hardware` এর ক্ষেত্রে এই ডেটা ট্রান্সফার করার জন্য বেশকয়েকটি প্রোটকল আছে, এই প্রোটকল গুলোর মধ্যে সাধারণত সর্বাধিক ব্যবহৃত প্রোটকলটি হল `UART (Universal Asynchronous Receiver Transmitter)`। এই পদ্ধতিটা অনেক পুরাতন এবং পুরাতন বা নতুন সব চিপেই ব্যবহারযোগ্য।

`UART` তে `8-bit` ডেটা ট্রান্সফার করা হয়, একটা থাকে লো লেভেল স্টার্ট বিট এবং ৮ টা ডেটা বিটস ও আরেকটি হাই লেভেল স্টপ বিট। সিরিয়াল কম্যুনিকেশন চালু করার জন্য লো লেভেল স্টার্ট বিট ও হাই লেভেল স্টপ বিট ব্যবহার করা হয়।

`UART` এর আরেকটি সুবিধা, কোন নির্দিষ্ট ভোল্টেজ লেভেলে ডেটা ট্রান্সফার করতে হবে এমন কোন বাধ্যবাধকতা নেই।`3.3V` কিংবা `5V` যে লজিকেই আপনার `MCU` চলুক না কেন তাতেই হবে। এখানে গুরুত্বপূর্ণ একটি কথা বলার দরকার, আপনি যে ডিভাইসের সাথে যোগাযোগ করতে চাচ্ছেন এই প্রোটকলের মাধ্যমে, দুই ক্ষেত্রে `Transmission speed`\* সমান হতে হবে।

## `UART` এর মাধ্যমে ডেটা পাঠানো হয় যেভাবে:

![alt text](http://www-inst.eecs.berkeley.edu/~cs150/sp11/lab_5/images/UARTFrame.png)

ধরা যাক, `UART Protocol` এর মাধ্যমে আমি `“hello”` ওয়ার্ড টি `Boka` নামক `MCU` তে পাঠাতে চাচ্ছি। তাহলে আমি যখন পাঠাব তখন এর সাথে একটি `Start Bit` বা ট্যাগ লাগানো হবে যাতে অন্য ডিভাইসটি বুঝতে পারে ডেটা ট্রান্সফার শুরু হতে যাচ্ছে এবং ডেটা রিসিভ করার জন্য তার তৈরি হতে হবে। কথা হল ডেটা পাঠাবো আমি পিসি থেকে, তার কান খোলা রাখলেই তো হয়, তার জন্য তাকে আবার তৈরি হতে হবে কেন?

বাস্তবে আমরা অনেক সময় অনেকের কথা ঠিকমত বুঝি না, মোটমাট এর কারণ হতে পারে পাঁচটি

* হয় সে তাড়াতাড়ি কথা বলছে
* অথবা এত ধীরে কথা বলছে যে শোনার আগ্রহ হারিয়ে ফেলি তাই বুঝি না
* আমি বুঝিনা এমন ভাষায় কথা বলছে
* তার কথার কোন মানে নেই
* আরেকজন যখন কথা বলছে তখন আমি শুনছি না কিংবা আমি যখন কথা বলছি সে শুনছে না

`UART/USART` এর ক্ষেত্রে কম্যুনিকেশনে যে ঝামেলাটা হয় সেটা হল প্রথম দুইটা এবং শেষেরটা। `Serial Communication Establishment` এর জন্য একজনের বলার গতি ও আরেকজনের শোনার গতি সমান হতে হবে। যদি তা না হয়, তাহলেই `PC` একটা কথা বললে `Boka` বুঝবে উল্টাটা। কিংবা `PC` যখন কথা বলছে তখন `Boka` যদি কান খাড়া না করে বা vice versa না হলে ডেটা পাঠানো সম্ভব হবে না। **এইকারণে** `PC` **যখন ডেটা পাঠাচ্ছে তখন** `Boka` **কে রিক্যুয়েস্ট করছে তার ঘড়ি** `(Clock)` **টা যেন PC এর সাথে মিলিয়ে** `Synchronized` **করে নেয়।** ধরা যাক `Boka MCU` তার `Clock` ঠিকঠাক করে নিল এবং সে `“hello”` ডেটাটি নেওয়ার জন্য প্রস্তুত। আমরা যেহেতু প্রোগ্রামিংয়ে এক্সপার্ট B| তাই আমরা অনেক আগে থেকেই জানি যে `String` হল `char` টাইপের `Null Terminated Array` মাত্র। তাই `String` পাস করতে হলে একটা একটা করে ক্যারেক্টার পাঠাতে হবে আগে, তাই না?

এইবার ডেটা ট্রান্সফারের সময় যদি ঘড়ির ব্যাটারি চলে যায় এবং **দুইটা ঘড়ি** `Synchronized` **না হয়** তবে আবারও ডেটা ট্রান্সফারে সমস্যা হবে। পরীক্ষা করে(!) দেখা গেছে `PC` ও `Boka MCU` এর মধ্যে সুষ্ঠু ডেটা ট্রান্সফার করার জন্য তাদের **ঘড়িদ্বয় শতকরা ৮০ ভাগ Accurate হতে হবে।**

আবারও মূল কথা থেকে সরে আসার জন্য দুঃখিত। >:( যাকগে যেটা বলছিলাম আরকি, `Start bit` দিল এবং বলল আমি ডেটা পাঠাচ্ছি, এইবার `Boka MCU Clock` ঠিক করা মাত্র `PC` পাঠানো শুরু করল। এই ডেটাগুলোই হল সেই কাঙ্ক্ষিত ডেটা যেটা আমরা পাঠাতে চাচ্ছি। এগুলোকে আমরা আঁতলামি করলে বলব `LSB (Least Significant Bit)`। মাথায় রাখতে হবে প্রতিটা বিট পাঠানোর সময় পুরা এক, মানে যদি একটা বিট পাঠাতে ২ মাইক্রোসেকেন্ড লাগে তাহলে তার পরের বিট পাঠাতেও একই সময় লাগবে। **রিসিভার বা** `Boka MCU` **একটা নির্দিষ্ট টাইম পরপর চেক করে দেখবে কি বিট আসছে এবং এই সময়টা হবে PC এর বিট পাঠানোর পর্যায়কালের অর্ধেক সময় বা এই উদাহরণে ১ মাইক্রোসেকেন্ড।**

এখানে আবার একটা কথা আছে, `PC` তো আর জানে না `Boka MCU` কখন চেক করে, `PC` শুধু জানে কখন তার ট্রান্সমিশন শুরু করতে হবে এবং কতক্ষণ পরপর বিট পাঠাতে হবে।

বিট পাঠাতে পাঠাতে যখন পুরো `“hello”` টাই `PC` পাঠিয়ে দিল সে এবার `“hello”` এর লেজের সাথে একটা `Parity Bit` পাঠিয়ে দিতে পারে \[may but not will]। এই `Parity Bit` টা কিন্তু `Stop Bit` না, এটা হল `Error checking Bit`। এই বিট `Receiver [Boka MCU] Error` চেকিংয়ের কাজে ব্যবহার করতে পারে। `Parity Bit` পাঠানোর পরপরই সে একটা `Stop Bit` পাঠিয়ে দেবে।

এই `Parity Bit` টা জেনারেট করার দায়িত্ব `Transmitter` এর কিন্তু `Parity Bit` টা কি হবে, ব্যবহার করা হবে কি হবে না সেটা নির্ভর করে `PC` ও `Boka MCU` এর সমঝোতার উপর। এখন ধরি সম্পূর্ণ `word` পাঠানোর পর যথাসময়ে `Boka MCU Stop Bit` টি পায় নি। তাহলে `Boka MCU` বোকার মত (নাকি চালাকের মত?) যতটুকু ডেটা পেয়েছে সম্পূর্ণটাই গার্বেজ ভ্যালু হিসেবে ধরবে এবং `Framing Error`\* দেখাবে।

তাই `UART Protocol` এর জন্য সবকিছু কনফিগার করে নেওয়াই ভাল। কারণ `UART` অটোমেটিক্যালি সবকিছু সেট করে নিতে পারে না, আর যদি `Sender` ও `Receiver` কে `Identically configure` না করা হয় তাহলে `Start, Stop কিংবা Parity Bit` এগুলো হোস্টে পাস হয় না।

আবারও ধরি `“hello”` ভালভাবেই গেল, কিন্তু আমি এখন `“world”` পাঠাব, তাহলে কী করব? কিছু করা লাগবে না, কনফিগারেশন ঠিক থাকলে খালি পাঠালেই হবে, `PC` আবারও একটা `Start Bit` পাঠিয়ে বলবে আরেকটি ডেটা আসছে রেডি হও এবং `Stop Bit` পাঠিয়ে বলবে ডেটা পাঠানো শেষ।

তাই যখন ডেটা পাঠানো হয় না তখন `Transmission line` কে `অলস লাইন` বলতে আপত্তি নেই। `USART` প্রায় একই ভাবে কাজ করে কিন্তু এর কাজের ধরণ একটু আলাদা এবং উন্নত। `USART` নিয়ে আরেকটি পরিচ্ছদে কথা বলা যাবে।

যাই হোক সিরিয়াল কম্যুনেকশন নিয়ে আমরা অগাধ জ্ঞানলাভ করলাম, চলুন দেখি এটাকে এবার অ্যাপ্লাই করতে পারি কিনা।

## আর্ডুইনোতে সিরিয়াল কম্যুনিকেশন:

আর্ডুইনোতে সিরিয়াল কম্যুনিকেশন তৈরি করা অনেক সহজ, এর কারণ অনেকগুলো, তার মধ্যে দুইটা কারণ হল সিরিয়াল কম্যুনিকেশনের জন্য ডেডিকেটেড `ATmega8u2` বা `ATmega16u2` চিপ এবং `Arduino.h` ফাইলটা। B|

আমরা শুধু দেখব সিরিয়াল কম্যুনিকেশনের মাধ্যমে কীভাবে পিসির সাথে আর্ডুইনো কথা বলতে পারে। তাহলে ঝটপট নিচের কোডটি কপি পেস্ট করে `Arduino IDE` তে বসিয়ে দিন। আমিও জানি আপনিও জানেন যে কোডটা নিজে লেখার মত সময় আপনার নাই, সময় না থাকলে কি করা; কপি পেস্ট করেন, আপনার ক্ষতি হইলে আমার কি :P

**কোডটা আপ্লোড করুন এবং আর্ডুইনো বোর্ড কানেক্টেড রাখুন!**

```
const int led = 13;
char command;

void setup() {
  Serial.begin(9600);
  Serial.println("Ready for command\nEnter A/a to turn on\nEnter other keys to turn off");
  pinMode(led, OUTPUT);
}

void ledOn()
{
  Serial.println("Led On!");
  digitalWrite(led, HIGH);
}

void ledOff()
{
  Serial.println("Led Off!");
  digitalWrite(led, LOW);
}


void loop() {
  if (Serial.available()){
    command = Serial.read();
    if (command == 'a' || command == 'A') ledOn();
    else ledOff();
  }
}
```

## আউটপুট:

![alt text](http://i.imgur.com/4WmUgyH.gif)

আউটপুট আরকি, নিজেই দেখে নিন।

## প্রোগ্রাম Walkthru:

**যেগুলোর ব্যাখ্যা দেওয়া নাই মনে হচ্ছে, পূর্বের পোস্টগুলোতে দেওয়া হয়েছে।**

### Line 5:

```
Serial.begin(9600);
```

`OOP` এর সূত্রমতে পাই, `Serial` হল একটি অবজেক্ট যার Definition `“Arduino.h”` হেডার ফাইলটিতে দেওয়া আছে। `begin` হল `Serial` এর একটি মেথড। `OOP` এর সময় বলেছিলাম, কোন অবজেক্টের মেথড ডাকার জন্য `objectName.methodName(parameter)` এই রুল ফলো করতে হয়। এখানেই ঠিক তাই করা হয়েছে, `begin` এর কাজ হল `Serial communication establish` করা।

`begin` মেথডে আমরা একটি ইন্টিজার ভ্যালু দেখতে পাচ্ছি `9600`! এটি হল `Baud Rate`। মানে কত স্পিডে আর্ডুইনো পিসির সাথে কথা বলবে? `UART` এর ক্ষেত্রে আমরা জানি স্পিড সমান না হলে ঝামেলা তাই আমরা আর্ডুইনো বোর্ডের স্পিড ঠিক করে দিলাম। আর পিসির স্পিড ঠিক করলাম `Serial Monitor` এর মাধ্যমে ;)

### Line 6:

```
  Serial.println("Ready for command\nEnter A/a to turn on\nEnter other keys to turn off");
```

`println` -> এই ফাংশনের কাজ হল সিরিয়াল মনিটরে কিছু প্রিন্ট করা। অর্থাৎ কিনা `printf(“Hello world”)` এর আর্ডুইনো `Serial comm` ভার্সন B|। `print` কমান্ড ও একই কাজ করবে তবে `println` ফাংশনটি কিছু প্রিন্ট করার পাশাপাশি একটা Enter বসিয়ে দেবে বা নিউলাইন প্রিন্ট করবে। যাতে আমাদের পড়তে সুবিধা হয়।

অর্থাৎ `println("blablabla")` হল `print("blablabla\n")` এর সমতুল্য।

### Line 11:

```
void ledOn()
{
  Serial.println("Led On!");
  digitalWrite(led, HIGH);
}
```

এই ফাংশনটির কাজ হল সিরিয়ালে সে প্রিন্ট করবে “বাত্তি জ্বালাইসি” ও বাত্তি জ্বালিয়ে দেবে। পরের ফাংশনটি কি করবে সেটা অনুমান করুন (বাড়ির কাজ) :P

### Line 24:

```
  if (Serial.available()){
```

এই `available` মেথডের কাজ হল চেক করে দেখা, আর্ডুইনো কি ডেটা গ্রহণে তৈরি কিনা? যদি হয় তাহলে তাকে পাঠাব নইলে নয়। আরও একটি মানে আমরা বের করতে পারি, `available()` মেথডের রিটার্ন টাইপ `boolean` বা `bool`।

### Line 25:

```
    command = Serial.read();
```

অর্থাৎ, সিরিয়ালে যদি আমি কিছু ইনপুট দেই তা আর্ডুইনো পড়ে `command` নামক ভ্যারিয়েবলে রাখবে। তারমানে `read()` মেথডের রিটার্ন টাইপ `char` (আপাতত এটাই জেনে রাখুন)

### Line 26 ও Line 27:

```
    if (command == 'a' || command == 'A') ledOn();
    else ledOff();
```

যদি সিরিয়ালে যেটা পাইসি সেটা `a` বা `A` এর সমান হয় তাহলে বাত্তি জ্বালাও। নইলে বাত্তি নিভাও :D

### একনজরে পুরো প্রোগ্রাম:

* একটা ধ্রুব সংখ্যা ১৩ নিলাম যার নাম led
* একটা ক্যারেক্টার টাইপ ভ্যারিয়েবল নিলাম যার নাম `command`
* `Serial communication` চালু করলাম `9600 bits per sec` স্পিডে
* `led` কে আউটপুট বানালাম
* একটা ফাংশন তৈরি করলাম `ledOn` নামে যার কাজ বাত্তি জ্বালানো ও আমাকে জানানো বাত্তি জ্বলেছে কিনা
* আরেকটা ফাংশন তৈরি করলাম `ledOff` নামে যার কাজ বাত্তি নিভানো ও আমাকে জানানো বাত্তি নিভেছে কিনা
* ইনফিনিটি লুপে প্রবেশ:
* যদি সিরিয়াল পাই, তাহলে সিরিয়ালে যা ইনপুট দেয় তা `command` এ রাখলাম
* `command` যদি `a` বা `A` এর সমান হয় তাহলে `ledOn()` ফাংশনরে ডাক দে
* যদি তা না হয় তাহলে `ledOff()` ফাংশনরে ডাক দে

সিরিয়াল নিয়ে ব্যাপক জ্ঞান দিলাম, পরবর্তীতে `ADC` এর সময় কাজে দেবে। তখন আমরা আরও নতুন কিছু দেখব।

## নোট:

### Baud Rate:

এর মানে কত বিট হারে ডেটা পাস হচ্ছে। `Arduino` বা সাধারণত ডিভাইসগুলোর `Baud Rate` হয় `9600 bits per second`। আর্ডুইনোর সর্বোচ্চ `Baud Rate 115200 bits per second`।

### Framing Error:

যদি `PC` ও `MCU` তে সিঙ্ক্রোনাইজেশন জাতীয় সমস্যা দেখা যায় কিংবা ডেটা সিগনাল `Interrupted` হয় তখন এই সমস্যাটা দেখায়।

## সচরাচর জিজ্ঞাস্য প্রশ্ন \[F. A. Q]

### Serial Monitor কী জিনিস? কী কাজে লাগে?

> ইয়ে Serial দেখার কাজে লাগে B|। সিরিয়াল মনিটর অনেক কাজে লাগে, সিরিয়ালে ডেটা পাঠানো, সিরিয়ালে নামক ওয়ালে ডিভাইসটা কি স্ট্যাটাস দিল তা দেখা যায়। কমান্ড পাঠানো যায়। ইত্যাদি কাজ করার জন্য `Serial Monitor` লাগে, আর্ডুইনোর বিল্ট-ইন সিরিয়াল মনিটর ছাড়াও অনেক ফ্রি ও ওপেনসোর্স সিরিয়াল মনিটর আছে বহুত ফাংশনসহ। আপাতত আমাদের তেমন ফিচার লাগে নাই বলে আমরা আর্ডুইনোর বিল্ট-ইন সিরিয়াল মনিটর ব্যবহার করছি।

### Serial Communication এর উপকারিতা কী?

> উপকারিতার কথা বলতে পারব না কিন্তু অপকারিতা নাই সেটা জানি :P। `Sensor checking`, `wireless/wired data transmission`, `interfacing` কিসে লাগে না সেটা বলেন! আস্তে আস্তে উপকারিতা বুঝতে পারবেন আশা রাখি।

### টাইটেলটা বুঝলাম না “সিরিয়াল কম্যুনিকেশন (সংক্ষিপ্ত সংস্করণ)” –  মানে??

> মানে হল এখানে যা আলোচনা করা হয়েছে তা `Serial communication` এর ধারেকাছেও নাই, এর যে ৪-৫ টা প্রোটকল আছে তার প্রত্যেকটা নিয়ে বিশাল বিশাল বই লেখা সম্ভব। বাকি প্রোটকলগুলো আপাতত লাগছে না বলেই সেগুলো এখান থেকে বাদ দেওয়া হয়েছে। আরেকটা সংস্করণ করে সেখানে বাকি প্রোটকল নিয়ে হালকা আলোচনা করার ইচ্ছা আছে।

আপাতত এই পর্যন্তই, পরের পরিচ্ছদে আমরা `ADC` শিখব!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://arduino.howtocode.dev/basic_ideas/serialcomm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
