第 6 回 トレイニングボード

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

6-1. Arduino 開発環境

今後のプログラミング演習のために、7seg LED と押しボタンのあるトレー ニングキットを作成します。 部品、回路図を提供しますので、各自作成してきてください。

部品表

機材 数量
7segLEDカソードコモン1
LED(3or5mm,赤or黃or緑)7
LED3mm(赤or黃or緑)4
三色LED OSTA5131A1
三色LED用キャップ1
ダイオード1N40074
トランジスタ2SA14412
トランジスタ2SC18152
NchMOSFET 2SK40172
フォトトランジスタL-51ROPT1D11
モータドライバL293DN1
抵抗100Ω2
抵抗120Ω3
抵抗220Ω1
抵抗330Ω25
抵抗22kΩ2
抵抗1kΩ6
抵抗1MΩ1
セメント抵抗0.1Ω5W1
半固定抵抗5kΩ3
コンデンサ0.1μF2
マブチモータ FA-130RA1
ピンソケット1x61
ピンソケット1x81
ピンヘッド1x401
タクトスイッチ3
単3電池2本用ボックス1
単3電池3本用ボックス1
9V電池用スナップ1
電池9V1
電池単33
arduinoシールド用基板1
錫メッキ線30cm
パックシリコーンチューブ1mm2mm15cm
ラッピングワイヤ10cm

回路図

回路図

実体配線図

基板表面
基板裏面

青い線は基板裏面の配線。赤い線は基板表面の配線。黄色い線は無視すること。

完成写真

基板表面

抵抗のリードは曲げて配線に使う。


基板表面

抵抗とジャンパを取り付ける。ジャンパは片方をはんだ付けして、反対側 の必要な長さにペンで印を付け、被覆を落としてはんだ付けする。


基板表面

Arduino との接続は、Arduino にピンを差してはんだ付けするとぴったり 揃う。


基板裏面

デバッグ

チェック
デバッグ
  1. スイッチの直上、左のLEDの下の抵抗の下の部分(写真の青い部分)が GND になっているので、 右下のGND端子と導通があるかをテスターで確認 する。
  2. 3Vの電池ケースに電池を入れ、青い部分に黒のマイナス端子をつけ、赤 のプラス端子を図の黄色い部分の端子に付けると、正常に配線されていれば 対応するLEDが点灯する。
  3. 7SEGのLEDが全く点灯しない場合は、GNDのライン(青い部分)をチェックする

テストプログラム

C言語版

const byte out[] = {6,7,8,9,10,11,12,13,A0,A1,A2,A3,0xff};
const byte button1 = 4;
const byte button2 = 5;
void setup() {
  for(byte i = 0; out[i] != 0xff; i++){
    pinMode(out[i], OUTPUT);
  }
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
}

void writeArray(bool signal){
  for(byte i = 0; out[i] != 0xff; i++){
    digitalWrite(out[i], signal);
  }
}
void loop() {
  static bool prev = HIGH;
  static bool now = HIGH;
  static bool condition = HIGH;

  now = digitalRead(button2);
  if(now == HIGH && prev == LOW){
    condition ^= true;
  }
  prev = now;
  writeArray(condition == digitalRead(button1));
}

アセンブリ言語版 switchtraining

;
.include        "m328Pdef.inc"
.cseg
.org	0x0000
		rjmp	reset
.org	INT_VECTORS_SIZE
reset:
	ldi     r16,high(RAMEND)
	out     SPH,r16 
		ldi		r16,low(RAMEND)
		out		SPL,r16
.equ	onb	= 0b00111111
.equ	ond	= 0b11000000
.equ	pullup	= 0b00110000
.equ	onc	= 0b00001111
		ldi		r16,onb
		out		ddrb, r16
		ldi		r16,ond
		out		ddrd, r16
		ldi		r16,pullup
		out		portd, r16
		ldi		r16,onc
		out		ddrc, r16
.def	now	= r17
.def	prev	= r18
.def	cond	= r19
		clr		prev
		ser		cond


.macro	clrport
		in	r16,@0
		andi	r16,~@1
		out	@0,r16
.endmacro
.macro setport
		in	r16,@0
		ori	r16,@1
		out	@0,r16
.endmacro


main:
		in	now,pind
		sbrc	prev,pind5
		rjmp	pressed
		sbrs	now,pind5
		rjmp	notpressed
nowpressed:
		ldi	r16,1<<pind4
		eor	cond,r16
notpressed:
pressed:
		andi	prev,~(1<<pind5)
		or	prev,now
		eor	now, cond
		sbrc	now,pind4
		rjmp	swon
swoff:
		clrport portb,onb
		clrport	portd,ond
		clrport portc,onc
		rjmp	main
swon:
		setport portb,onb
		setport	portd,ond
		setport portc,onc
		rjmp	main

.exit
;
.include "m32U4def.inc"
.cseg
.org	0x0000
	rjmp	reset
