こんにちは!まっきー(@makky_study)です。
ラズパイでSPI通信に挑戦!①に引き続き、SPI通信を学習していきます。
今回は、実際にプログラムを書いて、動かしていきます。
では、早速始めていきましょう!
今回作成するもの
可変抵抗で電圧の値を変え、その値を1秒ごとに出力するプログラムを作成する。こんな感じ↓

準備
用意するもの
- Raspberry Pi3B+
- ブレッドボード
- 10キロΩの可変抵抗
- A/Dコンバータ(MCP3008)
- ジャンパー線(オス・メス)
- ジャンパー線(オス・オス)
今回の目的は、可変抵抗をクルクルと操作することによって、画面にその時の電圧を表示させることです。
そのためには、電圧値を計算しなければいけません。MCP3008のデータシートに基づき、以下に計算方法をまとめました。

- LSB Size:分解能の値
- DigitalOutputCode:デジタルの出力値
例えば、基準電圧が3.3V、電源電圧も3.3Vだったとします。その場合、DOCは1023(0も含んでいるため)となります。
可変抵抗によってVinの値を表示させたいので、この式を少し変形し次のようにします。
Vin = Vref / 1024 * DOC
例を見てみましょう。DOCが最大の1,023だったとすると、式より
Vin = 3.3/1024*1023 ≒ 3.297 となります。
この太字の結果をターミナルに表示できるようにプログラムを組んでいきます。
電子回路図を見ていきましょう。
電子回路
まず、ラズパイとA/Dコンバータのピン配置を確認しておきましょう。
回路図のICはMCP3008 ではないですが気にしないでください。

コード
SPI通信用のライブラリ関数を紹介します。
使用するライブラリ関数
- wiringPiSPI.h:SPIヘッダファイル
- wiringPiSPISetup(int ssNo,int speed) :SPI通信速度(500kHz~32MHzで設定可能)
- wiringPiSPIDataRW(int ssNo,unsigned char *data,int len) :送受信するバイト型の配列、送受信するデータの長さ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <stdio.h> #include <string.h> #include <wiringPi.h> #include <wiringPiSPI.h> #define SS0 0 #define SPI_SPEED 500000 //500khz #define MCP3008_CH3 3 unsigned short Mcp3008RW(int ssNo,unsigned char adcChannel){//スレーブナンバー、アナログ入力チャンネル(3) unsigned short doc = 0;//digital output codeの値を戻り値とする unsigned char buff[3];//1bit char型 buff[0]=buff[1]=buff[2]=0; buff[0] = 0b00000001; buff[1] = 0b10110000; buff[2] = 0b00000000; wiringPiSPIDataRW(ssNo,buff,sizeof(buff));//これでデータ送信、受信を行う doc = (((buff[1]&3) <<8 ) | buff[2] ); return doc; } int main(void){ unsigned short doc = 0; wiringPiSetupGpio(); wiringPiSPISetup(SS0,SPI_SPEED); while(1){ doc = Mcp3008RW(SS0,MCP3008_CH3); printf("CH3 = %3XH",doc); printf("\tvoltage = %5.3f V\n",((3.3/1024)*(doc))); delay(1000); } return 0; } |
次に、関数詳細です。前回重要になるといったこのタイミングチャートと表を見比べながら見ていきましょう。

1~4行目 ヘッダーファイルインクルード
6~9行目 周波数、スレーブ番号、チャンネルをマクロ定義
11~21行目 A/D変換の通信処理を行う関数(表と見比べながら見てください)
最後の式を詳しく説明します。
1 |
doc = (((buff[1]&3) <<8 ) | buff[2] ) |
結論から言うと、docは出力データですのでB0~B9の10個の情報を格納する処理になります。
例えば、buf[1] = 0b00000010,buff[2]=0b10110010が入っていたとします。B0~B9までの10この値を取り出したいので、buff[1]を3つまり二進数で0b00000011。これを&演算をすることで下位2ビットを取り出せます。8ビット左シフトし、or演算でbuff[2]の値を合わせることで10bitのデータ0b1010110010が取り出せます。
メイン関数では、取り出した値を計算して表示しているだけなので、説明は省略します。
実際にプログラムを動かしてみると…

電圧の値が変わっていることがわかると思います。
目的達成です!
まとめ
- ラズパイでのA/D変換はSPI8bitセグメント通信で行う
- データシートを読み込むことで仕組みはある程度理解できる
ブラックボックスだったA/D変換の理解が、個人的にはかなり深まりました。
そろそろ、自分で成果物を決めて作成してみたいですね…
-
-
I2Cを使ってLCDに文字を表示させる!①(C言語)
続きを見る
-
-
I2Cを使ってLCDに文字を表示させる!②(C言語)
続きを見る