佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 6073|回复: 79

邀请各位设计无线小车

[复制链接]
发表于 18-2-2014 12:36 AM | 显示全部楼层 |阅读模式
一个人玩没意思,也没有太多时间设计与改良。我对机械有恐惧感,看着那一个个大小齿轮,额头冒汗,简直是我的死穴。希望各位加入,一齐来设计一个世上最便宜,功能最强且完美无疵的无线小车

帖子是由我发出,当然由我先开始啦!

小车功能
  • 一个webcam:用于拍攝与录影裙底风光。小桥流水,景色优美,千万别错过好时光!
  • 车前灯:裙底里面可能很暗,必须使用照明才能“一目了然”
  • 高音贝喇叭:看不顺眼的,horn他一下,吓到他屎尿齐流
  • 车速控制:小桥流水,景色优美,可以放慢速度,尽情欣赏。万一被媚媚发现了,加速逃之夭夭
  • 两轮驱动
  • 我想不到了,你来帮我想想


我比较熟悉Arduino,所以控制器是使用Arduino。喜欢pic的哥儿们,就展示你们的pic绝招吧。

无线接收发器是使用一个无线接路由器(router),就是一般用来上网的wifi 路由器,隋便一间电脑商店都可以购买到。也可以使用Wifi Shield,但价钱....嘿嘿,而且也不易购得。

客户控制软件可以是Android apps或者IOS apps。如果等我来编写程序,须等十年才能完成,所以这分轻松简单的工作就让给各位了。

为了展示我的才华,这里先编写两类控制,一个是web GUI,使用浏览器操纵。

另一个是Ms Windows client application。不好意思,它是用Delphi编写的,这样冷门的编程,应该没有几个人会注意。会VB或C编程的朋友,是时候炫耀了。

对于英文输入,没有人可以与我匹敌至于中文输入,妈妈没有教我,老师也不肯教我,自己又不求上进。所有想要篇写这样长的文章,不得不费上好长的时间来完成。这样吧!先佔用十一个版位(二楼至十二楼),然后给我三年的时间来完成

我先睡觉了,Sleep Mode启动了,请勿打扰
18/02/2014 12.30AM 本帖最后由 西门庆33 于 18-2-2014 07:30 PM 编辑

回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 18-2-2014 12:37 AM | 显示全部楼层
先决条件
  • 电脑必须安装了SSH(Secure Shell)客户端,建议使用PuTTy
  • 电脑必须安装了WinSCP
  • 路由器固件(router firmware)必须刷了OpenWRT
  • 必须能夠上网


SSH是一种加密网络协议,远程命令登录,而PuTTy是一个软件,类似telnet,通过键盘一行一行的输入指令。如果曾经使用过MS Dos的朋友,肯定知道什么是command line,操作非常烦恼。

为了弥补PuTTy的不足,WinSCP出现了,它拥有一个图形用户界面,方便操作。如果说Windows Explorer是MS Windows里的一个文件管理应用软件,那么WinSCP就是一个用在路由器里的文件管理应用软件。

请看如何使用PuTTy登录路由器。打开PuTTy,将会看到以下画面,输入Host Name及Port就行了
PuTTy login.jpg
  • Host Name是路由器的IP地址,我的路由器是设成192.168.0.1
  • Port必须是22
  • Connection type必须是SSH

设定完成后,请单击Open按钮就可以登入路由器了。输入路由器的user name及密码后将会看见以下画面:
Putty login1.jpg


使用WinSCP
  • 打开WinSCP
  • 输入Host name,也就是你的路由器IP地址,这里是192.168.0.1
  • Port number必须是22
  • 输入路由器的user name与密码
  • File protocol必须是SCP
设定完成后,请单击Save按钮。下次使用只要选择之前的设定就行了


使用WinSCP登入路由器,可能会出现以下错误信息。别管它,只要单击OK按钮就行了。


完成登入路由器后,将会出现以下画面



OpenWRT firmware
为何路由器的固件(firmware)必须升级至OpenWRT?
厂家的固件只能处理路由器本身的基本功能,OpenWRT则是一个专门为路由器设计的嵌入式Linux操作系统(为了容易明白,我称之为操作系统)。就好像个人电脑安装Windows XP, Windows 7等等,这都称操作系统(Operating System,简称OS)。

既然OpenWRT是一个Linux操作系统,那么应用在Linux的程序也就可以在 OpenWRT里运行了。应用在 Linux里的程序是不能直接装载在路由器里使用,它必须修改与重新编辑。这並不重要,因为已经有人为我们准备好了。我们的工作只是下载与安装就行了。 本帖最后由 西门庆33 于 18-2-2014 07:31 PM 编辑

评分

参与人数 1积分 +100 收起 理由
pic + 100 原创内容

查看全部评分

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:37 AM | 显示全部楼层
刷新OpenWRT固件(firmware)
完成了下面步骤后,如果不想玩遥控小车也无防,你可以把它当着Repeater(增加Wifi距离)使用,然后就此结速。



一个普通的路由器,刷了OpenWRT,立刻变成一个超级路由器,好比是一部嵌入式电脑,是否很神奇?

OpenWRT路由器能做什么呢?多得很,它可以是web server,file server,MP3 player,print server, internet收音机等等,编程方式也多样花。

有很多种型号的路由器都可以支持OpenWRT,请参考Supported Devices

