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

本日の内容


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

3-1. Arduino 開発環境

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

部品表

機材 数量
arduinoシールド用基板1
1x40ピンヘッド 1
1x6ピンソケット 1
タクトスイッチ 4
錫メッキ線 20cm
5W0.1Ωセメント 1
5W3Ωセメント 1
100Ω 2
120Ω 3
220Ω 1
330Ω 25
1kΩ 6
10kΩ 3
22kΩ 2
5kΩ半固定 3
10μF16V 2
9V電池 1
電池スナップ 1
単3電池 2
単3電池2本用ボックス 2
3mmLED(赤or黃or緑) 4
LED(3or5mm,赤or黃or緑) 7
カソードコモン7segLED 1
3色LED 1
3色LED用キャップ 1
FA-130RAモータ 1
1N4007 4
2sc1815 2
2sk4017 2
2sb1018A 2
ta7291p 2

回路図

回路図

実体配線図

基板表面
基板裏面

青い線が配線。黄色い線は無視すること。

完成写真

基板表面
基板裏面

デバッグ

デバッグ
  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.asm
;
; Created: 2018/09/17 4:39:20
; Author : sakamoto
;

.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

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

演習3-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);
}

演習3-2

volatile 宣言を使う

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

演習3-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);
}

演習3-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);
}

演習3-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);
}

演習3-6

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

演習3-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();
  }
}