仿照小米檯燈做一款智能檯燈

仿照小米檯燈做一款智能檯燈

學校電子電路設計大賽中有一題為設計一款智能檯燈,思來想去想不出哪種外觀比較好,最後決定copy一下雷總的檯燈外觀。

一、準備

智能檯燈系統基於Arduino平台,採用兩塊ATmega8主控晶元,綜合運用物聯網技術、感測技術。

需要使用[貝殼物聯](bigiot.net/)註冊一個賬號,獲得設備id和APIKEY

將獲得id和apikey填入master主機代碼中對應位置

二、功能

實現自動調光功能,人來燈亮,人走燈滅(熱釋電感測 器),並具有坐姿提醒功能,當使用者距離檯燈太近時, 檯燈能及時產生提示。

能夠實時顯示時間和日期,並具有鬧鈴提醒功能。

能夠檢測環境溫度和電池電量,並實時顯示,在電量不 足時能發出提示。

實現檯燈定時開關。

可實現遠程控制檯燈亮滅,並能對亮度進行調整。

可實現對光的切換,如白光切換成暖光。

上述提醒功能均為語音提示,開關為觸摸開關。

三、電路圖

無線充電功能未在圖上

四、使用方法

在貝殼物聯客戶端輸入5位數字 10XXX 調節冷光亮度,XXX從0到255

20XXX 調節暖光亮度,XXX從0到255

3XXXX 同時調節冷光和暖光,XXX從0到255

4XXXX 鬧鐘功能,XXXX為24小時制時間

5XXXX 定時打開檯燈,XXXX為24小時制時間

6XXXX 定時關閉檯燈,XXXX為24小時制時

7000X 人體感應功能,X為1表示打開,0為關閉

五、3D模型

檯燈全部採用3D列印,列印文件可以從這裡下載

六、實物照片

手焊燈管,5個白色led,4個暖色led

整體外觀

從左到右依次為 觸摸開關 oled屏幕 人體感應器

白光模式

暖光模式

白暖混開

白暖混開

七、視頻演示

https://www.zhihu.com/video/933037759271251968

外觀

https://www.zhihu.com/video/933032345850761216

觸摸開關

https://www.zhihu.com/video/933033160694960128

過近提醒

https://www.zhihu.com/video/933033191024070656

調光

https://www.zhihu.com/video/933034110826442752

定時開

https://www.zhihu.com/video/933034132100022272

定時關

https://www.zhihu.com/video/933034151179862016

鬧鐘

https://www.zhihu.com/video/933034179692736512

人體感應

八、代碼

master主機arduino代碼