由于TP-Link TL-MR3020 3G/4G Wireless N Router体积小,低功耗且便宜,所以我选择它作为遥控小车的无线收发器。
Untitled - 1.jpg
这是TP-Link TL-MR3020的规格:
  • CPU: Atheros AR7240@400MHz
  • Soc(无线): Atheros AR9330
  • RAM: 32MB
  • NAND: 4MB
  • 印刷电路板: 5.7 cmx 5.7cm
  • 外壳: 6.7cm x 7.4cm x 2.2cm
  • 耗电量: 最高1.25W
  • 通过USB B-Mini供电 (5volts)

价钱:RM70.00左右

升级至OpenWRT非常容易,只须几个步骤就行了。
首先必须下载正确的的路由器固件,刷了错误的固件,你的路由器就完蛋了(但还是有很高的机会救活)
通过OpenWRT的网站,下载这个固件

准备升级OpenWRT啦!!!
  • 打开浏览器
  • 输入http://192.168.0.254 (这是TL-MR3020的默认IP)
  • 输入路由器的User name和Password(两者都是admin)
  • 完成登入后,将会看到以下画面


  • 点击System Tools然后选择 Firmware Upgrade
  • 点击Browse按钮,再选择你之前下载了的固件文件,如图:
  • 最后点击Upgrade按钮开始升级了
  • 必须等待升级完成,中途不能断电,不然路由器就砖了(bricked),这时必须使用特别方法救活之

升级完成啦!是不是很简单?三岁小孩都会啦!
恭喜你拥有一个超级路由器


《《《《《 20/02/2014 10.20PM 更新 》》》》》
现在你的路由器拥有了一个由Lua语言编写的web GUI(Web 图形用户界面),方便设定路由器。同时不需要安装外部软件就可以使用Shell Script(SH),AWK,Lua编程。
最吸引人之处它已经是一个web server,只需把html,Javascript,CSS文件保存在路由器里的\www文件夹就可执行了。

现在就登录这个刷了OpenWRT的TL-MR3020吧!
  • 打开浏览器
  • 输入http://192.168.1.1 (注意:你的TL-MR3020 IP已经从192.168.0.254更换成192.168.1.1)
  • 你将会看到以下画面,暂时不需要输入username及password,只需点击Login按钮只行了

完成第一次登录后,记得一定要点击Go to password configuration以便更换password,不然你将不能使用SSH或者WinSCP(看二楼)
注意:如果你遇到不能登录,可能你的电脑IP地址属于不同组网络(TL-MR3020是192.168.1.1,而你的电脑是192.168.0.x),请再启动你的电脑以便更新IP192.168.1.x

以下是OpenWRT 路由器的第一个web GUI,在这里你可以设定与安装软件
First Screen.jpg


让这个TL-MR3020宝贝上网吧!
假设你已经有了一个上网的wifi modem router(我们称之为AP--Access Point),而这个TL-MR3020则通过你现在这个主AP上网(请看这楼第一张图片)。

这里我们建立两组不同的网络,如果你的主AP IP地址是192.168.1.1,TL-MR3020的AP IP地址则必须设成192.168.0.1。

相反的,如果你的主AP IP地址是192.168.0.1,那么TL-MR3020的AP IP地址就必须设成192.168.1.1。

使用以下设定为例
主AP TL-MR3020 (Client)
IP 192.168.1.1 192.168.0.1
SSID ABC 123

登录后,点击Network再点击 Wifi,然后点击Scan按钮。如图


将会列出附近的无线设备(AP),它们有各自的名字,称为SSID
选择你要连接的 SSID,然后点击Join Network按钮。如图


这个密码必须与你的主AP密码同样
完成密码输入后,请点击Submit按钮


以下画面将会出现,什么都别做,只是点击Save按钮就行了


此例子是要把TL-MR3020的IP地址设成192.168.0.1


把原本的192.168.1.1设为192.168.0.1
完成设定后,再点击Save & Apply按钮,TL-MR3020会重新启动

TL-MR3020现在可以上网了,任何电脑通过网络线(Patch cord)连接至TL-MR3020也是可以上网了
用此方法,可以让一台没有无线功能的电脑变成无线上纲


从TL-MR3020增加一个新的SSID
增加一个新的SSID目的是为了让拥有无线功能的电脑通过无线连接至TL-MR3020来上纲。

打开浏览器重新输入IP地址,这次的IP地址是http://192.168.0.1
登录后请点击Network再点击Wifi,之后点击Add按钮

注意:如果你遇到不能登录,可能你的电脑IP地址属于不同组网络(TL-MR3020是192.168.0.1,而你的电脑是192.168.1.x),请再启动你的电脑以便更新IP192.168.0.x

输入新的SSID,这里的SSID设为123。
Mode必须是AP
在Network选项里必须选择lan
完成后请点击Save按钮


给这个SSID设立一个密码,然后点击Save & Apply按钮
TL-MR3020会重新启动


有两个SSID个


用途:
有一间三层楼的屋子,上纲的wifi  modem router(主AP)放在最底层。三楼有一无线电脑和手机要上纲,但是wifi信号太弱不能连接。
解决方法是把TL-MR3020放在二楼,三楼的无线电脑或手机此时可以通过123的SSID连接至TL-MR3020,由于TL-MR3020已经通过无线连接主AP,所以任何设备连接至TL-MR3020也能上网了。

>>>>> 05/03/2014 7.15PM 更新 <<<<<
完成以上步骤后,阅读8楼和9楼然后才继续阅读4楼较为恰当 本帖最后由 西门庆33 于 5-3-2014 07:15 PM 编辑

