2012/02/23

Arduino練習:光敏電阻

之前以可變電阻控制呼吸燈的循環時間,這篇要以光敏電阻(photo resistor、photocell、light dependent resistor)控制LED的明滅。

電路圖(Fritzing格式)與程式原始碼,可在此下載

電路圖:

LED,長腳接腳位13,短腳接GND。

光敏電阻,一腳接5V,另一腳接到腳位A0與10k ohm電阻,電阻的另一腳接地。






// 從腳位A0讀取光敏電阻的值。
// 以腳位13控制LED。
void setup(){
  Serial.begin(115200);
  pinMode(A0, INPUT);
  pinMode(13, OUTPUT);
 
  digitalWrite(13, LOW);
}

int pr_min = 400;

void loop(){
  // 以analogRead()讀取光敏電阻的值,會回傳0~1023之間的值。


  int pr = analogRead(A0);

  // 並且把值輸出到序列埠,請用手遮蔽光敏電阻,看看變化。

  Serial.println(pr);

  // 若大於這個值,熄滅LED,若小於就點亮。
  // 請視需求修改pr_min。
  digitalWrite(13, pr > pr_min ? LOW : HIGH);
 
  delay(1000);
}

完成後,當外界光線強時,光敏電阻會讀到較大的值,LED就會熄滅;外界光線弱時,會讀到較小的值,LED就會亮起。


參考資料:

