2013/08/26

Arduino練習:四合一的七段顯示器

之前曾以四個七段顯示器製作時鐘,這篇則是介紹四合一的七段顯示器,目標是讓它從0000開始計數,然後每秒加1,0001、0002、0003、依此類推。

電路圖與原始碼可到GitHub下載,按「Download ZIP」即可全部下載,本篇程式碼位於子目錄SevenSegment4in1內。

底下是我買的共陰極、四合一型七段顯示器,每個七段顯示器含小數點。


底下是腳位圖,共有12個腳位,其中8個的功能就是控制七段顯示器,另4個腳位則代表想要控制哪一個七段顯示器,當腳位0為LOW、而腳位1、2、3為HIGH時,代表想要控制最右邊的七段顯示器,依此類推。


控制七段顯示器的8個腳位,a、b、c、d、e、f、g、h(dp),如下所示,本篇不使用h(dp)小數點。


因為有4個七段顯示器,我們必須使用掃描的方式不斷地顯示每一個七段顯示器,只要掃描速度夠快,基於視覺暫留原理,人眼便無法察覺,以為所有數字皆為同時顯示。

電路圖,沒什麼特別的,順著接即可,將在程式碼裡定義腳位的功能。

Arduino數位腳位2接到顯示器的0,
Arduino數位腳位3接到顯示器的g,
Arduino數位腳位4接到顯示器的c,
Arduino數位腳位5接到顯示器的h,
Arduino數位腳位6接到顯示器的d,
Arduino數位腳位7接到顯示器的e,
Arduino數位腳位8接到顯示器的b,
Arduino數位腳位9接到顯示器的1,
Arduino數位腳位10接到顯示器的2,
Arduino數位腳位11接到顯示器的f,
Arduino數位腳位12接到顯示器的a,
Arduino數位腳位13接到顯示器的3。

在下圖裡的四合一型七段顯示器擁有16個針腳,因為我找不到12個針腳的。




照理說,應該要串聯電阻220歐姆,不過我沒加也沒事orz。另外有些文章說Arduino輸出的電流不夠無法驅動,需加入NPN電晶體,不過我沒用也ok。

底下是程式碼:

// 定義腳位
#define PIN_0 2
#define PIN_g 3
#define PIN_c 4
#define PIN_h 5
#define PIN_d 6
#define PIN_e 7
#define PIN_b 8
#define PIN_1 9
#define PIN_2 10
#define PIN_f 11
#define PIN_a 12
#define PIN_3 13

// 共有4個七段顯示器,分別由針腳PIN_0、PIN_1、PIN_2、PIN_3控制
// 七段顯示器裡有8個LED(包含小數點)
#define POS_NUM 4
#define SEG_NUM 8
const byte pos_pins[POS_NUM] = {PIN_0, PIN_1, PIN_2, PIN_3};
const byte seg_pins[SEG_NUM] = {PIN_a, PIN_b, PIN_c, PIN_d, PIN_e, PIN_f, PIN_g, PIN_h};

// 底下定義由七段顯示器顯示數字時所需要的資料
#define t true
#define f false
const boolean data[10][SEG_NUM] = {
  {t, t, t, t, t, t, f, f}, // 0
  {f, t, t, f, f, f, f, f}, // 1
  {t, t, f, t, t, f, t, f}, // 2
  {t, t, t, t, f, f, t, f}, // 3
  {f, t, t, f, f, t, t, f}, // 4
  {t, f, t, t, f, t, t, f}, // 5
  {t, f, t, t, t, t, t, f}, // 6
  {t, t, t, f, f, f, f, f}, // 7
  {t, t, t, t, t, t, t, f}, // 8
  {t, t, t, t, f, t, t, f}, // 9
};

// 一支方便的函式,以格式字串輸出到序列埠
void pf(const char *fmt, ... ){
    char tmp[128]; // max is 128 chars
    va_list args;
    va_start (args, fmt );
    vsnprintf(tmp, 128, fmt, args);
    va_end (args);
    Serial.print(tmp);
}

