RTC・Bluetooth
1.RTC
1.1. RTCの概要
RTCの正式名称は「Real-Time Clock」で、リアルタイムクロックチップを意味します。リアルタイムクロックチップは、ピンを通じて外部に時間の読み書きインターフェースを提供し、通常は独立したバッテリーで駆動されます。これにより、外部システムの電源が切れた場合でも、チップ回路が正常に動作し、時間が正確に刻まれることを保証します。クロックチップによって内部メカニズムは異なりますが、Linuxシステムのドライバは異なるクロックチップの操作の詳細をカプセル化し、アプリケーションに統一された時間操作インターフェースを提供しています。
1.1.1 開発ボードのRTCリソース
EASY EAI Nano-TBには、デフォルトでRTC回路が【搭載されていません】。ベースボードでRTC機能をサポートしたい場合は、当社のRTCモジュールを使用して【拡張】することができます。

開発ボードのRTCリソース
RTC拡張の具体的な手順:
【まず】ベースボードの【電源を切り】、モジュールを【表を上にして】ベースボードの40PINインターフェースに挿入します。詳細は下図をご参照ください。

開発ボードのRTCリソース
しっかりと挿入した後、【電源を入れます】。 lsコマンドを使用して、RTCチップがシステムに認識されているか確認できます。
ls /dev/rtc\*
開発ボードのRTCリソース
ドライバが正常にロードされたことを確認した後、以下のコマンドでドライバにアクセスし、RTCチップの全情報を読み取ることができます。
cat /proc/driver/rtc
開発ボードのRTCリソース
1.1.2 RTC時間の読み書き
ここには、RTCチップクロックとシステムクロックの2つのクロックが関与します。RTCクロックの手動管理の本質は、クロックの同期です(システムクロックをRTCチップクロックに同期させるか、RTCチップクロックをシステムクロックに同期させるかのいずれかです)。
システムクロック:
システムクロックの本質は64ビットの整数であり、この整数は現在のEpochTimeとの時間差(秒単位)を表し、タイムスタンプと呼ばれます。このクロックはCPUメインチップのタイマーによって維持され、CPUの電源が切れると時間情報は失われます。オペレーティングシステムのクロックコマンドはdate です。
date # システム時間の照会date -s "2023-09-20 11:18:00" # システム時間の変更💡 注意 :Epoch Time 特定の時間を指します。1970年1月1日0時0分0秒です。現在が1970年1月1日0時0分0秒からN秒経過していると仮定すると、Linuxシステム内での時間値はNとなります。
RTCチップクロック: RTCチップ内部で維持されている時間です。システムの電源が切れた後は、バッテリーによって電力が供給されます。そのため、システムの電源が切れてもRTC時間は正常に進み続けます。RTCチップクロックの役割は、Linuxが稼働していない時でも時間情報を保持することです。
チップクロックからシステムクロックへの同期:
sudo hwclock --hctosysシステムクロックからチップクロックへの同期(または sudo hwclock -w)
sudo hwclock --systohcシステムクロックに同期させず、RTCチップクロックのみを照会したい場合は、以下のコマンドを使用します。
sudo hwclock -r
チップクロックからシステムクロックへの同期:
1.1.3 システムクロックの読み書き
本ドキュメントでは【RTCクロック】**に重点を置いて説明しています。
1.1.4 タイムゾーンと時刻同期サービス
-
タイムゾーン: 【RTCクロック】と【システムクロック】はどちらもUTC時間を使用しています。異なる地域で使用される時間については、タイムゾーンの影響を考慮する必要があります。
-
時刻同期サービス: 【RTCクロック】は手動で操作できるだけでなく、時刻同期サービスの影響も受けます。
1.2. クイックスタート
1.2.1 開発環境の準備
PC側のUbuntuシステムで runスクリプトを実行し、EASY-EAIコンパイル環境に入ります。詳細は以下の通りです。
cd ~/develop_environment1.2.2 ソースコードのダウンロードとサンプルのコンパイル
まず、仮想マシンのバックグラウンドターミナルで以下のコマンドを実行し、周辺機器サンプルソースコードの管理ディレクトリを作成します:
cd /optmkdir -p EASY-EAI-Nano-TB/demoサンプルプログラムをダウンロードします:
例えば、サンプルプログラムを「PC\D:」(指定はありません。ユーザーの任意の場所で構いません)にダウンロードします。
その後、ダウンロードしたサンプルを仮想マシンのファイルシステムにコピーします。手順は下図をご参照ください。

