之前
曾用過RTC即時時鐘DS1307,自買零件組裝,這篇則購買Adafruit的RTC即時時鐘
PCF8523電路板模組。
我的環境:Windows 10,Arduino IDE 1.8.1,Arduino Uno板子。
這款PCF8523模組的基本資料:
- 工作電壓:3.3V或5V
- 電池:CR1220
- 精確度:不高,一天可能誤差2秒
- 介面:I2C,位址0x68
正面照,左邊有5個腳位,右邊要裝電池CR1220。
背面照。
準備一顆CR1220電池。
線路很簡單:
Arduino Uno的5V,接到這款產品的VCC。
Arduino Uno的GND,接到這款產品的GND。
Arduino Uno的A4,接到這款產品的SDA。
Arduino Uno的A5,接到這款產品的SCL。
這款產品的SQW,不接。
近照。
以上是硬體部分,軟體部分要安裝
Adafruit的程式庫RTClib。到Arduino IDE選單-草稿碼-匯入程式庫-管理程式庫...,開啟程式庫管理員,找到「RTClib by Adafruit」,安裝。
便可在Arduino IDE選單-檔案-範例-RTClib-pcf8523找到範例程式。
編譯並燒錄,開啟序列埠監控視窗,出現如下畫面。
這支範例程式,會把草稿碼編譯的日期時間,設定到RTC裡,所以第一行會出現正確的日期時間,後兩行則是測試用,計算7天又12小時又30分又6秒之後的日期時間。
參考資料:
DS1307 Real Time Clock Breakout Board Kit | Adafruit Learning System。
葉大 請問一下 我想用呼吸燈的形式,可是我不要讓它自動閃滅,我要用監控來給數值給它多少就亮多少的亮度 麻煩您
ReplyDelete不麻煩。
Delete你提的是需求,不是問題。
請問你碰上什麼問題嗎?
懇請指教!
ReplyDelete不才想擷取四個訊號如下
電磁閥趨動上行訊號
電磁閥趨動下行訊號
氣壓缸上行死點訊號
氣壓缸下行死點訊號
想用此訊號計算出趨動訊號改變時氣壓缸移動所花費之時間
四個布林是想讓程式上報時只報一次
# define solenoid_down 3
# define solenoid_up 2
# define sensor_down 5
# define sensor_up 4
# define led_pin 13
# define SERIAL_BAUDRATE 19200
void setup()
{
pinMode (solenoid_down, INPUT);
pinMode (solenoid_up, INPUT);
pinMode (sensor_up, INPUT);
pinMode (sensor_down, INPUT);
pinMode (led_pin,OUTPUT);
Serial.begin(SERIAL_BAUDRATE);
}
void loop()
{
unsigned long time_previous;
unsigned long time_current;
int ut1;
int ut2;
int dt1;
int dt2;
boolean r;
boolean q;
boolean p;
boolean t;
int uso = digitalRead (solenoid_up);
int use = digitalRead (sensor_up);
int dso = digitalRead (solenoid_down);
int dse = digitalRead (sensor_down);
// step 1
if (dso == HIGH && uso == LOW && dse == HIGH && use == LOW )
{
if (t == true)
{
dt2 = time_current - time_previous;
Serial.print ("dt2=");
Serial.println (dt2);
}
t = false ;
time_previous = millis();
}
// step 2
if (dso == LOW && uso == HIGH && dse == HIGH && use == LOW)
{
time_current = millis();
p = true ;
}
// step 3
if (dso == LOW && uso == HIGH && dse == LOW && use == LOW)
{
if (p == true )
{
ut1 = time_current - time_previous;
time_previous = time_current;
Serial.print ("ut1=");
Serial.println(ut1);
}
p = false ;
time_current = millis();
q = true ;
}
// step 4
if (dso == LOW && uso == HIGH && dse == LOW && use == HIGH)
{
if (q == true )
{
ut2 = time_current - time_previous;
Serial.print("ut2=");
Serial.println(ut2);
}
q = false ;
time_previous = millis();
}
// step 5
if (dso == HIGH && uso == LOW && dse == LOW && use == HIGH)
{
r = true ;
time_current = millis();
}
// step 6
if (dso == HIGH && uso == LOW && dse == LOW && use == LOW)
{
if (r == true )
{
dt1 = time_current - time_previous;
time_previous = time_current;
Serial.print("dt1=");
Serial.println(dt1);
}
r = false ;
time_current = millis();
t = true ;
}
}
當 氣壓缸上行死點訊號 為 HIGH時,
Delete電磁閥趨動 是不是就會停止?
不會
Delete電磁閥上行趨動訊號會保持存在
> 想用此訊號計算出趨動訊號改變時氣壓缸移動所花費之時間
Delete請再說清楚一點。
要量哪裡到哪裡的時間?要量哪個狀況到哪個狀況之間的花費時間?
電磁閥趨動上行訊號觸發後氣缸會由下死點移動至上死點
Delete電磁閥趨動上行訊號會保持到下行訊號趨動前解除
電磁閥趨動下行訊號觸發後氣缸會由上死點移動至下死點
電磁閥趨動下行訊號會保持到上行訊號趨動前解除
電磁閥趨動及氣缸動作會呈現一有限狀態機的結果一直循環(您的書上有教過但我沒試過,我想以自己的想法寫)
在step1時電磁閥下行訊號及氣缸下死點訊號為真(若承接step6則計算及上報一次dt2,以布林t做為旗標)
在step2時電磁閥下行訊號解除,電磁閥上行訊號觸發,此時高壓氣體尚未進入缸體,故下死訊號為真,以布林p做為旗標
在step3時因高壓氣體進入缸體,故下死訊號會消失,在此計算出電磁閥上行訊號起,到下死訊號消失之時間差ut1並上報一次
在step4時高壓氣體持續推動氣缸直到上死感測器訊號觸發,在此計算出下死訊號消失至上死訊號觸發之時間差ut2並上報一次
step5~step6~step1則為下行的循環
我不知是否為以下宣告問題,是否提至全域較佳?
int ut1;
int ut2;
int dt1;
int dt2;
boolean r;
boolean q;
boolean p;
boolean t;
有限狀態機我會再試試
Delete大概是這樣,試試吧,只通過編譯,我沒真實的東西可以測試。
Deletehttps://pastebin.com/Qrqxqtq1
# define solenoid_down 3
# define solenoid_up 2
# define sensor_down 5
# define sensor_up 4
# define SERIAL_BAUDRATE 19200
void setup()
{
pinMode (solenoid_down, INPUT);
pinMode (solenoid_up, INPUT);
pinMode (sensor_up, INPUT);
pinMode (sensor_down, INPUT);
Serial.begin(SERIAL_BAUDRATE);
}
unsigned long time_so = 0;
unsigned long time_se = 0;
void loop()
{
int uso = digitalRead (solenoid_up);
int use = digitalRead (sensor_up);
int dso = digitalRead (solenoid_down);
int dse = digitalRead (sensor_down);
/* 在step1時電磁閥下行訊號及氣缸下死點訊號為真(若承接step6則計算及上報一次dt2,以布林t做為旗標) */
if (dso == HIGH && uso == LOW && dse == HIGH && use == LOW )
{
if (time_se != 0)
{
Serial.print ("dt2=");
Serial.println (millis() - time_se);
time_se = 0;
}
}
/* 在step2時電磁閥下行訊號解除,電磁閥上行訊號觸發, 此時高壓氣體尚未進入缸體,故下死訊號為真,以布林p做為旗標 */
else if (dso == LOW && uso == HIGH && dse == HIGH && use == LOW)
{
if (time_so == 0)
{
time_so = millis();
}
}
/* 在step3時因高壓氣體進入缸體,故下死訊號會消失, 在此計算出電磁閥上行訊號起,到下死訊號消失之時間差ut1並上報一次 */
else if (dso == LOW && uso == HIGH && dse == LOW && use == LOW)
{
if (time_so != 0)
{
time_se = millis();
Serial.print ("ut1=");
Serial.println(time_se - time_so);
time_so = 0;
}
}
/* 在step4時高壓氣體持續推動氣缸直到上死感測器訊號觸發, 在此計算出下死訊號消失至上死訊號觸發之時間差ut2並上報一次 */
else if (dso == LOW && uso == HIGH && dse == LOW && use == HIGH)
{
if (time_se != 0)
{
Serial.print ("ut2=");
Serial.println (millis() - time_se);
time_se = 0;
}
}
// step5; step5~step6~step1則為下行的循環
else if (dso == HIGH && uso == LOW && dse == LOW && use == HIGH)
{
if (time_so == 0)
{
time_so = millis();
}
}
// step 6
else if (dso == HIGH && uso == LOW && dse == LOW && use == LOW)
{
if (time_so != 0)
{
time_se = millis();
Serial.print ("dt1=");
Serial.println(time_se - time_so);
time_so = 0;
}
}
else
{
Serial.println ("Error: wrong state.");
}
}
感謝指教
ReplyDelete我試試看再向您回報
感謝先生指導,不才以switch 測試結果
ReplyDelete會有error 的訊息 , 是彈跳的問題
但整體的結果相當的成功,
經此一案後不才得到的心得為:
看先生的語法貌似 "SOP"
不才的語法有如 "走馬看花"
先生的參數用量精簡 , 不才的參數繁雜
尚有一大段學習的路要努力
再次感謝先生指導
> 但整體的結果相當的成功,
Delete恭喜。
> 參數用量精簡
有多少功能、用多少程式碼。多了會造成困擾。
> 參數繁雜
邏輯不夠清楚的關係。多寫幾次、多練習,:D。
我用的是有限狀態機的寫法,有6個狀態,
Delete也就是上面程式裡、最外圍的那些
if (狀態1)
else if(狀態2)
else if(狀態3)
else if(狀態4)
else if(狀態5)
else if(狀態6)
我想用的是您書上寫的 typedef enum{}state; + switch (state)的寫法
Delete我會試著去改改看 感謝
嗯,要釐清狀態變化。
Delete