// 設定某個七段顯示器所顯示的數字,
// 參數pos為0~3,指出想要更新哪一個七段顯示器,
// 參數n為0~9,顯示數字
void setDigit(int pos, int n){
  if(pos < 0 || 3 < pos){
    pf("error pos=%d\n", pos);
    return;
  }

  // 控制想要更新哪一個七段顯示器,將其腳位設為LOW
  // 其他腳位則設為HIGH,代表不更新。
  for(int p = 0; p < POS_NUM; p++){
    if(p == pos)
      digitalWrite(pos_pins[p], LOW);
    else
      digitalWrite(pos_pins[p], HIGH);
  }
  
  // 寫入數字
  if(0 <= n && n <= 9){
    for(int i = 0; i < SEG_NUM; i++){
      digitalWrite(seg_pins[i], data[n][i] == t ? HIGH : LOW);
    }
  }
  else{
    for(int i = 0; i < SEG_NUM; i++){
      digitalWrite(seg_pins[i], LOW);
    }
    digitalWrite(PIN_h, HIGH);
    pf("error pos=%d, n=%d\n", pos, n);
  }
}

// 設定整個四合一型七段顯示器想要顯示的數字
// 參數number的範圍應是0~9999
void setNumber(int number)
{
  int n0, n1, n2, n3;
  n3 = number / 1000;
  number %= 1000;
  n2 = number / 100;
  number %= 100;
  n1 = number / 10;
  n0 = number % 10;

  // 求出每個位數的值後,分別更新
  // 注意,此處以delay(5)隔開每個位數的更新
  setDigit(0, n0); delay(5);
  setDigit(1, n1); delay(5);
  setDigit(2, n2); delay(5);
  setDigit(3, n3); delay(5);
}

unsigned long time_previous;
void setup() {
  Serial.begin(115200);
 
  for(int i = 0; i < POS_NUM; i++){
    pinMode(pos_pins[i], OUTPUT);
    digitalWrite(pos_pins[i], HIGH);
  }
  for(int i = 0; i < SEG_NUM; i++){
    pinMode(seg_pins[i], OUTPUT);
    digitalWrite(seg_pins[i], LOW);
  }
 
  time_previous = millis();
}

int number = 0;
void loop() {
  // 經過一秒後就讓number加1
  unsigned long time_now = millis();
  if(time_now - time_previous > 1000){
    number++;
    time_previous += 1000;
    pf("number=%d\n", number);
  }

  // 不斷地寫入數字
  setNumber(number);
}

成功的話,一開始會顯示0000,然後是0001、0002、0003、等等。

可修改的地方:

  • 可使用4511減少腳位數量,但4511只能搭配共陰極七段顯示器。
  • 處理大於9999的情況。 
  • 修改setNumber函式裡delay(5)的延遲值,改成10或50,試試看有何效果。
參考資料:

