使用 Arduino 光敏、人体红外传感器、舵机来控制灯光开启。这里以不破坏原则使用舵机推动开关来实现开灯和关灯。 实现目标:区域内光线强度不够时,同时有人在区域内驱动舵机推动开关开灯,无人在或光线强度足够则关灯
接线图
控制代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
| #include <Servo.h>
Servo myservo;
int brightPin = 2;
int brightVal = 0;
int minLight = 250;
int ledPin = 13;
int infraredPin = 7;
int personState = LOW;
int lightState = LOW;
int switchPin = 9;
int openLight = HIGH;
int closeLight = LOW;
unsigned long delayMillis = 2000;
unsigned long lastMillis = 0; int lightOpen = 70; int lightClose = 180; void setup() { pinMode(ledPin, OUTPUT); pinMode(infraredPin, INPUT); myservo.attach(switchPin);
Serial.begin(9600);
myservo.write(90);
}
void loop() {
int nowState = myservo.read(); Serial.print("nowState -> "); Serial.println(nowState);
if (lightOpen == nowState){ Serial.print("open with high state\n\n"); lightState = HIGH; } if (lightClose == nowState){ Serial.print("open with low state\n\n"); lightState = LOW; } int brightState = detectiveBright(); int personState = detectivePerson();
if (personState){ lastMillis = millis(); } if (false == brightState){ lightState = LOW;
if (personState && LOW == lightState){ switchLight(openLight); lastMillis = millis(); Serial.print("first start the light,the lastmillis is:"); Serial.println(lastMillis); }else if (false == personState && HIGH == lightState){ Serial.print(" turn off:"); Serial.println(brightState); switchLight(closeLight); } }else{ lightState = HIGH; if (HIGH == lightState && false == personState){ unsigned long currentMillis = millis(); if ((currentMillis - lastMillis) > delayMillis){ Serial.print(" turn off:"); Serial.println(lastMillis); switchLight(closeLight); lastMillis = 0; }else{ unsigned long check = currentMillis - lastMillis; Serial.print("still have time to turn off:"); Serial.println(check); }
} }
delay(100); }
bool detectiveBright() { brightVal = analogRead(brightPin);
if (brightVal < minLight){ return false; }else{ return true; } }
bool detectivePerson() { int detectiveNum = 0; for (int i = 0; i < 20; i++){ personState = digitalRead(infraredPin); if (HIGH == personState){ detectiveNum++; delay(5); } }
Serial.print("detectivePerson -> detectiveNum: "); Serial.println(detectiveNum); if (detectiveNum >= 10){ Serial.print("perple on\n"); return true; }else{ Serial.print("perple off\n"); return false; } }
void switchLight(int state) {
int nowState = myservo.read();
if (state == openLight && lightOpen != nowState){ Serial.print("open"); myservo.write(lightOpen); } if (state == closeLight && lightClose != nowState) { Serial.print("close"); myservo.write(lightClose); }
lightState = state;
digitalWrite(ledPin, lightState);
Serial.print("switchLight(): "); Serial.println(lightState); }
|
13号口LED灯仅调试时使用,测试时需拿下LED灯,LED亮会影响光敏判断流程 舵机最好单独供电,人体红外探测范围约160度左右不够时可多加几位人体红外,面板包仅测试时使用,长期使用可能会不稳定