Physical Computing

Network and Information, Senshu Univ.

Menu
  • Home
  • Tips
  • About
  • admin

Month: December 2016

How to Use a Shift Register

December 21, 2016
| No Comments
| Tips

シフトレジスタの使い方について、説明します。 What is Shift Register? LPC824には、デジタル入出力に使えるピンが22本あります。これだけあれば、足りなくなることはないような気がしますよね。しかし、7セグLEDを使うと8本のデジタルピンを使ってしまいます。4桁の数字の表示器を作ろうと思ったら、単純な回路だと32本のピンが必要となり、足りません。そこで登場するのが、シフトレジスタです。 シフトレジスタ(shift register)は、マイコンのデジタル出力を増やすためのデバイスです。デジタル入力やPWM出力を増やすことはできないので、注意してください。ここでは、595や74×595、あるいは74HC595と呼ばれているシフトレジスタについて説明します。 シフトレジスタの中は、以下に示す図のようになっていると思ってください。 図中の「操作」と書かれているところは、マイコンのデジタル出力ピンに接続されます。「デジタル出力」と書かれているところが、増えたデジタル出力ピンです。つまり、1つシフトレジスタを使うと、8本 – 3本 = 5本、デジタル出力が節約できたことになります。さらにすごいことに、シフトレジスタは連結して使うことができます。つまり2個シフトレジスタを使っても、操作に使うデジタルピンは3本のままなのです。 シフトレジスタの操作は、以下の手順で行います。 クロック(clock)とラッチ(latch)をLOW(0)にする。 データレジスタ(data register)に、0か1を書き込む。 クロックをHIGH(1)にする。この時、R0からR7までのレジスタに格納されていた値は、それぞれ右にシフトする。つまり、R7の値は破棄され、R6の値がR7にコピーされる。これがR0まで繰り返される。さらに、データレジスタの値がR0にコピーされる。 クロックをLOWにする。 R0からR7まで値をセットし終わったら、ラッチをHIGH(1)にする。この時、R0からR7までの値に応じて、Q0からQ7までのデジタル出力ピンがHIGHまたはLOWになる。 ラッチをLOWにする。 この手順を見ると、なぜこのデバイスがシフトレジスタと呼ばれているのか分かると思います。 シフトレジスタは、コンピュータのあらゆるところに使われています。表示器やシリアル通信デバイス(UART)などです。 ここまでの話では、シフトレジスタはとても便利なデバイスで、良いことづくめのように思えますよね。しかし、これを使う時には、それなりの代償を払う必要があります。それは、スピードです。シフトレジスタではなく、マイコンのピンを直接使って8つのデジタル出力の状態を変化させるのには大した時間はかかりません。マイコン内部のレジスタの書き換えだけで済みます。ところがシフトレジスタを使った場合、8つのレジスタのセットを待たなくてはならず、しかもclockやlatchをHIGHにしてからLOWに戻すまでに、100nsから200nsほどの時間を置く必要があります。8つのデジタルピンの状態を変化させるのに、約1μsから2μsくらいの時間が、シフトレジスタを使わなかった時にかかる時間に加算されることになります。 How to Use それでは、シフトレジスタを使って7セグLEDに数字を表示してみましょう。7セグLEDの使い方は、TipsにあるHow to Use a Seven Segments LEDを参照してください。以下のように回路を作ります。ただし、シフトレジスタと7セグLEDを結ぶ線は、見にくくなるので省略してあります。 オレンジ色の線(dp17)がクロック、茶色の線(dp18)がラッチ、白い線(dp19)がデータレジスタです。シフトレジスタと7セグLEDは、ピン15(Q0)がピン1へ、ピン1(Q1)がピン2へ、ピン2(Q2)がピン3へと接続されます。 実際にブレッドボードを使って回路を作ってみると以下のようになります。 あとは、クロックとラッチ、データレジスタの操作だけで7セグLEDに数字を表示させることができます。シフトレジスタを操作するためのライブラリを作って見ましょう。ライブラリの作り方は、第13回の講義内容を見てください。まず、ShiftRegister595.hから作っていきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "mbed.h"
 
#define HIGH 1
#define LOW 0
 
class SR595 {
    
private:
    DigitalOut clock_pin;
    DigitalOut latch_pin;
    DigitalOut data_pin;
    
public:
    SR595(PinName, PinName, PinName);
    void set(int);
    void shift();
    void latch();
};
 

set()でデータレジスタへ値をセットし、shift()でクロックの操作をします。8bit分のデータをセットし終わったら、latch()でラッチの操作をします。 ShiftRegister595.cppは、以下の通りです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "ShiftRegister595.h"
 
