test.ino
#include <SPI.h> // W5100 擴展版(用SPI) 網路模組, RFID-RC522 模組(用SPI)
#include <Ethernet.h> // W5100 擴展版(用SPI) 網路模組
#include <Wire.h> // W5100 擴展版(用SPI) 網路模組
#include <DS1302.h> // D1302 時鐘模組
#include <MFRC522.h> // RFID-RC522 模組(用SPI)
#include <LiquidCrystal_I2C.h> // LCD 1602 I2C 顯示模組(用I2C)
// W5100 擴展版(用SPI) 網路模組
byte baMAC[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // physical mac address
char caServerName[]="www.somewhere.com.tw";
EthernetClient oEthernetClient;
// 開關模組 (含電阻) + LED燈,切換上班/下班
byte bButtonPin=2;
byte bUpDn=0; // 0=上班(up); 1=下班(dn);
byte bLedUpPin=3;
byte bLedDnPin=4;
// DS1302 時鐘模組
// DS1302 rtc([RST],[DAT],[CLOCK]); 三個pin
String strLastTimeSwitched=""; // 最後一次 自動切換 上班/下班 的時間
DS1302 rtc(7,6,5);
// 無源揚聲器
byte bTonePin=8;
// RFID-RC522 模組(用SPI)
// mifare card uid => 4 bytes, 7 bytes, 10 bytes
#define SDA_PIN_4_RFID 9
#define RST_PIN_4_RFID A0
String strUID="";
MFRC522 mfrc522(SDA_PIN_4_RFID, RST_PIN_4_RFID);
// LCD 1602 I2C 顯示模組(用I2C)
// Set the pins on the I2C chip used for LCD connections: addr,en,rw,rs,d4,d5,d6,d7,bl,blpol
long lTimeCurrent=0, lTimeLastClockShown=0, lTimeGap4Clock;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // 設定 LCD I2C 位址
void setup()
{
Serial.begin(9600);
Serial.println("Program Start");
// 先設定 pin mode
pinMode(bButtonPin, INPUT);
pinMode(bLedUpPin, OUTPUT);
pinMode(bLedDnPin, OUTPUT);
pinMode(bTonePin, OUTPUT);
// W5100 擴展版(用SPI) 網路模組
Serial.println("Ethernet Init");
SPI.begin();
ledShowError();
if(Ethernet.begin(baMAC)==0)
{
Serial.println("Failed to configure Ethernet using DHCP!");
while(true); // 網路不通,直接當機!
}
ledRefresh();
// DS1302 時鐘模組
Serial.println("Clock Init");
rtc.halt(false); // 設定時鐘為正常執行模式
// 以下是設定時間的方法,在電池用完之前,只要設定一次就行了
// rtc.writeProtect(false); //取消寫入保護,設定日期時要這行
// rtc.setDOW(FRIDAY); // 設定週幾,如FRIDAY
// rtc.setTime(22, 18, 0); // 設定時間 時,分,秒 (24hr format)
// rtc.setDate(3, 1, 2020); // 設定日期 日,月,年
// RFID-RC522 模組(用SPI)
Serial.println("MFRC522 Init");
mfrc522.PCD_Init();
// LCD 1602 I2C 顯示模組(用I2C)
Serial.println("LCD Init");
lcd.begin(16, 2); // 初始化 LCD,一行 16 個字元,共 2 行
lcd.clear();
lcd.backlight(); // 開啟背光
//lcd.noBacklight(); // 關閉背光
lcd.setCursor(0, 0); // 設定游標位置在第 1 行行首 (x,y)
lcd.print("Hello, world!");
Serial.println("Setup Okay......");
}
void ledShowError()
{
// 兩的 LED 恆亮,代表發生錯誤!
digitalWrite(bLedUpPin, HIGH);
digitalWrite(bLedDnPin, HIGH);
}
void ledRefresh()
{
if(bUpDn==0)
{
// 上班
digitalWrite(bLedUpPin, HIGH);
digitalWrite(bLedDnPin, LOW);
}
else
{
// 下班
digitalWrite(bLedUpPin, LOW);
digitalWrite(bLedDnPin, HIGH);
}
}
void checkButton()
{
if(digitalRead(bButtonPin)==HIGH)
{
bUpDn=bUpDn ^ 1; // xor 運算
ledRefresh();
}
}
void showClock()
{
lTimeGap4Clock=abs(lTimeCurrent-lTimeLastClockShown);
if(lTimeGap4Clock>499) // 499 milliseconds
{
// Serial.print(rtc.getDOWStr()); // 週幾
// Serial.print(rtc.getDateStr()); // 日期
// Serial.println(rtc.getTimeStr()); // 時間
lcd.setCursor(0, 1); // 設定游標位置在第 2 行行首 (x,y)
lcd.print(rtc.getTimeStr());
lTimeLastClockShown=lTimeCurrent;
}
}
void makeSoundCore(float fFrequency, int iDuration)
{
tone(bTonePin, fFrequency);
delay(iDuration);
}
void makeSoundWithUpAndDn()
{
// 上班/下班時間一到,會有一小段音樂。
int iD=200;
makeSoundCore(1975.5,iD*2);
makeSoundCore(1760.0,iD/2);
makeSoundCore(1568.0,iD);
makeSoundCore(1480.0,iD);
makeSoundCore(1318.5,iD);
makeSoundCore(1568.0,iD);
makeSoundCore(1174.7,iD*2);
makeSoundCore(1174.7,iD);
makeSoundCore(2093.0,iD);
makeSoundCore(1760.0,iD*2);
makeSoundCore(1174.7,iD);
makeSoundCore(1975.5,iD);
makeSoundCore(1568.0,iD*2);
noTone(bTonePin);
}
void checkTimeAndSwitchUpDn()
{
String strCurrentTime=rtc.getTimeStr(FORMAT_SHORT);
if(strLastTimeSwitched==strCurrentTime) { return; }
if(strCurrentTime=="05:00")
{
strLastTimeSwitched=strCurrentTime;
bUpDn=0;
ledRefresh();
Serial.println("switch up");
}
else if(strCurrentTime=="08:30"
|| strCurrentTime=="13:30")
{
strLastTimeSwitched=strCurrentTime;
bUpDn=0;
ledRefresh();
makeSoundWithUpAndDn();
Serial.println("switch up");
}
else if(strCurrentTime=="12:30"
|| strCurrentTime=="17:30")
{
strLastTimeSwitched=strCurrentTime;
bUpDn=1;
ledRefresh();
makeSoundWithUpAndDn();
Serial.println("switch down");
}
}
// 一刷感應卡,傳送封包、燈光閃爍、音樂響起
void readUID()
{
strUID=""; // 長度請用 strUID.length();
if(mfrc522.PICC_IsNewCardPresent() &&
mfrc522.PICC_ReadCardSerial())
{
byte *baId = mfrc522.uid.uidByte;
byte bIdSize = mfrc522.uid.size;
char caBuildBuffer[4] = {0};
for(byte i=0; i<bIdSize; i++)
{
sprintf(caBuildBuffer, "%02X", (uint8_t)baId[i]);
strUID.concat(caBuildBuffer);
}
mfrc522.PICC_HaltA();
}
}
void ledBlink()
{
byte b1=0;
for(int i=0; i<2; i++)
{
b1=b1 ^ 1;
if(b1==0)
{
digitalWrite(bLedUpPin, HIGH);
digitalWrite(bLedDnPin, LOW);
}
else
{
digitalWrite(bLedUpPin, LOW);
digitalWrite(bLedDnPin, HIGH);
}
delay(50);
}
}
void makeSoundAndBlinkLedWithSucceeded()
{
tone(bTonePin, 523.25);
//delay(100);
ledBlink();
tone(bTonePin, 1046.5);
//delay(100);
ledBlink();
tone(bTonePin, 2093.0);
//delay(100);
ledBlink();
noTone(bTonePin);
ledRefresh();
}
void sendPacket()
{
bool booSuccess=false;
if(oEthernetClient.connect(caServerName, 8080)) // 8080 是 port number
{
Serial.println("Connected");
String strDate=rtc.getDateStr();
String strTime=rtc.getTimeStr();
String strGet="GET /test.php?updn="+String(bUpDn)+"&uid="+strUID+"&date="+strDate+"&time="+strTime+" HTTP/1.0";
oEthernetClient.println(strGet);
oEthernetClient.println("Host: www.somewhere.com.tw");
oEthernetClient.println(); //end of get request
ledBlink();
ledRefresh();
booSuccess=true;
}
else
{
Serial.println("Connection Failed"); // error message if no client connect
Serial.println();
ledShowError();
booSuccess=false;
}
while(oEthernetClient.connected() && !oEthernetClient.available())
{
// waits for data 等待資料傳送完畢!
delay(1);
}
while(oEthernetClient.connected() || oEthernetClient.available())
{
// connected or data available
char c=oEthernetClient.read(); // gets byte from ethernet buffer
Serial.print(c); // prints byte to serial monitor
}
Serial.println();
Serial.println("Disconnecting.");
Serial.println();
oEthernetClient.stop(); // stop client
if(booSuccess==true)
{
makeSoundAndBlinkLedWithSucceeded();
}
}
void loop()
{
lTimeCurrent=millis();
checkButton();
showClock();
checkTimeAndSwitchUpDn();
readUID();
if(strUID.length()>0)
{
sendPacket();
}
delay(1);
}