评分

参与人数 1积分 +100 收起 理由
pic + 100 原创内容

查看全部评分

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:38 AM | 显示全部楼层
软件编程
软件主要分为三部分
  • 运行在Arduino 的固件(Arduino Sketch)
  • 运行在路由器上Shell Script,让客户端应用软件与Arduino沟通
  • 运行在电脑与智能手机的客户端应用软件,用于控制小车。另外还有一个保存在路由器的web客户端应用软件。

智能手机的客户端应用软件还没来得及编写,希望哥哥们代劳

以上软件已经压缩成一个zip文件,从这里下载。zip文件里包含了三个文件夹,它们是:
  • Arduino_Wifi_Car:Arduino固件
  • www:包含了Shell Script和web客户端应用软件
  • Delphi Wifi Car:使用Delphi 7编译的客户端应用软件

1.) Arduino_Wifi_Car文件夹
这是Arduino的固件,文件夹里有一个Arduino_Wifi_Car.ino文件,请把此代码上载至Arduino
详细请看五楼

2.) www文件夹
使用WinSCP把此文件夹保存至TL-MR3020里的\www文件夹
\www文件夹里有几个文件与文件夹,详细请看六楼


请把保存在/www/cgi-bin里的文件permissions更换成0755


3.) Delphi Wifi Car件夹
里面包括了运行在Ms Windows的客户端应用软件代码,必须使用Delphi 7编辑。希望有人使用别的语言编写。
详细请看七楼
本帖最后由 西门庆33 于 21-2-2014 10:28 PM 编辑

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:38 AM | 显示全部楼层
Arduino代码
  1. ////////// blink LED variables
  2. #define BLINK_LED_PIN 13     //the number of the LED pin
  3. int ledState = LOW;          //ledState used to set the LED
  4. long previousMillis = 0;     //will store last time LED was updated
  5. long interval = 500;         //interval at which to blink (milliseconds)

  6. ////////// motor variables
  7. #define MOTOR_ENABLE_PWM_PIN 6    // H-bridge enable (pin 1 & pin 9)
  8. #define LEFT_MOTOR_LOGIC1_PIN 7   // H-bridge leg 1 (pin 2, 1A)
  9. #define LEFT_MOTOR_LOGIC2_PIN 8   // H-bridge leg 2 (pin 7, 2A)
  10. #define RIGHT_MOTOR_LOGIC1_PIN 9  // H-bridge leg 1 (pin 10, 3A)
  11. #define RIGHT_MOTOR_LOGIC2_PIN 10  // H-bridge leg 2 (pin 15, 4A)
  12. #define CAR_HORN_PIN 2
  13. #define HEADLIGHTS_PIN 3
  14. #define INITIAL_SPEED 20
  15. #define DELAY_BETWEEN_MOTOR_CHANGE_DIRECTION 200
  16. int Current_speed, speeds = 0;

  17. ////////// use to determine car action
  18. #define FORWARD 1
  19. #define LEFT 2
  20. #define STOP 3
  21. #define RIGHT 4
  22. #define BACKWARD 5
  23. byte car_action, previous_car_action = STOP;

  24. ////////// serial variables
  25. boolean Rxenable = false;
  26. String inputString = "";         //a string to hold incoming data
  27. boolean stringComplete = false;  //whether the string is complete

  28. void setup()
  29. {
  30.   // set the digital pin as output:
  31.   pinMode(BLINK_LED_PIN, OUTPUT);  
  32.   pinMode(LEFT_MOTOR_LOGIC1_PIN, OUTPUT);
  33.   pinMode(LEFT_MOTOR_LOGIC2_PIN, OUTPUT);
  34.   pinMode(MOTOR_ENABLE_PWM_PIN, OUTPUT);
  35.   pinMode(RIGHT_MOTOR_LOGIC1_PIN, OUTPUT);
  36.   pinMode(RIGHT_MOTOR_LOGIC2_PIN, OUTPUT);
  37.   pinMode(CAR_HORN_PIN, OUTPUT);
  38.   pinMode(HEADLIGHTS_PIN, OUTPUT);

  39.   Serial.begin(9600);
  40.   Serial.println("Wifi RC car");
  41.   car_stop();  
  42. }

  43. void loop()
  44. {
  45.   blinkLED(); //blink LED every second
  46.   
  47.   if (stringComplete) {
  48.     inputString.toUpperCase();
  49.     process_command();
  50.     inputString = ""; //clear the string:
  51.     stringComplete = false;
  52.     Rxenable = false;
  53.   }  
  54. }//end loop


  55. void process_command()
  56. {
  57.   char command=inputString[1];
  58.   switch (command) {
  59.   case '2':  
  60.     car_forward();
  61.     break;   
  62.   case '3':
  63.     car_headLight();
  64.     break;      
  65.   case '4':  
  66.     car_left();
  67.     break;   
  68.   case '5':  
  69.     car_stop();
  70.     break;
  71.   case '6':  
  72.     car_right();
  73.     break;
  74.   case '7':
  75.     car_horn();
  76.     break;      
  77.   case '8':  
  78.     car_backward();
  79.     break;
  80.   case 'S':  
  81.     //extract from first character until end
  82.     //eg. if inputString=@S20 then speeds=20
  83.     speeds = stringToInt(inputString.substring(2));
  84.     car_speed();
  85.     break;   
  86.   }  
  87. }

  88. void load_car_speed()
  89. {
  90.   //if the car is not moving then run the car with INITIAL_SPEED
  91.   if (previous_car_action == STOP) {
  92.     speeds = INITIAL_SPEED;
  93.     car_speed();
  94.   }  
  95.   
  96.   if ((car_action == FORWARD && previous_car_action == BACKWARD)
  97.   || (car_action == BACKWARD && previous_car_action == FORWARD)
  98.   || (car_action == LEFT && previous_car_action == RIGHT)
  99.   || (car_action == RIGHT && previous_car_action == LEFT))
  100.   {
  101.     leftMotor_stop();
  102.     rightMotor_stop();
  103.     delay(DELAY_BETWEEN_MOTOR_CHANGE_DIRECTION);
  104.   }

  105.   previous_car_action = car_action;
  106. }

  107. void car_stop()
  108. {
  109.   car_action = STOP;
  110.   leftMotor_stop();
  111.   rightMotor_stop();  
  112. }

  113. void car_forward()
  114. {
  115.   car_action = FORWARD;
  116.   load_car_speed();
  117.   leftMotor_run();
  118.   rightMotor_run();
  119. }

  120. void car_backward()
  121. {
  122.   car_action = BACKWARD;
  123.   load_car_speed();
  124.   leftMotor_backward();
  125.   rightMotor_backward();
  126. }

  127. void car_left()
  128. {
  129.   car_action = LEFT;
  130.   load_car_speed();
  131.   rightMotor_run();
  132.   leftMotor_stop();
  133. }

  134. void car_right()
  135. {
  136.   car_action = RIGHT;
  137.   load_car_speed();
  138.   leftMotor_run();
  139.   rightMotor_stop();
  140. }

  141. void car_horn()
  142. {
  143.   // Serial.print("Horn");  
  144.   if (digitalRead(CAR_HORN_PIN)==LOW) {
  145.     digitalWrite(CAR_HORN_PIN, HIGH);
  146.   } else {
  147.     digitalWrite(CAR_HORN_PIN, LOW);
  148.   }   
  149. }

  150. void car_headLight()
  151. {
  152.   // Serial.print("Head Light");  
  153.   if (digitalRead(HEADLIGHTS_PIN)==LOW) {
  154.     digitalWrite(HEADLIGHTS_PIN, HIGH);
  155.   } else {
  156.     digitalWrite(HEADLIGHTS_PIN, LOW);
  157.   }  
  158. }

  159. void car_speed()
  160. {
  161.   Current_speed = speeds;
  162.   int speeds_mapped = map(Current_speed, 0, 100, 80, 255);
  163.   analogWrite(MOTOR_ENABLE_PWM_PIN, speeds_mapped);
  164. }

  165. //////////////////////// leftt motor
  166. void leftMotor_run()
  167. {
  168.   digitalWrite(LEFT_MOTOR_LOGIC1_PIN, LOW);
  169.   digitalWrite(LEFT_MOTOR_LOGIC2_PIN, HIGH);
  170. }

  171. void leftMotor_backward()
  172. {
  173.   digitalWrite(LEFT_MOTOR_LOGIC1_PIN, HIGH);
  174.   digitalWrite(LEFT_MOTOR_LOGIC2_PIN, LOW);  
  175. }

  176. void leftMotor_stop()
  177. {
  178.   digitalWrite(LEFT_MOTOR_LOGIC1_PIN, LOW);
  179.   digitalWrite(LEFT_MOTOR_LOGIC2_PIN, LOW);
  180. }

  181. //////////////////////// right motor
  182. void rightMotor_run()
  183. {
  184.   digitalWrite(RIGHT_MOTOR_LOGIC1_PIN, LOW);
  185.   digitalWrite(RIGHT_MOTOR_LOGIC2_PIN, HIGH);
  186. }

  187. void rightMotor_backward()
  188. {
  189.   digitalWrite(RIGHT_MOTOR_LOGIC1_PIN, HIGH);
  190.   digitalWrite(RIGHT_MOTOR_LOGIC2_PIN, LOW);  
  191. }

  192. void rightMotor_stop()
  193. {
  194.   digitalWrite(RIGHT_MOTOR_LOGIC1_PIN, LOW);
  195.   digitalWrite(RIGHT_MOTOR_LOGIC2_PIN, LOW);
  196. }

  197. ////////// convert string to integer
  198. int stringToInt(String str)
  199. {
  200.   char char_string[str.length()+1];
  201.   str.toCharArray(char_string, str.length()+1);
  202.   return atoi(char_string);
  203. }

  204. ////////// blink LED without delay
  205. void blinkLED()
  206. {
  207.   unsigned long currentMillis = millis();

  208.   if(currentMillis - previousMillis > interval) {
  209.     // save the last time you blinked the LED
  210.     previousMillis = currentMillis;   

  211.     // if the LED is off turn it on and vice-versa:
  212.     if (ledState == LOW)
  213.       ledState = HIGH;
  214.     else
  215.       ledState = LOW;

  216.     // set the LED with the ledState of the variable:
  217.     digitalWrite(BLINK_LED_PIN, ledState);
  218.   }  
  219. }

  220. /*
  221.   SerialEvent occurs whenever a new data comes in the
  222. hardware serial RX.  This routine is run between each
  223. time loop() runs, so using delay inside loop can delay
  224. response.  Multiple bytes of data may be available.
  225. */
  226. void serialEvent() {
  227.   while (Serial.available()) {
  228.     char inChar = (char)Serial.read(); // get the new byte:
  229.     if (inChar == '@') {     // Can start recording after [url=home.php?mod=space&uid=1968553]@[/url] symbol
  230.       Rxenable = true;
  231.     }
  232.    
  233.     if (Rxenable==true) {
  234.       inputString += inChar; // add it to the inputString:
  235.       // if the incoming character is a carriage return, set a flag
  236.       // so the main loop can do something about it:
  237.       if (inChar == '\r') {
  238.         stringComplete = true;
  239.       }
  240.     }
  241.   }
  242. }