SR595::SR595(PinName _clock_pin, PinName _latch_pin, PinName _data_pin):
                clock_pin(_clock_pin), latch_pin(_latch_pin), data_pin(_data_pin) {
}
 
void SR595::set(int x) {
    clock_pin = LOW;
    latch_pin = LOW;
    data_pin = x;
    wait_us(1);
}
 
void SR595::shift() {
    clock_pin = HIGH;
    wait_us(1);
    clock_pin = LOW;
}
 
void SR595::latch() {
    latch_pin = HIGH;
    wait_us(1);
    latch_pin = LOW;
}
 

クロックやラッチの操作をする時に、1μsのwaitを入れています。これは、少し時間をかけ過ぎですので、用途によってはもう少し小さい値で書き換えた方が良いでしょう。 このライブラリを使って7セグLEDに数字を表示させるプログラムを書いて見ましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "mbed.h"
#include "ShiftRegister595.h"
 
void disp_num(SR595, int[][8], int);
void clear_num(SR595);
 
SR595 sr(dp17, dp18, dp19);
 
int led_pattern[11][8]={
                    {0,0,0,1,0,0,0,1},        // 0
                    {0,1,1,1,1,1,0,1},        // 1
                    {0,0,1,1,0,0,1,0},        // 2
                    {1,0,0,1,0,0,1,0},        // 3
                    {1,1,0,1,0,1,0,0},        // 4
                    {1,0,0,1,1,0,0,0},        // 5
                    {0,0,0,1,1,1,0,0},        // 6
                    {1,1,0,1,0,0,1,1},        // 7
                    {0,0,0,1,0,0,0,0},        // 8
                    {1,0,0,1,0,0,0,0},        // 9
                    {1,1,1,0,1,1,1,1}         // dot
                  };
 
 
int main() {
    int i = 0;
    while(1) {
        disp_num(sr, led_pattern, i);
        i = (i + 1) % 10;
        wait(0.5);
    }
}
 
void disp_num(SR595 _sr, int _led_pattern[][8], int x) {
    int i;
    clear_num(_sr);
    for(i = 7; i >= 0; i--) {
        _sr.set(_led_pattern[x][i]);
        _sr.shift();
    }
    _sr.latch();
}
 
void clear_num(SR595 _sr) {
    int i;
    for(i = 0; i < 8; i++) {
        _sr.set(0);
        _sr.shift();
    }
    _sr.latch();
}
 

上記のプログラムで注意する点は、データをセットする順番です。8bit分のデータをセットする必要がありますが、最初にセットしたデータは最後のレジスタ(Q7)に入り、最後にセットしたデータは最初のレジスタ(Q0)に入ります。 本当は、7セグLEDを操作する関数も、クラスを使ってライブラリ化する方が良いと思います。興味がある人は、挑戦してみてください。 — by 飯田周作、専修大学

Read More »

Posted in Tips Tagged mbed, physical computing, 専修大学

Homework (Due 2017.1.9)

December 21, 2016
| No Comments
| Announcement

年明け最初の火曜日授業は、2017年1月10日(火)です。冬休みの宿題をやってきてください。ただし、皆さんも年末年始には様々なイベントがあって、なかなか忙しいでしょうから、かける時間は12時間程度とします。これは、丸一日+半日の計算です。一日4時間作業したとすると、3日分ですね。 Due Date 提出期限は、1月9日(月)の20:00です。CoursePowerに提出先が作成されています。必ず、PDF形式で提出してください。 Assignment 宿題は、最終成果物の制作を進めることです。 課題1. 回路の完成 すでに作成済みの回路図にしたがって、全てのデバイスをマイコンと接続してください。レポートには、回路図と作成した回路の写真を入れてください。 課題2. 最終成果物の機能を洗い出す 最終成果物に必要とされている機能を、箇条書きで挙げてください。例えば、「ボタンが押されるたびにLEDの点灯パターンを変える。点灯パターンは3種類ある。」というのが機能です。最終成果物は、この機能が寄せ集められたものです。機能は、細かく分けて定義することもできれば、大きなくくりで定義することもできます。そこは、実験のしやすさと、他者への説明のしやすさを考慮して決定してください。 課題3. 機能の実現 課題2で洗い出した機能を、時間の許す限り実装します。 — by 飯田周作、専修大学

Read More »

Posted in Announcement Tagged mbed, physical computing, 専修大学

# 13 Project Week 3

December 19, 2016
| No Comments
| Class materials

