1、概述編程
目前安裝的燈開關常安置在牆壁上,每次開關燈須要起身到開關跟前纔可以進行開關燈,十分麻煩。故而旨在設計一款能夠藉助手機APP操控的自動開關燈裝置,同時不需拆裝原有開關,直接在原有開關上面添加便可,便捷實用。函數
開關燈功能經過舵機的擺動來實現,擺動角度經過測試獲得;oop
爲了加強體驗感,在面板上方增長三個觸摸按鈕,能夠保證手觸碰開關燈功能學習
爲了避免影響原有開關及減少佔據體積,裝置須要適應原有開關進行設計。測試
2、設計內容ui
3、實物拼裝this
4、控制系統搭建spa
圖 舵機控制器實物圖翻譯
PWM,即Pulse-width modulation,是用佔空比不一樣的方波來模擬「模擬輸出」的一種方式,舵機的轉動角度是經過調節PEM(脈衝寬度調製)信號的佔空比來實現的。須要使用ARArduino上的PWM口控制。設計
電壓舵機供電5-7v,接受高一點的電壓;邏輯電路電壓:3-5V;通訊接口:使用i2c通訊,就是SCL、SDA引腳;其中SCL接A5,SDA接A4
OE反使能腳:這個引腳低電平使能,不接的話模塊內部默認已經接地使能了,因此正常使用能夠不接。
學習資料:https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all
3.藍牙模塊接線
RX接TX,TX接RX,VCC接5V,GND接GND
4.觸摸開關
—接GND,+接5V,S接信號端(D3-D13),此處接D四、D六、D10.
5.SG90舵機連線
舵機信號線分別接二、四、7,按顏色匹配接口。
5、程序編寫
void setup() { // put your setup code here, to run once:
Serial.begin(38400); } void sendcmd() { Serial.println("AT"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } // Get response: OK
delay(1000); // wait for printing
Serial.println("AT+NAME=Sonny"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000); Serial.println("AT+ADDR?"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000); Serial.println("AT+PSWD=2113"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000); /*Serial.println("AT+PSWD?"); while(Serial.available()) { char ch; ch = Serial.read(); Serial.print(ch); } delay(1000);*/ } void loop() { sendcmd(); }
連接:https://pan.baidu.com/s/1nwniWXiRJ5x7yIPrK--Iuw
提取碼:xp1t
經常使用編程語句:
(1)設置頻率
setPWMFreq(freq) eg: pwm.setPWMFreq(1000); // set the PWM frequency to the maximum value of 1000Hz
Description: 用來調節PWM頻率,範圍 freq:40-1000Hz
(2)設置高低脈寬
如下示例將致使通道15從低電平開始,在脈衝中高達25%左右 (在4096中打勾1024),轉換回脈衝的低75%(勾選3072),並保持低位 對於最後25%的脈衝: eg: setPWM(15, 1024, 3072);
(3)
Example 1: (assumes that the LED0 output is used and (delay time) + (PWM duty cycle) 100 %) Delay time = 10 %; PWM duty cycle = 20 % (LED on time = 20 %; LED off time = 80 %). Delay time = 10 % = 409.6 ~ 410 counts = 19Ah. Since the counter starts at 0 and ends at 4095, we will subtract 1, so delay time = 199h counts. LED0_ON_H = 1h; LED0_ON_L = 99h (LED start turn on after this delay count to 409) LED on time = 20 % = 819.2 ~ 819 counts. LED off time = 4CCh (decimal 410 + 819 1 = 1228) LED0_OFF_H = 4h; LED0_OFF_L = CCh (LED start turn off after this count to 1228)
/*************************************************** 這是16通道PWM和伺服驅動器的一個例子,驅動16個伺服電機 ****************************************************/ #include <Wire.h> //16路舵機控制板頭文件 #include <Adafruit_PWMServoDriver.h> //16路舵機控制板頭文件 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();//以這種方式調用,它使用默認地址0x40。 //Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);//也能夠用不一樣的地址調用它 void setServoPulse(uint8_t n, double pulse); //以秒爲單位設置脈衝長度函數 void pwm_text(); //16路舵機控制板測試函數,效果是來回轉動,16路同時 /*根據你的伺服制做,脈衝寬度最小和最大可能變化,你想要這些儘量小大而不碰到 硬中止,對於最大範圍。你必須調整它們以匹配你的伺服系統!*/ #define SERVOMIN 102 //這是「最小」脈衝長度計數(在4096中) #define SERVOMAX 408 //這是「最大」脈衝長度計數(在4096中) void setup() { Serial.begin(9600); Serial.println("16 channel Servo test!"); pwm.begin(); pwm.setPWMFreq(60); //設置頻率60Hz 可用50Hz 40-1000//測試對電機的速度沒有影響 } /********************主函數********************/ void loop() { pwm_text(); //16路舵機控制板測試函數,效果是來回轉動,16路同時 } /********************************************/ void pwm_text(){ //16路舵機控制板測試函數,效果是來回轉動,16路同時 //每次驅動一個伺服驅動器 for (uint16_t pulse = SERVOMIN; pulse < SERVOMAX; pulse++) { pwm.setPWM(15, 0, pulse); //pulse翻譯爲脈衝 } delay(500); for (uint16_t pulse = SERVOMAX; pulse > SERVOMIN; pulse--) { pwm.setPWM(15, 0, pulse); //pulse翻譯爲脈衝 } delay(500); } //若是您想以秒爲單位設置脈衝長度,則可使用此函數。 //例如SET伺服脈衝(0,0.001)是一個1毫秒的脈衝寬度,但不精確! void setServoPulse(uint8_t n, double pulse) //以秒爲單位設置脈衝長度函數 { double pulselength;//精度浮點數 pulselength = 1000000; // 1,000,000 us per second 每秒100萬 pulselength /= 60; // 60 Hz Serial.print(pulselength); Serial.println(" us per period"); pulselength /= 4096; // 12 bits of resolution 12位分辨率 Serial.print(pulselength); Serial.println(" us per bit"); pulse *= 1000; pulse /= pulselength; Serial.println(pulse); pwm.setPWM(n, 0, pulse); }
pwm.setPWMFreq(1000)
(2)
pwm.setPWM(15, 1024, 3072)
(3)
#include <Wire.h> #include <Adafruit_PWMServoDriver.h>
//默認地址 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); //9g舵機 高電平寬度在20ms內經過控制脈衝寬度範圍0.5ms~2.5ms
#define SERVOMIN 102 // this is the 'minimum' pulse length count (out of 4096) 0度
#define SERVOMAX 512 // this is the 'maximum' pulse length count (out of 4096) 180度
void setup() { Serial.begin(9600); Serial.println("16 channel Servo test!"); pwm.begin(); pwm.setPWMFreq(50); //頻率 50Hz,最高60Hz
} void setServoPulse(uint8_t n, double pulse) { double pulselength; pulselength = 1000000; // 1,000,000 us per second
pulselength /= 50; // 50 Hz
Serial.print(pulselength); Serial.println(" us per period"); pulselength /= 4096; // 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit"); pulse *= 1000; pulse /= pulselength; Serial.println(pulse); pwm.setPWM(n, 0, pulse); } //設置9g舵機角度
void servo_9g_write(uint8_t n,int Angle) { double pulse = Angle; pulse = pulse/90 + 0.5; setServoPulse(n,pulse);//0到180度映射爲0.5到2.5ms
} void loop() { unsigned char serialRead; if (Serial.available() > 0) { serialRead = Serial.read(); servo_9g_write(2,serialRead);//控制第1路度數
servo_9g_write(4,serialRead);//控制第2路度數
servo_9g_write(7,serialRead);//控制第3路度數
} }
6、運行測試
簡易版程序運行
#include <Servo.h> Servo myservo1; // 建立一個舵機對象,左側燈開關 Servo myservo2; // 建立一個舵機對象,中間燈 Servo myservo3; // 建立一個舵機對象,右側燈開關 void setup() { pinMode(10,INPUT); //設置引腳 10 爲輸入模式,左開關 pinMode(6,INPUT); //設置引腳 6 爲輸入模式 ,中間開關 pinMode(4,INPUT); //設置引腳 4 爲輸入模式 Serial.begin(9600); //設置波特率爲9600 myservo1.attach(2); // 將引腳9上的舵機與聲明的舵機對象鏈接起來 myservo3.attach(12); // 將引腳9上的舵機與聲明的舵機對象鏈接起來 myservo2.attach(3); // 將引腳9上的舵機與聲明的舵機對象鏈接起來 } void loop() { // put your main code here, to run repeatedly: delay(200); //延時200毫秒 while(Serial.available()) { char c=Serial.read(); Serial.println(c); if(c=='0') { Serial.println("BT is ready!"); for(int pos = 0; pos < 45; pos += 1){ // 舵機從0°轉到180°,每次增長1° myservo1.write(pos); // 給舵機寫入角度 delay(15); // 延時15ms讓舵機轉到指定位置 } } if(c=='1') { for(int pos = 45; pos>=1; pos-=1) { // 舵機從180°轉回到0°,每次減少1° myservo1.write(pos); // 寫角度到舵機 delay(15); // 延時15ms讓舵機轉到指定位置 } } if(c=='2') { Serial.println("BT is ready!"); for(int pos = 0; pos < 180; pos += 1){ // 舵機從0°轉到180°,每次增長1° myservo2.write(pos); // 給舵機寫入角度 delay(15); // 延時15ms讓舵機轉到指定位置 } } if(c=='3') { for(int pos = 180; pos>=1; pos-=1) { // 舵機從180°轉回到0°,每次減少1° myservo2.write(pos); // 寫角度到舵機 delay(15); // 延時15ms讓舵機轉到指定位置 } } if(c=='4') { Serial.println("BT is ready!"); for(int pos = 0; pos < 180; pos += 1){ // 舵機從0°轉到180°,每次增長1° myservo3.write(pos); // 給舵機寫入角度 delay(15); // 延時15ms讓舵機轉到指定位置 } } if(c=='5') { for(int pos = 180; pos>=1; pos-=1) { // 舵機從180°轉回到0°,每次減少1° myservo3.write(pos); // 寫角度到舵機 delay(15); // 延時15ms讓舵機轉到指定位置 } } } }