复制代码
此wifi遥控小车使用了一个Arduino作为控制器,请浏览这里关于更多Arduino资料。

别让272行的Arduino代码吓着了,其实很简单也易懂。

为了方便调试,建议每个输出连接一LED,在不连接马达的情况下也能知道Arduino是否正常工作。

代码动用了一个串口作为接收指令,baud rate设为9600,所有指令必须有一Carriage Return作为结束。 自Arduino1.0版本起,serialEvent()函数就集成在IDE里了,毎一次loop都会运行 serialEvent()。当串口出现数据时,serialEvent()一直loop至接收到Carriage Return,之后资料将会保存在 inputString变数里。只要接收到一个Carriage Return,serialEvent()会跳出,接着运行process_command(),代码将会根据接收到的指令运行不同的工作,比如转左,开灯。。。。。。

当Arduino操作时,D13每隔500 milli seconds (0.5秒)闪烁一次,没有什么特别功能,只是让你知道:"嗨!我正在操作"。这个闪烁功能是由 blinkLED()负责,由于它是一个没有延迟(delay)的闪烁功能,所以它不会影响其他的代码运行。

发送到串口的指令格式必须如下:
@command\r 或者@Sx\r

数据必须由一个@起始,接下来才是command。没有@起始的数据都会作废。

