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让舵机转到指定位置 } } } }