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,試試看有何效果。
參考資料:

111 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
    Replies
    1. 請問遺下這個程式碼還能上傳嗎 我也是遇到一樣問題

      Delete
    2. 上傳跟這份程式碼,有什麼關係?

      什麼問題?

      Delete
    3. 因為你上面程式碼的連結已經失效 我想知道要怎麼更改這個問題
      我將sensors.setWaitForConversion(false);寫進SETUP後 有比較好一點 只是數字是一直閃爍的 但是可以判斷的出數字
      想請問"拉長等待時間"是還要甚麼程式碼呢?

      Delete
    4. 連結失效,嗯,我也找不到了。

      > 數字一直閃爍
      可能程式裡有delay吧,影響7段顯示器的掃描程序。

      your code?

      Delete
    5. #include
      #include

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

      // 運用程式庫建立物件
      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();
      sensors.setWaitForConversion(false);

      }

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

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


      digitalWrite(24, HIGH);
      if((sensors.getTempCByIndex(0)) > 40)
      {
      digitalWrite(26, HIGH);
      }
      else
      {
      digitalWrite(26, LOW);
      }
      number = ((int)((sensors.getTempCByIndex(0))*100));
      // 不斷地寫入數字
      setNumber(number);

      }

      Delete
    6. 你在loop()裡呼叫sensors.getTempCByIndex的次數太多了吧。

      試試吧,只通過編譯。
      https://pastebin.com/b4BVPque

      Delete
    7. 你好 上面程式編譯不過ㄟ
      'class DallasTemperature' has no member named 'isConversionAvailable'
      出現這段

      Delete
    8. 你的DallasTemperature版本跟我的不一樣。

      改成
      sensors.isConversionComplete();
      試試

      Delete
    9. 雖然我剛剛將 if(sensors.isConversionAvailable(addr)){]刪除就可以了
      現在加回來也可以使用
      非常感謝老師!!找到我心頭大患!

      Delete
    10. 刪除的話,程式行為是錯的。
      會讀到IDLE_TIME秒前的舊資料。嘛,也是可以啦。
      不過那樣的話,就不必寫得這麼複雜了。

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

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

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

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

      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
  30. int digit1=12;
    int digit2=11;
    int digit3=10;
    int digit4=9;
    int segA=2;
    int segB=3;
    int segC=4;
    int segD=5;
    int segE=6;
    int segF=7;
    int segG=8;
    byte seven_seg_digits[10][7]=
    {
    {1,1,1,1,1,1,0},//0
    {0,1,1,0,0,0,0},//1
    {1,1,0,1,1,0,1},//2
    {1,1,1,1,0,0,1},//3
    {0,1,1,0,0,1,1},//4
    {1,0,1,1,0,1,1},//5
    {0,0,1,1,1,1,1},//6
    {1,1,1,0,0,1,0},//7
    {1,1,1,1,1,1,1},//8
    {1,1,1,0,1,1,0},//9
    };
    void setup(){
    pinMode(segA,OUTPUT);
    pinMode(segB,OUTPUT);
    pinMode(segC,OUTPUT);
    pinMode(segD,OUTPUT);
    pinMode(segE,OUTPUT);
    pinMode(segF,OUTPUT);
    pinMode(segG,OUTPUT);
    pinMode(digit1,OUTPUT);
    pinMode(digit2,OUTPUT);
    pinMode(digit3,OUTPUT);
    pinMode(digit4,OUTPUT);
    }
    void loop(){
    displayNumber(millis()/1000);
    }
    void displayNumber(int toDisplay){
    #define DIGIT_ON HIGH
    #define DIGIT_OFF LOW
    for(int digit=1;digit<5;digit++){
    switch(digit){
    case 1:
    digitalWrite(digit4,HIGH);
    lightNumber(toDisplay % 10);
    toDisplay /=10;
    break;
    case 2:
    digitalWrite(digit3,HIGH);
    lightNumber(toDisplay % 6);
    toDisplay /=6;
    break;
    case 3:
    digitalWrite(digit2,HIGH);
    lightNumber(toDisplay % 10);
    toDisplay /=10;
    break;
    case 4:
    digitalWrite(digit1,HIGH);
    lightNumber(toDisplay % 6);
    toDisplay /=6;
    break;
    }
    delayMicroseconds(6000);
    lightNumber(10);
    digitalWrite(digit4,LOW);
    digitalWrite(digit3,LOW);
    digitalWrite(digit2,LOW);
    digitalWrite(digit1,LOW);
    }
    }
    void lightNumber(byte numberToDisplay){
    byte pin=2;
    for(byte seg=0; seg<7; ++seg){
    digitalWrite(pin, seven_seg_digits[numberToDisplay][seg]);
    ++pin;
    }
    }
    都只會顯示8888跟0000請問是什摸
    問題啊

    ReplyDelete
    Replies
    1. lightNumber(10); 這一行是什麼作用?

      Delete
    2. 我是照課本打的lightNumber(10);關閉七段顯示器所有LED

      Delete
    3. 是嗎? 根據你的程式碼,
      seven_seg_digits的有效索引值是0~9,但你卻傳入10。

      Delete
    4. 四合一的七段顯示器,啟用電壓沒搞錯嗎?HIGH是啟用嗎?還是LOW?

      Delete
    5. 只覺得lightNumber(10);這行怪怪的,
      看不出有什麼問題。

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

    ReplyDelete
  32. 請問若一個Arduino 的板子接兩個四合一ok嗎?目前遇到一個狀況,當我接兩個的時候千位數的燈會比較亮,其餘的都很暗
    但若只接一個四合一則沒有這個問題

    ReplyDelete
    Replies
    1. 那就另外提供電源給四合一的七段顯示器。

      Delete
    2. 我是使用mega的版子,22~33為1號四合一,34~45為2號四合一,您上述教學的線路規畫我不知道該如何另外提供電源耶,是否可以指導小弟呢?謝謝老師

      Delete
    3. 自己弄的話,可以加電晶體,類似這樣子
      https://electronics.stackexchange.com/questions/93155/cheap-4-digit-7-segment-display-driver

      也可用TM1637,專門用來驅動7-seg display的晶片,
      http://playground.arduino.cc/Main/TM1637


      Delete
    4. 請問老師,加電晶體,這個電晶體是要用什麼型號的呢?

      Delete
  33. Anonymous14/8/17 18:37

    This comment has been removed by the author.

    ReplyDelete
  34. Anonymous14/8/17 19:06

    老師妳好 ,我有跟前面幾位有一樣的問題,數字顯示出來只有千位數字恆亮,其他位數都會一閃一閃的,請問這樣該如何解決?
    程式碼:
    // 匯入程式庫標頭檔
    #include
    #include

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

    // 運用程式庫建立物件
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    // 定義腳位
    #define PIN_0 A5
    #define PIN_g A4
    #define PIN_c A3
    #define PIN_h A2
    #define PIN_d A1
    #define PIN_e A0
    #define PIN_b 2
    #define PIN_1 3
    #define PIN_2 4
    #define PIN_f 5
    #define PIN_a 6
    #define PIN_3 7

    // 共有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(9600);

    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);
    }
    Serial.begin(9600);
    Serial.println("Temperature Sensor");
    // 初始化
    sensors.begin();
    }

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

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


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

    ReplyDelete
    Replies
    1. 因為delay,想辦法去掉loop裡的delay。

      Delete
    2. Anonymous15/8/17 15:54

      我把兩個delay(100);都去掉了但顯示器還是一直閃(似乎四位都會閃,不過千位數字很亮,百十個位就相對暗很多),有再接六伏電源了,不過還是一樣。

      Delete
    3. 把loop改成
      void loop() {
      // 要求匯流排上的所有感測器進行溫度轉換(不過我只有一個)
      sensors.requestTemperatures();
      // 取得溫度讀數(攝氏)並輸出,
      // 參數0代表匯流排上第0個1-Wire裝置
      float t = sensors.getTempCByIndex(0);
      Serial.println((int)(t*100));

      number = ((int)(t*100));

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

      試試吧,因為getTempCByIndex會花時間。

      如果還不行,就要多改一點了,不要常常去呼叫getTempCByIndex。

      Delete
    4. 老師您好,我也是在結合DS18B20和七段顯示器上出現千位數字很亮 其他位數字有閃爍情形
      以下附上code 其他函式設定與 "ㄚ哭拿" 相同就僅附上相異之處
      還請麻煩老師幫忙

      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);
      }
      sensors.begin();
      sensors.getAddress(tempDeviceAddress, 0);
      sensors.setResolution(tempDeviceAddress, resolution);
      \\參考DallasTemperature範本中 修改解晰度用以提升反應時間 範本建議 int resolution = 9;
      sensors.setWaitForConversion(false);
      }

      void loop() {
      sensors.requestTemperatures();
      setNumber(sensors.getTempCByIndex(0)*100);
      }

      想請問老師 上面賴柏瑋和亞諠是怎麼解決閃爍的問題的呢?
      感謝

      Delete
    5. > 賴柏瑋和亞諠是怎麼解決閃爍的問題的呢?
      修改程式。

      你的程式要改的話,可參考DallasTemperature的範例,
      https://github.com/milesburton/Arduino-Temperature-Control-Library/tree/master/examples
      其中的WaitForConversion與WaitForConversion2,
      在loop裡盡量少呼叫requestTemperatures與getTempCByIndex。


      Delete
  35. 不好意思,我想問要怎麼把四位數七段顯示器結合LED燈做成類似紅綠燈的裝置
    指令如下
    綠燈亮10秒、七段顯示器顯示倒數0010、0009、0008...;
    黃燈亮1秒、七段顯示器顯示倒數0001、0000;
    紅燈亮10秒、七段顯示器顯示倒數0010、0009、0008...;

    ReplyDelete
    Replies
    1. 你這樣問,我不知道怎麼回答。
      把電路組起來,寫寫程式吧。

      應該會用到 有限狀態機 的程式撰寫技巧。

      Delete
  36. 要如何改成電子鐘(分跟小時)

    ReplyDelete
  37. 請問如何把HC-SR04這個測距吐出來的資料~用4個7段顯示器顯示呢?

    ReplyDelete
  38. 請問如何把HC-SR04這個測距吐出來的資料~用4個7段顯示器顯示呢?

    ReplyDelete
  39. 請問如何把HC-SR04這個測距吐出來的資料~用4個7段顯示器顯示呢?

    ReplyDelete
  40. Anonymous5/12/22 12:26

    請問一下我要如何把上面的程式加一個按鈕來控制

    ReplyDelete