ソースコードのダウンロードとサンプルのコンパイル
最後に、該当するサンプルのディレクトリに移動してコンパイル操作を実行します。具体的なコマンドは以下の通りです:
cd EASY-EAI-Nano-TB/demo/12_RTC./build.sh💡 注意 :依存ライブラリはボード上に配置されているため、クロスコンパイル中は/mnt のマウントを維持する必要があります。

ソースコードのダウンロードとサンプルのコンパイル
コンパイルが成功すると、Release ディレクトリに test-rtcという実行可能プログラムが生成され、開発ボードの /userdata/ディレクトリに自動的に配置されます。
1.2.3 サンプルの実行
シリアルポートデバッグまたはSSH経由でボードのバックグラウンドにアクセスし、サンプルが配置されているディレクトリに移動します:
cd /userdata
サンプルの実行
以下のコマンドを実行してサンプルを起動します。
sudo ./test-rtc実行結果は以下の通りです。

サンプルの実行
1.3. C言語での使用例
RTCのC言語での使用例です。コードのパスは 12_RTC/test-rtc/main.c です。コーディングの参考にしてください。以下のコードは、RTCクロックの読み書き操作のフローを示しています:
int main(int argc, char const *argv[]){ const char *strDateTime = "2023-09-21 15:22:37";
// 文字列をtm構造体タイプの時間情報に変換する struct tm tm = {0}; strptime(strDateTime, "%Y-%m-%d %H:%M:%S", &tm);
// RTCデバイスを開く int rtc_fd = open("/dev/rtc0", O_RDWR); if (rtc_fd < 0) { perror("open RTC device /dev/rtc0 faild."); close(rtc_fd); return -1; }
printf("---パラメータ設定前の日時---\n"); system("date");
/*** 1. ネットワーク時刻同期サービスを停止 ***/ system("systemctl stop ntp.service");
/*** 2. 事前に設定した時間を【RTCクロック】に書き込む ***/ struct rtc_time rtc_tm; rtc_tm.tm_sec = tm.tm_sec; rtc_tm.tm_min = tm.tm_min; rtc_tm.tm_hour = tm.tm_hour; rtc_tm.tm_mday = tm.tm_mday; rtc_tm.tm_mon = tm.tm_mon; rtc_tm.tm_year = tm.tm_year; if (ioctl(rtc_fd, RTC_SET_TIME, &rtc_tm) < 0) { perror("set data time to rtc0"); perror("RTC時間の設定に失敗しました"); close(rtc_fd); return -1; }
/*** 3. 【RTCクロック】を【システムクロック】に同期させる ***/ // 先ほど書き込んだRTCクロックパラメータを読み出す if (ioctl(rtc_fd, RTC_RD_TIME, &rtc_tm) < 0) { perror("RTC時間の読み取りに失敗しました"); close(rtc_fd); return -1; } close(rtc_fd);
tm.tm_sec = rtc_tm.tm_sec; tm.tm_min = rtc_tm.tm_min; tm.tm_hour = rtc_tm.tm_hour; tm.tm_mday = rtc_tm.tm_mday; tm.tm_mon = rtc_tm.tm_mon; tm.tm_year = rtc_tm.tm_year; struct timeval tv; tv.tv_sec = mktime(&tm); tv.tv_usec = 0;
// システムクロックに時間を同期 if(0 != settimeofday(&tv, (struct timezone *)0)){ perror("システム時間の設定に失敗しました"); }
printf("---パラメータ設定後の日時---\n"); system("date");
return 0;2.Bluetooth
2.1. Bluetoothの概要
Bluetoothプロトコルスタックにおいて、Bluetoothのデータ転送には主に2つのプロトコルが使用されます。SPP(クラシックBluetoothシリアルポートプロトコル)とBLE(Bluetooth Low Energy プロトコル)です。
-
シングルモードBluetoothモジュール: SPPまたはBLEのいずれか一方のみをサポートします。
-
デュアルモードBluetoothモジュール: SPPとBLEの両方を同時にサポートします。
EASY-EAI-Nano-TBで採用されているBluetoothモジュールはDB37であり、これは【BLEプロトコルのみをサポートする】【シングルモード】のBluetoothモジュールです。
2.1.1 BlueZ
BlueZは現在最も成熟したオープンソースのBluetoothプロトコルスタックであり、GNU General Public License (GPL)に基づいてリリースされたオープンソースプロジェクトです。Linux公式のBluetoothプロトコルスタックとなっており(Linux2.4.6からLinuxカーネルの一部となっています)、主要なLinuxディストリビューションで広く応用されています。 つまり、「Linux上でどのようにBluetoothを使用するか?」=「どのようにBlueZを使用するか?」と理解して差し支えありません。
具体的に言うと、BlueZはLinuxが公式にサポートするオープンソースのBluetoothプロトコルスタック処理ツールセットであり、以下のツールが含まれています: bccmd, bluemoon, bluetoothctl, bluetoothd, btattach, btmon, ciptool, hciattach, hciconfig, hcidump, hcitool, hex2hcd, l2ping, l2test, mpris-proxy, rctest, rfcomm, sdptool。
2.1.2 事前準備
まず、BlueZをインストールします。
apt-get install bluezBlueZが正常にインストールされたか確認します:
bluetoothctl -v以下のようにバージョン番号が出力されれば、BlueZは正常にインストールされています。

事前準備
hciconfigツールを利用することで、Bluetoothデバイスが正常に動作しているか確認できます。
hciconfig -a
事前準備
2.2. Bluetoothツール
hci*系のツールは一般的にBluetoothプロトコルスタックのHCI層を直接操作するために使用されますが、新しいバージョンのBlueZツールセットでは徐々にメンテナンスされなくなっています。現在、Bluetoothデバイスを操作するための主流ツールは、bluetoothdおよび bluetoothctl です。
2.2.1 bluetoothd
これはBluetoothドライバを管理するための【アプリケーション層】のサービスであり、基本的には起動しておくだけで問題ありません。psコマンドを使用して、バックグラウンドで起動しているか確認できます:
sudo ps -ef \| grep -i bluetoothd
bluetoothd
Ubuntuシステムでは、このプロセスを手動で起動・停止する必要はありません。systemctlサービスを通じて bluetoothd を管理します。bluetoothdサービスの起動/停止およびステータス確認のコマンドは以下の通りです:
sudo systemctl status bluetooth.service ## bluetoothdサービスのステータスを確認sudo systemctl start bluetooth.service ## bluetoothdサービスを起動(再起動後は状態が保存されません)sudo systemctl stop bluetooth.service ## bluetoothdサービスを停止(再起動後は状態が保存されません)sudo systemctl enable bluetooth.service ## サービスを有効化(デバイス再起動後、bluetoothdが自動起動します)sudo systemctl disable bluetooth.service ## サービスを無効化(デバイス再起動後、bluetoothdは自動起動しません)2.2.2 bluetoothctl
D-Busを介して bluetoothd とやり取りするツールであり、bluetoothdサービスのクライアントに相当します。bluetoothctl は bluetoothdを介して間接的にBluetoothハードウェアを操作します。bluetoothctlにはシェルインタラクション機能が内蔵されており、コマンドラインで直接 bluetoothctlツールを実行すると、このツールの内部シェルに入ることができます。

bluetoothctl
helpと入力すると、このツールでサポートされているコマンドを確認できます。

bluetoothctl
Bluetoothチップの電源を入れるコマンド:
power on
Bluetoothチップの電源を入れるコマンド:
advertiseサブメニューに入る: チップの名前を変更し、他のBluetoothマスター(ホスト)からスキャンして発見できるようにします。
menu advertisename EASY-EAI-Nano-TB
advertiseサブメニューに入る:
その後、back コマンドで上位メニューに戻ります:
back2.3. BLEプロトコル通信
BLE (Bluetooth Low Energy) はGATTに基づいています。
2.3.1 開発ボードをマスター(ホスト)とする場合
まず、【スマートフォン】のBluetoothデバッグアシスタントアプリを【スレーブとして設定】します:スレーブモードをオンにし、アドバタイズ(ブロードキャスト)を開始します。

開発ボードをマスター(ホスト)とする場合
次に、開発ボード側(bluetoothctl 内)で【スキャンの開始】、【スキャンの停止】、【デバイスの接続】を行います。
スキャンの開始:
scan onターゲットデバイスを発見した後、スキャンを停止:
scan offスキャンされたデバイスを一覧表示(MACアドレスを見つける):
devicesターゲットデバイスとのペアリング、信頼(Trust)、接続:
pair xx:xx:xx:xx:xx:xxtrust xx:xx:xx:xx:xx:xxconnect xx:xx:xx:xx:xx:xxBluetooth接続が成功した後、Bluetoothマスター(開発ボード)で gatt サブメニューに入ります:
menu gattキャラクタリスティック属性を確認:
list-attributes(【BLEデバッグアシスタントアプリ】から、fff1 は【スレーブの送信】用、fff2 は【スレーブの受信】用であることがわかります)
スレーブ送信のキャラクタリスティック属性は以下の通りです:
Characteristic (Handle 0x0000) /org/bluez/hci0/dev_78_C3_C4_C4_94_8D/service002f/char0030 0000fff1-0000-1000-8000-00805f9b34fb Unknownスレーブ受信のキャラクタリスティック属性は以下の通りです:
Characteristic (Handle 0x0000) /org/bluez/hci0/dev_78_C3_C4_C4_94_8D/service002f/char0034 0000fff2-0000-1000-8000-00805f9b34fb Unknown2.3.1.1 マスター受信、スレーブ送信
まず、fff1 を選択します。
select-attribute /org/bluez/hci0/dev_78_C3_C4_C4_94_8D/service002f/char0030次に、通知(notify)をオンにします。
notify on
マスター受信、スレーブ送信
その後、アプリを操作して、1ByteのHexデータを開発ボードへ送信します。
)
マスター受信、スレーブ送信
2.3.1.2 マスター送信、スレーブ受信
属性を fff2 に変更して選択します。
select-attribute /org/bluez/hci0/dev_78_C3_C4_C4_94_8D/service002f/char0034その後、write 操作を実行します。
write 0x67最終的に、アプリ上で開発ボードから送信されたデータを受信できます。