.org	INT_VECTORS_SIZE
reset:
	ldi     r16,high(RAMEND)
	out     SPH,r16 
	ldi		r16,low(RAMEND)
	out		SPL,r16
.equ	onb	= 0b11110000
.equ	onc	= 0b10000000
.equ	ond	= 0b11000000
.equ	one	= 0b01000000
.equ	onf	= 0b11110011
.equ	pullup4	= 0b00010000 ; D4
.equ	pullup5	= 0b01000000 ; C6

		ldi		r16,onb
		out		ddrb, r16
		ldi		r16,onc
		out		ddrc, r16
        ldi		r16,ond
		out		ddrd, r16
        ldi		r16,one
		out		ddre, r16
        ldi		r16,onf
		out		ddrf, r16
		ldi		r16,pullup4
		out		portd, r16
		ldi		r16,pullup5
		out		portc, r16
.def	nowc	= r17
.def	prev	= r18
.def	cond	= r19
.def    nowd    = r20
		clr		prev
		ser		cond


.macro	clrport
		in	r16,@0
		andi	r16,~@1
		out	@0,r16
.endmacro
.macro setport
		in	r16,@0
		ori	r16,@1
		out	@0,r16
.endmacro


main:
		in	nowc,pinc
        in  nowd,pind
		sbrc	prev,pinc6
		rjmp	pressed
		sbrs	nowc,pinc6
		rjmp	notpressed
nowpressed:
		ldi	r16,1<<pind4
		eor	cond,r16
notpressed:
pressed:
		andi	prev,~(1<<pinc6)
		or	prev,nowc
		eor	nowd, cond
		sbrc	nowd,pind4
		rjmp	swon
swoff:
		clrport portb,onb
		clrport portc,onc
		clrport	portd,ond
		clrport porte,one
  		clrport portf,onf
		rjmp	main
swon:
		setport portb,onb
		setport portc,onc
        setport	portd,ond
		setport porte,one
		setport portc,onf
        rjmp	main

.exit
;
.include "m4809def.inc"
.cseg
.org	0x0000
	rjmp	reset
.org	INT_VECTORS_SIZE
reset:

	ldi     r16,low(RAMEND)
    out     CPU_SPL,r16
    ldi     r16,high(RAMEND)
    out     CPU_SPH,r16 
  
.equ    ona = 0b00000010
.equ	onb	= 0b00000011
.equ	onc	= 0b00000000
.equ	ond	= 0b00001111
.equ	one	= 0b00001111
.equ	onf	= 0b00010000
.macro	enableport
		lds    r16,@0
        ori    r16,@1
        sts    @0,r16
.endmacro
.macro	pullupport
        lds     r16,@0
        ori     r16,PORT_PULLUPEN_bm
        sts    @0,r16
.endmacro

        enableport  PORTA_DIR,ona
        enableport  PORTB_DIR,onb
        enableport  PORTC_DIR,onc
        enableport  PORTD_DIR,ond
        enableport  PORTE_DIR,one
        enableport  PORTF_DIR,onf
        pullupport PORTC_PIN6CTRL ; pin4 = C6
        pullupport PORTB_PIN2CTRL ; pin5 = B2

.def	nowc	= r17
.def	prev	= r18
.def	cond	= r19
.def    nowb    = r20
		clr		prev
		ser		cond


.macro	clrport
		lds	r16,@0
		andi	r16,~@1
		sts	@0,r16
.endmacro
.macro setport
		lds	r16,@0
		ori	r16,@1
		sts	@0,r16
.endmacro


main:
        lds     nowc,PORTC_IN
        lds     nowb,PORTB_IN
		sbrc	prev,6
		rjmp	pressed
		sbrs	nowc,6
		rjmp	notpressed
nowpressed:
		ldi	r16,1<<2
		eor	cond,r16
notpressed:
pressed:
		andi	prev,~(1<<6)
		or	prev,nowc
		eor	nowb, cond
		sbrc	nowb,2
		rjmp	swon
swoff:
		clrport PORTA_OUT,ona
		clrport PORTB_OUT,onb
		clrport PORTC_OUT,onc
		clrport	PORTD_OUT,ond
		clrport PORTE_OUT,one
  		clrport PORTF_OUT,onf
		rjmp	main
swon:
		setport PORTA_OUT,ona
		setport PORTB_OUT,onb
		setport PORTC_OUT,onc
        setport	PORTD_OUT,ond
		setport PORTE_OUT,one
		setport PORTF_OUT,onf
        rjmp	main

.exit

6-2. C,C++クリニック

演習6-1

volatile 宣言を使う

スケッチ例の Blink を改造して、自分の1秒待つ関数 mydelay を作ろう。