command是一个单字,例:
@2 (向前跑)
@4 (转左)
@5 (停)

@Sx只是用来控制速度,x的值是0至100,0为停,100为最快速度
速度是由 analogWrite来控制D6,此输出必须支持PWM。由于它是8位分辨率,其值位于0与255之间。为了易读,我使用了map()函数,把它的范围值map成0至100。如果连接一LED至D6,你可以控制它的亮度。

\r则是Carriage Return的写法。没有接收到Carriage Return,Arduino将不会执行小汽操纵或特定工作。

喇叭(D2)与汽车(D3)双态触发(toggle),第一次开,下一次是关。

最后要捕充的是在load_car_speed()函数里(第97行)有一个INITIAL_SPEED常数 (现设为20 PWM,其值位于0与100之间),用处是当小车停止时,接下来收到向前或向后指令,小车将会使用这速度移动。另外在第112行有一 DELAY_BETWEEN_MOTOR_CHANGE_DIRECTION 常数它的用处是当马达反方向旋转时,先让马达停顿一下(现在设为200 milli seconds),用于保护马达。但我不知道是否必要!

本帖最后由 西门庆33 于 22-2-2014 07:41 PM 编辑

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:38 AM | 显示全部楼层
web编程
这里的编程是基于web方面处理,好处是不须另外安装客户端应用软件就可遥控小车,且是cross platform,坏外是程序必须先安装在路由器,这将会占用路由器的flash记忆体。

在www主目录里有三个文件和三个子目录,car.html是主页,car.css是layout(skin), car.js包含一系列的function(函数)。而子目录cgi-bin里有一个名为car的文件,其作用是让路由器与Arduino沟通。代码非常简单,只有三行,如下
  1. #!/bin/sh
  2. cmd=$QUERY_STRING  
  3. echo $cmd+"\r" > /dev/ttyUSB0
复制代码
  • 第一行是注明使用什么script。#!/bin/sh表示使用Shell script#!/bin/lua则是使用lua。当然还有其他编程方式。

  • 第二行是把QUERY_STRING 值(字串)分配给cmd,QUERY_STRING 的值是通过URL查询而取得。只有在?分隔符後的字串才会分配给QUERY_STRING。例:
  1. http://routerIP/cgi-bin/car?@S20
复制代码
从上面的例子,我们得知QUERY_STRING 的值是@S20

  • 第三行是从URL取得的cmd(这里指QUERY_STRING)输出到dev/ttyUSB0(如果用在Ms Windows,是指COM1),
正常来讲,不用编写复杂的web图形用户界面也是可以控制这个小车的。只要打开浏览器输入如下URL格式就行了
  1. http://routerIP/cgi-bin/car?@command
复制代码
其中routerIP是你的TL-MR3020的IP地址,这里是192.168.0.1,command则是你想要执行的指令,车转左、车转右、车打灯等等。例:

车转左
  1. http://192.168.0.1/cgi-bin/car?@4
复制代码
车转右
  1. http://192.168.0.1/cgi-bin/car?@6
复制代码
视频(这指令不用运行/cgi-bin/car,只是让你知道如何查看视频)
  1. http://192.168.0.1:8080/?action=stream
复制代码
上面例子解释如何通过URL控制小车,当然,使用图形用户界面控制小车更为容易。你又要编写入程序了。

想要执行car.html主页时,只需在浏览器里输入http://yourRouterIP/car.html(yourRouterIP是指你的路由器IP地址,这里例子是192.168.0.1)就行了,下面画面将会出现。由于还没完成webcam方面安装,视频部分将是空白。