講義日: 2016.12.20 火曜日の講義では、C++でライブラリを作成する方法について説明します。次回の火曜日は年明けの1月10日です。1月10日は、教室ではなく、ワーキングスペースで作品完成のための作業を行います。 I. Defining a Class mbedは、C++でプログラミングします。C++は、C言語をオブジェクト指向言語に拡張したものですから、C言語の文法は、そのまま使えます。 C++は、クラスベースのオブジェクト指向言語です。クラスを定義して、それを具体化しオブジェクトを生成します。クラスの定義は、以下のように行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Foo {
private:
   int x, y;
public:
    Foo(int, int);
    int method1();
    int method2(float);
};
 
Foo::Foo(int _x, int _y) {
    x = _x;
    y = _y;
}
 
int Foo::method1() {
    ...
}
 
int Foo::method2(float _val) {
   ...
}
 

class クラス名 { … }で、クラスの定義をします。クラス本体にあるpublic:以下に宣言されている変数やメソッドは、他のオブジェクトから参照および呼び出しが可能です。private:以下に宣言されている変数およびメソッドは、このクラス内でしか参照および呼び出しができません。 C++の一般的な書き方としては、メソッドのプロトタイプ宣言とその定義は別々に書きます。例えば、method1()を見てみると、メソッド本体の定義は、クラス本体の外側にありますよね。メソッド本体の定義をする時には、method1()の本名であるFoo::method1()と書いて定義を行います。 さらに、一般的には、クラスの定義はヘッダファイルで、メソッドの定義はcppファイルで行うことが多いです。ここでは、Foo.hとFoo.cppに分けて見ましょう。まず、Foo.hを定義します。

1
2
3
4
5
6
7
8
9
class Foo {
private:
   int x, y;
public:
    Foo(int, int);
    int method1();
    int method2(float);
};
 

次に、Foo.cppです。先頭行で、Foo.hをインクルードしています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "Foo.h"
 
Foo::Foo(int _x, int _y) {
    x = _x;
    y = _y;
}
 
int Foo::method1() {
    ...
}
 
int Foo::method2(float _val) {
   ...
}
 

このように、ヘッダファイルとcppファイルに分ける利点は何でしょうか?これは、ヘッダファイルだけ見れば、このクラスの使い方分かるからです。メソッド本体の定義は、往々にして長くなりがちですから、プロトタイプ宣言だけがまとめられているヘッダファイルを作ると可読性が上がるのです。 Make your Own Libraries それでは、自分で定義したクラスをmbedのライブラリにして見ましょう。まず、mbed Compilerで新しいプロジェクトを作ってください。ここでは、MyOwnLibraryというプロジェクト名にしました。 「新規」から、「新しいライブラリ…」を選び、Fooという名前をつけてください。 以下のようになるはずです。 Fooが選択されていることを確認して、「新規」から「新しいファイル…」を選択します。ファイル名は、Foo.hにします。これで、Fooというライブラリフォルダの中に、Foo.hというヘッダファイルを作ることができました。Foo.hの中身は以下のようにします。

1
2
3
4
5
6
7
8
9
class Foo {
private:
    int x;
public:
    Foo(int);
    set(int);
    get();
};
 

今度は、Foo.cppを作りましょう。Foo.hと同じ要領で作成してください。Foo.cppの中身は、以下のようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "Foo.h"
 
Foo::Foo(int _x) {
    x = _x;
}
 
void Foo::set(int n) {
    x = n;
}
 
int Foo::get() {
    return x;
}
 

これらを使うようにmain.cppを書き換えます。Foo.hをインクルードしていることに注意してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "mbed.h"
#include "Foo.h"
 
Serial pc(USBTX, USBRX);
Foo myFoo(10);
 
int main() {
    wait(1);
    pc.printf("%d\n", myFoo.get());
    myFoo.set(0);
    pc.printf("%d\n", myFoo.get());
    return 0;
}

これをコンパイルして、LPC824に送ると、以下のような結果を得ます。 II. Practical Work 今週は、各自で手順を決めて最終成果物の作成を進めてください。先週終わらなかったデバイスのテストがある場合には、それを優先させてください。 今週の提出物は、作業報告書です。フォーマットは自由ですが、作品の進捗がわかる写真を2枚以上含めてください。 — by 飯田周作、専修大学

Read More »

Posted in Class materials Tagged mbed, physical computing, 専修大学

How To Use a Seven Segments LED

December 19, 2016
| No Comments
| Tips

