SSブログ

Arduinoで7セグLEDを使ってみる [Arduino]

秋月電子の,「ダイナミック接続4桁高輝度赤色7セグメントLED表示器 カソードコモン カソード共通接続」OSL40562-LRを入手したので,Arduinoで動かしてみる.

今回は,ArduinoのIOピンで直接制御してみる.高輝度で点灯させるにはトランジスタを併用してLEDへの電流を確保する必要があるが,ひとまずIOピンから出力できる電流量で点灯させてみる.

Arduino Unoでは,IOピンの定格電流は40mAのようなので,これを前提に考えると...

OSL40562-LRの順方向電圧はtyp2Vだが,Minが1.8Vなのでそれで計算する.
ArduinoのIOは5Vなので,
5V - 1.8 V = 3.2V
小数点も含めると8個のLEDがあるので,Totalで30mAぐらいに収めるとすると,1LEDあたり,
30mA / 8 = 3.75mA
3.2V / 3.75mA = 0.85KΩ
ということになる.

というわけで,手元にある抵抗から近いものを探して820Ωを採用.
実際に点灯させてみれば分かるが,室内で見ている限りこれで十分な視認性が得られる.

こんな感じで接続する.
7segLed_回路図.png

あとは,Arduino側のスケッチだが,今回は,Adafruitが公開しているLibraryを参考に改変して,出力する桁数を指定可能な7セグLED点灯用ライブラリを作ってみた.

表示テスト用のスケッチとあわせて示そう.

まず,ライブラリだが,以下の3つのファイルからなる.
Led7segment.h
Led7segment.cpp
keywords.txt
で,適当なディレクトリに,Led7segmentディレクトリを作成し,上記3つのファイルを保存してやればよい.

順にコードを示そう.

まず,Led7segment.h
/*
 * 数値を7セグLED用向けビットマップ値に変換する
 */

#ifndef LED_7SEGMENT_H
#define LED_7SEGMENT_H

class Led7segment
{
public:
    void print(unsigned char *buff, double value,
               unsigned int numeric_digits, unsigned int frac_digits = 1); 
    /*
     * buff           : 格納先バッファ(呼び出し元で必要なサイズ分を用意すること)
     * value          : 変換する値
     * numeric_digits : 出力する桁数(-符号含む桁数."."は含まない).例えば出力が"12.34"なら4.
     * frac_digits    : 出力する小数点以下桁数(桁数不足で表示できない場合は丸められる)
     */

private:
    void write(unsigned char *buff, unsigned int x, unsigned int num, bool is_dot = false);
    void write_minus(unsigned char *buff, int display_index);
    void write_space(unsigned char *buff, int display_index);
    void write_error(unsigned char *buff, int display_index);
};

#endif // LED_7SEGMENT_H


次に,Led7segment.cpp
/*
 * This is a library for 7segment LED OSL40562-LR.
 * 
 * function Led7segment::print were copied and modified from
 * Adafruit-LED-Backpack-Library(original function: Adafruit_7segment::printFloat).
 * https://github.com/adafruit/Adafruit-LED-Backpack-Library
 */
/*************************************************** 
  This is a library for our I2C LED Backpacks
  Designed specifically to work with the Adafruit LED Matrix backpacks 
  ----> http://www.adafruit.com/products/
  ----> http://www.adafruit.com/products/
  These displays use I2C to communicate, 2 pins are required to 
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.  
  MIT license, all text above must be included in any redistribution
  
  https://github.com/adafruit/Adafruit-LED-Backpack-Library/blob/master/license.txt
 ****************************************************/

#include <math.h>
#include "Led7segment.h"