注意:
请参考二楼的WinSCP把www文件夹复制至路由器的www文件夹

在这里的web编程不需要特别的网页制作软件,使用Notepad直接编辑就行了。不过我还是要介绍一个好用,免费,轻巧的WYSIYWG(What you see is what you get)网页制作软件--kompoZer。用kompoZer打开car.html,你会看到以下画面。
Kompozer.jpg
使用kompoZer非常容易,自己摸索吧!

运行car.html时,它先会读取几个外部文件,如下
  • ../codebase/dhtmlxcommon.js
  • ../codebase/dhtmlxslider.js
  • ../codebase/ext/dhtmlxslider_start.js
  • ../../codebase/dhtmlxslider.css
  • car.js
  • car.css
其中1至4是我从网站下载的JavaScript组件,用处是建立和显示sliderbar,上面图片的sliderbar就是用这个组件建立的。

接下来是建立键盘捕捉,代码如下
  1. <body onkeypress="return keyPressed(event)" onkeyup="keyUp(event)"
复制代码
第一次运行时将会运行autoRun()程序
  1. onload="autoRun()"
复制代码
设背景为黑色
  1. style="background-color: black;">
复制代码
显示webcam视频,其中192.168.0.1是路由器的IP地址,通信口是8080
  1. <div class="img"> <a target="_parent"><img
  2. style="border: 0px solid ; width: 320px; height: 190px;"
  3. src="http://192.168.0.1:8080/?action=stream"></a></div>
复制代码
接下来是一系列的imageClick功能,点击了谋个图象就会执行相对的指令。以下代码从images文件夹里读取b2.png以便显示在屏幕,当不能完整读取b2.png文件时(原因很多,可能internet有问题), Forward 字体将会取代之。点击了这个b2.png图象,将会执行runCmd(2)
  1. <div class="img"> <a target="_parent" href="javascript:runCmd(2)"><img
  2. src="images/b2.png" id="2" alt="Forward"></a>
  3. </div>
复制代码
imageClick的指令或者从cgi(可以是Arduino的状态)返回的值将会分配给result,然後显示在固字位置
  1. <p class="padding"> Command: <span id="result"></span></p>
复制代码
以上所有函数呼叫(function call)都是储存在car.js里。


另外你会看到很多<div..>,这是它的属性,包括位置,字形等等。这些属性都储存在car.css
  1. <div class="img">
  2. .
  3. .
  4. .
  5. </div>
复制代码
键盘捷径,请参考car.js的function keyPressed(e)和function keyUp(e),第10行至72行。
Keyboard
Function
Command
Up Arrow
向前移
@2
Down Arrow
向后移
@8
Left Arrow
转左
@4
Right Arrow
转右
@6
Space
停止
@5
Q
Cam (保留)
Q
W
切换车灯
W
A
喇叭
A
S
麦克风 (保留)
S
1
速度 1
@S20
2
速度 2
@S40
3
速度 3
@S60
4
速度 4
@S70
5
速度 5
@S100

本帖最后由 西门庆33 于 27-2-2014 11:28 PM 编辑

回复

使用道具 举报

Follow Us
 楼主| 发表于 18-2-2014 12:38 AM | 显示全部楼层
Client application编程
我这个运行在Ms Windows的客户应用程序是使用Delphi 7写的,应该没人感兴趣,这里随便带过。如果你懂Visual Studio编程,请放马过来。
控制也是使用HTTP GET method, 请参考六楼的http://routerIP/cgi-bin/car?@command


如果想使用自己的设定(包括按键),可以建立一config.txt文件,把它保存在客户应用程序的文件夹里。内容如果如下
  1. [Settings]
  2.     StartCharacter= @
  3.     IpAddress= 192.168.0.1
  4.     CamPort= 8080
  5. 'mic
  6.     Key1= A
  7. 'head light
  8. Key3= S
  9. 'horn
  10. Key7= Z
  11. 'mic
  12. Key9= X
  13. 'key for predefined speed
  14.     Speed1= 1
  15.     Speed2= 2
  16.     Speed3= 3
  17.     Speed4= 4
  18.     Speed5= 5
复制代码
本帖最后由 西门庆33 于 28-2-2014 12:08 AM 编辑

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:38 AM | 显示全部楼层
安装驱动程序至TL-MR3020
路由器(TL-MR3030)还没有安装相对的驱动程序前,是不能与Arduino沟通的。好比打印文章前,电脑必须先安装了打印机驱动。

这里示范两种不同的方式来安装驱动程序至路由器,只要使用其中一种方法就行了。
  • 使用 OpenWRT固件(firmware)本身的web GUI
  • 使用二楼的SSH

第一种方法
  • 打开浏览器
  • 输入http://192.168.0.1 (192.168.0.1是TL-MR3020的IP地址)
  • 输入TL-MR3020的userName和密码开始登录路由器
  • 点击System->Network,已安装了的Packages(程序包)将会列出来,如图
Installed packages.jpg

  • 想要知道什么程序包可以下载与使用,请点击Available packages,不过它将出现空白,因为你还没有下载“程序包表”
  • 点击Update lists按钮(上面图象有显示Update lists按钮的位置),如果TL-MR3020已经on-line,以下画面将会出现。点击A至Z按钮或者输入程序包的名称以便列出相对的程序包。 WOH!!!,实在太多程序可以安装与使用,你说OpenWRT路由器强吗?
