Arduino控制舵机和无刷电机(ESC)

2019-04-13 14:49发布

1.Arduino控制舵机     舵机是一种位置伺服的驱动器,主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号(给舵机1.5ms脉宽、周期为20ms的PWM信号,舵机应该处在中位)将获得的直流偏置电压与电位器的电压比较,获得电压差输出。经由电路板上的IC判断转动方向,再驱动无核心马达开始转动,透过减速齿轮将动力传至摆臂,同时由位置检测器送回信号,判断是否已经到达定位。适用于那些需要角度不断变化并可以保持的控制系统。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。一般舵机旋转的角度范围 是0 度到180 度。     所有的舵机都有外接三根线,一般用棕、红、橙三种颜 {MOD}进行区分,棕 {MOD}为接地线,红 {MOD}为电源正极线,橙 {MOD}为信号线。     舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的,标准PWM(脉冲宽度调制)信号的周期固定为20ms (50Hz),理论上脉宽分布应在1ms到2ms 之间,但是,事实上脉宽 可由0.5ms 到2.5ms 之间,脉宽和舵机的转角0°~180°相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。     用Arduino 控制舵机的方法有两种,一种是通过Arduino的普通数字传感器接口产生占空比不同的方波,模拟产生PWM信号进行舵机定位,第二种是直接利用Arduino 自带的Servo函数进行舵机的控制, 这种控制方法的优点在于程序编写,缺点是只能控制2路舵机,因为 Arduino 自带函数只能利用数字9、10 接口。Arduino 的驱动能力有限,所以当需要控制1 个以上的舵机时需要外接电源。 1.1方法一:模拟产生PWM信号        将舵机接数字12接口上(这种方法不是使用analogwrite产生PWM,因此不必使用PWM口)。编写一个程序让舵机转动到用户输入数字所对应的角度数的位置,并将角度打印显示到屏幕上。 int servopin = 12; // 定义数字接口12连接伺服舵机信号线 int myangle; // 定义角度变量 int pulsewidth; // 定义脉宽变量 int val; void servopulse(int servopin, int myangle) // 定义一个(伺服)脉冲函数 { pulsewidth = (myangle*11)+500; // 将角度转化为500-2480的脉宽值(0.5ms~2.5ms的脉宽) digitalWrite(servopin, HIGH); // 将舵机接口电平至高 delayMicroseconds(pulsewidth); // 延时脉宽值的微妙数 digitalWrite(servopin,LOW); // 将舵机接口电平至低 delay(20-pulsewidth/1000); // 至低的时间远长于至高的时间 } void setup() { pinMode(servopin, OUTPUT); // 设定舵机接口为输出接口 Serial.begin(9600); // 连接到串行端口,波特率为9600 Serial.println("servo=o_seral_simple ready"); } // 将0到9的数转化为0到180角度,并让LED闪烁相应数的次数 void loop() { val = Serial.read(); // 读取串行端口的值(读取char型数据返回int类型) if (val>'0'&&val<='9') { val = val - '0'; // 将特征量转化为数值变量() val = val*(180/9); // 将数字转化为角度 Serial.print("moving servo to "); Serial.print(val, DEC); // print as an ASCII-encoded decimal Serial.println(); for (int i=0; i<=50; i++) // 给予舵机足够的时间让它转到指定角度 { servopulse(servopin, val); // 引用脉冲函数 } } } 1.2方法二:自带的Servo函数        使用时必须#include          Servo也是一个Class,可以创建自己的Servo,例如:Servo myservo;        1、attach(接口)——设定舵机的接口(数字9或10)        2、write(角度)——设定旋转角度(0°~180°)        3、read()读取舵机角度 #include Servo myservo; // create servo object to control a servo int potpin = 0; // analog pin used to connect the potentiometer int val; // variable to read the value from the analog pin void setup() { myservo.attach(9); // attaches the servo on pin 9 to the servo object Serial.begin(9600); } void loop() { val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023) val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180) Serial.println(val); myservo.write(val); // sets the servo position according to the scaled value delay(15); // waits for the servo to get there } 1.3关于 -'0'  int val; void setup() { Serial.begin(9600); } void loop() { /*if(Serial.available()>0) { val = Serial.read(); // Serial.read() 读取char型数据,返回的类型根据变量绑定的类型自动转换 Serial.println(val); }*/ while(Serial.available()) { val = Serial.read(); Serial.println(val); if (val > '0'&& val <='9') { val = val - '0'; Serial.println(val-'0'); } } }
2. Arduino控制无刷电机        关于电调的控制信号:电调信号是pwm信号,信号频率为50Hz,一个周期为20ms。对于电调来讲,高电平脉宽为1ms表示停转,高电平脉宽为2ms表示满油门运转;对于舵机来说1.5ms是归中,1ms和2ms分别为左右满舵。(因此下面才直接用Servo库来给实现ESC信号的输出)。 关于Servo.write()和Servo.writeMicroseconds() 0.Servo.writeMicroseconds(): Writes a value in microseconds (uS) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle. 1.servo.write() allows a maximum of 180 servo positions   servo.writeMicroseconds() allows a maximum of 1000 servo positions 2.The "write" method simply maps the "degrees" to microseconds and calls the "writeMicroseconds" method anyway.    The "degree" of turn is simply a convenient abstraction, and few bother to calibrate it.   控制程序: #include // Using servo library to control ESC Servo esc; // Creating a servo class with name as esc int val; // Creating a variable val void setup() { esc.attach(9); // Specify the esc signal pin,Here as D9 esc.writeMicroseconds(1000); // initialize the signal to 1000 Serial.begin(9600); } void loop() { val= analogRead(A0); // Read input from analog pin a0 and store in val val= map(val, 0, 1023,1000,2000); // mapping val to minimum and maximum(Change if needed) Serial.println(val); esc.writeMicroseconds(val); // using val as the signal to esc } 补充:电调1ms停转,2ms满油门运转,是指的单向电调,且是方波脉冲。而一般双向电调,1ms反转最大油门,1.5油门中点,2ms满油门正转。