マスター送信、スレーブ受信
2.3.2 開発ボードをスレーブとする場合
サンプルプログラムをダウンロードします:
例えば、サンプルプログラムを「PC\D:」(指定はありません。ユーザーの任意の場所で構いません)にダウンロードします。
その後、bluetooth-gatt フォルダを開発ボードに転送し、開発ボードで新しいターミナルを開いて、gatt-server サービス(【マスター】と通信するためのアプリケーション)をコンパイルして実行します。

開発ボードをスレーブとする場合

開発ボードをスレーブとする場合
再び bluetoothctl に戻り、以下のコマンドを実行してBluetoothアドバタイズを開始します:
advertise on
開発ボードをスレーブとする場合
【BLEデバッグアシスタントアプリ】を使用して、開発ボードのBluetoothをスキャンし、接続します。

開発ボードをスレーブとする場合
2.3.2.1 マスター受信、スレーブ送信
【BLEデバッグアシスタントアプリ】から開発ボードのデータを読み取ります。

マスター受信、スレーブ送信
上記の操作を実行すると、開発ボード上の gatt-server に以下の情報が出力されます:

マスター受信、スレーブ送信
2.3.2.2 マスター送信、スレーブ受信
【BLEデバッグアシスタントアプリ】から開発ボードへデータを送信します。

マスター送信、スレーブ受信
開発ボード上の gatt-server は以下の情報を受信します:

マスター送信、スレーブ受信