#include <aJSON.h> n#include <dht11.h> // dht11頭文件n#include <SPI.h> //=======================n#include <Wire.h> // Oledn#include <Adafruit_GFX.h> // 頭文件n#include <Adafruit_SSD1306.h> //=======================nn#define LED_warm 5 // LED暖光正極連接針腳5n#define LED_cold 6 // LED冷光正極連接針腳6n#define Buzzer 7 //蜂鳴器n#define ADDRESS_DS1307 0x68 //I2C addressn#define Button 2 //The Touching Buttonn#define Pyro 3 //熱釋電n//============= BigIoT登錄信息 ===========nString DEVICEID="3670"; //IDnString APIKEY="31166021a"; //APIKEYn//=========================================nn//================ BigIoT數據 =============nunsigned long lastCheckInTime = 0; //記錄上次報到時間nconst unsigned long postingInterval = 20000; // 每隔20秒向伺服器報到一次nunsigned long lastUpdateTime = 0;//上次上傳數據時間nString inputString = ""; //從BigIoT獲取的數據nboolean stringComplete = false;nboolean CONNECT = true; nchar* parseJson(char *jsonString);n//=========================================nn//========溫度濕度=======ndht11 DHT11;n#define DHT11PIN 4n//=======================nn//======== 外部時鐘 =====nbyte timeBcd[] = {0, 0, 0, 0, 0, 0, 0};nint Time[3]={0,0,0}; //hour,minute,secondn//time = {year, month, date, day, hours, minutes, seconds};n//=======================nn//====== Clock Time ====nint Clock[2]={24,61};n//======================nn//== 全局計時 ==nint count1=0;nint count2=0; //發送數據nint count3=0; //選擇溫濕度發送nint count4=0; //熱釋電延時n//==============nn//== 蜂鳴器開啟 ==nbool BuzzerOpen=0;n//================nn//=== Timing ====nint Timing_Open[2]={24,60};nint Timing_Close[2]={24,60};n//===============nn//=== LED Control ====nint LED_warm_power=0;nint LED_cold_power=0;n//====================nn//==== Battery Voltage =====nfloat Battery=0.0;n//==========================nnvoid setup() n{n attachInterrupt(digitalPinToInterrupt(Button), Button_Pressed, FALLING);n attachInterrupt(digitalPinToInterrupt(Pyro), Pyro_Change, CHANGE);n pinMode(LED_warm, OUTPUT);n pinMode(LED_cold, OUTPUT);n pinMode(Buzzer, OUTPUT);n Serial.begin(115200);n Wire.begin(); // 加入 I2C 匯流排,作為主機n}nnvoid loop() n{n n Get_Time();n Clock_on();n Check_Battery();n Check_Timing();n n Wire.beginTransmission(7); //發送數據到設備號為7的從機n if(count1>900) //循環時間函數n {n count2++;n count4++;n count1=0;n Serial.println(count2);n Serial.print(Time[0]);Serial.print(:);Serial.print(Time[1]);Serial.print(:);Serial.println(Time[2]);n Serial.print("Battery: ");Serial.println(Battery);n Serial.print("Pyro: ");Serial.println(digitalRead(Pyro));n }nn if(count2>5) n {n checkIn(); //登陸函數n SendTempHum();n count2=0;n }n if (count4>60)n {n LED_warm_power=0;n LED_cold_power=0;n count4=0;n }n analogWrite(LED_warm,LED_warm_power);n analogWrite(LED_cold,LED_cold_power);nn F_BigIoT(); n count1++;n}nnvoid Check_Timing()n{n if (Timing_Open[0]==Time[0]&&Timing_Open[1]==Time[1])n {n LED_warm_power=255;n LED_cold_power=255;n count4=0;n }n if (Timing_Close[0]==Time[0]&&Timing_Close[1]==Time[1])n {n LED_warm_power=0;n LED_cold_power=0;n }n}nnvoid Pyro_Change()n{n if ((LED_warm_power==0)&&(LED_cold_power==0))n {n LED_warm_power=255;n LED_cold_power=255;n count4=0;n }n else count4=0;n}nnvoid Button_Pressed()n{n if (LED_warm_power!=255&&LED_warm_power!=204&&LED_warm_power!=153&&LED_warm_power!=102&&LED_warm_power!=51&&LED_warm_power!=0) LED_warm_power=306;n LED_warm_power-=51;n if (LED_warm_power<0) LED_warm_power=255;n if (LED_cold_power!=255&&LED_cold_power!=204&&LED_cold_power!=153&&LED_cold_power!=102&&LED_cold_power!=51&&LED_cold_power!=0) LED_cold_power=306;n LED_cold_power-=51;n if (LED_cold_power<0) LED_cold_power=255;n count4=0;n}nnvoid Check_Battery()n{n int sensorValue = analogRead(A0);n Battery = sensorValue * (5.0 / 1023.0);n if (Battery<3.4) digitalWrite(Buzzer,HIGH);n else digitalWrite(Buzzer,LOW);n}nnvoid Clock_on()n{n if (Clock[0]==Time[0]&&Clock[1]==Time[1]&&Time[3]%2==0) digitalWrite(Buzzer, HIGH);n else digitalWrite(Buzzer, LOW);n}nnvoid Get_Time()n{n Wire.beginTransmission(ADDRESS_DS1307);n Wire.write(0x00);n Wire.endTransmission();n Wire.requestFrom(ADDRESS_DS1307, 7);n if (Wire.available() >= 7)n {n for (int i = 0; i < 7; i++)n {n timeBcd[6-i] = Wire.read();n }n }n Time[0]=(timeBcd[4]/16)*10+timeBcd[4]%16;n Time[1]=(timeBcd[5]/16)*10+timeBcd[5]%16;n Time[2]=(timeBcd[6]/16)*10+timeBcd[6]%16;n}nnvoid SendTempHum() // 溫濕度模塊 n{n int chk = DHT11.read(DHT11PIN); n int Temperature_float=(float)DHT11.temperature; //溫度n int Humidity_float=(float)DHT11.humidity; //濕度n if(count3==1)n update1(DEVICEID,"3382",Temperature_float); //上傳溫度 n if(count3==2) n update1(DEVICEID,"3384",Humidity_float); //上傳濕度 nn char Sending[10]="";n char Temprature[2]="";n char Humidity[2]="";n char BatteryCent[2]="";n itoa(Temperature_float,Temprature,10);n itoa(Humidity_float,Humidity,10);n itoa(((Battery-3.5)/0.8)*100,BatteryCent,10);n if (Temperature_float<10.0)n {n Temprature[1]=Temprature[0];n Temprature[0]=0;n }n if (Humidity_float<10.0)n {n Humidity[1]=Humidity[0];n Humidity[0]=0;n }n if (((Battery-3.5)/0.8)*100<10.0)n {n BatteryCent[1]=BatteryCent[0];n BatteryCent[0]=0;n }n strcat(Sending,Temprature);n strcat(Sending,",");n strcat(Sending,Humidity);n strcat(Sending,",");n strcat(Sending,BatteryCent);n strcat(Sending,"n");n Serial.println(Sending);n Wire.beginTransmission(7); //發送數據到設備號為7的從機n Wire.write(Sending); // 發送變數n Wire.endTransmission(); // 停止發送n n if (count3==2) count3=0;n count3++;n}nnvoid checkIn() n{ n //登陸函數n if (!CONNECT) n {n Serial.print("+++");n delay(500); n Serial.print("rn"); n delay(1000);n Serial.print("AT+RSTrn"); n delay(6000);n CONNECT=true;n lastCheckInTime=0;n }n elsen {n Serial.print("{"M":"checkin","ID":"");n Serial.print(DEVICEID);n Serial.print("","K":"");n Serial.print(APIKEY);n Serial.print(""}rn");n lastCheckInTime = millis(); n }n}nnvoid processMessage(aJsonObject *msg)n{ //接受函數n aJsonObject* method = aJson.getObjectItem(msg, "M");n aJsonObject* content = aJson.getObjectItem(msg, "C"); n aJsonObject* client_id = aJson.getObjectItem(msg, "ID"); n if (!method) {n return;n }n String M=method->valuestring;n String C=content->valuestring;n String F_C_ID=client_id->valuestring;n if(M=="say")n { //接收字元串n long data=C.toInt();n switch (data/10000)n {n case 0:n LED_warm_power=LED_cold_power=0;n break;n case 1:n LED_warm_power=data%1000;n LED_cold_power=0;n break;n case 2:n LED_warm_power=0;n LED_cold_power=data%1000;n break;n case 3:n LED_warm_power=data%1000;n LED_cold_power=data%1000;n break;n case 4:n Clock[0]=(data%10000)/100;n Clock[1]=data%100;n break;n case 5:n Timing_Open[0]=(data%10000)/100;n Timing_Open[1]=data%100;n break;n case 6:n Timing_Close[0]=(data%10000)/100;n Timing_Close[1]=data%100;n break;n }n }n}nnvoid sayToClient(String client_id, String content)n{n Serial.print("{"M":"say","ID":"");n Serial.print(client_id);n Serial.print("","C":"");n Serial.print(content);n Serial.print(""}rn");n lastCheckInTime = millis();n}nnvoid update1(String did, String inputid, float value)n{ n //上傳函數n Serial.print("{"M":"update","ID":"");n Serial.print(did);n Serial.print("","V":{"");n Serial.print(inputid);n Serial.print("":"");n Serial.print(value);n Serial.println(""}}");n lastCheckInTime = millis();n lastUpdateTime= millis(); n}nnvoid serialEvent() n{n while (Serial.available()) n {n char inChar = (char)Serial.read();n inputString += inChar;n if (inChar == n) n {n stringComplete = true;n }n }n}nnvoid F_BigIoT()n{n serialEvent();n if (stringComplete)n {n inputString.trim();n if(inputString=="CLOSED")n {n Serial.println("connect closed!");n CONNECT=false; n }n elsen {n int len = inputString.length()+1; n if(inputString.startsWith("{") && inputString.endsWith("}"))n {n char jsonString[len];n inputString.toCharArray(jsonString,len);n aJsonObject *msg = aJson.parse(jsonString);n processMessage(msg);n aJson.deleteItem(msg); n }n }n // clear the string:n inputString = "";n stringComplete = false; n }n}n