namespace {
const unsigned char digits_table[] = {
   /*   _____
    *  |  A  |
    * F|     |B
    *  |_____|
    *  |  G  |
    * E|     |C
    *  |_____|  o DP
    *     D
    */
            /*    DP G F E D C B A */
    0x3F,   /* 0 : 0 0 1 1 1 1 1 1 */
    0x06,   /* 1 : 0 0 0 0 0 1 1 0 */
    0x5B,   /* 2 : 0 1 0 1 1 0 1 1 */
    0x4F,   /* 3 : 0 1 0 0 1 1 1 1 */
    0x66,   /* 4 : 0 1 1 0 0 1 1 0 */
    0x6D,   /* 5 : 0 1 1 0 1 1 0 1 */
    0x7D,   /* 6 : 0 1 1 1 1 1 0 1 */
    0x07,   /* 7 : 0 0 1 0 0 1 1 1 */
    0x7F,   /* 8 : 0 1 1 1 1 1 1 1 */
    0x6F,   /* 9 : 0 1 1 0 1 1 1 1 */
    0x00,   /*   : 0 0 0 0 0 0 0 0 */
    0x40,   /* - : 0 1 0 0 0 0 0 0 */
    0x80,   /* . : 1 0 0 0 0 0 0 0 */
};

const int SPACE_INDEX = 10;
const int MINUS_INDEX = 11;
const int DOT_INDEX   = 12;

} // namespace

void Led7segment::print(unsigned char *buff, double value,
                        unsigned int numeric_digits, unsigned int frac_digits) 
{ 
    const unsigned int base = 10;
    bool is_minus = false;

    int display_index = numeric_digits - 1;

    if (value < 0) {
        is_minus = true;
        numeric_digits--;
        value *= -1;
    }

    if (numeric_digits <= frac_digits) {
        frac_digits = numeric_digits - 1;
    }

    unsigned long to_int_factor = pow(base, frac_digits) + 0.5;
    unsigned long display_value = value * to_int_factor + 0.5;
    unsigned long max_limit = pow(base, numeric_digits) + 0.5;

    while (display_value >= max_limit) {
        to_int_factor /= base;
        display_value = value * to_int_factor + 0.5;
        frac_digits--;
    }

    if (to_int_factor != 0) {
        if (display_value != 0) {
            for (int i = 0; (display_value != 0) || (i <= frac_digits); i++) {
                const bool is_dot = (frac_digits != 0) && (i == frac_digits);
                write(buff, display_index--, display_value % base, is_dot);

                display_value /= base;
            }
        }
        else {
            for (int i = 0; i <= frac_digits; i++) {
                const bool is_dot = (frac_digits != 0) && (i == frac_digits);
                write(buff, display_index--, 0, is_dot);
            }
        }

        if (is_minus == true) {
            write_minus(buff, display_index--);
        }

        while (display_index >= 0) {
            write_space(buff, display_index--);
        }
    }
    else {
        while (display_index >= 0) {
            write_error(buff, display_index--);
        }
    }
}

void Led7segment::write(unsigned char *buff, unsigned int i, unsigned int num, bool is_dot)
{
    if (is_dot == true) {
        buff[i] = digits_table[num] | digits_table[DOT_INDEX];
    }
    else {
        buff[i] = digits_table[num];
    }
}

void Led7segment::write_minus(unsigned char *buff, int display_index)
{
    write(buff, display_index, MINUS_INDEX);
}

void Led7segment::write_space(unsigned char *buff, int display_index)
{
    write(buff, display_index, SPACE_INDEX);
}

void Led7segment::write_error(unsigned char *buff, int display_index)
{
    write(buff, display_index, MINUS_INDEX);
}


最後に,keywords.txt
Led7segment	KEYWORD1
print	KEYWORD2


ダウンロードするなら,こちらから.
Led7segment.zip.jpg
ただし,So-netのブログでは,zip圧縮ファイルのアップロードができないため,zip圧縮してから拡張子に.jpgをつけて無理矢理アップロードしている.
なので.ダウンロードしたら.jpgを消してzipファイルとして展開してやってください.

また,ライブラリの追加方法は,「arduino ライブラリ 追加」等で検索してみてください.

