2014年11月5日水曜日

Arduinoで7セグLEDを動かそう!

こんにちは、今日は表題のとおり、Arduinoを用いてカソードコモン・タイプの7セグメントLEDを表示したいと思います。


準備

7セグメントLEDは各々のセグメントが独立しています。これらのピン配置を把握することが必要です。
+--+
|     |
+--+
|     |
+--+ dp.



私が用いた7セグLEDは地元の部品屋から買い付けたSHARPの余りもの(店長談)GL8P156です。
ピンアサインは以下の写真のようになっています。

大体20mA位でドライブするようです。Arduinoから出ているデジタルピンの出力は最大で40mA/pin、マイコンチップ全体のポート出力は最大200mAとのことなので、電流制限と損壊のリスクを低減するために、カソードコモン側に330Ωの抵抗を挿入します。

ちなみにGalileo gen1だと電流制限抵抗は不要になります。(ピン出力が20mA/pinで丁度よくなるため)


ソースコードは以下の通り。memcpy関数を呼び出すので、必然的にmemory.hをインクルードする必要があります。今回のような単純な配列ならこれでもいいのですが、memcpy関数を構造体に適用することは避けてください。代入文でどうにかなると思います。


#include <stdio.h>
#include <memory.h>
// font buffer.
int light[] = {
  0,0,0,0,0,0,0,0};
// font data.
int font0[] = {
  2,3,4,7,8,9,0,0};  // font data for "0".
int font1[] = {
  2,7,0,0,0,0,0,0};  // same as above, but value differs.
int font2[] = {
  3,2,5,9,8,0,0,0};
int font3[] = {
  3,2,5,7,8,0,0,0};
int font4[] = {
  4,5,2,7,0,0,0,0};
int font5[] = {
  3,4,5,7,8,0,0,0};
int font6[] = {
  3,4,5,9,7,8,0,0};
int font7[] = {
  4,3,2,7,0,0,0,0};
int font8[] = {
  4,3,2,5,9,7,8,0};
int font9[] = {
  2,3,4,5,7,8,0,0};
int blockSize = sizeof(light);  //get entire size of light buffer for memcpy.
int seg;  // pin number to light 7segLED.
int counter = 0;  // general counter.
void setup() {
  // put your setup code here, to run once:
  for(int i=2;i<=13;i++){
    pinMode(i, OUTPUT);
  }
  Serial.begin(9600);
}
void loop() {
  // put your main code here, to run repeatedly:
  //  allLow();
  segmentSet(counter%10);
  segmentHigh();
  delay(200);
  segmentLow();
  //  allLow();
  //  delay(10);
  counter++;
}
void allLow(){
  for(int i=2;i<=9;i++){
    digitalWrite(i, LOW);
  }
}
void segmentSet(int x){
  switch(x){
  case 0:
    memcpy(light, font0, blockSize);
    break;
  case 1:
    memcpy(light, font1, blockSize);
    break;
  case 2:
    memcpy(light, font2, blockSize);
    break;
  case 3:
    memcpy(light, font3, blockSize);
    break;
  case 4:
    memcpy(light, font4, blockSize);
    break;
  case 5:
    memcpy(light, font5, blockSize);
    break;
  case 6:
    memcpy(light, font6, blockSize);
    break;
  case 7:
    memcpy(light, font7, blockSize);
    break;
  case 8:
    memcpy(light, font8, blockSize);
    break;
  case 9:
    memcpy(light, font9, blockSize);
    break;
  default:
    break;
  }
}
void segmentHigh(){
  for(int i=0;i<=7;i++){
    seg = light[i];
    if(seg!=0){
      digitalWrite(seg, HIGH);
    }
    else{
    }
  }
}
void segmentLow(){
  for(int i=0;i<=7;i++){
    seg = light[i];
    if(seg!=0){
      digitalWrite(seg, LOW);
    }
    else{
    }
  }
}
segmentSet()関数で7セグ表示用int型のバッファlight に引数で指定されたフォントデータfontx(x=数字)配列をコピーします、コピーする長さblockSizeはsizeof演算子で算出します。

今回はsizeof(light), sizeof(font0)...sizeof(font9)の長さが揃っているので、どれを指定しても構いませんね。

segmentHigh()関数で表示バッファの配列を読み出し、0でなければ指定されたピンをHIGHにします、結果としてフォントバッファに溜まっている任意の数字のパターンが点灯するわけです。
segmentLow()関数では、表示バッファの配列を読み出し、0でなければ指定されたピンをLOWにします、結果として先ほど表示した数字が消灯するわけですね。
for文で全部のピンに対してdigitalWriteしてもいいのですが、関係ないピンまで実行してしまうので時間がかかってちらつきが増えます。

Arduino UNO、または他のArduino、Arduino互換ボード、Intel Galileo (Gen1)で動きます(*^-^*)
冒頭のfont配列変数を適宜指定することにより、色々な文字が表示できます。

0 件のコメント:

コメントを投稿