2015年4月10日 星期五

Arduino countdown timer

 好久沒有用洞洞板做東西了..
這次是一個Arduino 倒數計時器,只是比一般的計時器多了一個警告的控制,也就是說倒數到幾分鐘會亮黃燈,歸零就亮紅燈這樣,功能很簡單,
架構就是三個按鈕,上/下/開始(長按:設定警告分鐘),一個Reset(回到開始的設定),然後兩個LED與四個七段顯示器.另外因為Pin不夠用了,所以加了一個74HC595控制七段顯示器的abcdefg

很亂的配線...
程式方面比較複雜的有兩個,長按切換模式,以及四個七段顯示器的掃描

接線圖我就不畫了,反正把程式碼的各個Pin設定好就能用

#include <stdio.h>

byte digit[8] = {1, 3, 5, 6, 7, 2, 4, 0};
byte num[4] = {5, 6, 7, 4};
byte led[3] = {2, 3, A4};
byte button[3] = {A0, A1, A2};
int SER_Pin = 8;   //pin 14 on the 75HC595
int RCLK_Pin = 9;  //pin 12 on the 75HC595
int SRCLK_Pin = A3; //pin 11 on the 75HC595
int reset = 10;

#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8
boolean registers[numOfRegisterPins];
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
  { 1, 0, 1, 1, 1, 1, 1 }, // = 6
  { 1, 1, 1, 0, 0, 0, 0 }, // = 7
  { 1, 1, 1, 1, 1, 1, 1 }, // = 8
  { 1, 1, 1, 0, 0, 1, 1 } // = 9
};


void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 3; i++) {
    pinMode(button[i], INPUT_PULLUP);
  }
  pinMode(reset, INPUT_PULLUP);
  for (int i = 0; i <= 3; i++) {
    pinMode(num[i], OUTPUT);
  }
  for (int i = 0; i < 3; i++) {
    pinMode(led[i], OUTPUT);
    digitalWrite(led[i], HIGH);
  }

  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  clearRegisters();
  writeRegisters();
}
int second = 0;
int minute = 0;
int lastth = 0;
int lastminute = 0;
uint32_t lastbutton = 0;
uint32_t counttime = 0;
uint32_t ledtime = 0;
bool counting = 0;
int state = 0;
bool settime = 0;//0=countdown 1=last
int th = 5;
void loop() {
  if (settime) {
    disp(th / 10, th % 10, 0, 0);
    digitalWrite(led[1], HIGH);
  }
  else if(0==digitalRead(reset)){
   settime=0;
   counting =0;
   minute = lastminute;
   th = lastth;
   second = 0;
 }
 else {
  disp(minute / 10, minute % 10, second / 10, second % 10);
  if (millis() - counttime > 1000) {
 
    if (counting == 1) {
      second--;
      if (second < 0) {
        minute--;
        second = 59;
      }
      if (minute < 0) {
        minute = 0;
        second = 0;
      }
      Serial.print(minute);
      Serial.print(",");
      Serial.println(second);
      if (minute < th) {
        digitalWrite(led[0], HIGH);
       // Serial.println("Alarm");
      }
      else {
        digitalWrite(led[0], LOW);
      }
      if (minute <= 0 && second <= 0) {
        digitalWrite(led[1], HIGH);
        //Serial.println("STOP");
      }
      else {
        digitalWrite(led[1], LOW);
      }
      state = !state;
      digitalWrite(led[2], state);
      //Serial.println(digitalRead(led[2]));
    }
    else {
        //Serial.print(digitalRead(led[0]));
        //Serial.print(digitalRead(led[1]));
        //Serial.println(digitalRead(led[2]));
       // digitalWrite(led[0], !digitalRead(led[0]));
       // digitalWrite(led[1], !digitalRead(led[1]));
     }
     counttime = millis();
   }
   else if (millis() - ledtime>200){
     if (counting == 0){
      digitalWrite(led[0], !digitalRead(led[0]));
      digitalWrite(led[1], !digitalRead(led[1]));
      state = !state;
        digitalWrite(led[2], state);  //ditry fix about digitalRead error on led2
        ledtime = millis();
      }
    }
  }
  scan();

}
void change(int i) {
  switch (i) {
    case 0:
    if (0 == settime) {
      if(counting){
        counting = 0;
      }
      else{
        counting = 1;
        lastminute = minute;
        lastth = th;
      }
    }
    else {
    }
    break;
    case 1:
    if (0 == settime && counting == 0) {
      minute++;
      second = 0;
      //Serial.println(minute);
    }
    else  if (1 == settime) {
      th++;
      //Serial.println(th);
    }

    break;
    case 2:
    if (0 == settime && counting == 0) {
      minute--;
      if (minute < 0) {
        minute = 0;
      }
      second = 0;
      //Serial.println(minute);
    }
    else if (1 == settime) {
      th--;
      if (th < 0) {
        th = 0;
      }

      //Serial.println(th);
    }
    break;
  }


}
void scan() {
  uint32_t start = 0;
  int flag = 0;
  for (int i = 0; i <= 2; i++) {

    if (0 == digitalRead(button[i])) {


      if (millis() - lastbutton > 150) {
        start = millis();
        while (0 == digitalRead(button[i])) {
          if (settime) {
            disp(th / 10, th % 10, 0, 0);
          }
          else {
            disp(minute / 10, minute % 10, second / 10, second % 10);
          }
          if (i == 0 && millis() - start  >= 500 && flag==0) {
            settime = !settime;
            //Serial.print("SET TIME:");
            //Serial.println(settime);
            flag = 1;
            lastbutton = millis();
         
          }
        }

        if(flag==0){
          change(i);
          lastbutton = millis();
        }
      }

      //Serial.println(millis() - start);
    }

  }

}
void disp(int a, int b, int c, int d) {
  int data[4] = {a, b, c, d};
  for (int dig = 0; dig <= 3; dig++) {

    for (byte seg = 0; seg < 7; ++seg) {
      setRegisterPin(digit[seg], !seven_seg_digits[data[dig]][seg]);
      // digitalWrite(digit[seg], !seven_seg_digits[data[dig]][seg]);
    }
    writeRegisters();
    digitalWrite(num[dig], HIGH);
    delayMicroseconds(100);
    digitalWrite(num[dig], LOW);
  }
}