slaver從機arduino代碼

#include <Wire.h>//聲明I2C庫文件n#include <SPI.h>n#include <Wire.h>n#include <Adafruit_GFX.h>n#include <Adafruit_SSD1306.h>nbyte timeBcd[] = {0, 0, 0, 0, 0, 0, 0};n#define ADDRESS_DS1307 0x68nchar a[10]=" ";n#define OLED_RESET 4nAdafruit_SSD1306 display(OLED_RESET);n#define LOGO16_GLCD_HEIGHT 16 //定義顯示高度 n#define LOGO16_GLCD_WIDTH 16 //定義顯示寬度 nn#define Speaker_Dist 8nnnint x;//變數x值決定主機的LED是否點亮n//初始化n#if (SSD1306_LCDHEIGHT != 64)nerror("Height incorrect, please fix Adafruit_SSD1306.h!");n#endifnn//============= 超聲波模塊=================nconst int TrigPin = 2;nconst int EchoPin = 3;nfloat distance;n//=========================================nnvoid setup()n{ Serial.print(a[0]);n Wire.begin(7); // 加入 i2c 匯流排,設置從機地址為 #4n Wire.onReceive(receiveEvent); //註冊接收到主機字元的事件n //Wire.onRequest(requestEvent); // 註冊主機通知從機上傳數據的事件n Serial.begin(115200);n display.begin(SSD1306_SWITCHCAPVCC, 0x3C);//設置串口波特率nnn pinMode(TrigPin, OUTPUT);n pinMode(EchoPin, INPUT);n pinMode(Speaker_Dist, OUTPUT);n digitalWrite(Speaker_Dist, LOW);n}n//主程序nchar c;nvoid loop()n{ n Serial.print(a[0]);n Wire.onReceive(receiveEvent);n //=========時間函數============n Wire.beginTransmission(ADDRESS_DS1307);n Wire.write(0x00);n Wire.endTransmission();n Wire.requestFrom(ADDRESS_DS1307, 7);n if (Wire.available() >= 7)n {n for (int i = 0; i < 7; i++)n {n timeBcd[6 - i] = Wire.read();n }n }nn//printn Serial.print("20"); Serial.print(timeBcd[0], HEX); Serial.print("/");n Serial.print(timeBcd[1], HEX); Serial.print("/"); Serial.print(timeBcd[2], HEX);n Serial.print(" "); n Serial.print(timeBcd[4], HEX); Serial.print(":");n Serial.print(timeBcd[5], HEX); Serial.print(":");n Serial.print(timeBcd[6], HEX); Serial.println();nn if (a[0]>1&&timeBcd[0]!=0)n {n display.clearDisplay();n display.setTextSize(1); //設置字體大小n display.setTextColor(WHITE); //設置字體顏色白色n display.setCursor(0, 0); //設置字體的起始位置n display.print("Temperature : ");n display.print(a[0]);//輸出字元並換行n display.print(a[1]);n display.println(" C");n display.print("Humidity : ");n display.print(a[3]);n display.print(a[4]);n display.println("%");n display.print("BatteryCent : ");n display.print(a[6]);n display.print(a[7]);n display.println("%");n display.print("20"); display.print(timeBcd[0], HEX); display.print("/");n display.print(timeBcd[1], HEX); display.print("/"); display.print(timeBcd[2], HEX);n display.print(" ");n display.print(timeBcd[4], HEX); display.print(":");n display.print(timeBcd[5], HEX); display.print(":");n display.print(timeBcd[6], HEX); display.println();n display.display();n if(a[6]==0)n {n display.clearDisplay();n display.setTextSize(2); //設置字體大小n display.setTextColor(WHITE); //設置字體顏色白色n display.setCursor(0, 0); //設置字體的起始位置n display.println(" LOW");n display.println("BATTERY!!!");n display.display();n }nn }n AlarmDist();n}nn// 當從機接收到主機字元,執行該事件nvoid receiveEvent(int howMany)n{ n int i=0;n n while ( Wire.available() > 1) // 循環執行,直到數據包只剩下最後一個字元n { n c = Wire.read(); // 作為字元接收位元組n Serial.println(c);n a[i]=c;n i++;// 把字元列印到串口監視器中n }n}nnvoid AlarmDist()n{n digitalWrite(TrigPin, LOW);n delayMicroseconds(2);n digitalWrite(TrigPin, HIGH);n delayMicroseconds(10);n digitalWrite(TrigPin, LOW);n n distance = pulseIn(EchoPin, HIGH) / 58.0;n if (distance<=20&&distance>0)n {n digitalWrite(Speaker_Dist, HIGH);n delayMicroseconds(2);n }n digitalWrite(Speaker_Dist, LOW);n}n

九、配件清單

應評論區要求,附物品清單一份

歡迎訪問我的網站

張世博的BLOG - 若不復為無益之事,何以悅有生之涯www.h1997l1997.cn圖標

和我的github

h1997l1997 (BenBoErBa-ZhangShiBo)github.com圖標

本項目相關文件下載

h1997l1997/Intelligent-desk-lampgithub.com

感謝@裂帛碎玉 同學在演示視頻中出演,和對我寫的亂七八糟代碼的優化(尤其是改了一大堆我隨便起的變數名)

最後的最後,麻煩雷總給個小贊~

@雷軍


推薦閱讀:

小米為什麼不肯採用預售模式?

TAG:南京航空航天大学 | 小米科技 | 物联网 |