
C言語で温湿度をLCD表示する
(ネット検索して得られた情報を参考にしてプログラムを試行する)
*プログラムを記述するにはテキストエディタが必要になる。
RasPiのOSにGUIに馴染むいくつかのテキストエディタがあるが教則本にある Geany が
プログラム開発では使い勝手が良いと思う。
*RasPi5のI2Cンターフェースを有効にすること。
→ I2Cモード切り替えページへ
一度でうまくいかないときは再度モード切替の操作を行う必要がある
*回路図
*I2Cインターフェース上にLCDを接続したらI2Cのアドレスを確認する
プログラムにI2Cアドレスとして記述する必要がある
sudo i2cdetect -y 1
正しく回路が繋がっているとLCDのアドレスがhex数値で表示される
例では 0x27 LCDユニットのI2Cアドレスとなる
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
*GPIOピンにてDHT11のDATA-INと接続する番号を回路図と異なるピンに変更する場合は
プログラムにてGPIO番号を変更する必要がある
------------------------------------------------------------------------
RasPi5ではgccコンパイラを使用する。
GPIOを操作するライブラリとしてwiringPiを使用するので予めインストールしておくこと
このライブラリを使用することによりI2Cインターフェースなどの細かい制御が予め関数化
されているのでC言語のプログラムでは関数を呼び出すだけでI2Cを使用できる
*コンパイル例(CソースファイルがLCD_DHT11.cの場合)
gcc LCD_DHT11.c -o LCD_DHT11 -lwiringPi
*実行例
./LCD_DHT11
サンプルプログラムの概要は、温湿度センサーDHT11からデータを読み込んで
I2Cインターフェースに接続されたLCDに温度/湿度を表示する
<サンプルプログラムの動作手順>
(続にいうフローチャートを文書化したもの)
------------------------------------------------------------------------
1.C言語のプログラムで使用するヘッダー類を記述する
・stdio.h stdlib.h string.h wiringPi.h wiringPiI2C.h
2.プログラムで使用する定数類を定義する
// LCD コマンド定義
LCD_CHR 1 // データモード
LCD_CMD 0 // コマンドモード
LCD_LINE_1 0x80 // 1行目
LCD_LINE_2 0xC0 // 2行目
LCD_BACKLIGHT 0x08 // バックライト ON
ENABLE 0b00000100 // Enable ビット
// LCD の I2C アドレス(モジュールによって異なる)
I2C_ADDR 0x27
// DHT11からデータを読み込むビットクロック数
MAX_TIMINGS 85
// GPIOの物理ピン番号(DHT11のデータピンと接続)
DHT_PIN 7 // GPIO4
------------------------------------------------------------------------
3.ソース内に記述されている関数のプロトタイプ宣言を行う
void lcd_init(void);
void lcd_byte(int bits, int mode);
void lcd_toggle_enable(int bits);
void lcd_loc(int line);
void lcd_text(const char *s);
int read_dht11_data() ;
------------------------------------------------------------------------
4.グローバルで使用するワーク変数
int data[5] = {0, 0, 0, 0, 0}; //DHT11から受取る5バイト分
char TempStr[40]; // 温度表示文字列
char HumiStr[40]; // 湿度表示文字列
int fd; // I2C ファイルディスクリプタ
------------------------------------------------------------------------
5.C言語のプログラムにて最初に実行される関数main()を記述する
・変数定義
int res ;
char dispBuf[40]; //LCDに書込む文字列形成用バッファ
int FlgLcdMark=0; //LCDの文字列に*を表示するタイミングを決めるフラグ
・ライブラリwiringPi関数にてwiringPi 初期化する
エラーなら「wiringPi の初期化に失敗しました」を表示して終了
・ライブラリwiringPiI2CSetup関数にてアドレス0x27のI2Cハンドルを取得する
エラーなら「I2C デバイスが見つかりません (アドレス 0x27)」を表示して終了
・関数lcd_init()にてLCDの初期化を行う
・LCDに以下のオープニングメッセージを表示する
1行目:Hello Raspberry
2行目:Pi 5 LCD Test
2秒間、時間を費やす
・以下の処理を繰り返す
a.関数read_dht11_data()にてDHT11から温湿度データ5バイト(40bit)を取得
b.正常に温湿度データを取得できたら以下をLCDに表示
LCD1行目:Temp:<取得した温度> C <*>
LCD2行目:Humi:<取得した湿度> % <*>
<*>は、繰り返すごとに*マークを表示、非表示する
→プログラムが動いていることを示すため
c.温湿度データを取得できなかったら以下をLCDに表示する
LCD1行目:Temp:------------
LCD2行目:Humi:------------
d.2秒間、時間を費やす
・プログラムを終了するには ctrl-Cで終了させる
------------------------------------------------------------------------
6.関数lcd_init(void)
・LCDユニットに対してI2Cを通して電源投入後の初期化手順の6コマンドをLCDに送る
a)コマンド(0x33)Initialize
b)コマンド(0x32)Initialize
c)コマンド(0x06)Cursor move direction
d)コマンド(0x0C)Display On,Cursor Off, Blink Off
e)コマンド(0x28)Data length, number of lines, font size
f)コマンド(0x01)Clear display
・時間(5ms)を待つ(LCD側の動作との整合)
------------------------------------------------------------------------
7.関数lcd_byte(int bits, int mode)
・LCDに対する1バイトを2バイトに成形してLCDに書込み、その後、取込タイミング情報を書込む
mode=0:コマンド/mode=1:表示データ、LCDの文字を照らすLEDをonにする
a)上位データ形成:bits8bitから上位4bitを取得してmodeとLCD_BACKLIGHTビットを付加する
b)下位データ形成:bits8bitから下位4bitを取得して上位4ビットへシフトして
modeとLCD_BACKLIGHTビットを付加する
c)I2CインターフェースでLCDアドレスに上位データを書込む
d)LCDにデータを取り込むタイミング情報を書込む
e)I2CインターフェースでLCDアドレスに下位データを書込む
d)LCDにデータを取り込むタイミング情報を書込む
------------------------------------------------------------------------
8.関数lcd_toggle_enable(int bits) //(E) Enable パルス作成
・I2Cを通して書込んだデータをLCDが内部に取込むタイミング情報を送る
タイミング情報(E)をlow→hi→low(トグル)する
a)時間(500μs)を待つ(LCD側の動作との整合)
b)LCDに対する1バイトに取込タイミング情報=1を付加して書込む
c)時間(500μs)を待つ(LCD側の動作との整合)
d)LCDに対する1バイトに取込タイミング情報=0を付加して書込む
e)時間(500μs)を待つ(LCD側の動作との整合)
------------------------------------------------------------------------
9.関数 lcd_loc(int line)
・LCDに対してカーソル(表示位置)のコマンドを送る
------------------------------------------------------------------------
10.関数 lcd_text(const char *s)
・lineで指定された行にs文字列を表示する
a)LCDの1行分の文字列sを1文字ずつ データ書込みを繰り返す
------------------------------------------------------------------------
11.関数 read_dht11_data()
・温湿度センサーDHT11からGPIOピンを通してデジタル値を取得する
・変数定義
int laststate = HIGH; DHT11と接続されているピンの状態を保存する
int counter = 0; GPIOピンから取得するデータビット数
int i=0, j = 0; 整数値のワーク
int iBitChgCnt = 0; デバッグ用変数
int res = -1; 関数の戻り値
・DHT11から取得する5バイト(40ビット)バッファに0を書込み
・GPIOピンを出力モードにする
・GPIOピンに0レベルを書込む(lowレベルにする)
・18ms待つ
・GPIOピンに1レベルを書込む(Highレベルにする)
・40μs待つ
・GPIOピンを入力モードにする
・以下の処理を85回程度繰り返す
(正常にデータが取得できていると84回繰り返す)
a)直前の入力レベルと異なる状態になるまでGPIOピン7のレベルを読み続ける
およそ255μS以上レベルが変化しなかったらDHT11データ取得ループから抜ける
およそ255μS以内にレベルが変化したら、そのレベルを保存する
b)ループに入って4回以上レベルが変化して偶数回のレベル変化のタイミングで
データビット取得を行う
データバイトを1ビットずつ左にシフトして最下位ビットの位置に
→およそ17μs以上でレベルが変化したら1、
16μs以内のレベル変化だったら0を置く
c)上記のデータ形成の繰り返しで40ビット(5バイト)を取得できていたら
チェックサムを確認する
チェックサムが合致したら正常データと判定して温度文字列、湿度文字列を作成する
d)40ビットを正常に取得できていなかったら温度文字列、湿度文字列を空にする
エラー表示として[Data not good,<5バイトの取得データバイト>]
e)40ビット(5バイト)のデータが正しく取得できたら1、失敗なら-1を返して
関数を終了する
------------------------------------------------------------------------