注釈
こんにちは、SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Communityへようこそ!FacebookでRaspberry Pi、Arduino、ESP32に興味を持つ仲間たちと一緒に、さらに深く探求しましょう。
参加する理由は?
専門的なサポート: コミュニティやチームの助けを借りて、販売後の問題や技術的な課題を解決できます。
学び&共有: スキルを向上させるためのヒントやチュートリアルを交換できます。
限定プレビュー: 新製品の発表やスニークピークにいち早くアクセスできます。
特別割引: 最新製品に対して、特別な割引をお楽しみいただけます。
イベントプロモーションとギブアウェイ: ギブアウェイや季節のプロモーションに参加できます。
👉 さあ、一緒に探求し、創造しましょう![ここ]をクリックして、今日から参加しましょう!
32. ストップウォッチ
このエキサイティングなプロジェクトでは、4桁の7セグメントディスプレイを使って機能的なストップウォッチを作成する方法を学びます。このレッスンの終わりまでに、複数桁の7セグメントディスプレイを制御する方法を理解し、分と秒を計測するシンプルなストップウォッチを構築できるようになります。デジタルディスプレイの世界に飛び込み、Arduinoのスキルを向上させましょう!
このレッスンの終わりまでに、次のことができるようになります:
4桁の7セグメントディスプレイをマルチプレックス化する方法を学ぶ。
単一の桁に数字を表示するコードを書く。
数字のスクロール表示を作成する。
4桁の7セグメントディスプレイを使って分と秒を計測するストップウォッチを実装する。
AND演算子と>>演算子を学ぶ。
4桁の7セグメントディスプレイを学ぶ
はじめに
4桁の7セグメントディスプレイを見つけてください。
7セグメントディスプレイは、8の字型のコンポーネントで、7つのLEDをパッケージ化しています。ディスプレイ内の各LEDには位置セグメントが割り当てられ、その接続ピンの1つが長方形のプラスチックパッケージから引き出されています。このLEDピンは、それぞれの個別のLEDを表す"a"から"g"までのラベルが付けられています。
4桁のディスプレイは、4つの7セグメントディスプレイを組み合わせたもので、それぞれが1桁を表しています。必要なピンの数を減らすために、各ディスプレイのセグメントはマルチプレックスされており、各セグメントピンが他のディスプレイの対応するセグメントピンに接続されています。
これによりピン数は減りますが、制御の複雑さは増します。例えば、"a"ピンに電圧をかけると、すべての桁の"a"セグメントが点灯します。どの桁にセグメントを表示するかを制御するために、各桁には個別の制御ピン(d1~d4)があります。
その結果、数字「2222」を表示するには、d1、d2、d3、d4に電圧をかける必要があります。すべてのディスプレイが桁を表示するので、入力a、b、d、e、g、dpにも電圧をかける必要があります。
ピン配置
一般的な4桁の7セグメントディスプレイには、各側面に6つずつ、合計12ピンがあります。
4つのピン(d1、d2、d3、およびd4)は、各桁を制御します。残りのピンはセグメントに対応しています。
コモンカソードまたはコモンアノード
4桁の7セグメントディスプレイがコモンカソードかコモンアノードかを判断するには、マルチメータを使用します。また、次の手順でディスプレイの各セグメントが正常に動作しているかをテストすることもできます。
マルチメータをダイオードテストモードに設定します。ダイオードテストは、ダイオードや類似の半導体デバイス(LEDなど)の順方向伝導をチェックするために使用されるマルチメータの機能です。マルチメータはダイオードに微小電流を流します。ダイオードが正常であれば、電流を通過させます。
4桁の7セグメントディスプレイをブレッドボードに挿入します。ディスプレイのピン d1 と同じ行にワイヤを挿入し、それをマルチメータの黒いリードで接触させます。ディスプレイのピン e と同じ行にもう1本のワイヤを挿入し、それを赤いリードで接触させます。
いずれかのLEDセグメントが点灯するかどうかを確認します。点灯する場合、ディスプレイがコモンカソードであることを示しています。点灯しない場合、赤と黒のリードを入れ替えてください。入れ替え後にセグメントが点灯する場合、ディスプレイがコモンアノードであることを示しています。
注釈
私たちのキットには、コモンカソードの4桁7セグメントディスプレイが含まれています。制御ピンd1-d4をLOWに、セグメントピンa-gをHIGHに設定して動作させます。
質問
4桁の7セグメントディスプレイの左端の桁(d1)に「2」を表示したい場合、d1~d4およびa~gのピンのレベルはどうすればよいでしょうか?
7セグメントディスプレイ |
HIGHまたはLOW |
7セグメントディスプレイ |
HIGHまたはLOW |
|---|---|---|---|
d1 |
a |
||
d2 |
b |
||
d3 |
c |
||
d4 |
d |
||
e |
|||
f |
|||
g |
|||
dp |
回路の構築
必要なコンポーネント
1 * Arduino Uno R3 |
1 * 4桁7セグメントディスプレイ |
4 * 220Ω抵抗 |
1 * マルチメーター |
|
|
|
|
1 * USBケーブル |
1 * ブレッドボード |
||
|
|
構築手順
配線図に従って、または以下の手順に従って回路を構築してください。
4桁7セグメントディスプレイをブレッドボードに挿入します。
4つの220Ω抵抗をブレッドボードに挿入します。
制御ピンd1を最初の抵抗の片側に接続します。抵抗のもう片側をArduino Uno R3のピン10に接続します。これにより、制御ピンd1が抵抗を介してピン10に接続されます。
同様に、d2をピン11、d3をピン12、d4をピン13に接続します。
次に、adpピンを配線表に従ってArduinoのピン2~9に接続します。
7セグメントディスプレイ |
Arduino Uno R3 |
|---|---|
a |
2 |
b |
3 |
c |
4 |
d |
5 |
e |
6 |
f |
7 |
g |
8 |
dp |
9 |
コードの作成 - 一桁に「2」を表示する
次に、4桁7セグメントディスプレイの一桁に数字を表示するコードを書いてみましょう。
Arduino IDEを開き、「ファイル」メニューから「新規スケッチ」を選択して新しいプロジェクトを開始します。
スケッチを
Lesson32_Show_2_One_Digitという名前で保存し、Ctrl + Sを押すか「保存」をクリックして保存します。まず、4桁7セグメントディスプレイのセグメントピンと桁ピンを格納する2つの配列を作成します。
// Define the pins of the segments and the digits on the 4-digit 7-segment display
int segmentPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; // Segments a~g and dp (decimal point)
int digitPins[] = { 10, 11, 12, 13 }; // Digits d1-d4
void setup()関数内で、すべてのピンを出力として設定します。この4桁7セグメントディスプレイはコモンカソードタイプなので、最初にすべてのセグメントピンをLOW、すべての桁ピンをHIGHに設定してディスプレイをオフにします。
void setup() {
// Set all segment pins as output
for (int i = 0; i < 8; i++) {
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], LOW); // Ensure all segments are off initially
}
// Set all digit pins as output and turn them off (common cathode, so HIGH is off)
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH);
}
}
loop()関数内で、最初の桁(d1)を有効にするには、その状態をLOWに設定します。右端の桁(d4)を有効にする場合は、0を3に変更してください。
void loop() {
digitalWrite(digitPins[0], LOW); // Turn on first digit
}
数字「2」を表示するには、セグメントa、b、d、e、およびgを
HIGHに設定します。これで数字「2」が表示されます。
void loop() {
digitalWrite(digitPins[1], LOW); // Turn on first digit
digitalWrite(segmentPins[0], HIGH); //Turn on segment a
digitalWrite(segmentPins[1], HIGH); //Turn on segment b
digitalWrite(segmentPins[3], HIGH); //Turn on segment d
digitalWrite(segmentPins[4], HIGH); //Turn on segment e
digitalWrite(segmentPins[6], HIGH); //Turn on segment g
}
コードをArduino Uno R3ボードにアップロードすると、最初の桁に数字「2」が表示されます。
// Define the pins of the segments and the digits on the 4-digit 7-segment display
int segmentPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; // Segments a~g and dp (decimal point)
int digitPins[] = { 10, 11, 12, 13 }; // Digits d1-d4
void setup() {
// Set all segment pins as output
for (int i = 0; i < 8; i++) {
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], LOW); // Ensure all segments are off initially
}
// Set all digit pins as output and turn them off (common cathode, so HIGH is off)
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH);
}
}
void loop() {
digitalWrite(digitPins[1], LOW); // Turn on first digit
digitalWrite(segmentPins[0], HIGH); //Turn on segment a
digitalWrite(segmentPins[1], HIGH); //Turn on segment b
digitalWrite(segmentPins[3], HIGH); //Turn on segment d
digitalWrite(segmentPins[4], HIGH); //Turn on segment e
digitalWrite(segmentPins[6], HIGH); //Turn on segment g
}
コード作成 - 1桁に数字をスクロール表示
前のプロジェクトでは、1桁に「2」を表示する方法を学びました。しかし、0から9までの数字をスクロール表示したい場合、同じ方法を使うと非常に長くなってしまいます。
レッスン28では、コモンカソードディスプレイでの数字0〜9のバイナリ、10進数、および16進数コードを学びました。
数字 |
バイナリ |
10進数 |
16進数 |
|---|---|---|---|
0 |
B00111111 |
63 |
0x3F |
1 |
B00000110 |
6 |
0x06 |
2 |
B01011011 |
91 |
0x5B |
3 |
B01001111 |
79 |
0x4F |
4 |
B01100110 |
102 |
0x66 |
5 |
B01101101 |
109 |
0x6D |
6 |
B01111101 |
125 |
0x7D |
7 |
B00000111 |
7 |
0x07 |
8 |
B01111111 |
127 |
0x7F |
9 |
B01101111 |
111 |
0x6F |
1桁に0から9の数字をスクロールさせる方法
先ほど保存したスケッチ
Lesson32_Show_2_One_Digitを開き、「ファイル」メニューから「名前を付けて保存...」を選択し、Lesson32_Scroll_Numbers_One_Digitに名前を変更して保存します。数字0〜9のバイナリコードを
numArray[]配列に格納します。
// Define the pins of the segments and the digits on the 4-digit 7-segment display
int segmentPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; // Segments a~g and dp (decimal point)
int digitPins[] = { 10, 11, 12, 13 }; // Digits d1-d4
//display 0,1,2,3,4,5,6,7,8,9
int numArray[] = { B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111 };
次に、選択した数字を指定した桁に表示する関数を作成します。
void displayNumberOnDigit(int number, int digit) {
// Turn off all digits to prevent ghosting when switching numbers
for (int i = 0; i < 4; i++) {
// Turn off digit (common cathode -> HIGH is off)
digitalWrite(digitPins[i], HIGH);
}
// Set the segments for the current number
int value = numArray[number];
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], (value >> i) & 1); // Set each segment
}
// Turn on the selected digit (common cathode -> LOW is on)
digitalWrite(digitPins[digit], LOW);
}
番号を切り替える際にゴースティングを防ぐためにすべての桁をオフにします。
// Turn off all digits to prevent ghosting when switching numbers
for (int i = 0; i < 4; i++) {
// Turn off digit (common cathode -> HIGH is off)
digitalWrite(digitPins[i], HIGH);
}
ビット演算を使用して各数字に対応するセグメントを点灯します。
// 現在の番号のセグメントを設定する int value = numArray[number]; for (int i = 0; i < 8; i++) { digitalWrite(segmentPins[i], (value >> i) & 1); // Set each segment }
ここで、
numArray[]配列の要素が変数valueに割り当てられます。numberが2の場合、numArray[]の3番目の要素(B01011011)がvalueに割り当てられます。次に、
forループでB01011011の8ビット(Bを除く)をsegmentPins[i]配列にdigitalWrite()を使用して書き込みます。これにより、セグメントa、b、d、e、およびgが1に設定され、c、f、およびdpが0に設定されて、数字2が表示されます。&はAND演算子で、ビットごとのAND演算を実行します。1&1は1、1&0は0になります。
>>は右シフト演算子で、指定したビット数だけ右にシフトします。たとえば、iが1の場合、B01011011は1ビット右にシフトし、右端のビットが削除され、左に0が追加されます。iが2の場合、B01011011は2ビット右にシフトし、右端の2ビットが削除され、左に2つの0が追加されます。右シフトの結果に対して、ビットごとのAND演算が1と行われ、1または0が得られます。
表示する数字の桁のみを有効にします。
// Turn on the selected digit (common cathode -> LOW is on)
digitalWrite(digitPins[digit], LOW);
void loopのメインプログラムで、forループを使用して、左端の桁が0から9までの数字をスクロールするようにします。
void loop() {
// Display numbers 0 to 9 sequentially on the first digit (D1)
for (int num = 0; num < 10; num++) {
displayNumberOnDigit(num, 0); // Display the number on digit 1 (index 0)
delay(1000); // Display each number for 1 second
}
}
以下は完成したコードです。これをArduino Uno R3にアップロードすると、左端の桁に0から9までの数字がスクロール表示されるのが確認できます。
// Define the pins of the segments and the digits on the 4-digit 7-segment display
int segmentPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; // Segments A-G and DP (decimal point)
int digitPins[] = { 10, 11, 12, 13 }; // Digits D1-D4
//display 0,1,2,3,4,5,6,7,8,9
int numArray[] = { B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111 };
void setup() {
// Set all segment pins as output
for (int i = 0; i < 8; i++) {
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], LOW); // Ensure all segments are off initially
}
// Set all digit pins as output and turn them off (common cathode, so HIGH is off)
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH);
}
}
void loop() {
// Display numbers 0 to 9 sequentially on the first digit (D1)
for (int num = 0; num < 10; num++) {
displayNumberOnDigit(num, 0); // Display the number on digit 1 (index 0)
delay(1000); // Display each number for 1 second
}
}
void displayNumberOnDigit(int number, int digit) {
// Turn off all digits to prevent ghosting when switching numbers
for (int i = 0; i < 4; i++) {
// Turn off digit (common cathode -> HIGH is off)
digitalWrite(digitPins[i], HIGH);
}
// Set the segments for the current number
int value = numArray[number];
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], (value >> i) & 1); // Set each segment
}
// Turn on the selected digit (common cathode -> LOW is on)
digitalWrite(digitPins[digit], LOW);
}
質問
プログラミングにおいて、ビット単位の演算( AND や OR )は、データの個々のビットを操作する上で重要です。ビット単位の AND 演算( & )は、オペランドの各ビットを比較し、両方のビットが1の場合に1、それ以外の場合は0を返します。一方、ビット単位の OR 演算( | )は、少なくとも1つのビットが1である場合に1、両方のビットが0の場合にのみ0を返します。
この情報を踏まえて、式 (B01011011 >> 2) | 1 を考えてみましょう。2ビット右シフトしたバイナリ数 B01011011 に対して、ビット単位の OR 演算を1と行った結果はどうなりますか?
コード作成 - ストップウォッチ
これまでに、一桁の数字を表示し、その数字をスクロールする方法を学びました。今回は、4桁の7セグメントディスプレイを使用してストップウォッチを作成する方法を学びましょう。
ストップウォッチを作成するには、左側の2桁で分を、右側の2桁で秒を表示します。
秒数が59に達すると0にリセットされ、分数が1増加します。
分数が99に達すると0にリセットされ、再びカウントが開始されます。
先ほど保存したスケッチ
Lesson32_Show_2_One_Digitを開き、「名前を付けて保存...」を選択し、Lesson32_Stopwatchに名前を変更して保存します。次に、時間の要素を保存するための3つの変数を作成します。
previousMillisは最後に表示が更新されてからの時間を記録し、secondsとminutesはストップウォッチの時間を保存します。
// Define the pins of the segments and the digits on the 4-digit 7-segment display
int segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9}; // Segments A-G and DP (decimal point)
int digitPins[] = {10, 11, 12, 13}; // Digits D1-D4
//display 0,1,2,3,4,5,6,7,8,9
int numArray[] = { B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111 };
// Variables to store time components
unsigned long previousMillis = 0; // Stores the last time the display was updated
int seconds = 0; // Stores the second count
int minutes = 0; // Stores the minute count
void loop()関数内で:
millis()関数を使用して、Arduinoボードが現在のプログラムを実行し始めてからのミリ秒数を返します。1000ミリ秒(1秒)ごとに秒数を1ずつ増加させます。秒数が60に達すると0にリセットされ、分数が増加します。分数が100に達すると0にリセットされ、再びカウントが開始されます。
各ループの反復ごとに
updateDisplay()を呼び出して、現在の秒数と分数に基づいてディスプレイを積極的にマルチプレックスします。
void loop() {
unsigned long currentMillis = millis(); // Get the current time in milliseconds
if (currentMillis - previousMillis >= 1000) { // Check if a second has passed
previousMillis = currentMillis; // Reset the timer
seconds++; // Increment the seconds
if (seconds >= 60) { // Check if 60 seconds have passed
seconds = 0; // Reset seconds
minutes++; // Increment the minutes
if (minutes > 99) { // Check if 100 minutes have passed
minutes = 0; // Reset minutes
}
}
}
updateDisplay(); // 現在の時間を表示するようにディスプレイを更新
}
updateDisplay()関数について: 1秒ごとに表示を設定する代わりに、updateDisplay()はメインループ内で継続的に呼び出されます。この関数は各桁を順に処理し、短時間その桁を点灯させてから再びオフにします。このプロセスは高速で繰り返され、安定した表示が行われているように見えます。
void updateDisplay() {
for (int digit = 0; digit < 4; digit++) {
setDigitValues(minutes, seconds, digit);
digitalWrite(digitPins[digit], LOW); // Turn on current digit
delay(5); // Delay to keep the digit visible
digitalWrite(digitPins[digit], HIGH); // Turn off digit
}
}
setDigitValues()関数について:setDigitValues()は、現在の時間(分と秒)に基づいて各桁のセグメントを設定します。この関数は、桁が有効になるたびに呼び出され、正しい値を表示するようにします。
void setDigitValues(int mins, int secs, int digit) {
int values[] = {
mins / 10, // tens of minutes
mins % 10, // ones of minutes
secs / 10, // tens of seconds
secs % 10 // ones of seconds
};
int value = numArray[values[digit]];
for (int segment = 0; segment < 8; segment++) {
digitalWrite(segmentPins[segment], (value >> segment) & 1);
}
}
以下は完成したコードです。これをArduinoボードにアップロードすると、4桁の7セグメントディスプレイにストップウォッチが表示されるのを確認できます。
// Define the pins of the segments and the digits on the 4-digit 7-segment display
int segmentPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 }; // Segments A-G and DP (decimal point)
int digitPins[] = { 10, 11, 12, 13 }; // Digits D1-D4
//display 0,1,2,3,4,5,6,7,8,9
int numArray[] = { B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111 };
// Variables to store time components
unsigned long previousMillis = 0; // Stores the last time the display was updated
int seconds = 0; // Stores the second count
int minutes = 0; // Stores the minute count
void setup() {
// Set all segment pins as output
for (int i = 0; i < 8; i++) {
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], LOW); // Ensure all segments are off initially
}
// Set all digit pins as output and turn them off (common cathode, so HIGH is off)
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], HIGH);
}
}
void loop() {
unsigned long currentMillis = millis(); // Get the current time in milliseconds
if (currentMillis - previousMillis >= 1000) { // Check if a second has passed
previousMillis = currentMillis; // Reset the timer
seconds++; // Increment the seconds
if (seconds >= 60) { // Check if 60 seconds have passed
seconds = 0; // Reset seconds
minutes++; // Increment the minutes
if (minutes > 99) { // Check if 100 minutes have passed
minutes = 0; // Reset minutes
}
}
}
updateDisplay(); // Update the display to show the current time
}
void updateDisplay() {
for (int digit = 0; digit < 4; digit++) {
setDigitValues(minutes, seconds, digit);
digitalWrite(digitPins[digit], LOW); // Turn on current digit
delay(5); // Delay to keep the digit visible
digitalWrite(digitPins[digit], HIGH); // Turn off digit
}
}
void setDigitValues(int mins, int secs, int digit) {
int values[] = {
mins / 10, // tens of minutes
mins % 10, // ones of minutes
secs / 10, // tens of seconds
secs % 10 // ones of seconds
};
int value = numArray[values[digit]];
for (int segment = 0; segment < 8; segment++) {
digitalWrite(segmentPins[segment], (value >> segment) & 1);
}
}
最後に、コードを保存して作業スペースを整理することを忘れないでください。
まとめ
今回のレッスンでは、4桁の7セグメントディスプレイの機能を探り、Arduinoを使ってそれを制御する方法を学びました。まず、1桁に数字を表示する方法を学び、次に数字をスクロールする方法を学びました。最後に、これらのスキルを組み合わせて、分と秒を表示するシンプルなストップウォッチを作成しました。このプロジェクトを通じて、デジタルディスプレイについて学ぶだけでなく、Arduinoでのプログラミングスキルも向上しました。レッスンを完了したことを称賛し、さらに素晴らしいプロジェクトを作成するために実験を続けてください!