update list.jpg


  • 寻找你要安装的程序包,然后点击Install。下面示范安装一个FTDI USB-Serial驱动程序
1.jpg

注意:使用不同的USB-Serial转换器必须安装不同的驱动程序,请根据以下报表安装你的USB-Serial驱动程序
USB-Serial 驱动程序
Arduino Demilanove 或者 FTDI usb-serial kmod-usb-serial-ftdi
Teensy / Arduino Uno / Arduino Mega kmod-usb-acm
基于PL2303 的USB-Serial转换器kmod-usb-serial-pl2303
基于CP201x 的USB-Serial转换器 kmod-usb-serial-cp210x


第二种方法
以下步骤是使用SSH安装驱动,如果已经使用了上面的第一种方法安装,请跳过这里。
  • 先使用Putty登录路由器,请参考二层

更新程序包表
  1. opkg update
复制代码
如果使用Arduino Demilanove 或者 FTDI usb-serial
  1. opkg install kmod-usb-serial-ftdi
复制代码
如果使用Teensy / Arduino Uno / Arduino Mega
  1. opkg install kmod-usb-acm
复制代码
如果使用基于PL2303 的USB-Serial转换器
  1. opkg install kmod-usb-serial-pl2303
复制代码
如果使用基于CP201x 的USB-Serial转换器
  1. opkg install kmod-usb-serial-cp210x
复制代码
检查驱动是否安装成功
把Arduino或者USB-Serial转换器插入TL-MR3020的USB通信口,输入以下指令
  1. dmesg | grep -i usb
复制代码
你将会看到类似画面(请注意黄色部分)
2.jpg

驱动安装大功告成


本帖最后由 西门庆33 于 1-3-2014 04:12 PM 编辑

回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 18-2-2014 12:39 AM | 显示全部楼层
安装webcam驱动
安装webcam驱动非常简单,只需几个步骤就行了。与8楼的安装方法类似,也是可以使用两种方法来安装。

这里重复8楼的图片
第一种方法
  • 打开浏览器
  • 输入http://192.168.0.1 (192.168.0.1是TL-MR3020的IP地址)
  • 输入TL-MR3020的userName和密码开始登录路由器
  • 点击System->Network,已安装了的Packages(程序包)将会列出来,如图

  • 点击Update lists按钮(上面图象有显示Update lists按钮的位置),如果TL-MR3020已经on-line,以下画面将会出现。点击A至Z按钮或者输入程序包的名称以便列出相对的程序包。

  • 想要知道什么程序包可以下载与使用,请点击Available packages
  • 这里我们要安装kmod-video-uvc mjpg-streamer驱动
  • 在Filter输入框里,先输入kmod-video-uvc ,然后点击Find package按钮,等kmod-video-uvc 出现后,点击Install
  • 使用上面同样的步骤,继续安装mjpg-streamer

webcam设定
webcam驱动安装完成了,接下来是更改设定
  • 根据2楼如何使用WinSCP更改 /etc/config/mjpg-streamer 文件(如果在Ms Windows,我们是使用notepad。但是更改路由器的文件,必须使用WinSCP),
  • 默认值是禁用webcam,将option enabled "0"改为option enabled "1"以便启动webcam
  • 根据你要用的分辨率,更改option resolution ,以下是使用640x480
  • 由于TL-MR3020性能不太强,建议使用320x240。如果只是使用 webcam,没有控制别的设备(比如Arduino),将可以使用1280x720
  • 完成设定后,请保存文件,然后重新启动路由器。
  1. config mjpg-streamer core
  2.          option enabled "1"
  3.          option device "/dev/video0"
  4.          option resolution "640x480"
  5.          option fps "5"
  6.          option www "/www/webcam"
  7.          option port "8080"
复制代码
.
第二种步骤
你也可以使用SSH安装webcam驱动
根据2楼如果使用puTTy,然后SSH至路由器
输入以落下令
  1. opkg update
  2. opkg install kmod-video-uvc
  3. opkg install mjpg-streamer
复制代码
这里放一张安装过程图片
2.jpg
安装完成了,请继续更改设定。步骤与上面一样

检验webcam驱动是否安装成功
把webcam插入路由器的usb通信口,输入以下指令
  1. dmesg | grep -i usb
复制代码
将会出现类似画面
3.jpg

使用浏览器测试webcam,请输入以下URL
  1. http://192.168.1.1:8080/?action=snapshot
复制代码
或者
  1. http://192.168.1.1:8080/?action=stream
复制代码
注意:
除了Internet Explorer,其他的浏览器都可以使用

本帖最后由 西门庆33 于 5-3-2014 08:20 PM 编辑

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:39 AM | 显示全部楼层
电路图与pcb设计
我是使用一颗SN754410NE H-Bridge控制两个马达,Arduino D6 (ATMega328 引脚12) 是一个PWM引脚,它连接至H-Bridge的enable引脚以用来控制马达速度。注意,由于两个马达操作是使用同样的速度,Arduino D11 (ATMega328 引脚17)是没有焊接的,请保留空着。如果将来两个马达要操作个别的速度,Arduino D11就必须焊接了,前提是D6与D11之间的连接必须切断。

这是一个自制的Arduino,由于使用了8Mhz内部时钟(没有使用crystal),所以电路非常简单。如果想学习烧录8Mhz Bootloader,请浏览这里



