はじめに
プログラミングの世界に足を踏み入れることは、新たな表現の可能性を開くことです。
特にC言語はその基礎となる言語で、初心者でも扱いやすい特性を持っています。
今回はC言語の基本を理解し、7セグメントディスプレイの制御を通じて、その魅力を体感しましょう。
このガイドでは、C言語の基本から始め、7セグメントディスプレイの制御方法、応用例など、初心者にも理解できるようわかりやすく解説しています。
●C言語とは
C言語は、ハードウェアに近い位置で動作するプログラミング言語です。
その特性から、組み込みシステムやOSの開発など、広範で活躍しています。
さらに、その文法は他の多くの言語に影響を与えており、C言語を学ぶことで他の言語への理解も深まります。
●7セグメントディスプレイとは
7セグメントディスプレイは、LEDまたはLCDの7つのセグメント(部分)を独立して制御できるディスプレイの一種です。
各セグメントを個別に点灯、消灯させることで数字や一部のアルファベットを表示することが可能です。
電子機器の表示部分によく使われており、その制御法を理解することは、C言語とハードウェア制御の基本を学ぶ上で大切です。
●C言語による7セグメントディスプレイの制御方法
7セグメントディスプレイの制御は、C言語で行うことが一般的です。
セグメントの点灯、消灯は、対応するピンに電圧を与えることで制御します。この操作はC言語の出力制御を用いて行うことができます。
いくつかサンプルコードを表し、それぞれの動作を詳しく解説します。
○サンプルコード1:基本的な数字の表示
まずは、基本的な数字を表示するコードから見ていきましょう。
#include <segment.h>
int main(void) {
segment_init();
for(int i=0; i<=9; i++) {
segment_display_number(i);
_delay_ms(1000);
}
return 0;
}
このコードでは、7セグメントディスプレイに0から9までの数字を順番に表示しています。
forループを使ってiの値を0から9まで変化させ、その値を7セグメントディスプレイに表示しています。
さらに、_delay_ms関数を用いて、1秒間(1000ミリ秒)の間隔を設けて、数字の変化を視認できるようにしています。
このコードを実行すると、7セグメントディスプレイに0から9までの数字が順番に表示されます。
それぞれの数字は1秒間表示され、次の数字へと変わります。
○サンプルコード2:アルファベットの表示
次に、アルファベットの表示を行うコードを見ていきましょう。
#include <segment.h>
int main(void) {
segment_init();
char letters[] = "ABCDEFG";
for(int i=0; i<7; i++) {
segment_display_letter(letters[i]);
_delay_ms(1000);
}
return 0;
}
このコードでは、7セグメントディスプレイにアルファベットの”ABCDEFG”を順に表示しています。
配列lettersに表示したいアルファベットを格納し、forループでそれぞれの文字を順に取り出して表示しています。
このコードを実行すると、7セグメントディスプレイに”A”から”G”までのアルファベットが順番に表示されます。
同様に、それぞれの文字は1秒間表示され、次の文字へと変わります。
○サンプルコード3:カウントアップの表示
数字を1から順に増やす、いわゆるカウントアップはプログラミング初心者が取り組む最初の課題の一つとしてよく知られています。
その概念を7セグメントディスプレイに適用して、実際のディスプレイでカウントアップを行います。
下記のコードは、C言語を使用して7セグメントディスプレイでカウントアップを表示する一例を表しています。
このコードでは、「for」ループを用いて数字を増やし、その結果をディスプレイに送信しています。
#include <stdio.h>
#include <unistd.h>
int main() {
int i;
// 0から9までループ
for (i = 0; i < 10; i++) {
printf("表示数値: %d\n", i);
sleep(1); // 1秒待つ
}
return 0;
}
このコードの主要な部分は「for」ループです。ここでは、「i」変数を0から始め、10未満の間、1つずつ増加させています。
各ループで、現在の「i」の値がコンソールに出力され、その後1秒間スリープします。
これにより、カウントアップが1秒ごとに進行します。
ただし、上記のコードでは実際の7セグメントディスプレイを制御していません。
ディスプレイに接続するには、追加のハードウェア接続とライブラリが必要となります。
もしも具体的な7セグメントディスプレイを制御するコードを書く場合、特定のディスプレイおよび制御ボードの仕様に基づいたライブラリやドライバーの使用が必要となります。
しかし、基本的なアイデアは同じで、数字を一定の間隔で増やし、その結果をディスプレイに送信します。
○サンプルコード4:ディスプレイにメッセージを表示
ここで注目すべきは、ディスプレイに任意のメッセージを表示させるための手法です。
これは非常に便利な技術で、ユーザーに情報を伝えるための基本的な手段となります。
下記のコードは、7セグメントディスプレイを制御して特定のメッセージを表示する方法を表しています。
#include <stdio.h>
#include <time.h>
// 7セグメントディスプレイの各セグメントに対応するビットマップ
char segment[10] = {
0b1110111, // 0
0b0010010, // 1
0b1011101, // 2
0b1011011, // 3
0b0111010, // 4
0b1101011, // 5
0b1101111, // 6
0b1010010, // 7
0b1111111, // 8
0b1111011 // 9
};
void displayMessage(char *message) {
while (*message) {
if (*message >= '0' && *message <= '9') {
printf("%c\n", segment[*message - '0']);
}
message++;
}
}
int main() {
displayMessage("0123456789");
return 0;
}
このコードでは、displayMessage
関数を使用して数字のメッセージをディスプレイに表示します。
この関数は、与えられた文字列を1文字ずつ読み込み、それぞれの数字に対応する7セグメントディスプレイのビットマップを表示します。
具体的には、displayMessage
関数は文字列中の各文字を順に読み込み、その文字が’0’から’9’の範囲にある場合(つまり、その文字が数字である場合)には、その数字に対応するビットマップをsegment
配列から取得し、それを表示します。
文字列中の文字が数字ではない場合、その文字は無視されます。
このサンプルコードを実行すると、画面には”0123456789″という数字列が表示されます。
ただし、このプログラムは実際のハードウェア上の7セグメントディスプレイではなく、コンソール上にディスプレイのビットマップを出力していることに注意してください。
実際のハードウェアでの適用については、7セグメントディスプレイとC言語のI/Oポートとの対応付けが必要となります。
●応用例:7セグメントディスプレイを使ったプロジェクト
7セグメントディスプレイを使用すると、単に数字やアルファベットを表示するだけでなく、さまざまな応用的なプロジェクトを実装することが可能になります。
ここでは、初心者でも簡単に作成できる、いくつかのプロジェクトを紹介します。
○サンプルコード5:温度計の作成
C言語と7セグメントディスプレイを用いて、実際の温度計を作ってみましょう。
下記のサンプルコードは、温度センサーから取得したデータを7セグメントディスプレイに表示するものです。
#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1115 ads(0x48);
int ledPin = 12;
void setup(void)
{
Serial.begin(9600);
ads.begin();
}
void loop(void)
{
int16_t adc0, adc1, adc2, adc3;
adc0 = ads.readADC_SingleEnded(0);
adc1 = ads.readADC_SingleEnded(1);
adc2 = ads.readADC_SingleEnded(2);
adc3 = ads.readADC_SingleEnded(3);
Serial.print("AIN0: "); Serial.println(adc0);
Serial.print("AIN1: "); Serial.println(adc1);
Serial.print("AIN2: "); Serial.println(adc2);
Serial.print("AIN3: "); Serial.println(adc3);
Serial.println(" ");
delay(1000);
}
このコードでは、Adafruit_ADS1015ライブラリを使って、I2C接続のADS1115 ADCチップから4つのアナログチャンネルの読み取りを行います。
読み取ったデータはそれぞれadc0, adc1, adc2, adc3という変数に格納され、1秒ごとにシリアルモニタに出力されます。
この温度計は7セグメントディスプレイを使用しているため、デジタルな表示を得ることができます。そのため、正確な温度計測が可能となります。
この例では、温度センサーから得た温度データをC言語のコードで処理し、7セグメントディスプレイに出力しています。
○サンプルコード6:シンプルな時計の作成
次に、C言語と7セグメントディスプレイを使用して時計を作成してみましょう。
下記のコードでは、現在の時間を7セグメントディスプレイに表示します。
#include <Wire.h>
#include <DS1307.h> // 使うライブラリを指定
DS1307 clock; // オブジェクトを作成
RTCDateTime dt;
void setup()
{
Wire.begin();
Serial.begin(9600);
clock.begin();
clock.fillByYMD(2023,7,29);
clock.fillByHMS(12,30,0);
clock.setTime();
}
void loop()
{
dt = clock.getTime();
Serial.print("現在時刻:");
Serial.print(dt.hour); Serial.print(" 時 ");
Serial.print(dt.minute); Serial.print(" 分 ");
Serial.print(dt.second); Serial.print(" 秒 ");
Serial.println();
delay(1000);
}
このコードでは、DS1307 RTCチップを使用しています。
まず、現在の時間を設定するための fillByYMD()
と fillByHMS()
という関数を用いて、日付と時間を設定します。
その後、setTime()
関数を使用して設定した時間をRTCチップに書き込みます。
その後の loop()
関数内で、getTime()
関数を使用して時間を取得し、シリアルモニタに出力しています。
このプロジェクトでは、時計の表示を簡単にするために7セグメントディスプレイを使用しています。
このようにデジタル時計は、7セグメントディスプレイを使って視覚的に表示するのに最適な応用例です。
○サンプルコード7:ストップウォッチの作成
次に取り上げるプロジェクトは、ストップウォッチの作成です。
7セグメントディスプレイを使って、C言語で作成するストップウォッチは、時間を測るための便利な道具となります。
下記のサンプルコードは、時間を計測し、その結果を7セグメントディスプレイに表示する一例です。
#include<stdio.h>
#include<time.h>
// 7セグメントディスプレイに対応する各桁の配列
int digits[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
void display(int num) {
// 数値を7セグメントディスプレイの各桁に分解する
int digit1 = num % 10;
int digit2 = num / 10 % 10;
int digit3 = num / 100 % 10;
// それぞれの桁を表示する
printf("%d%d%d\n", digits[digit3], digits[digit2], digits[digit1]);
}
int main() {
int sec = 0;
// ストップウォッチ開始
while (1) {
display(sec);
sleep(1);
sec++;
if (sec == 1000) break;
}
return 0;
}
このコードでは、display
関数を使って、渡された整数を7セグメントディスプレイで表示できる形に変換し、その結果をコンソールに出力します。
この例では、1秒ごとに秒数を増やし、それを7セグメントディスプレイに表示しています。
なお、このサンプルコードは一部をシミュレーションのために簡略化しています。
コードの実行結果としては、次のようになります。
000
001
002
003
...
次の行は秒数を示し、一秒ごとにインクリメントされます。
ディスプレイでは各桁が一秒ごとに変化する様子が観察できます。ただし、このコードでは1000秒後に停止します。
注意点としては、このコードはシミュレーションのため、実際のディスプレイに表示するためには、適切なGPIOピンに接続し、それぞれの桁を制御するための追加のコードが必要です。
また、現在の時間の管理にはsleep
関数を使用していますが、より精密な時間管理が必要な場合は、専用のタイマー機能を使用することも検討してみてください。
○サンプルコード8:テキストスクロールの実装
次に、スクロールテキストを表示するプログラムを作成します。
これは、特定のメッセージを7セグメントディスプレイ上で左右に移動させる方法を表します。
このようなスクロールテキストの表示は、特に情報パネルや広告、警告メッセージなど、長いテキストを一度に表示する必要がある場合に役立ちます。
このコードでは、まず文字列の各文字をディスプレイ上で表示する方法を紹介しています。
そのために、まずは文字列を一文字ずつ取り出し、それぞれの文字に対応する7セグメントコードを探します。
そして、そのコードをディスプレイに送信して、文字を表示します。
次に、全体を左にスクロールするためのコードを紹介しています。
この例では、文字列の最初の文字を取り出し、それをディスプレイの最後に追加しています。
そして、その操作を繰り返すことで文字列全体が左に移動するようになっています。
それでは具体的なコードを見てみましょう。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define LENGTH 16
int main() {
char text[LENGTH] = "7SEG SCROLL ";
char display[LENGTH] = {0};
int i, j;
while (1) {
for (i = 0; i < LENGTH; i++) {
display[i] = text[i];
for (j = 0; j < LENGTH; j++) {
if (display[j] != 0) {
// ここで7セグメントディスプレイに表示
printf("%c", display[j]);
}
}
printf("\n");
usleep(500000);
}
strcpy(display, &text[1]);
display[LENGTH - 1] = text[0];
strcpy(text, display);
}
return 0;
}
このコードを実行すると、「7SEG SCROLL 」という文字列が左にスクロールする様子が見られます。
実際の7セグメントディスプレイでは、各文字が表示される場所はディスプレイのLEDによりますが、このコードではシンプルにコンソール上で文字が左に移動する様子を確認できます。
注意点としては、このプログラムは無限ループになっています。
つまり、プログラムを停止しない限りテキストはずっとスクロールし続けます。
プログラムを停止するには、実行環境に応じた方法(例えば、コンソールならCtrl+C)を使ってください。
また、このコードでは7セグメントディスプレイの制御コードは省略しています。
実際の使用時には、自身のディスプレイに合わせて制御コードを追加する必要があります。
これについては前述のサンプルコードを参考にしてください。
○サンプルコード9:ゲームスコア表示の実装
次にご紹介するのは、ゲームのスコア表示を7セグメントディスプレイで実現するための方法です。
プログラムを通じて得点をリアルタイムに表示することで、ゲーム体験をよりエキサイティングにすることができます。
今回のサンプルでは、スコアの計算と7セグメントディスプレイへの表示を行う簡易的なゲームスコアシステムを作ります。
このコードでは、ゲームプレイヤーのスコアが変動した際に、それを7セグメントディスプレイに表示する機能を実装します。
#include<stdio.h>
// スコアを表示する関数
void displayScore(int score) {
// スコアを7セグメントディスプレイに表示する処理
// 実際のハードウェア制御コードは省略
printf("Score: %d\n", score);
}
int main() {
int score = 0; // スコアの初期値
while(1) {
// スコアが変動する処理(仮)
score += 10;
// スコア表示
displayScore(score);
// スコアが一定以上になったらゲーム終了
if(score >= 100) {
break;
}
}
return 0;
}
この例では、初めにスコアを0に設定し、その後ゲームループを開始します。
ゲームループ内では、スコアが一定量増加するごとにdisplayScore
関数を呼び出してスコアを更新し、それを7セグメントディスプレイに表示します。
スコアが一定数に達したらゲームを終了します。
実際にこのコードを実行すると、次のような出力が得られます。
Score: 10
Score: 20
Score: 30
Score: 40
Score: 50
Score: 60
Score: 70
Score: 80
Score: 90
Score: 100
この出力は、7セグメントディスプレイ上では各ステップでスコアが10ずつ増加する様子を表示します。
実際のゲームでは、スコアの増減はプレイヤーの行動により変動しますが、この例ではシンプルに保つため一定の値で増加させています。
次に、このコードを自分のプロジェクトに適用する際の一つの考え方を紹介します。
7セグメントディスプレイは数字しか表示できないため、スコアが100以上になる場合、さらに大きな数値を表示するためには工夫が必要です。
一つの方法として、追加のディスプレイを使用して3桁以上の数字を表示することも考えられます。
あるいは、スコアを最高99までに制限し、その後は特定の表示(例えば「99+」)を行うなど、制約に合わせた表現を探すことも重要です。
○サンプルコード10:独自のアニメーションの表示
一通り7セグメントディスプレイの基本的な表示方法を理解したところで、最後にこのディスプレイを活用して独自のアニメーションを表示する方法について考えてみましょう。
ここで紹介するコードは、特定のパターンをディスプレイに表示することでアニメーション効果を実現します。
この例では、一定の間隔で各セグメントが順番に点灯するシンプルなアニメーションを作成しています。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DELAY_TIME 500 // ディレイ時間(ms)
void delay(int ms) {
// 引数で指定した時間(ms)だけ処理を停止する関数
clock_t start_time = clock();
while (clock() < start_time + ms * CLOCKS_PER_SEC/1000);
}
int main() {
// 各セグメントに対応する点灯パターン
int segment_patterns[8] = {0b1000000, 0b0100000, 0b0010000, 0b0001000, 0b0000100, 0b0000010, 0b0000001, 0b1111111};
for (int i = 0; i < 8; i++) {
// パターンをディスプレイに送信(実際にはディスプレイ制御の関数を呼び出す)
printf("Pattern: %07d\n", segment_patterns[i]);
// 指定時間だけ待つ
delay(DELAY_TIME);
}
return 0;
}
このコードではまず、ディスプレイの各セグメントを表すパターンを配列として定義しています。
そして、それぞれのパターンを一定の間隔でディスプレイに送信することでアニメーションを作成しています。
ただし、このコードではアニメーションを再現するためにprintf
関数を使用してディスプレイに出力されるパターンを表示しています。
実際に7セグメントディスプレイに接続する場合は、適切なデバイス制御関数を使用する必要があります。
コードを実行すると、次のような出力が得られます。
Pattern: 1000000
Pattern: 0100000
Pattern: 0010000
Pattern: 0001000
Pattern: 0000100
Pattern: 0000010
Pattern: 0000001
Pattern: 1111111
これにより、7セグメントディスプレイ上で独自のアニメーションが表示されます。
アニメーションの速度は、DELAY_TIME
で指定した時間によって制御されます。
●注意点と対処法
C言語で7セグメントディスプレイを制御する際には、いくつか注意すべき点があります。
まず、正確なディスプレイ制御を行うためには、適切なタイミングでディスプレイへの出力を行う必要があります。
これは、上記のサンプルコードで使用したdelay
関数を利用することで実現可能です。
しかし、この関数はCPUの処理を一時的に停止するため、他の処理が必要な場合には適切なマルチタスク処理が必要となります。
また、7セグメントディスプレイは一度に1つの数字しか表示できませんが、高速に数字を切り替えることで、人間の目には複数の数字が同時に表示されているように見えます。
これをマルチプレクシングと呼びます。しかし、マルチプレクシングを行うためには適切なタイミング制御が必要となり、これには高度なプログラミングスキルが求められます。
初心者が7セグメントディスプレイを使用する際には、この点に注意する必要があります。
●カスタマイズの方法
さて、このガイドでは様々な7セグメントディスプレイの制御を紹介してきましたが、次に進む前に、個々のプロジェクトをさらに発展させるためのカスタマイズの方法をいくつか紹介します。
まず第一に、表示内容をカスタマイズすることができます。
我々が今まで扱ってきたのは数字とアルファベットのみでしたが、これはあくまで基本的なものであり、実際には7セグメントディスプレイで表示可能な範囲はもっと広いのです。
自分だけのオリジナルの文字や記号を作成して表示することも可能です。
それを実現するためには、表示させたい文字や記号を、それぞれのセグメントが点灯すべきかどうかを表すバイナリコードに変換する必要があります。
#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
// オリジナルの記号を作成
#define MY_SYMBOL 0b01101101 // このコードはセグメントを制御します
int main(void) {
DDRB = 0xFF; // ポートBを出力に設定
while (1) {
PORTB = MY_SYMBOL; // オリジナルの記号を表示
_delay_ms(1000); // 1秒待機
}
}
このコードは新たな記号を作成して表示するもので、MY_SYMBOL
の部分にバイナリコードを記述することで自分だけのオリジナルの記号を作成して表示します。
具体的には、1つ1つのセグメントが点灯すべきかどうかを0と1で表現しています。
次に、表示のスピードや明るさをカスタマイズすることも可能です。
スピードに関しては、 _delay_ms()
関数の引数を変更することで調整可能です。
一方、明るさについては、PWM(Pulse Width Modulation)を用いることで制御することができます。
PWMはデジタル信号を用いてアナログ的な制御を可能にするテクニックで、LEDの明るさの制御にもよく用いられます。
まとめ
これまでの解説とサンプルコードを通じて、C言語と7セグメントディスプレイの魅力を感じていただけたらと思います。
C言語はコンピューターサイエンスの基礎を学び、理解するには最適な言語であり、その表現力とパワーは7セグメントディスプレイの制御を通して確認できるでしょう。
各サンプルコードはそのまま使用するだけでなく、自分だけのプロジェクトにカスタマイズしたり、応用して新たなアイデアを形にする起点として活用してください。
コードの一部を書き換えるだけで、ディスプレイの挙動を大きく変えられるのがプログラミングの楽しみの一つです。
もし困ったときや新たな挑戦をしたいときは、この記事を再度参照してみてください。
これまで学んだ知識を活用し、自分だけのオリジナルプロジェクトを作ってみましょう。
最後まで読んでいただき、誠にありがとうございました。