で,表示テスト用のスケッチは,Led_7seg.ino.
Led7segmentライブラリの使い方は,Led7segment.hと,これを見れば分かると思う.
なお,このスケッチではMsTimer2ライブラリを使用しているので,別途追加してやってください.
#include <MsTimer2.h>
#include <Led7segment.h>

const int anode_pins[] = {
    12, // A
    8,  // B
    5,  // C
    3,  // D
    2,  // E
    11, // F
    6,  // G
    4,  // DP
};

const int cathode_pins[] = {
    13, // DIG.1
    10, // DIG.2
    9,  // DIG.3
    7,  // DIG.4
};

const int ANODE_PINS_NUM   = sizeof(anode_pins)   / sizeof(anode_pins[0]);
const int CATHODE_PINS_NUM = sizeof(cathode_pins) / sizeof(cathode_pins[0]);

unsigned int display_buffer[CATHODE_PINS_NUM] = {0};

void write_1digit(const unsigned char bitmap)
{
    for (int i = 0; i < ANODE_PINS_NUM; i++) {
        digitalWrite(anode_pins[i], bitmap & (1 << i) ? HIGH : LOW);
    }
}

void clear()
{
    for (int i = 0; i < ANODE_PINS_NUM; i++) {
        digitalWrite(anode_pins[i], LOW);
    }
}

void write()
{
    for (int i = 0; i < CATHODE_PINS_NUM; i++) {
        digitalWrite(cathode_pins[i], LOW);
        write_1digit(display_buffer[i]);
        delayMicroseconds(100);
        clear();
        digitalWrite(cathode_pins[i], HIGH);
    }
}

void print_7seg(unsigned char *buff)
{
    noInterrupts();
    for (int i = 0; i < CATHODE_PINS_NUM; i++) {
        display_buffer[i] = buff[i];
    }
    interrupts();
}

void setup()
{
    for (int i = 0; i < ANODE_PINS_NUM; i++) {
        pinMode(anode_pins[i], OUTPUT);
    }

    for (int i = 0; i < CATHODE_PINS_NUM; i++) {
        pinMode(cathode_pins[i], OUTPUT);
        digitalWrite(cathode_pins[i], HIGH);
    }
    
    MsTimer2::set(1, write);
    MsTimer2::start();
}

void loop()
{
    unsigned char buff[CATHODE_PINS_NUM] = {0};
    const unsigned int numeric_digits = CATHODE_PINS_NUM;
    const unsigned int frac_digits = 3;

    Led7segment led;

    for (long i = -1000; i <= 10000; i++) {
        double d = i;
        led.print(buff, d, numeric_digits, frac_digits);
        print_7seg(buff);
        delay(100);
    }
    
    for (long i = -1000; i <= 10000; i++) {
        double d = i / 10.0;
        led.print(buff, d, numeric_digits, frac_digits);
        print_7seg(buff);
        delay(100);
    }
    
    for (long i = -1000; i <= 10000; i++) {
        double d = i / 100.0;
        led.print(buff, d, numeric_digits, frac_digits);
        print_7seg(buff);
        delay(100);
    }
    
    for (long i = -1000; i <= 10000; i++) {
        double d = i / 1000.0;
        led.print(buff, d, numeric_digits, frac_digits);
        print_7seg(buff);
        delay(100);
    }
}


この表示テスト用スケッチでは,
・-1000  〜 10000  まで,1    ずつ
・-100.0 〜 1000.0 まで,0.1  ずつ
・-10.00 〜 100.00 まで,0.01 ずつ
・-1.000 〜 10.000 まで,0.001ずつ
順に表示する動作になっていて,桁数が足りなくて表示できない値は「----」と表示されます.

それでは,お試しあれ.

タグ:7セグLED
nice!(0)  トラックバック(0) 
共通テーマ:日記・雑感

nice! 0

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。