自制的Arduino是没有usb-serial接口的,所以我使用了以下usb-serial转换器

这是一个Prolific PL2303 USB-Serial 转换器,所以必须执行 opkg install kmod-usb-serial-pl2303安装驱动至路由器。

H-Bridge设计有许多方式,有空才聊。
现在要注意的是这个 SN754410NE 有显著的电压降(voltage drop),如果马达电源(SN754410NE的第8引脚)是5V,你可能只取得3V在马达的接脚。
另外,马达电源(SN754410NE的第8引脚)最底是4.5V,底于4.5V就不能正常工作。




本帖最后由 西门庆33 于 20-3-2014 10:20 PM 编辑

回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:39 AM | 显示全部楼层
保留给车身与车轮
回复

使用道具 举报

 楼主| 发表于 18-2-2014 12:40 AM | 显示全部楼层
保留给其他。
回复

使用道具 举报

发表于 18-2-2014 11:34 AM | 显示全部楼层
保留给俺作参考,顺便监督楼主不会弃楼。。。。
回复

使用道具 举报

 楼主| 发表于 18-2-2014 06:36 PM | 显示全部楼层
可怜草泥马 发表于 18-2-2014 11:34 AM
保留给俺作参考,顺便监督楼主不会弃楼。。。。

太贪心的缘固,我现在後悔了。
不过我说了需要三年的时间来完成编写,请慢慢等待吧
回复

使用道具 举报

发表于 18-2-2014 08:01 PM | 显示全部楼层
太复杂了!不过为了看到裙底风光是值得的。。。。

评分

参与人数 1人气 +5 收起 理由
weitao + 5 我笑了!!!

查看全部评分

回复

使用道具 举报

发表于 18-2-2014 09:01 PM | 显示全部楼层
LZ为何不用TX2B/RX2B?
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 18-2-2014 09:44 PM | 显示全部楼层
koksoon980 发表于 18-2-2014 08:01 PM
太复杂了!不过为了看到裙底风光是值得的。。。。

说复杂,並不复杂,说容易,也真不容易。还没真正开始,制作时可能会比想象中容易。
回复

使用道具 举报

 楼主| 发表于 18-2-2014 10:11 PM | 显示全部楼层
weitao 发表于 18-2-2014 09:01 PM
LZ为何不用TX2B/RX2B?

TX2B/RX2B真的不错,不用编程,也能完成遥控。只需要设计一个发送器和一个接收器就行了。不过它是不适合用来制作这类遥控小车。

  • 不能连接Webcam。最重要的一环:裙底风光也就不能实现了
  • 不能通过PC遥控,包括手机(Android/IOS)。也没有图形用户界面。
  • 没有时速控制
  • 距离有限(WIFI有很多方式增强信号和增加距离)
  • 不能通过internet遥控
  • TX-2B只能有五个频道控制
  • 扩展空间(功能)有限


路由器遥控小车还有许多功能。夸张点,因为这个路由器已经变成了一部嵌入式电脑

本帖最后由 西门庆33 于 18-2-2014 10:19 PM 编辑

回复

使用道具 举报

发表于 18-2-2014 10:30 PM | 显示全部楼层
西门庆33 发表于 18-2-2014 10:11 PM
TX2B/RX2B真的不错,不用编程,也能完成遥控。只需要设计一个发送器和一个接收器就行了。不过它是不适合用 ...

LZ不好意思!!!我错了!只好期待你的作品!!!
回复

使用道具 举报

发表于 19-2-2014 10:11 AM | 显示全部楼层
两轮驱动

单是这个两轮驱动就是一个大项目了。。。,。
你的2轮平衡, 跌倒后能自己爬起来, 这个要先独立建立起来先。。


简单的做法。。
一台智能手机, 能数据上网的,含前后Camera 的, 含GPS 的。
透过USB 扩展I/O, 或者蓝牙扩展I/O, 以便发信号去你的 2 轮车控制板, 方向控制, 速度控制, 控制你的horn 开灯 有的没的。。。或者喇叭, 你要说话, 传回mic 都可以吧。。
你需要编写一个Android Apps,就可以轻松的透过互联网传回画面, 和控制2轮车。  


喜欢轻度折腾的做法:
如果不要用Smart phone, 可以用RPI (RasberryPi) 或CB (CubieBoard) 这类的主板, 加3G GSM 模块, Webcam 之类的, 再追加GPS定位。
镜头要有2个Servor motor 控制角度/高度, 方向, 然后你要编写Linux/Android 下能运行的程序。

非折腾不喜的做法:
我理解, 也些人喜欢折腾的, 他们认为折腾才有乐趣。。
那么, 就尽量不要用模块了。。。所有的东西,控制, 通讯都老老实实的用MCU 去做吧。。。
嗯。。到猴年马月时, 估计就做出来了。。。



在PC/手机 控制方面, 能上网Web base 控制就可以了。。
因为含GPS, 使用3G 数据联网, 只要有信号, 跨国控制都可以。。
GPS 是防丢, 被人绑架/捡去了还有机会找回。。走丢了,迷路了, 还有可能自己导航回来 (可能你又要多1年的时间去做这个功能)


其实, 你要的都能做到。。即使是2轮车的机械部分,相信都有模块, 和很多参考资料了。


最后, 也是最重要的, 你的预算多少钱。。??
多少钱啊?

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 23-4-2024 11:24 PM , Processed in 0.083893 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表