以下のプログラムで1秒点灯するように ??? の部分に数字を入れよう。


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
void mydelay(){
  for(volatile long i=0; i< ???; i++){
  }
}
void loop(){
  digitalWrite(LED_BUILTIN, HIGH);
  mydelay();
  delay(10);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

演習6-2

volatile 宣言を使う

演習6-1の volatile 宣言を外すと動きがどう変化するか確かめよう。

演習6-3

static 宣言を使う

以下のプログラムの長短を考えよう。

プログラム1


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
bool flag = true;
void loop(){
  digitalWrite(LED_BUILTIN, flag);
  flag = !flag;
  delay(1000);
}

プログラム2


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
void loop(){
  static bool flag = true;
  digitalWrite(LED_BUILTIN, flag);
  flag = !flag;
  delay(1000);
}

プログラム3


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
void loop(){
  bool flag = true;
  digitalWrite(LED_BUILTIN, flag);
  flag = !flag;
  delay(1000);
}

演習6-4

クラス宣言を使う

以下のプログラムの動作を考えよう。

プログラム1


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  bool flag = true;
public:
  void invert(){
  flag = !flag;
  digitalWrite(LED_BUILTIN, flag);
  }    
};
Led led;
void loop(){
  led.invert();
  delay(1000);
}

プログラム2


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  bool flag = true;
public:
  void invert(){
  flag = !flag;
  digitalWrite(LED_BUILTIN, flag);
  }    
};
void loop(){
  static Led led;
  led.invert();
  delay(1000);
}

プログラム3


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  bool flag = true;
public:
  void invert(){
  flag = !flag;
  digitalWrite(LED_BUILTIN, flag);
  }    
};
void loop(){
  Led led;
  led.invert();
  delay(1000);
}

プログラム4


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  bool flag = true;
public:
  void invert(){
  flag = !flag;
  digitalWrite(LED_BUILTIN, flag);
  }    
};
void loop(){
  static Led* p = new Led();
  p->invert();
  delay(1000);
}

演習6-5

クラスを使って機能を抽象化

以下のプログラムの動作を考えよう。

プログラム1


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  int times;
  void blinkLed(){
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
  }
public:
  Led(int t):times(t){}
  void flash(){
    for(int i=0; i<times; ++i){ 
      blinkLed();
    }    
    delay(1000);
  }
};
void loop(){
  static Led led(3);
  led.flash();
}

プログラム2


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  int times;
  void blinkLed(){
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
  }
public:
  Led(int t):times(t){}
  void flash(){
    for(int i=0; i<times; ++i){ 
      blinkLed();
    }    
    delay(1000);
  }
};
void loop(){
  static Led* leds[]={new Led(1), new Led(2), new Led(3), NULL};
  for(Led** p = leds; *p != NULL; ++p){
    (*p)->flash();
  }
}

プログラム3


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  int times;
  void blinkLed();
public:
  Led(int t);
  void flash();
};
Led::Led(int t):times(t){}
void Led::blinkLed(){
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}
void Led::flash(){
  for(int i=0; i<times; ++i){ 
    blinkLed();
  }    
  delay(1000);
}
void loop(){
  static Led* leds[]={new Led(1), new Led(2), new Led(3), NULL};
  for(Led** p = leds; *p != NULL; ++p){
    (*p)->flash();
  }
}

プログラム4

右のメニューから複数タブを作って、プログラムを分割する。

BlinkCpp

#include "Led.h"
void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
void loop(){
  static Led* leds[]={new Led(1), new Led(2), new Led(3), NULL};
  for(Led** p = leds; *p != NULL; ++p){
    (*p)->flash();
  }
}
Led.h

class Led {
  int times;
  void blinkLed();
public:
  Led(int t);
  void flash();
};
Led.cpp

#include "Arduino.h"
#include "Led.h"
Led::Led(int t):times(t){}
void Led::blinkLed(){
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}
void Led::flash(){
  for(int i=0; i<times; ++i){ 
    blinkLed();
  }    
  delay(1000);
}

演習6-6

演習6-1を利用して、1秒間の間だけ高速で点滅させて半分の明るさにする halfBlink メソッドを作りなさい。

演習6-7

だんだん明るくなってだんだん暗くなるような softBlink メソッドを作りなさい。

おまけ

やり過ぎ感のある、継承によるオブジェクトの作り分け


void setup(){
  pinMode(LED_BUILTIN,OUTPUT);    
}
class Led {
  void blinkLed(){
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);
  }
protected:
  virtual int times()=0;
public:
  virtual ~Led(){}
  void flash(){
    for(int i=0; i<times(); ++i){ 
      blinkLed();
    }    
    delay(1000);
  }
};
class Led2 : public Led {
protected:
  virtual int times(){
    return 2;
  }
};
class Led3 : public Led {
protected:
  virtual int times(){
    return 3;
  }
};
void loop(){
static Led* leds[]={new Led2(), new Led3(), NULL};
  for(Led** p = leds; *p != NULL; ++p){
    (*p)->flash();
  }
}