7セグメントLEDの使い方を説明します。 What is Seven Segments LED? 7セグメントLEDとは、0から9までの数字1桁が表示できるデバイスです。一般的には、「ナナセグLED」とか、単に「ナナセグ」とか呼ばれています。ここでは、7セグLEDと呼びます。 7セグLEDは、大きく分けて2種類のものが存在しています。この2つは、それぞれアノードコモン、カソードコモンと呼ばれています。LEDは、極性があるデバイスで、電源のプラス側に接続する足をアノード、グランド(マイナス)側に接続する足をカソードと呼びましたよね。アノードコモンとは、このアノードが共通で、カソードが別々の足に割り当てられているタイプのものです。図で示すと、以下のようになっています。 カソードコモンはこの逆で、以下のようになっています。 つまり、アノードコモンを使う時にはシンク電流を使い、カソードコモンを使う時にはソース電流を使うことになります。 How to Use 実際に、どの足がどのLEDに対応しているかは、製品によって異なり、データシートで確認しなければいけません。ここでは、Para Light Electronics社のA-551SRD-Aという、アノードコモンの7セグLEDを使って説明します。データシートによると、この製品は以下のようになっています。 7セグというのは7つの部分という意味ですが、点があるので実際には8つのLEDが存在します。ピン番号は、以下のような配置になっています。 今、ピン1をdp9、ピン2をdp10、ピン3をdp11、ピン4をdp12、ピン5をdp16、ピン6をdp17、ピン7をdp18、ピン8をdp19に接続したとしましょう。この時、0と表示するには、ABCDEFを光らせれば良いわけです。具体的には、dp9、dp10、dp11、dp16、dp17、dp18を0にセットします。 実際に、ブレッドボード状に配線すると、以下のようになります。 配線が多くて、面倒ですね。7セグLEDのLEDは一般的な赤色LEDなので、順方向電圧低下は2Vで計算して良いでしょう。あまり明るく光らせる必要はないので、2mAから3mAくらいの電流が流れれば十分です。この例では、470Ωの抵抗を使用していますから、2.7mAくらいの電流が流れているはずです。 How to Program 7セグLEDで数字を表示するには、7個のLEDの点灯消灯をそれぞれ指定すれば良いですよね。しかし、一々プログラム中で指定していては面倒なので、以下のような配列で定義しましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int led_pattern[11][8]={
                    {0,0,0,1,0,0,0,1},        // 0
                    {0,1,1,1,1,1,0,1},        // 1
                    {0,0,1,1,0,0,1,0},        // 2
                    {1,0,0,1,0,0,1,0},        // 3
                    {1,1,0,1,0,1,0,0},        // 4
                    {1,0,0,1,1,0,0,0},        // 5
                    {0,0,0,1,1,1,0,0},        // 6
                    {1,1,0,1,0,0,1,1},        // 7
                    {0,0,0,1,0,0,0,0},        // 8
                    {1,0,0,1,0,0,0,0},        // 9
                    {1,1,1,0,1,1,1,1}         // dot
                  };
 

2次元配列の縦方向が、0から9までの数字と点に対応します。横方向は、8つのLEDを点灯させるか消灯させるかで、今回はアノードコモンを使っていますから、0で点灯、1で消灯です。横方向の並び順は、ピン番号順になっています。つまりled_pattern[x][0]がピン1、led_pattern[x][1]がピン2、led_pattern[x][7]がピン8となっています。この配列の定義は、7セグLEDをどのように配線したかと、アノードコモンなのかカソードコモンなのかによって変わりますから注意してください。 DigitalOutの定義も、配列を用いて行います。

1
2
DigitalOut pins[8] = {dp9, dp10, dp11, dp12, dp16, dp17, dp18, dp19};
 

これは、先ほどのled_patternと同様に、ピン番号順になっています。 そうすると、当然、以下のような関数が欲しくなります。

1
2
3
void disp_num(DigitalOut[], int[][8], int);
void clear_num(DigitalOut[]);
 

disp_num()は、引数で指定した数字を7セグLEDに表示する関数です。clear_num()は、全消灯で何も表示しないようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void disp_num(DigitalOut _pins[], int _led_pattern[][8], int x) {
    int i;
    clear_num(_pins);
    for(i = 0; i < 8; i++) {
        _pins[i] = _led_pattern[x][i];
    }
}
 
void clear_num(DigitalOut _pins[]) {
    int i;
    for(i = 0; i < 8; i++) {
        _pins[i] = 1;
    }
}
 

最後に、完全なサンプルプログラムを載せておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "mbed.h"
 
void disp_num(DigitalOut[], int[][8], int);
void clear_num(DigitalOut[]);
 