//set all register pins to LOW
void clearRegisters() {
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    registers[i] = HIGH;
  }
}


//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
void writeRegisters() {

  digitalWrite(RCLK_Pin, LOW);

  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    digitalWrite(SRCLK_Pin, LOW);

    int val = registers[i];

    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);

  }
  digitalWrite(RCLK_Pin, HIGH);

}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value) {
  registers[index] = value;
}

void serialEvent(){
 
  minute = Serial.parseInt();
  second = Serial.parseInt();
  th = Serial.parseInt();
  counting = Serial.parseInt();
  settime = 0;
  while(Serial.available()){
      int dummy = Serial.read();// statement
  }


}

====Update:2016/08/28====
Video:

17 則留言:

  1. 你好,想請問可以跟你買這個倒數計時器嗎?
    或是定製一個? 謝謝!

    回覆刪除
    回覆
    1. 我現在的確是沒在用這台,擺在一邊當中,我想賣掉是沒啥問題
      不過這東西真的不難,要不要試著做一個看看?

      刪除
    2. 因為我完全不會做這種東西哈哈,然後我需要做一個定時炸彈的道具,所以非常需要它,另外想問你如果加一顆會閃的小燈的話估價大概是多少錢呢?

      刪除
    3. 另外想再請問這個定時器的尺寸是多少呢?

      刪除
    4. 上面那張板子是7.2x4.8cm
      話說倒數的時候冒號是會閃的,應該就可以?
      我先開個1000台幣好了

      刪除
    5. 上面那張板子是7.2x4.8cm
      話說倒數的時候冒號是會閃的,應該就可以?
      我先開個1000台幣好了

      刪除
    6. 嗯嗯好哇謝謝你我的電話是0912409086,再請你聯絡我可以嗎?非常感謝你!!

      刪除
    7. https://youtu.be/WqFxN_58jpk

      刪除
  2. 問下 是用IDE寫的嗎?爲什麼我用IDE那些register的code都是錯誤的?

    回覆刪除
    回覆
    1. Code,接線圖,錯誤訊息都沒給我很難說什麼

      刪除
    2. By the way, IDE其實是整合開發環境的意思
      所以沒有任何Debug作用
      就像是我拿電腦在寫Code的感覺

      刪除
    3. 作者已經移除這則留言。

      刪除
  3. 作者已經移除這則留言。

    回覆刪除
  4. 可以請問這個要怎麼接線?

    回覆刪除
  5. Hi,

    This is a very good project.

    Pls share schematic.

    Thank you.

    回覆刪除
  6. 想知道接線圖 有點複雜

    回覆刪除
  7. I have a basketball gameclock and score board project. may i know a good book so that i can understand the coding?

    回覆刪除