2015年05月 文档列表
电滑板攻略 – 主控板程序
由 动力老男孩 发表于 2015/05/21 22:57:41这一部分内容也许会有点儿枯燥,对Arduino了解不多的同学,可能要先去预习一下。如果大家有需要的话,我也可以考虑发一系列Arduino的入门教程
- #include <EEPROM.h>
- #include <Servo.h>
- #include <SoftwareSerial.h>
- SoftwareSerial mySerial(11, 5); //Product board
- int motorPin = 12; // The pin output PWM to control motor
- int motorPin2 = 0; // For the new board with 2 motors, if motorPin2 < 0, then ignore it
- int hornPin = 10;
- int hornOffTime = 1000; // Cannot use horn too long, must less than 1s
- int hornStartTime = 0;
- int power = 50; // Control pow value, from 0 to 100;
- long lastRecvTime = 0; // If cannot recv control info in 0.2s, stop the moto
- int shutDownTimeRange = 200;
- int powerScale = 100; //if set the power scale by mobile
- int testingValue = 0;
- int lightMode = 2; // 1: on; 2:off; 3: auto
- int lightCtrlPin = 10;
- int envLightSensorPin = 1;
- boolean lightStatus = false; // shutdown ligth by default
- Servo powerServo;
- Servo powerServo2;
- // The Led pin for debug
- int ledPin = 13;
- int light = 1;
- int counter = 0;
- // Beep pin
- int beepPin = 6;
- boolean beepStatus = false;
- // Connect to speaker
- int tonePin = 6;
- // battery pin
- int batteryPin = 0;
- float batteryScale = 11;
- float batteryAlert = 3.5;
- void setup()
- {
- pinMode(ledPin,OUTPUT);
- pinMode(beepPin,OUTPUT);
- pinMode(lightCtrlPin,OUTPUT);
- pinMode(hornPin,OUTPUT);
- powerScale = EEPROM.read(0);
- if (powerScale <= 0 || powerScale > 100) powerScale = 100;
- lightMode = EEPROM.read(1);
- if (lightMode <= 0 || lightMode > 3) lightMode = 2; // default light off
- Serial.begin(9600);
- mySerial.begin(9600);
- powerServo.attach(motorPin);
- if (motorPin2 > 0) powerServo2.attach(motorPin2);
- }
- void checkBattery()
- {
- if (counter == 0 || counter == 200) {
- int readValue = analogRead(batteryPin);
- if (readValue > 5 && batteryScale * readValue / 1024 * 5 < batteryAlert * 6) {
- digitalWrite(beepPin, beepStatus);
- beepStatus = !beepStatus;
- } else {
- digitalWrite(beepPin, 0);
- }
- }
- }
- void updateCounter() {
- counter++;
- if (counter >= 400) counter = 0;
- }
- void switchLight()
- {
- if (counter == 0) {
- digitalWrite(ledPin, light);
- light = 1 - light;
- //Serial.println(testingValue);
- }
- }
- void sendPowerInfo()
- {
- if (counter == 0) {
- mySerial.write((byte)(analogRead(batteryPin) / 4));
- }
- }
- void loop()
- {
- long t0 = micros();
- int readPower = -1;
- while(mySerial.available()) {
- readPower = mySerial.read();
- lastRecvTime = micros();
- digitalWrite(ledPin, light);
- light = 1 - light;
- //counter = 0;
- if (readPower > 100) {
- break;
- }
- }
- if (readPower > -1 && readPower <= 100) {
- // Normal status
- power = readPower;
- }
- if (readPower == 255 || (lastRecvTime > 0 && (t0-lastRecvTime)/1000 > shutDownTimeRange)) {
- power = 50; // 松手默认滑行
- }
- if (readPower > 100 && readPower <= 200) {
- powerScale = readPower - 100;
- EEPROM.write(0, (byte) powerScale);
- }
- if (readPower > 200 && readPower <= 203) {
- lightMode = readPower - 200;
- EEPROM.write(1, (byte) lightMode);
- }
- if (readPower == 204) {
- digitalWrite(hornPin, 1); // start horn
- hornStartTime = t0;
- tone(tonePin, 4000);
- }
- //if (readPower == 205 || (hornStartTime > 0 && (t0 - hornStartTime) / 1000 > hornOffTime)) {
- if (readPower == 205) {
- digitalWrite(hornPin, 0); // stop horn
- hornStartTime = 0;
- noTone(tonePin);
- }
- // light control
- if (lightMode == 1) {
- // light on
- digitalWrite(lightCtrlPin, 1);
- lightStatus = true;
- } else if (lightMode == 2){
- // light off
- digitalWrite(lightCtrlPin, 0);
- lightStatus = false;
- } else {
- //auto
- int envLight = analogRead(envLightSensorPin);
- testingValue = envLight;
- if (!lightStatus && envLight < 800) {
- lightStatus = true;
- }
- if (lightStatus && envLight > 900) {
- lightStatus = false;
- }
- digitalWrite(lightCtrlPin, lightStatus);
- }
- updateCounter();
- switchLight();
- checkBattery();
- double T = 2500;
- // if has power scale
- double scaledPower = power;
- if (power > 50) {
- scaledPower = 50 + (power - 50) * powerScale / 100;
- }
- double len = 900 + scaledPower * 12; //(0~100对应总周期0.9ms~2.1ms)
- powerServo.writeMicroseconds(len);
- if (motorPin2 > 0) powerServo2.writeMicroseconds(len);
- int leftMs = (int) (t0 + T - micros());
- if (leftMs > 1500 && (t0-lastRecvTime)/1000 < shutDownTimeRange) {
- sendPowerInfo();
- leftMs = (int) (t0 + T - micros());
- }
- if (leftMs < 1) leftMs = 1;
- delayMicroseconds(leftMs);
- }
电动滑板攻略 – 蓝牙控制原理
由 动力老男孩 发表于 2015/05/19 00:27:50- #include <SoftwareSerial.h>
- SoftwareSerial mySerial(12, 11);
- void setup()
- {
- mySerial.begin(9600); //设置波特率
- }
- void loop()
- {
- int readValue = 50; //这里会换成从摇杆得到的读数
- mySerial.write((byte)readValue);
- delay(100);
- }
mySerial就是软件串口,你可以看到就用简单的 mySerial.write(xxx) 就可以从遥控器向滑板发送数据了。
- #include <SoftwareSerial.h>
- SoftwareSerial mySerial(12, 11);
- int powerValue = 50; //摇杆默认位于0~100的中点
- void setup()
- {
- mySerial.begin(9600); //设置波特率
- }
- void loop()
- {
- while(mySerial.available()) {
- powerValue = mySerial.read();
- }
- // 此处用powerValue来控制电机
- delay(2500);
- }
其中两个主要的函数 mySerial.available() 用于判断当前蓝牙模块是否有数据进来;mySerial.read() 用于读一个字节的数据。
电动滑板攻略 – 无刷电机控制原理
由 动力老男孩 发表于 2015/05/14 18:23:13机械部分就绪之后,就是各种软件和电子的工作了,首先我们看看怎么控制一个无刷电机。我们用的电机是外转子无刷电机,型号是5065。
PWM是“怕玩命”的缩写,英文写法是“Pulse-width modulation”,也有些外行人士把它翻译成“脉冲宽度调制”。对于没有听说过PWM的同学,请先参考一下我的另一篇博客Arduino的模拟输入和输出。
简单的说,对于传统的控制信号,假设最高速的时候控制电压是1,那么可以输出0.5来表示一般的速度。但是对于单片机来说,输出0和1是方便的,输出0.5会比较麻烦。这种情况了,可以快速的在0和1之间切换,达到的效果就和0.5很相似了。
电调的控制,就是使用了PWM的方式。不过它不是通过占空的比例来控制转速,而是用1的脉冲宽度来判断:
输出高电平2.1ms左右,表示最大值;
输出高电平0.9ms左右,表示最小值。
下面这段代码,用蓝牙发送0~100的数值给单片机,就可以模拟航模摇杆从油门最小推到最大的情况:
#include <Servo.h> #include <SoftwareSerial.h> SoftwareSerial mySerial(11, 5); int motorPin = 12; // 用于控制电机的管脚 Servo powerServo; void setup() { mySerial.begin(9600); powerServo.attach(motorPin); } void loop() { double T = 2500; // 脉冲周期2.5ms,相当于400Hz long t0 = micros(); // 记录当前时间 int readPower = 50; //默认是中点位置50 while(mySerial.available()) { // 从蓝牙输入一个0~100的值 readPower = mySerial.read(); } double len = 900 + readPower * 12; //(0~100对应总周期0.9ms~2.1ms) powerServo.writeMicroseconds(len); int leftMs = (int) (t0 + T - micros()); //休眠到下一个周期继续循环 delayMicroseconds(leftMs); }
需要注意的是,航模和车模的电调操控方式是不同的。航模的油门是从最低点开始,推到头是最大值;而车模的电调平时处于中点位置,向上推到头表示加速,向下拉到头表示刹车。滑板就是使用的车模电调模式,也就是说高电平从 1.5ms~2.1ms是加速区域、从1.5ms~0.9ms是刹车区域。
好盈的电调一般都支持很多模式,另外还有很多可选的参数。如果想修改它的模式,可以按住小按钮后接通电源,然后按照说明书的提示进行设置。
不差钱的同学可以买一个编程器,插上电调之后可以直接设置。
电动滑板攻略 – 传动和连接
由 动力老男孩 发表于 2015/05/14 14:17:48对于技术宅来说,最麻烦的事情莫过于加工零件了,因为大部分人家里不会有车床铣床这样的加工工具。
电动滑板器件清单
由 动力老男孩 发表于 2015/05/05 16:54:28终于到了大家最关注的器件清单了,电滑板的方案非常非常多,作为DIYer,很多时候需要选择适合自己的器件。比如我改装活力板的时候,就使用了电动自行车的电调,还有越速400W的有刷电机,因为后轮很大;后来改装滑板的时候,因为轮径很小,就改用了无刷电机的方案。这里的器件清单是我测试过,比较好用的方案,其中有些器件并不一定是最优的,仅供大家参考。大部分器件在万能的淘宝都可以搜到,因为价格波动比较大,我就不推荐链接了。
1. 滑板
之前讲过了:长板、双翘板、小鱼板,根据喜好自己选择。
2. 海鸥架
海鸥架也有不同尺寸的,改装电滑板最好用长板的海鸥架。下面这个图里的海鸥架,其中右边的那个带法兰盘(就是那个凸台),是专门用来安装电滑板的。可惜现在这种支架已经买不到了,只能用左边那种标准支架来改装了。
3. 电机 (推荐型号:N5065)
我选用的电机是N5065无刷电机,其中5065表示电机的直径是50mm,长度是65mm。N表示电机型号,具体代表什么我也不清楚,下面是N5065和C5065的对比:
可以看到,N5065的屁股是平的,C5065的屁股是尖的,相对来说 N5065的功率会大一些,当然价格也要贵一些。
需要注意的是,这些电机几乎都是为航模设计的,所以特性跟滑板的需求并不一致。航模应用里是带动螺旋桨,转速越高的时候负载越大。而电滑板在启动的阶段阻力非常大,一旦跑起来的之后阻力会突然变小,之后才又随着速度增加而增大。所以电动滑板在启动之后经常会有一个突然加速(美国那边一万多块钱的boosted board也这样),请大家务必要小心。要解决顿挫感,可能唯一的办法是换大轮子和大直径的电机。
有些同学可能会觉得N5065比较贵,实际上我试过很多电机,以我的体重70公斤为参考,C5065、C5055、N5055这些电机都可以带动。启动的时候会有一些区别,功率小的电机,启动的时候会比较费劲。如果你体重比较轻,可以试试小号的电机。
电机还有一个重要参数叫KV值,所谓的KV值就是电压增加1伏的时候,转速增加的数量。简单的说:KV值越大转速越快。那么问题来了,KV值是越大越好呢,还是越小越好?对于咱们的电滑板来说,基本上是越小越好,因为电机的转速对滑板来说太快了,遥控器基本上没有机会推到头。我一般选用的是KV270左右的电机,假如最高时速是25公里,那么选用KV400的电机,最高时速就可能达到37公里,这个速度摔倒的话基本就得去医院住一阵子了……
4. 电调(推荐型号:150A)
电调的全称是“电子调速器”,它的作用是调节电机转速。遥控器或手机发出的控制信号,是通过蓝牙传给单片机。单片机的功率非常小,带一个玩具小马达还凑合,带动滑板这么大的家伙,就需要电调了。电调最主要的参数就是电流,比如80A,150A。这个值显然越大越好,当然也是越大越贵。
我刚做滑板的时候还是冬天,那会儿先买了个80A的电调回来测试,发现还挺好用的。接着春天到了,万物复苏,阳光明媚,电调爆了……
在公园里跑着跑着,滑板下面直接开始冒绿色的明火,呼呼的开始烧。换一块烧一块,几天功夫烧掉了3块。这才知道是因为气温升高,散热不如冬天好了。
随后我换了一个150A的电调,具体型号是 QuicRun WP-8BL150,之后就再也没有烧过了。
有一些朋友说120A的应该也可以用,不过我没有试过。不是因为有钱任性,而是之前烧怕了,如果有用过120A电调的朋友,欢迎分享一下自己的型号和经验。
5. 电池 (推荐6S 5200mAh锂电池)
锂电池的种类也有好多种,我选用的这种是航模用的锂电池,6S表示是6片锂电池串联而成,江湖上的黑话叫“六串”。每片电池充满电的时候是4.2V左右,整块电池是25.2V。随着电池的使用,电压会逐步下降。电压过低会严重影响锂电池的寿命,所以建议在3.5V时就要开始充电,如果低于3V的话基本就算是废了。后面的程序部分,我会介绍如何在板上采集电池电压,然后在低电量的时候让喇叭发出滴滴的警报。
6. 充电器 (推荐 B6)
这种锂电池需要使用专门的平衡充,最常见的充电器就是这种B6充电器。充电略有点儿麻烦,需要稍微设置一下。
7. 传动结构(需要定制)
目前常见的电滑板方案,都是一对减速齿轮,用皮带连接,通过一个支架安装在轮子上。
我选用的齿轮比是大轮66齿,小轮16齿,用15mm*232齿的皮带连接,传动比大约是4:1左右。
支架的安装是个麻烦的事情,对于有法兰盘的海鸥架,只需要用一个片来连接就行,在该打孔的地方打上孔。如果不定制的话,也可以自己动手磨。我收集的百宝箱里有一段钢制的导轨,最初两个版本的支架,就是用砂轮磨出来的。其中那些奇怪的曲线,是因为钢轨打孔非常困难,只好用砂轮从外面掏进去。
8. 轮子 (推荐83mm*52mm长板轮)
滑板的轮子尺寸种类都很多,对于电滑板来说,平稳非常重要,所以轮子需要大一点儿。需要注意的是,很多店家卖轮子的时候,是不包含轴承的,因为轴承这东西价格差别很大,专业的玩家可能使用的轴承比轮子还贵。这个就看你的不差钱程度啦。
另外还需要注意的是,7里面的传动结构,跟轮子和海鸥架都需要配合,所以最好等海鸥架和轮子都到手之后,量好尺寸,再开始定制同步轮和支架。
9. 控制板 (自己做)
控制板是在滑板上的,用来接收信号和控制电机的部分。它的核心是一块Arduino单片机,通信部分是一个蓝牙模块。
这是我的长板上的控制部分,这个板子可以接两个电机,上面还带了电池电量检测、环境亮度检测、灯带、警报喇叭等功能。这一部分需要的零七八碎的部件比较多,统一和遥控器的清单列在最后面。在后面的攻略里,会发出原理图,有兴趣的同学可以去照单采购。强大的HelloPlanet同学做出了PCB板(后面提到的遥控器板子也做了),患有电路恐惧症的同学,也许可以直接购买(暂时没有淘宝链接,先看看有没有同学需要吧)
10. 遥控器
如果你手头有一个android手机的话,其实完全可以不需要遥控器,很多人会担心手机操控不方便,玩滑板的时候怎么能看着手机呢?
其实不用担心,我的APP做成了全屏界面,你完全不需要看着手机,直接用手在屏幕上下移动就可以了。上半屏幕是加速,越往上速度越快;下半屏幕是刹车,越往下刹车越重。手指头越过中间的区域时,我会让手机震动一下,就知道是过了中点了。
如果你是土豪型的iPhone用户,或者觉得手机的手感不太好,或者怕紧急情况下把手机摔坏,也可以做一个手持的遥控器。跟它对比的是常见的枪式车模遥控器,这个枪型的东西其实用户体验很糟糕。扣板机是加速,向前推扳机是刹车。问题是遇到紧急情况时,很多人下意识的反应是握拳,反而会出现危险。
手持的遥控器,主要部分也是由Arduino和蓝牙模块组成(遥控器的蓝牙需要使用主设备,滑板上的使用从设备)。具体的原理图和器件清单,我也会在后续的攻略中陆续发出。
~~~~~~~~~~~~~~~~~~这是一条分割线~~~~~~~~~~~~~~~~~~~~~~
控制板和遥控器中使用的器件清单,有些略有调整,不一定都更新在里面了。
我写攻略比较啰嗦,所以更新的比较慢,大家不要着急。这里是目录页,我每写一篇就会更新到这个里面。