DigitalOut pins[8] = {dp9, dp10, dp11, dp12, dp16, dp17, dp18, dp19};
int led_pattern[11][8]={
                    {0,0,0,1,0,0,0,1},        // 0
                    {0,1,1,1,1,1,0,1},        // 1
                    {0,0,1,1,0,0,1,0},        // 2
                    {1,0,0,1,0,0,1,0},        // 3
                    {1,1,0,1,0,1,0,0},        // 4
                    {1,0,0,1,1,0,0,0},        // 5
                    {0,0,0,1,1,1,0,0},        // 6
                    {1,1,0,1,0,0,1,1},        // 7
                    {0,0,0,1,0,0,0,0},        // 8
                    {1,0,0,1,0,0,0,0},        // 9
                    {1,1,1,0,1,1,1,1}         // dot
                  };
 
int main() {
    int i = 0;
    while(1) {
        disp_num(pins, led_pattern, i);
        i = (i + 1) % 10;
        wait(0.5);
    }
}
 
void disp_num(DigitalOut _pins[], int _led_pattern[][8], int x) {
    int i;
    clear_num(_pins);
    for(i = 0; i < 8; i++) {
        _pins[i] = _led_pattern[x][i];
    }
}
 
void clear_num(DigitalOut _pins[]) {
    int i;
    for(i = 0; i < 8; i++) {
        _pins[i] = 1;
    }
}
 

— by 飯田周作、専修大学

Read More »

Posted in Tips Tagged mbed, physical computing, 専修大学

How to use a Servo

December 13, 2016
| No Comments
| Tips

サーボモータの使い方を説明します。 What is Servo motor? DCモータは、電流を流すと一定の方向に回転し続けるモータです。この時、直流電流を使うのでDCモータと呼びます。対して、サーボモータは、もう少し賢いモータで、角度を指定して回転させることができます。サーボモータの中には、モータの軸がどのくらい回転したかを感知できるセンサと、モータの動きを制御するコントローラが入っています。 サーボモータのインターフェイスは、Vcc、GND、信号線の3つです。VCCには、必ず外部電源を使います。製品によって異なりますが、多くの場合、4.8Vから6Vの間の電圧を必要とします。GNDは、マイコンのグランドと接続します。信号線に、PwmOutを使ってパルス波を与えると、デューティ比に応じて角度が変わります。可動域は、180°のものが多いようです。 サーボモータは様々な種類が販売されていますが、マイコンで制御できる電子工作用のものは、大体500円から5,000円くらいの範囲の価格で手に入ります。この手のサーボモータは、以下のような信号を使います。 周期: 20ms パルス幅: 1ms(1000μs)から2ms(2000μs) ただし、パルス幅は製品によってかなり違いがあり、また、同じ製品でも個体差があります。よって、使用する際には、必ず事前に実験を行なって実際の値を決める必要があります。 How to Use それでは、早速使ってみましょう。ここでは、GWSという会社のPICO STDという製品を使ってみます。価格は、800円でした。以下のような回路を作ります。 ポイントは、外部電源(6V)のグラウンドをLPC824のグランドと接続すること、外部電源のプラスはLPC824の5Vや3.3Vと繋がないことです。外部電源を使う時には、常にこの2つを守ります。 プログラムは以下のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "mbed.h"
 
#define MIN_PW 800    // GWS pico std
#define MAX_PW 2100   // GWS pico std
PwmOut servo(dp16);
int main() {
    servo.period_ms(20);          // servo requires a 20ms period
    wait(1);
    
    while(1) {
        servo.pulsewidth_us(MIN_PW);
        wait(1);
        servo.pulsewidth_us(MIN_PW + (MAX_PW - MIN_PW) / 2);
        wait(1);
        servo.pulsewidth_us(MAX_PW);
        wait(1);
    }        
}
 
 

PwmOutのpulsewidth_us()に、800から2100の値を渡して、角度の調整をしています。しかし、この製品の場合には、可動域は180°よりもかなり狭いようです。800より小さい値や2100より大きな値を指定しても、角度は変わりません。この辺は、実験してみましょう。 — by 飯田周作、専修大学

Read More »

Posted in Tips Tagged mbed, physical computing, 専修大学

Posts navigation

1 2 Next

Recent Posts

  • NE22の学生さんたちへ
  • 13 発表会
  • 12 発表準備
  • 11 実装
  • 10 要素テスト

Archives

  • July 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • January 2018
  • December 2017
  • November 2017
  • October 2017
  • September 2017
  • July 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016

Categories

  • Announcement
  • Class materials
  • Tips
  • Uncategorized

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Physical Computing 2023 | Powered by WordPress.