16 comments:

  1. Anonymous3/12/15 20:22

    請問有沒有什麼方法能利用取樣的方式(比如說每十秒取一次),然後再把讀取出來的a0數據全部加起來呢?

    ReplyDelete
    Replies
    1. 就照你說的寫成程式。

      以millis()或某計時器程式庫來取出10秒時間間隔,讀取數據後加總存在全域變數。大概是這樣吧,有什麼問題嗎?

      Delete
  2. 葉前輩 您好:
    請問您,如果我只想在低於pr設定值時,讓LED發光只維持3秒鐘,然後自動熄滅,
    一直維持到下一次的pr低於設定值事件發生,才重新觸發LED發光3秒鐘的這個動作,
    要如何做比較好呢?
    我已經可以在低於pr設定值時,將LED發光並且設定為3秒鐘後熄滅,但是熄滅之後又重新跑loop點亮...而不是一直維持熄滅狀態...
    我一直試一直想,想到現在還是想不出來...T_T,都快凌晨4點了...
    總覺得有甚麼指令可以簡單達成這樣的要求...

    ReplyDelete
    Replies
    1. 大致寫法如下 請自行補上其他部分
      int led_stauts = LOW; // LOW代表led熄滅 此時應偵測pr值
      unsigned long time_old; // 記錄點亮led時的時間

      void loop(){
      if(led_status == LOW && analogRead(A0) < PR_MIN)
      digitalWrite(LED_PIN, HIGH);
      led_status = HIGH;
      time_old = millis();
      }

      if(led_status == HIGH && millis() - time_old > 3000){
      digitalWrite(LED_PIN, LOW);
      led_status = LOW;
      }
      }

      大概如此 沒真的測試過

      Delete
    2. 謝謝葉前輩的協助,我試了前輩的寫法,
      產生的結果是當A0 < pr_min時,LED持續亮著,沒有變化
      我猜測是程式又重新發現第一個if成立,所以繼續讓LED亮著,
      於是我拿掉最後一行led_status = LOW;去避掉第一個if,
      結果變成:在 A0 < pr_min 狀態時只亮3秒,雖然達到我想要的,但是之後的 A0 < pr_min 就無法再觸發任何動作了
      LED永遠是暗的...(附帶一提:前輩寫的第一行stauts拼錯我已經修改好)

      我有查到pulseIn()這個指令,但不太會使用,不知道能不能應用在這上面?
      下面是我重新用的,但結果還是一樣,我有增加了delay()讓我觀察狀態...實在很苦手~~"

      int led = 3;

      void setup(){
      Serial.begin(115200);
      pinMode(A0, INPUT);
      pinMode(3, OUTPUT);
      analogWrite(led,0);
      }

      int pr_min = 600;
      int led_status = LOW; // LOW代表led熄滅 此時應偵測pr值
      unsigned long time_old; // 記錄點亮led時的時間
      unsigned long duration; // 記錄點亮led時的時間

      void loop(){

      if(led_status == LOW && analogRead(A0) < pr_min){
      digitalWrite(led, HIGH);
      led_status = HIGH;
      time_old = millis();
      //duration = pulseIn(led, HIGH);//計算HIGH的時間(可否應用這個指令達成目的?)
      //Serial.println(time_old);
      delay(1000);
      }
      if(led_status == HIGH && millis()-time_old>3000 ){
      Serial.println(time_old);
      digitalWrite(led, LOW);
      //time_old = 0;
      led_status = LOW;//當我移除這段時,LED如我所願只維持3秒鐘HIGH,但是之後永遠都LOW了,即使我重新遮蔽光敏電阻也沒動作
      //但我希望的是每次環境由"亮"-->"暗"時,觸發一次LED HIGH,然後永遠維持LOW。(直到下一次的環境由"亮"-->"暗"再重新只亮LED3秒)
      delay(1000);
      }
      /*if(analogRead(A0) >= pr_min){
      time_old = 0;
      }*/
      }

      Delete
    3. > 但我希望的是每次環境由"亮"-->"暗"時,觸發一次LED HIGH
      你之前的描述 並沒有說出這點

      藉由修改 我之前寫的程式 也可以改出你想要的行為 不過我不想改了 orz

      請參考拙作<> 裏頭有解釋何謂 有限狀態機
      可運用此種程式設計技巧 解決你的問題

      Delete
    4. 哈哈~好的
      十分感謝葉前輩!

      Delete
  3. 葉前輩您好:
    我想用可變電阻控制一整排串聯的led(約70顆),是否要多加模組?程式該如何寫?

    ReplyDelete
  4. 葉前輩您好:
    我想用可變電阻控制一整排串聯的led(約70顆),是否要多加模組?程式該如何寫?

    ReplyDelete
    Replies
    1. 哪種led?
      控制?要控制什麼?

      > 程式該如何寫?
      這問題太大了,無從回答。就跟問王建民如何贏球一樣。

      Delete
    2. 控制明亮,V3 LED

      Delete
    3. 首先,你說的是需求,不是問題。需求的答案會是一篇文章或一本書。

      什麼是V3 LED?
      難道是要串聯70個3V LED,那不就要準備近140 V的電源?
      我沒看過接這麼多的,而且你要怎麼控制每一顆的明亮?

      我認為該使用WS2812之類的LED吧。

      Delete
  5. 你好,我想要做光敏電阻結合馬達的裝置,就是LED燈亮的同時馬達會轉,
    這是我寫的程式碼,不知道哪裡出了問題,可以請你幫我看看嗎,謝謝。
    const int analogPin = A0;
    int Vin = 0;
    const int presetVal = 400;
    const int ledPin = 8;
    const int motorpin = 7;
    void setup() {
    pinMode(ledPin, OUTPUT);
    }

    void loop() {
    Vin = analogRead(analogPin);
    if (Vin < presetVal) {
    digitalWrite(ledPin, HIGH);
    digitalWrite(motorpin,HIGH);
    }
    if (Vin > presetVal) {
    digitalWrite(ledPin, LOW);
    digitalWrite(motorpin,LOW);
    }

    }

    ReplyDelete
    Replies
    1. 看不出問題。

      什麼馬達?
      電路圖?

      Delete
    2. 直流馬達,不能直接接到arduino的腳位,
      你有接電晶體 or H橋電路 or 馬達驅動模組嗎?

      Delete