C言語

ラズパイでLED点灯②(応用編)

ラズパイでLED点灯②(応用編)

スポンサーリンク

こんにちは!機械学習の「教師あり学習」のアルゴリズムに苦戦しています。駆け出しエンジニアのまっきーです。まだまだ勉強が足りませんね....

今回は、前回に引き続きLED点灯を行っていきたいと思います。

本日は3つの課題に取り組みます!PDFはこちらからダウンロードできます。

課題一覧

  1. 左シフトを繰り返すLED点灯
  2. 左シフトと右シフトを繰り返すLED点灯
  3. キーボードから入力された数値を2進数でLEDに表示する

電子回路

回路図は前回と全く同じです。

画像に alt 属性が指定されていません。ファイル名: LED点灯回路-1-1024x803.jpg

左シフトを繰り返すLED点灯

シフト演算とは、ビットを左右にシフトさせる演算のことです。

シフト演算には右シフト(>>)と左シフト(<<)があります
右シフトは連続したビットを右に、左シフトはビットを左にずらします

0010 0110 -右に1シフト-> 0001 0011
0011 0101 -左に2シフト-> 1101 0100

例えばこのように2進ビット列を左右に振ることができます
シフト演算で溢れたビットは抹消されます

ソースコード

#include <stdio.h>
#include <wiringPi.h>

int led[4] = {23,24,20,21};//LED0,LED1,LED2,LED3

int ShiftBit(int bit);

int main(void){
	int i;
	int bit = 1;
	//wiringPi初期化、LEDを出力に設定
	if(wiringPiSetupGpio() == -1) return 1;
	for(i=0;i<4;i++){
		pinMode(led[i],OUTPUT);
	}
	//無限ループ作成
	while(1){
		
		ShiftBit(bit);
		bit = bit << 1;
		if(bit > 8) bit = 1;
	}
	return 0;
}
int ShiftBit(int bit){
	int i;
	for(i=0;i<4;i++){
		digitalWrite(led[i],bit&1);
		bit = bit >> 1;
	}
		delay(100);
}

前回の課題で学習したビット操作をそのまま使用しました。

メイン関数で、左シフトをbitが8(二進数で1000)より大きくなったら1に戻すことで連続点灯をさせました。点灯間隔は0.1秒にしています。

著者のソースコードでは、for文のカウント変数であるiを左シフトさせていました。

こんなやり方もできるんですね!勉強になります。

while(1){                   //永久ループ
        for(i=1;i<16;i<<=1){    //変数iをfor文内で左シフトさせる
            Led4bit(i);         //変数iを4bit出力する
            delay(500);         //0.5秒時間待ち
        }
    }

左シフトと右シフトを繰り返すLED点灯

ソースコード

#include <stdio.h>
#include <wiringPi.h>

int led[4] = {23,24,20,21};//LED0,LED1,LED2,LED3

int ShiftBit(int bit);

int main(void){
	int i;
	int bit = 1;
	//wiringPi初期化、LEDを出力に設定
	if(wiringPiSetupGpio() == -1) return 1;
	for(i=0;i<4;i++){
		pinMode(led[i],OUTPUT);
	}
	//無限ループ作成
	while(1){
		
		bit = 1;
		 
		for(i=0;i<3;i++){
		ShiftBit(bit);
		bit = bit << 1;
		}
		bit =8;
		for(i=0;i<3;i++){
		ShiftBit(bit);
		bit = bit >> 1;
		}
	}
	
	return 0;
}

int ShiftBit(int bit){
	int i;
	for(i=0;i<4;i++){
		digitalWrite(led[i],bit&1);
		bit = bit >> 1;	
	}
	delay(300);
}

少し強引ではありますが、先ほどの問題と同じように右シフトをさせました。

左シフト4回、右シフト4回繰り返すと重なる部分ができてしまいます。

そのため、for文の繰り返しを3回ずつに減らすことで課題通りに点灯させることができました。

著者のソースコードはこちらです。

for文の初期化を利用し、if文と合わせるという使い方は初めて見ました。こちらの方がやはりコードがまとまっていて見やすいですね。

    while(1){
        for(i=0;i<4;i++){       //4回左シフト
            if (i==0){ ledData=0b0001;} //iが0になったら,ledDataを1に初期化する
            Led4bit(ledData);
            ledData<<=1;
            delay(500);
        }
        for(i=0;i<2;i++){       //2回右シフト
            if(i==0) {ledData=0b0100;} //iが0になったら,ledDataを0100に初期化する
            Led4bit(ledData);
            ledData>>=1;
            delay(500);            
        }
    }

キーボードから入力された数値を2進数でLEDに表示する

ソースコード

#include <stdio.h>
#include <wiringPi.h>

int led[4] = {23,24,20,21};//LED0,LED1,LED2,LED3

int ShiftBit(int bit);

int main(void){
	int i;
	int num; //入力値格納用
	//wiringPi初期化、LEDを出力に設定
	if(wiringPiSetupGpio() == -1) return 1;
	for(i=0;i<4;i++){
		pinMode(led[i],OUTPUT);
	}
	//無限ループ作成
	while(1){
	
		printf("0~15,please enter the number >>> ");
		scanf("%d",&num);
		if(num >= 16 || num < 0){
			printf("check your number again");
		}else{
		ShiftBit(num);
	}
	}
	return 0;
}
int ShiftBit(int bit){
	int i;
	for(i=0;i<4;i++){
		digitalWrite(led[i],bit&1);
		bit = bit >> 1;	
	}
}

個人的にLEDの問題の中で一番簡単でした。scanf,printfを用いてユーザーに数字を入力させるようにしただけです。

著者のソースコードも同じような感じでしたが、

        }else{
            printf("入力の値が範囲外です\n\n");
            Led4bit(0);         //全てのLEDを消灯
        }

このように、求めてる値以外の入力の時、LEDをすべて消灯させていました。

このような細かい操作もしっかりと書かないといけませんね。

まとめと反省

・Lチカは、ただの点灯だけではなく、いろいろなことが実現できる

・LEDを用いてのビット操作は視覚的に理解しやすく、とてもいい教材になる

・やはりできるだけシンプルに見やすいコードを書くことが大切

次はタクトスイッチを用いた課題に取り組んでいきたいと思います!

ありがとうございました。

スポンサーリンク

-C言語