0. はじめに
自動制御連合講演会 2025 で,Takuya Otani (https://x.com/ta98otani) さんとお話する機会があり,Simulink と M5Stack の連携に関するわたしの困りごとを相談しました.具体的には,以下の 2 点です.
- M5Stack の LCD にデータを表示させたい.
(Simulink で実装すると,LCD は漆黒の色のままなので…) - リモートで車輪型倒立振子を動かしたい
(みんなリモートで動かして楽しそう…)
わたしの方からは Simulink, M5Stack FIRE + Unit Roller485 で動かす方法をお伝えし,逆に Takuya Otani さんにはわたしの困りごとの開発をお願いすることで,個人的にコラボすることとなりました(知らない知識を得られる…ワクワク).
今回は「リモート指令で車輪型倒立振子を動かしたい」の前段階のお話で,
MATLAB からのリモート指令で BLDC モータ Unit Roller485 を動かす!
ことを目標とします.そのために,BLE (Bluetooth Low Energy) と呼ばれる「低消費電力」に特化した Bluetooth のプロトコルを利用します.
LCD の表示については,後日,Takuya Otani (https://x.com/ta98otani) さんが公開されるのではないかと思います.
1. 使用するソフトウェアと機器
1.1 配布するファイル
ここからダウンロードできます.配布する MATLAB/Simulink のファイルは
- send_1byte.m
- send_2bytes.m
- receive_1byte_R2024b.slx
- receive_2bytes_R2024b.slx
- BLE_angle_control_1byte_R2024b.slx
- BLE_angle_control_2bytes_R2024b.slx
です.また,Application download の Baud rate を 115200 に変更した
- receive_1byte_R2024b_baudrate115200.slx
- receive_2bytes_R2024b_baudrate115200.slx
- BLE_angle_control_1byte_R2024b_baudrate115200.slx
- BLE_angle_control_2bytes_R2024b_baudrate115200.slx
も置いておきました.
1.2 ソフトウェア
ソフトウェアは MATLAB R2024b です.使用した Toolbox は
- MATLAB
- Simulink
- Control System Toolbox
です.これに加えてフリーの
- Simulink Support Package for Arduino Hardware
のインストールが必要です.その際,ESP32 の設定追加も忘れずに!
インストール手順はココで説明しています.
1.3 機器
まずは,Bluetooth が搭載された M5Stack CORE シリーズ のマイコン.わたしは手持ちの
で動作確認をしました.Arduino だと別途,Bluetooth を用意しなければならないので,M5Stack は便利です!
また,Unit Roller485 を動かしたい場合は,
- Unit Roller485 LITE
- Unit Roller485 …… スリップリングが内蔵されたタイプです
をご用意ください(どちらでも可).
1.4 準備
M5Stack と PC を USB ケーブルで接続し,デバイスマネージャで M5Stack の COM 番号を調べておきます.
配布するすべての Simulink モデルは「コンフィギュレーションパラメータ」(もしくは「ハードウェア設定」)で
のように COM 番号を手動で設定します.なお,M5Stack を使用しますので,Simulink 側でハードウェアボードとして
- ESP32-WROOM
を選択しています.なお,Application download の Baud rate は必要に応じて 115200 に落としてください.
その他の「コンフィギュレーションパラメータ」は以下を確認してください.
今回の例のように,I2C でやり取りするデータの種類が少なければ,固定ステップサイズを 0.005 秒くらいまで短くできますが,データの種類が多くなってくると,もっと長くしなければなりません.
2. MATLAB からリモート指令を M5Stack に送ってみる
2.1 1 バイトデータの場合
2.1.1 Simulink モデルおよび M ファイル
Simulink モデル
および M ファイル
clear
m5 = ble("Arduino");
% UUID の設定
Service = "fce70352-c544-48f4-9760-7568263b7922";
Characteristic = "b570118e-df2f-4545-9cf9-eff837991f54";
data_c = characteristic(m5, Service, Characteristic);
while 1
ref = input("ref = "); % -128 ~ 127 の値を入力
% int8 を uint8 に変換(ビットパターン保持)
valuesToSend = typecast(int8(ref), 'uint8');
write(data_c, valuesToSend);
end
を作業フォルダに保存しておきます.
ざっくりとした注意点は以下の通り.
Simulink を実行した後,MATLAB のコマンドウィンドウで以下のように入力することで,周辺にある Bluetooth デバイスを確認することができます.
>> blelist
bluetoothlist を実行して、近くの Bluetooth Classic デバイスを検出してください。
ans =
4×5 table
Index Name Address RSSI Advertisement
_____ __________ ______________ ____ _____________
1 "" "765F38F68068" -30 1×1 struct
2 "Arduino" "3C8A1FD670AA" -42 1×1 struct
3 "" "55EFE94FD626" -66 1×1 struct
4 "Quest 3S" "47FA002D24EE" -72 1×1 struct
M5Stack は "Arduino" という名前で認識されますので,M ファイル send_1byte.m では
m5 = ble("Arduino");
と記述しています.もしかしたら
m5 = ble("3C8A1FD670AA");
のようにアドレス指定にしないとうまく認識しないかもw
M ファイル send_1byte.m では,
ref = input("ref = "); % -128 ~ 127 の値を入力
% int8 → uint8 に変換(ビットパターン保持)
valuesToSend = typecast(int8(ref), 'uint8');
write(data_c, valuesToSend);
の部分で,
- double 型の $\tt ref$ を入力
- $\tt int8(ref)$ で符号あり 8 ビット整数(1 バイト整数)に変換
- $\tt typecast(int8(ref), 'uint8')$ で符号なし 8 ビット整数(1 バイト整数)に変換
という順で変換し, MATLAB 関数 $\tt write$ により送信しています.ここで,MATLAB 関数 $\tt write$ で使用できる送信データは uint8(符号なし 8 ビット整数) でなければならないことに注意が必要です.
一方で,Simulink ブロック $\tt BLE\ Receive$ では,int8(符号あり 8 ビット整数) が出力されます.ややこしいですねww
M ファイル send_1byte.m や Simulink モデル receive_1byte_R2024b.slx(あるいは receive_1byte_R2024b_baudrate115200.slx)には 2 種類の 128 ビットの識別子 UUID
- Service
- Characteristic
が設定されています.配布するファイルから値を変更する必要はありませんが,これらは
>> char(java.util.UUID.randomUUID())
ans =
'fce70352-c544-48f4-9760-7568263b7922'
>> char(java.util.UUID.randomUUID())
ans =
'b570118e-df2f-4545-9cf9-eff837991f54'
のようにして生成しました.
Simulink モデル receive_1byte_R2024b.slx(あるいは receive_1byte_R2024b_baudrate115200.slx)の実行中にデータを受信していないときは,0 を返すような処理をしています.
2.1.2 実行してみる
以下の手順で実行してください.
- M5Stack と PC を USB ケーブルで接続します.
- Simulink モデル receive_1byte_R2024b.slx(あるいは receive_1byte_R2024b_baudrate115200.slx)をエクスターナルモードで実行します(「ハードウェア」のタグで「監視と調整」をクリック).実行が開始されると,M5Stack の LCD は真っ黒になりますが,気にしないでください.
- M ファイル send_1byte.m を実行します.動画のように MATLAB のコマンドウィンドウから ref の値を入力すると,Simulink モデルの $\tt Display$ の表示が切り替わることが確認できます.
- 終了したい場合は,コマンドウィンドウでキーボード操作「Ctrl + C」により,M ファイルの実行を強制終了してくださいw
実行した様子の動画を以下に示します.
スクリーンショットを以下に示します.
M ファイル send_1byte.m では $-128 \sim 127\ (-2^7 \sim 2^7 - 1)$ の int8(符号あり 8 ビット整数)のデータを,$0 \sim 255\ (0 \sim 2^8 - 1)$ の uint8(符号なし 8 ビット整数)に変換してから送信し,M5Stack (Simulink) で受信ていることに注意してください.そのため,
- $127$ より大きな値を指定すると,$127$ で頭打ちとなる(動画の例では $\tt ref=180$ と指定すると,$\tt Display (ref)$ には $\tt 127$ が表示される)
- $-128$ より小さな値を指定すると,$-128$ で頭打ちとなる(動画の例では $\tt ref=-180$ と指定すると,$\tt Display (ref)$ には $\tt -128$ が表示される)
という問題があります.つまり,
>> int8(180)
ans =
int8
127
>> int8(-180)
ans =
int8
-128
ということですね.
2.2 2 バイトデータの場合
上記のように,1 バイトの送受信データは,$-128 \sim 127\ (-2^7 \sim 2^7 - 1)$ の範囲に制限されます.今回,Roller485 の角度制御をリモート指令で行いたいわけですから,このままでは,目標角を $360^{\circ}$ とか $-360^{\circ}$ に設定できません.この問題を解決するには,送受信データを 2 バイトとすることが考えられます.そうすることで,$-32768 \sim 32767\ (-2^{15} \sim 2^{15} - 1)$ の範囲を扱うことができるようになります.
2.2.1 Simulink モデルおよび M ファイル
Simulink モデル
および M ファイル
clear
m5 = ble("Arduino");
% UUID の設定
Service = "fce70352-c544-48f4-9760-7568263b7922";
Characteristic = "b570118e-df2f-4545-9cf9-eff837991f54";
data_c = characteristic(m5, Service, Characteristic);
while 1
ref = input("ref = "); % -32768 ~ 32767 の値を入力
% --- int16 を 2 バイトの uint8 に変換(ビットパターン保持)---
bytesToSend = typecast(int16(ref), 'uint8'); % 1x2 の uint8 ベクトルになる
write(data_c, bytesToSend);
end
を作業フォルダに保存しておきます.
ざっくりとした注意点は以下の通り.データ変換の詳細については,最下部の付録を参照してください.
残念ながら,int16(2 バイト)データをそのまま送信することはできない(uint8 でしか送信できない)仕様なので,1 バイトずつに分割し,uint8 の 2 次元ベクトルとして送信する必要があります.
そこで,M ファイル send_2bytes.m では,
ref = input("ref = "); % -32768 ~ 32767 の値を入力
% --- int16 を 2 バイトの uint8 に変換(ビットパターン保持)---
bytesToSend = typecast(int16(ref), 'uint8'); % 1x2 の uint8 ベクトルになる
write(data_c, bytesToSend);
の部分で,
- double 型の $\tt ref$ を入力
- $\tt int16(ref)$ で符号あり 16 ビット整数(2 バイト整数)に変換
- $\tt typecast(int16(ref), 'uint8')$ でビットパターンをそのまま 2 バイトに分解する(int16 を「上位バイト + 下位バイト」の 2 つの uint8 に分解する)
という順で変換し,分解した 2 バイトの符号なし 8 ビット整数 (uint8) を MATLAB 関数 $\tt write$ により送信しています.
たとえば,正の値だと
>> ref = 360;
>> int16(ref)
ans =
int16
360
>> typecast(int16(ref), 'uint8')
ans =
1×2 の uint8 行ベクトル
104 1
負の値だと
>> ref = -360;
>> int16(ref)
ans =
int16
-360
>> typecast(int16(ref), 'uint8')
ans =
1×2 の uint8 行ベクトル
152 254
というような感じです.
一方で,Simulink ブロック $\tt BLE\ Receive$ で受信されたデータは,2 バイトの 8 ビット符号あり整数 (int8) として出力されます.さらにややこしいですねww
Simulink ブロック $\tt BLE\ Receive$ から出力された 2 バイトの int8 を元の形式に戻すために,
- Simulink ブロック ${\tt Data Type Conversion}$ により 2 バイトの uint8 に変換
- Simulink ブロック ${\tt Byte Unpack}$ により 2 バイトの uint8 を uint18 に変換
- Simulink ブロック ${\tt Data Type Conversion1}$ により double に変換
という処理を行っています.
2.2.2 実行してみる
以下の手順で実行してください.
- M5Stack と PC を USB ケーブルで接続します.
- Simulink モデル receive_2bytes_R2024b.slx(あるいは receive_2bytes_R2024b_baudrate115200.slx)をエクスターナルモードで実行します(「ハードウェア」のタグで「監視と調整」をクリック).
- M ファイル send_2bytes.m を実行します.動画のように MATLAB のコマンドウィンドウから ref の値を入力すると,Simulink モデルの $\tt Display$ の表示が切り替わることが確認できます.
- 終了したい場合は,コマンドウィンドウでキーボード操作「Ctrl + C」により,M ファイルの実行を強制終了してくださいww
実行した様子の動画を以下に示します.
スナップショットだとこんな感じです.
3. Simulink モデル
3.1 Simulink ライブラリ roller485lib のインストール
後日,Qiita の別記事で使用方法を公開予定ですが,わたしが作成した Unit Roller485 用の Simulink ライブラリ
をインストールします.
Download ZIP を選択すると,
- Roller485lib-main.zip
がダウンロードされるので,解凍してできるフォルダ Roller485lib-main(のなかのフォルダ Roller485lib-main)を
- C:\Users\ユーザ名\Documents\MATLAB
にコピペしてください.ファイル構成は
- MATLAB
- Roller485lib-main
- sample_roller485lib
<フォルダの中身は省略> - slblocks.m
- README.md
- roller485.png
- roller485_matlab_fcn.png
- roller485lib.slx
- LICENSE.txt
- sample_roller485lib
- Roller485lib-main
となります.そして,M ファイル
% startup.m
addpath('C:\Users\ユーザ名\Documents\MATLAB\Roller485lib-main')
をフォルダ
- C:\Users\ユーザ名\Documents\MATLAB
に保存してください.つまり,
- C:\Users\ユーザ名\Documents\MATLAB\startup.m
としてください.そして,MATLAB を再起動すると,Simulink ライブラリ roller485lib が使用できるようになります.コマンドウィンドウで
>> roller485lib
と入力すると,Simulink ライブラリ roller485lib が開きます.
このライブラリ自体は R2023a 以上に対応しています.
3.2 Simulink モデル
Simulink モデル
をダウンロードしてください(R2024b 以上に対応).M ファイルはすでに利用した
- M ファイル send_2bytes.m
です.
3.3 実行してみる
以下の手順で実行してください.
-
M5Stack と PC を USB ケーブルで接続します.
-
Simulink モデル BLE_angle_control_2bytes_R2024b.slx(あるいは BLE_angle_control_2bytes_R2024b_baudrate115200.slx)をスタンドアロンモードで実行します(「ハードウェア」のタグで「ビルド、展開起動」をクリック).M5Stack をバッテリーなど外部から給電しているのであれば,M5Stack にダウンロードが終了したら,USB ケーブルを抜いても大丈夫です.

-
M5Stack の電源を入れたら,5 秒位内に Roller485 の軸の基準位置を決定します.5 秒が経過したら角度の比例制御が始まります.制御が始まったら,手で外乱を与えても,基準位置に戻ろうとすることを確認してください.
-
M ファイル send_2bytes.m を実行します.動画のように MATLAB のコマンドウィンドウから ref の値を入力すると,Roller485 の軸の角度が目標角に制御されることが確認できます.
-
終了したい場合は,コマンドウィンドウでキーボード操作「Ctrl + C」により,M ファイルの実行を強制終了してくださいwww
実行した様子の動画を以下に示します.
Mac でも動くようですよ!
4. おわりに
というわけで,Takuya Otani (https://x.com/ta98otani) さんに感謝!
Roller485 を利用した車輪型倒立振子もリモートで簡単な動作をさせることまではできるようになりました.
1 年前は Simulink で M5Stack や Roller485 をこんな感じで動かせるとは思っていませんでしたが,ずいぶんと進んだような気がする.
ここまでくれば,Bluetooth のボタンやジョイスティックとかでリモート制御ができるかも.
追記
勉強しているうちに,MATLAB で BLE を使う解説記事があることに気づきましたww
皆さんがお試ししていたのは 2020 年頃なんですね.
ちなみに,今回使用した Sumulink ブロック $\tt BLE\ Receive$ が導入されたのは R2021b からなので,強者たちは恐るべし…
付録
A.1 M モデル send_2bytes.m の信号の流れ
M モデル send_2bytes.m では,以下のようなデータ変換を行っています.
<略>
while 1 % 無限ループ
ref = input("ref = "); % -32768 ~ 32767 の値を入力
% --- int16 を 2 バイトの uint8 に変換(ビットパターン保持)---
bytesToSend = typecast(int16(ref), 'uint8'); % 1x2 の uint8 ベクトルになる
write(data_c, bytesToSend);
end
${\tt int16(ref)}$
double 型の $\tt ref$ を int16 型に変換します.
\begin{align}
{\tt double:}\
{\tt ref}
\quad\longrightarrow\quad
{\tt int16:}\
{\tt V}_{\tt int16}
\end{align}
${\tt typecast(int16(ref), 'uint8')}$
まず,次式に従って int16 型を uint16 型に変換します ($2^{16} = 65536$).
\begin{align}
{\tt uint16:}\
{\tt V}_{\tt uint16} =
\begin{cases}
{\tt V}_{\tt int16} + 65536 & ({\tt V}_{\tt int16} < 0) \\
{\tt V}_{\tt int16} & ({\tt V}_{\tt int16} \ge 0)
\end{cases}
\end{align}
そして,8 ビット(1 バイト)ごとに分割した uint8 型の
\begin{align}
{\tt uint8:}&\ [\,\begin{array}{cc}
{\tt L}_{\tt uint8} & {\tt M}_{\tt uint8}
\end{array}\,]
\quad \cdots\cdots\ {\rm Little\ Endian}
\end{align}
の要素(リトルエンディアンの並び)を,次式を満足するように決定します ($2^{8} = 256$).
\begin{align}
{\tt V}_{\tt uint16} = 256 \times {\tt M}_{\tt uint8} + {\tt L}_{\tt uint8}
\end{align}
ただし,
- 上位ビット ${\tt M}_{\tt uint8}$ (MSB)
- 下位ビット ${\tt L}_{\tt uint8}$ (LSB)
は $0$ から $255$ までの整数です.
《補足》
ちなみに,さらに
\begin{align}
{\tt int8:}&\ [\,\begin{array}{cc}
{\tt L}_{\tt int8} & {\tt M}_{\tt int8}
\end{array}\,]
\end{align}
と変換するには,
\begin{align}
{\tt L}_{\tt int8} &= \left\{\begin{array}{ll}
{\tt L}_{\tt uint8} & ({\tt L}_{\tt uint8} < 128) \\
{\tt L}_{\tt uint8} - 256 & ({\tt L}_{\tt uint8} \ge 128)
\end{array}\right.
\\
{\tt M}_{\tt int8} &= \left\{\begin{array}{ll}
{\tt M}_{\tt uint8} & ({\tt M}_{\tt uint8} < 128) \\
{\tt M}_{\tt uint8} - 256 & ({\tt M}_{\tt uint8} \ge 128)
\end{array}\right.
\end{align}
とします.これが,Simulink ブロック ${\tt BLE\ Receive}$ から出力される $\tt Data$ になります.
たとえば,${\tt ref} = 360$ のとき,
\begin{align}
{\tt int16:}\
{\tt V}_{\tt int16} = 360 \ge 0
\end{align}
であり,
\begin{align}
{\tt uint16:}\
{\tt V}_{\tt uint16}
&=
{\tt V}_{\tt int16}
= 360
\end{align}
なので,
\begin{align}
{\tt V}_{\tt uint16} &= 256 \times {\tt M}_{\tt uint8} + {\tt L}_{\tt uint8}
\\
&= 256 \times 1 + 104
\end{align}
です.したがって,
\begin{align}
{\tt uint8:}&\ [\,\begin{array}{cc}
{\tt L}_{\tt uint8} & {\tt M}_{\tt uint8}
\end{array}\,]
= [\,\begin{array}{cc}
104 & 1
\end{array}\,]
\end{align}
が得られます.MATLAB では
>> ref = 360;
>> typecast(int16(ref), 'uint8')
ans =
1×2 の uint8 行ベクトル
104 1
となります.
ちなみに,
\begin{align}
{\tt L}_{\tt int8} &= {\tt L}_{\tt uint8} = 104
& ({\tt L}_{\tt uint8} = 104 < 128) \\
{\tt M}_{\tt int8} &= {\tt M}_{\tt uint8} = 1
& ({\tt M}_{\tt uint8} = 1 < 128)
\end{align}
より
\begin{align}
{\tt int8:}&\ {\tt Data}
= [\,\begin{array}{cc}
{\tt L}_{\tt int8} & {\tt M}_{\tt int8}
\end{array}\,]
= [\,\begin{array}{cc}
104 & 1
\end{array}\,]
\end{align}
が得られます.MATLAB では
>> ref = 360;
>> typecast(int16(ref), 'int8')
ans =
1×2 の int8 行ベクトル
104 1
となります.
たとえば,${\tt ref} = -360$ のとき,
\begin{align}
{\tt int16:}\
{\tt V}_{\tt int16} = -360 < 0
\end{align}
であり,
\begin{align}
{\tt uint16:}\
{\tt V}_{\tt uint16}
&=
{\tt V}_{\tt int16} + 65536
\\
&= -360 + 65536
\\
&= 65176
\end{align}
なので,
\begin{align}
{\tt V}_{\tt uint16} &= 256 \times {\tt M}_{\tt uint8} + {\tt L}_{\tt uint8}
\\
&= 256 \times 254 + 152
\end{align}
です.したがって,
\begin{align}
{\tt uint8:}&\ [\,\begin{array}{cc}
{\tt L}_{\tt uint8} & {\tt M}_{\tt uint8}
\end{array}\,]
= [\,\begin{array}{cc}
152 & 254
\end{array}\,]
\end{align}
が得られます.MATLAB を利用すると,
>> ref = -360;
>> typecast(int16(ref), 'uint8')
ans =
1×2 の uint8 行ベクトル
152 254
のように結果を確認できます.
ちなみに,
\begin{align}
{\tt L}_{\tt int8} &= {\tt L}_{\tt uint8} -256
= 152 - 256 = -104
& ({\tt L}_{\tt uint8} = 152 \ge 128) \\
{\tt M}_{\tt int8} &= {\tt M}_{\tt uint8} -256
= 254 - 256 = -2
& ({\tt M}_{\tt uint8} = 254 \ge 128)
\end{align}
より
\begin{align}
{\tt int8:}&\ {\tt Data}
= [\,\begin{array}{cc}
{\tt L}_{\tt int8} & {\tt M}_{\tt int8}
\end{array}\,]
= [\,\begin{array}{cc}
-104 & -2
\end{array}\,]
\end{align}
が得られます.MATLAB を利用すると,
>> ref = -360
ref =
-360
>> typecast(int16(ref), 'int8')
ans =
1×2 の int8 行ベクトル
-104 -2
のように結果を確認できます.
A.2 Simulink モデル receive_2bytes_R2024b.slx の信号の流れ
Simulink モデル receive_2bytes_R2024b.slx では,以下のようなデータ変換を行っています.
Simulink ブロック ${\tt BLE\ Receive}$ から 2 バイトのリトルエンディアンの $\tt Data$ が
\begin{align}
{\tt int8:}&\ {\tt Data} = [\,\begin{array}{cc}
{\tt L}_{\tt int8} & {\tt M}_{\tt int8}
\end{array}\,]
\end{align}
のように受信されます.Simulink ブロック ${\tt Data\ Type\ Conversion}$ で変換されたデータ
\begin{align}
{\tt uint8:}&\ [\,\begin{array}{cc}
{\tt L}_{\tt uint8} & {\tt M}_{\tt uint8}
\end{array}\,]
\end{align}
の各要素は
\begin{align}
{\tt L}_{\tt uint8} &= \left\{\begin{array}{ll}
{\tt L}_{\tt int8} + 256 & ({\tt L}_{\tt int8} < 0) \\
{\tt L}_{\tt int8} & ({\tt L}_{\tt int8} \ge 0)
\end{array}\right.
\\
{\tt M}_{\tt uint8} &= \left\{\begin{array}{ll}
{\tt M}_{\tt int8} + 256 & ({\tt M}_{\tt int8} < 0) \\
{\tt M}_{\tt int8} & ({\tt M}_{\tt int8} \ge 0)
\end{array}\right.
\end{align}
です ($2^8 = 256$).そして,Simulink ブロック ${\tt Byte\ Unpack}$ では,
\begin{align}
{\tt uint16:}&\
{\tt V}_{\tt uint16}
= 256 \times {\tt M}_{\tt uint8} + {\tt L}_{\tt uint8}
\end{align}
と変換した後,
\begin{align}
{\tt int16:}&\
{\tt V}_{\tt int16} = \left\{\begin{array}{ll}
{\tt V}_{\tt uint16} - 65536 & ({\tt V}_{\tt uint16} > 32767) \\
{\tt V}_{\tt uint16} & ({\tt V}_{\tt uint16} \le 32767)
\end{array}\right.
\end{align}
と変換しています ($2^{16} = 65536,\ 2^{15} - 1 = 32767$).最終的には,これを double 型に変換して $\tt ref$ を復元しています.
たとえば,
\begin{align}
{\tt int8:}&\ {\tt Data} = [\,\begin{array}{cc}
{\tt L}_{\tt int8} & {\tt M}_{\tt int8}
\end{array}\,]
= [\,\begin{array}{cc}
104 & 1
\end{array}\,]
\end{align}
のとき,
\begin{align}
{\tt L}_{\tt uint8} &= {\tt L}_{\tt int8}
= 104\ &({\tt L}_{\tt int8} \ge 0)
\\
{\tt M}_{\tt uint8} &= {\tt M}_{\tt int8}
= 1\ &({\tt M}_{\tt int8} \ge 0)
\end{align}
と変換されます.そして,
\begin{align}
{\tt uint16:}\
{\tt V}_{\tt uint16}
&= 256 \times {\tt M}_{\tt uint8} + {\tt L}_{\tt uint8}
\\
&= 256 \times 1 + 104
\\
&= 360 \ (\le 32767)
\end{align}
と変換した後,
\begin{align}
{\tt int16:}\
{\tt V}_{\tt int16} &= {\tt V}_{\tt uint16}
= 360
\end{align}
と復元されます.
たとえば,
\begin{align}
{\tt int8:}&\ {\tt Data} = [\,\begin{array}{cc}
{\tt L}_{\tt int8} & {\tt M}_{\tt int8}
\end{array}\,]
= [\,\begin{array}{cc}
-104 & -2
\end{array}\,]
\end{align}
のとき,
\begin{align}
{\tt L}_{\tt uint8} &= {\tt L}_{\tt int8} + 256
= -104 + 256 = 152\ &({\tt L}_{\tt int8} < 0)
\\
{\tt M}_{\tt uint8} &= {\tt M}_{\tt int8} + 256
= -2 + 256 = 254\ &({\tt M}_{\tt int8} < 0)
\end{align}
と変換されます.そして,
\begin{align}
{\tt uint16:}\
{\tt V}_{\tt uint16}
&= 256 \times {\tt M}_{\tt uint8} + {\tt L}_{\tt uint8}
\\
&= 256 \times 254 + 152
\\
&= 65176 \ (> 32767)
\end{align}
と変換した後,
\begin{align}
{\tt int16:}\
{\tt V}_{\tt int16} &= {\tt V}_{\tt uint16} - 65536
\\
&= 65176 - 65536
\\
&= -360
\end{align}
と復元されます.


































