続いて、スケッチ2、スケッチ3の記述内容とポイントを見ていきましょう。
//----------------------------------- //OLEDに時間を表示する //----------------------------------- void disp_time(int time) { //表示位置を設定する(1行目左) set_cursor(OLED_1L_POS_X, OLED_1L_POS_Y); //時間を表示する Serial.print(time); Serial.print("min"); //不要な領域をクリアする int spcCount; if(time < 10) { spcCount = OLED_1L_LEN - 4; } else { spcCount = OLED_1L_LEN - 5; } for(int i = 0; i < spcCount; i++) { Serial.print(" "); } } //----------------------------------- //OLEDにスタートメッセージを表示する //----------------------------------- void disp_start_message(char message[]) { //表示位置を設定する(1行目右) set_cursor(OLED_1R_POS_X, OLED_1R_POS_Y); //クリアする for(int i = 0; i < OLED_1R_LEN; i++) { Serial.print(" "); } //表示位置を設定する(1行目右) set_cursor(OLED_1R_POS_X, OLED_1R_POS_Y); //メッセージを表示する Serial.print(message); } //----------------------------------- //OLEDにメッセージを表示する //----------------------------------- void disp_message(char message[]) { //表示位置を設定する(2行目左) set_cursor(OLED_2L_POS_X, OLED_2L_POS_Y); //クリアする for(int i = 0; i < OLED_2L_LEN; i++) { Serial.print(" "); } //表示位置を設定する(2行目左) set_cursor(OLED_2L_POS_X, OLED_2L_POS_Y); //メッセージを表示する Serial.print(message); } //----------------------------------- //OLEDの表示位置を設定する //----------------------------------- void set_cursor(int x, int y) { //OLEDの表示位置設定用のエスケープシーケンスを組み立てて出力する OLED_CURSOR[2] = OLED_CURSOR_POSITION[x]; OLED_CURSOR[3] = OLED_CURSOR_POSITION[y]; write_escape_sequence(OLED_CURSOR, 4); } //----------------------------------- //OLEDにエスケープシーケンスを出力する //----------------------------------- void write_escape_sequence(char escseq[], int length) { //OLEDにエスケープシーケンスを2進数で出力する for(int i = 0; i < length; i++) { Serial.write(escseq[i]); } }
それでは、モジュールの中身を見ていきましょう。
4行目から始まる「disp_time(int time)」は、ディスプレイの左端に残り時間を表示する関数です。
6行目で、カーソルセット関数の「set_cursor()」を呼び出して、文字列のスタート位置を指定。8〜9行目で、「Serial.print()」を使って残り時間を表示させています。
11〜20行目は、残り時間の桁数に合わせて不要な文字を削除しています。これは、カウントダウンのたびに全体を書き換えると表示がチカチカしてしまうのを防ぐ処理です。状態を表示する関数「disp_start_message()」とメッセージを表示する関数「disp_message()」も、やっていることは基本的に同じです。
55行目からは、カーソル位置を指定する関数「set_cursor()」です。引数でX座標、Y座標を受け取り、「write_escape_sequence()」を呼び出しています。
64行目に、ESCシーケンスを送信する関数「write_escape_sequence()」が記述されています。バイナリデータを扱うため、「Serial.write()」を使っているのがポイントです!
void setup() { //OLEDとのシリアル通信を開始 Serial.begin(9600); //OLEDクリア write_escape_sequence(OLED_CLR, 2); //開始時間を取得する G_start_time = millis(); //スタートメッセージを表示 disp_start_message("Start"); } void loop() { unsigned long current_time; // if(G_time > 0) { current_time = millis(); if(current_time - G_start_time >= ONE_MINUITE) { //1分経過 G_time--; if(G_time <= 0) { //終了メッセージを表示 disp_start_message("End"); //メッセージを表示 disp_message("Walking"); } G_start_time = current_time; } //時間を表示する disp_time(G_time); } }
ここまで準備できれば、後は簡単! 「setup()」でシリアル通信をスタートさせましょう。すると、ディスプレイに文字が表示されるので、「write_escape_sequence()」を呼び出して文字を全てクリア(5行目)。タイマーをスタートさせて、「Start」の文字をディスプレイに表示させます。
「loop()」では、カウントダウンしながら残り時間を示し、最後に「End」の文字をディスプレイに表示させます。なお、以下のダウンロード用ファイル(mono08.zip)は、スケッチ1〜3を1本にまとめたものが格納されています。
これまでになくプログラムが長いので、「えっ〜!!」と思うかもしれませんが、大丈夫です。ディスプレイを制御するためのESCシーケンスがちょっとややこしいだけで、そこをつかんでからプログラムを読み進めて行けば「なるほど〜!」と理解できるはずです。
前述の通り、最初の意気込みから後退した感は否めませんが、これでディスプレイに文字を表示させることに成功しました! さすがにこのまま「完成」では悔しいので、次回、スイッチとブザーを搭載した理想の「運動しなさい! 電光掲示板」を完成させたいと思います! 応援よろしくお願いします!! (次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.