72 comments:

  1. 呵~~~我同你一樣不信邪,
    突然有天 7 SEG.就不亮了,
    後來我都乖乖加電阻.

    ReplyDelete
  2. 我想把DS18B20的程式http://yehnan.blogspot.tw/2013/01/arduinods18b20.html跟這個4合一七段的程式合併
    顯示感測的數值在七段上 可是我做到最後可以顯示溫度了 但是百.十.個位數會一直閃
    加了這行之後就會開始一直閃sensors.requestTemperatures(); 就會開始一直閃
    可以教我一下如何合併嗎 ??

    ReplyDelete
  3. 小弟我剛學 亂湊湊出來了 你幫我看看

    // 匯入程式庫標頭檔
    #include
    #include

    // Arduino數位腳位22接到1-Wire裝置
    #define ONE_WIRE_BUS 22

    // 運用程式庫建立物件
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);

    // 定義腳位
    #define PIN_0 2
    #define PIN_g 3
    #define PIN_c 4
    #define PIN_h 5
    #define PIN_d 6
    #define PIN_e 7
    #define PIN_b 8
    #define PIN_1 9
    #define PIN_2 10
    #define PIN_f 11
    #define PIN_a 12
    #define PIN_3 13

    // 共有4個七段顯示器,分別由針腳PIN_0、PIN_1、PIN_2、PIN_3控制
    // 七段顯示器裡有8個LED(包含小數點)
    #define POS_NUM 4
    #define SEG_NUM 8
    const byte pos_pins[POS_NUM] = {PIN_0, PIN_1, PIN_2, PIN_3};
    const byte seg_pins[SEG_NUM] = {PIN_a, PIN_b, PIN_c, PIN_d, PIN_e, PIN_f, PIN_g, PIN_h};

    // 底下定義由七段顯示器顯示數字時所需要的資料
    #define t true
    #define f false
    const boolean data[10][SEG_NUM] = {
    {t, t, t, t, t, t, f, f}, // 0
    {f, t, t, f, f, f, f, f}, // 1
    {t, t, f, t, t, f, t, f}, // 2
    {t, t, t, t, f, f, t, f}, // 3
    {f, t, t, f, f, t, t, f}, // 4
    {t, f, t, t, f, t, t, f}, // 5
    {t, f, t, t, t, t, t, f}, // 6
    {t, t, t, f, f, f, f, f}, // 7
    {t, t, t, t, t, t, t, f}, // 8
    {t, t, t, t, f, t, t, f}, // 9
    };

    // 一支方便的函式,以格式字串輸出到序列埠
    void pf(const char *fmt, ... ){
    char tmp[128]; // max is 128 chars
    va_list args;
    va_start (args, fmt );
    vsnprintf(tmp, 128, fmt, args);
    va_end (args);

    }

    // 設定某個七段顯示器所顯示的數字,
    // 參數pos為0~3,指出想要更新哪一個七段顯示器,
    // 參數n為0~9,顯示數字
    void setDigit(int pos, int n){
    if(pos < 0 || 3 < pos){
    pf("error pos=%d\n", pos);
    return;
    }

    // 控制想要更新哪一個七段顯示器,將其腳位設為LOW
    // 其他腳位則設為HIGH,代表不更新。
    for(int p = 0; p < POS_NUM; p++){
    if(p == pos)
    digitalWrite(pos_pins[p], LOW);
    else
    digitalWrite(pos_pins[p], HIGH);
    }

    // 寫入數字
    if(0 <= n && n <= 9){
    for(int i = 0; i < SEG_NUM; i++){
    digitalWrite(seg_pins[i], data[n][i] == t ? HIGH : LOW);
    }
    }
    else{
    for(int i = 0; i < SEG_NUM; i++){
    digitalWrite(seg_pins[i], LOW);
    }
    digitalWrite(PIN_h, HIGH);
    pf("error pos=%d, n=%d\n", pos, n);
    }
    }

    // 設定整個四合一型七段顯示器想要顯示的數字
    // 參數number的範圍應是0~9999
    void setNumber(int number)
    {
    int n0, n1, n2, n3;
    n3 = number / 1000;
    number %= 1000;
    n2 = number / 100;
    number %= 100;
    n1 = number / 10;
    n0 = number % 10;

    // 求出每個位數的值後,分別更新
    // 注意,此處以delay(5)隔開每個位數的更新
    setDigit(0, n0); delay(5);
    setDigit(1, n1); delay(5);
    setDigit(2, n2); delay(5);
    setDigit(3, n3); delay(5);
    }

    unsigned long time_previous;
    void setup() {
    Serial.begin(115200);

    for(int i = 0; i < POS_NUM; i++){
    pinMode(pos_pins[i], OUTPUT);
    digitalWrite(pos_pins[i], HIGH);
    }
    for(int i = 0; i < SEG_NUM; i++){
    pinMode(seg_pins[i], OUTPUT);
    digitalWrite(seg_pins[i], LOW);
    }

    time_previous = millis();
    pinMode(24, OUTPUT);
    pinMode(26, OUTPUT);
    Serial.begin(115200);
    Serial.println("Temperature Sensor");
    // 初始化
    sensors.begin();
    }

    int number = 0;
    void loop(void) {
    // 要求匯流排上的所有感測器進行溫度轉換(不過我只有一個)
    sensors.requestTemperatures();

    // 取得溫度讀數(攝氏)並輸出,
    // 參數0代表匯流排上第0個1-Wire裝置
    Serial.println((int)((sensors.getTempCByIndex(0))*100));

    delay(100);
    digitalWrite(24, HIGH);
    if((sensors.getTempCByIndex(0)) > 40)
    {
    digitalWrite(26, HIGH);
    }
    else
    {
    digitalWrite(26, LOW);
    }
    number = ((int)((sensors.getTempCByIndex(0))*100));

    // 不斷地寫入數字
    setNumber(number);

    }

    ReplyDelete
    Replies
    1. 下面那24跟26腳是給繼電器的

      Delete
    2. 上面那個程式到底是哪裡讓我的七段一直閃?? 搞不懂 千位數就不會這樣

      Delete
  4. 你的loop()裡有delay(100);,所以七段顯示器會閃。

    四合一的七段顯示器,採用視覺暫留原理,必須不停地掃描顯示,不能停頓。

    ReplyDelete
  5. 是嗎?
    試試看吧
    http://pastebin.com/U6QEwgj8

    ReplyDelete
  6. 或可試試調整setNumber裡面的
    setDigit(0, n0); delay(5);
    setDigit(1, n1); delay(5);
    setDigit(2, n2); delay(5);
    setDigit(3, n3); delay(5);
    嘗試看看把5調小或調大。

    ReplyDelete
  7. 是不會閃了 不過7段顯示變成 (溫度亂打的)
    1953
    1
    1985
    1
    2123
    2
    多跳了一個千位出來 其他不會亮
    delay(5)剛剛好

    ReplyDelete
  8. 我剛剛看了一下 ARDUINO上那顆L一直亮滅(間隔1秒) 我記得他不是連著13腳 而且滅時就是只顯示千位的時候 跟這有關係嗎?

    ReplyDelete
  9. 只顯示1?其他不會亮,嗯,很奇怪。可能是晶片回傳錯的值。

    嗯,看來程式庫DallasTemperature預設為同步模式,會等溫度感測晶片轉換完後才回傳,
    改成非同步模式,但要拉長等待時間。


    試試吧http://pastebin.com/jkcJaNhq
    只編譯過,沒實際跑過。

    ReplyDelete
  10. 還是一樣耶 只不過兩個數字delay時間變長 單純只打七段0000-9999都不會這樣 沒關西喇 我在找找看 你休息吧 時間晚了不好意思浪費你這麼多時間 感謝你 至少比一開始有進步了

    ReplyDelete
    Replies
    1. 嗯,我弄錯API了。

      sensors.setCheckForConversion(false);
      改成
      sensors.setWaitForConversion(false);

      Delete
  11. 太感謝你拉~~終於OK了 我原本還想說拿著一直閃的去給教授評分

    ReplyDelete
  12. 已經試過0000~9999,我也想製作能讓溫度顯示在四合一七段上面,請問能否提供電路圖 感恩

    ReplyDelete
    Replies
    1. 沒有。

      請參考本篇跟Arduino練習:溫度感測DS18B20
      http://yehnan.blogspot.tw/2013/01/arduinods18b20.html
      然後撰寫程式碼。

      另可參考拙作《Arduino輕鬆入門:範例分析與實作設計》
      http://yehnan.blogspot.tw/2014/02/arduino_21.html
      裡頭有介紹數位溫度感測器DS18B20、溫濕度感測器DHT11、溫度氣壓感測器BMP085,
      不過都是使用LCD來顯示。

      LCD的操作可參考這篇
      以LiquidCrystal程式庫控制LCD(相容於Hitachi HD44780)
      http://yehnan.blogspot.tw/2012/02/arduinoliquidcrystallcdhitachi-hd44780.html

      Delete
  13. 請問5v蜂鳴器買不到可以使用3v串連100歐姆或是使用6 v的嗎

    ReplyDelete
    Replies
    1. 假定使用5V的Arduino板子,
      用6V蜂鳴器的話,應不會燒壞,但推得動嗎?

      用3V蜂鳴器的話,假設它需要10ma,那麼(5 - 3) / 0.01 = 200,應該串聯200 ohm電阻。
      假設它需要15ma的話,那麼應該串聯約150 ohm電阻。

      Delete
  14. 請問10k可變電阻是使用一般的還是精密的

    ReplyDelete
    Replies
    1. 您是問哪一篇啊?
      一般的即可。

      Delete
    2. 我是參考範例實作與實作分析7-1節
      請問蜂鳴器是將黑色接線接到200歐姆電阻,再將電阻接地嗎?

      Delete
    3. 電阻接黑線或紅線,應該都可以。

      Delete
    4. 請問 我使用200歐姆的電阻串連 蜂鳴器沒有發出聲音, LCD一子是顯示85度不會改變 是捨麼原因呢?

      Delete
    5. 85度是DS18B20的重置值,代表DS18B20沒有收到指令進行溫度轉換。


      Delete
    6. 原因很多,線路錯了、程式碼不對、DS18B20壞了、等等。

      Delete
    7. 好 我在檢查確認 謝謝

      Delete
    8. 您好,我使用書上寄生模式時溫度一子顯示85度,使用一般模式時 是負30~35之間,
      電路圖及程式碼都確認過沒有問題。

      Delete
    9. 呃,您都確認過沒有問題了,那怎麼辦?

      請提供詳盡清晰的電路照片與程式碼。

      Delete
    10. 程式碼是參照書上的

      #include
      #include
      #include
      #define SERIAL_BAUDRATE 19200
      #define LCD_RS_PIN 2
      #define LCD_E_PIN 3
      #define LCD_D4_PIN 4
      #define LCD_D5_PIN 5
      #define LCD_D6_PIN 6
      #define LCD_D7_PIN 7
      #define BUZZER_PIN 11
      #define DS18B20_PIN 12

      #define TEMPERATURE_HIGH_LIMIT 38 // 攝氏Celsius
      #define TEMPERATURE_LOW_LIMIT 10 // 攝氏Celsius

      #define NOTE_C5 523 // Do
      #define NOTE_CS5 554
      #define NOTE_D5 587 // Re
      #define NOTE_DS5 622
      #define NOTE_E5 659 // Mi
      #define NOTE_F5 698 // Fa
      #define NOTE_FS5 740
      #define NOTE_G5 784 // So
      #define NOTE_GS5 831
      #define NOTE_A5 880 // La
      #define NOTE_AS5 932
      #define NOTE_B5 988 // Si

      LiquidCrystal lcd(LCD_RS_PIN, LCD_E_PIN, LCD_D4_PIN, LCD_D5_PIN, LCD_D6_PIN, LCD_D7_PIN);
      OneWire oneWire(DS18B20_PIN);
      DallasTemperature tSensors(&oneWire);
      float c;
      float f;

      void pf(const char *fmt, ... ){
      char tmp[256];
      va_list args;
      va_start(args, fmt);
      vsnprintf(tmp, 256, fmt, args);
      va_end(args);
      Serial.print(tmp);
      }

      void alarmHandler(uint8_t *){
      lcd.setCursor(0, 1);
      lcd.write(byte(1));
      lcd.print(' ');
      if(TEMPERATURE_HIGH_LIMIT <= c){
      lcd.print("Too Hot!");
      tone(BUZZER_PIN, NOTE_C5, 3000 / 4);
      }
      else if(c <= TEMPERATURE_LOW_LIMIT){
      lcd.print("Too Cold!");
      tone(BUZZER_PIN, NOTE_B5, 3000 / 4);
      }
      }

      byte smileFace[8] = { // 笑臉
      B00000,
      B10001,
      B00000,
      B00000,
      B10001,
      B01110,
      B00000,
      };
      byte cryFace[8] = { // 哭臉
      B00000,
      B10001,
      B00000,
      B00000,
      B00000,
      B01110,
      B10001,
      };
      byte degreeCircle[8] = { // 代表「度」的小圈圈
      B00010,
      B00101,
      B00010,
      B00000,
      B00000,
      B00000,
      B00000,
      };

      void setup(void)
      {
      Serial.begin(SERIAL_BAUDRATE);
      while(!Serial){
      }
      lcd.createChar(0, smileFace);
      lcd.createChar(1, cryFace);
      lcd.createChar(2, degreeCircle);
      lcd.begin(16, 2);
      tSensors.begin();

      int deviceCount = tSensors.getDeviceCount();
      pf("There are %d device(s).\n", deviceCount);

      for(int i = 0; i < deviceCount; i++){
      uint8_t a[8];
      tSensors.getAddress(a, i);
      pf("Device index %d, address 0x %02x %02x %02x %02x %02x %02x %02x %02x\n",
      i, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
      // 設定溫度上下限
      tSensors.setHighAlarmTemp(a, TEMPERATURE_HIGH_LIMIT);
      tSensors.setLowAlarmTemp(a, TEMPERATURE_LOW_LIMIT);
      tSensors.setAlarmHandler(alarmHandler); // 設定警告處理函式
      }
      }

      void loop(void)
      {
      tSensors.requestTemperatures();
      c = tSensors.getTempCByIndex(0);
      f = tSensors.toFahrenheit(c);
      Serial.print("Temperature is ");
      Serial.print(c);
      Serial.print(" degree(Celsius), ");
      Serial.print(f);
      Serial.println(" degree(Fahrenheit).");

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(c);
      lcd.write(byte(2));
      lcd.print('C');
      lcd.setCursor(0, 1);
      lcd.write(byte(0));

      tSensors.processAlarms();
      delay(1000);
      }

      Delete
    11. 請提供詳盡清晰的電路照片。

      Delete
  15. This comment has been removed by the author.

    ReplyDelete
  16. 想請問此種7段顯示器可否透過74hc595來達到簡化街角的問題?
    以及想問老師74hc595是否可以串聯控制,謝謝

    ReplyDelete
    Replies
    1. > 74hc595是否可以串聯控制
      可以,請參考
      Arduino練習:霹靂車燈,以16個LED,製作霹靂車燈來回跑的效果,以兩顆74HC595控制16個LED。
      http://yehnan.blogspot.tw/2012/02/arduino_19.html

      > 此種7段顯示器可否透過74hc595來達到簡化街角的問題
      可以。但似乎不太直覺。

      通常會採用MAX7219,可控制8x8共陰極單色LED矩陣,或是8個七段顯示器(含小數點)。請參考拙作《Arduino輕鬆入門:範例分析與實作設計》,
      http://yehnan.blogspot.tw/2014/02/arduino_21.html
      的「5.5節 8x8 LED矩陣與MAX7219」。

      Delete
  17. This comment has been removed by the author.

    ReplyDelete
  18. 請問如何將DHT11測出的數值加進單顆七段顯示器裡

    ReplyDelete
  19. 這是我用DHT11的程式

    #include

    #define dht_dpin 2 //定義訊號要從Pin A0 進來

    dht DHT;

    void setup(){
    Serial.begin(9600);
    delay(300); //Let system settle
    Serial.println("Humidity and temperature\n\n");
    delay(700); //Wait rest of 1000ms recommended delay before
    //accessing sensor
    }

    void loop(){
    DHT.read11(dht_dpin); //去library裡面找DHT.read11
    Serial.print("Humidity = ");
    Serial.print(DHT.humidity);
    Serial.print("% ");
    Serial.print("temperature = ");
    Serial.print(DHT.temperature);
    Serial.println("C ");
    delay(1000); //每1000ms更新一次
    }

    ReplyDelete
    Replies
    1. 這一篇不就是在講七段顯示器嗎?有什麼問題嗎?

      另外,你程式碼loop()裡有delay(1000); ,這會對四合一的七段顯示器造成影響。
      應改用http://yehnan.blogspot.tw/2014/03/arduinoled.html裡的程式寫法。

      By the way,拙作「Arduino輕鬆入門:範例分析與實作設計」的第7.2節,讀取DHT11、顯示在LCD上,可供參考。

      Delete
    2. 若是我用單顆的七段顯示器4顆(不是四合一)
      那是要個別寫入單顆嗎?

      Delete
    3. 呃,沒試過。
      那樣的話,要二三十條線耶,
      不過就不必處理四合一的七段顯示器的掃描問題。

      Delete
  20. 我想先用4511做線會比較少

    ReplyDelete
  21. Anonymous7/8/15 12:00

    想請問Arduino的A0~A3接至7447的A~D,之後將7447的A~G接至四位數的七段顯示器A~G,然後將四位數的七段顯示器0~3接至Arduino的9~12,要使四位數的七段顯示器顯示0~9的話,程式上要怎麼撰寫呢??

    ReplyDelete
    Replies
    1. 7447應用於共陽極七段顯示器。
      四位數的七段顯示器、腳位0~3,控制顯示哪一個位數,例如腳位0為LOW、其他為HIGH,代表控制第0個位數。(也可能相反。)
      四位數的七段顯示器A~G,由7447的A0~A3控制,
      請參考拙作《Arduino輕鬆入門:範例分析與實作設計》的5.2節,該節使用4511(控制共陰極七段顯示器),原理相同。

      Delete
    2. Anonymous7/8/15 14:32

      謝謝!!我寫出來了^^

      Delete
  22. 可以請問一下那個Arduino和7位數碼管的模擬圖是用什麼軟件畫出來的嗎?

    ReplyDelete
  23. cdavid78920/2/16 12:48

    請教一下葉老師,若我用74164也可以嗎? 若不行CODE 應該要如何修改?

    ReplyDelete
    Replies
    1. 已於另一篇回覆。

      Delete
    2. 葉老師,我現在會1個seg顯示個位數,如果要進位成十位數,要如何進位

      Delete
    3. 不知道如何回答。

      這一篇不就是介紹如何使用四合一的七段顯示器嗎?

      Delete
  24. 不好意思請教一下,假如要將按鍵記數顯示於七段顯示器上,該將程式如何給合併,目前只知道顯示七段顯示器0000~9999
    功能的程式,
    按鍵記數:http://ohcoder.com/blog/2015/12/06/arduino-fun-button-count/
    七段顯示器0000~9999:http://www.arduino.cn/thread-3140-1-1.html

    ReplyDelete
    Replies
    1. > 該將程式如何給合併
      這不是問題,而是需求。

      請問問題是什麼?

      Delete
  25. 不好意思請問一下,本人我剛學,所以不懂為什麼void loop裡的意思
    // 經過一秒後就讓number加1
    unsigned long time_now = millis();
    if(time_now - time_previous > 1000){
    number++;
    time_previous += 1000;
    }
    如果我直接用
    delay(1000)
    number++
    也可以嗎?

    ReplyDelete
    Replies
    1. 為什麼不實際試試看呢?

      答案是不行,

      因為必須使用掃描的方式不斷地顯示每一個七段顯示器,只要掃描速度夠快,基於視覺暫留原理,人眼便無法察覺,以為所有數字皆為同時顯示。

      使用delay的話,就沒辦法達成上述要求。

      Delete
    2. 謝謝老師,我還有一個問題。
      我想做三組2位數的 輝光管 掃描
      因為有3個數字所以我做了3個setNumber()的副程式
      所以丟給它掃描是
      set_s(s);
      set_m(m);
      set_h(h); //功能是setNumber()的功能
      它會不會變成一次3個setDigit()同時輸出?

      Delete
    3. 看不太懂你的問題。

      > 會不會變成一次3個setDigit()同時輸出?
      不會。

      Delete
    4. 就會不會同時執行那三個副程式

      Delete
    5. 不會。Arduino沒有多個CPU核心,無法平行處理。

      執行程式都是從上到下,依序執行。

      Delete
    6. 原來如此,謝謝老師~

      Delete
  26. This comment has been removed by the author.

    ReplyDelete
  27. 老師您好,我想請問一下,我做的實驗是跟這個4合一七段的程式合併
    顯示感測器(MCP9701A)的數值在七段上,我們做到最後已經可以顯示溫度了,但是每個位數都會一直閃,
    我們有嘗試參考了老師您在17/12/14解決的方法,只不過網址打開不了

    我們程式如下:
    int sensorPin = A1;
    int analogin = 0;
    int ledg = 10; //選擇引腳的LED
    int ledp = 11;//選擇引腳的LED
    int tmp;

    int i,j;
    int count=0;
    int number;
    unsigned long time=0;
    const byte num[10]=
    { B11000000,B11111001,B10100100,B10110000,B10011001,
    B10010010,B10000010,B11111000,B10000000,B10010000};
    const int seg[]={2,3,4,5,6,7,8,9};
    const int digit[]={10,11,12,13};

    void setup() {
    Serial.begin(9600);
    pinMode(ledg,OUTPUT); // 定義LED為輸出腳
    pinMode(ledp,OUTPUT); // 定義LED為輸出腳
    analogReference(INTERNAL); //内部1.1V

    for(i=0;i<8;i++)
    pinMode(seg[i],OUTPUT);
    for(i=0;i<4;i++)
    {
    pinMode(digit[i],OUTPUT);
    digitalWrite(digit[i],HIGH);
    }
    }

    void loop() {
    // read the value from the sensor:
    int tmp;
    analogin = analogRead(sensorPin);
    Serial.println(analogin);
    tmp=(analogin-400)/19.5;
    Serial.print("tmp=");
    Serial.println(tmp);
    if(tmp>=26) \\設定當溫度大於等於26,ledp亮;相反,ledg亮。
    {
    digitalWrite(ledp,HIGH);
    digitalWrite(ledg,LOW);
    delay(500);
    }
    else
    {
    digitalWrite(ledg,HIGH);
    digitalWrite(ledp,LOW);
    delay(500);
    }

    number=count;
    for(i=3;i>=0;i--)
    {
    for(j=0;j<8;j++)
    {
    if(bitRead(num[number%10],j))
    digitalWrite(seg[j],HIGH);
    else
    digitalWrite(seg[j],LOW);
    }
    digitalWrite(digit[i],LOW);
    delay(5);
    digitalWrite(digit[i],HIGH);
    number=number/10;
    count=tmp;

    }
    }


    ReplyDelete
  28. 老師您好,我想請問一下,我做的實驗是跟這個4合一七段的程式合併
    顯示感測器(MCP9701A)的數值在七段上,我們做到最後已經可以顯示溫度了,但是每個位數都會一直閃,
    我們有嘗試參考了老師您在17/12/14解決的方法,只不過網址打開不了

    我們程式如下:
    int sensorPin = A1;
    int analogin = 0;
    int ledg = 10; //選擇引腳的LED
    int ledp = 11;//選擇引腳的LED
    int tmp;

    int i,j;
    int count=0;
    int number;
    unsigned long time=0;
    const byte num[10]=
    { B11000000,B11111001,B10100100,B10110000,B10011001,
    B10010010,B10000010,B11111000,B10000000,B10010000};
    const int seg[]={2,3,4,5,6,7,8,9};
    const int digit[]={10,11,12,13};

    void setup() {
    Serial.begin(9600);
    pinMode(ledg,OUTPUT); // 定義LED為輸出腳
    pinMode(ledp,OUTPUT); // 定義LED為輸出腳
    analogReference(INTERNAL); //内部1.1V

    for(i=0;i<8;i++)
    pinMode(seg[i],OUTPUT);
    for(i=0;i<4;i++)
    {
    pinMode(digit[i],OUTPUT);
    digitalWrite(digit[i],HIGH);
    }
    }

    void loop() {
    // read the value from the sensor:
    int tmp;
    analogin = analogRead(sensorPin);
    Serial.println(analogin);
    tmp=(analogin-400)/19.5;
    Serial.print("tmp=");
    Serial.println(tmp);
    if(tmp>=26) \\設定當溫度大於等於26,ledp亮;相反,ledg亮。
    {
    digitalWrite(ledp,HIGH);
    digitalWrite(ledg,LOW);
    delay(500);
    }
    else
    {
    digitalWrite(ledg,HIGH);
    digitalWrite(ledp,LOW);
    delay(500);
    }

    number=count;
    for(i=3;i>=0;i--)
    {
    for(j=0;j<8;j++)
    {
    if(bitRead(num[number%10],j))
    digitalWrite(seg[j],HIGH);
    else
    digitalWrite(seg[j],LOW);
    }
    digitalWrite(digit[i],LOW);
    delay(5);
    digitalWrite(digit[i],HIGH);
    number=number/10;
    count=tmp;

    }
    }


    ReplyDelete
    Replies
    1. 腳位10為什麼用於ledg、也用於digit?

      使用掃描方式,必須不斷地顯示每一個七段顯示器,只要掃描速度夠快,基於視覺暫留原理,人眼便無法察覺,以為所有數字皆為同時顯示。

      你loop裡有delay(500);,暫停太久了,導致掃描速度不快,所以會閃。

      把兩個delay(500);都刪除,應該就可以了吧。

      Delete
    2. This comment has been removed by the author.

      Delete
  29. 謝謝您,已經成功了~
    腳位10 11原先是四合一七段顯示器的千位及百位,後來發現千位與百位不會用到,便把10 11當作led的腳位來使用了,一下子忘記改過來了~
    另外我想請問一下,如果要讓溫度感測器能每10秒偵測一次的話,我應該要加delay()嗎? 還是要用其他的方式呢?

    ReplyDelete
    Replies
    1. 請參考
      http://yehnan.blogspot.tw/2014/03/arduinoled.html

      Delete