2012-04-04

以瀏覽器控制HiTechnic自主平衡機器人HTWay

HTWay除了最初以IRReceiver接收PF IR遙控方式之外,在HiTechnic Blog中,相繼也介紹了Android APP以及NXT等兩種控制版本,事實上這兩者都同樣是以藍芽無線方式控制,只是採用不同的使用者介面(UI)
這裡將再運用前一篇“以瀏覽器控制Mindstorms NXT”的方式,以瀏覽器為操作介面,經由Arduino Web Server透過XBee無線方式傳送指令來對HTWay進行控制。
也因此會以NXTBee取代原來的IRReceiver作為接收遙控指令。
(Controlling HTWay via Browser)

(Video )

最主要的實作為:
更改HTWay的接收遙控方式,這需要修改HTWayNXC程式。



變更Web page為圖形介面,這需要讓Arduino web server能夠傳送內嵌圖像給瀏覽器以及解決ATMmega328只有2K SRAM的問題。

修改HTWayControl Code
HiTechnic HTWayNXC程式碼維持機器人平衡(Balance code)控制機器人移動(Control code)兩部份區隔開來,可以分別依據自己的需求進行修改。
例如,想要以其他的感應器取代原來的GYRO來偵測機器人的平衡狀態,則只需修改Balance code,而不會影響Control code
同樣,在本次實作,控制方式以NXTBee取代IRReceiver,所以,就只需修改Control code,將接收到的指令,轉換成為更新控制機器人移動所用到的:motorControlDrivemotorControlSteer這兩個全域變數的值。
原來的IR版本會定期去讀取IRReceiver感應器暫存器值,並存到pfData八個元素的陣列中,而只使用前兩個元素值來更新全域變數值。本次實作在盡量不變更原程式碼的前提下,也同樣使用pfData陣列來存放控制指令的轉換值:修改Control code中讀取控制值的呼叫function
task taskControl()
{
  Follows(main);
  short control_wait_times;
  char pfData[8];
  while(true) {
    //
Mark原來的程式碼
    //
ReadSensorHTIRReceiver(IR_RECEIVER, pfData);
    //
if (pfData[IR_LEFT] == -128) pfData[IR_LEFT] = 0;
    //
if (pfData[IR_RIGHT] == -128) pfData[IR_RIGHT] = 0;
   
    //
改為讀取RS485 port
   
ReadCommandFromRS485(pfData);
    // Set control Drive and Steer.  These are in motor degree/second
    motorControlDrive = (pfData[IR_LEFT] + pfData[IR_RIGHT]) *
                                          CONTROL_SPEED / 200.0;
    motorControlSteer = (pfData[IR_LEFT] - pfData[IR_RIGHT]) *
                                          CONTROL_SPEED / 200.0;
    Wait(CONTROL_WAIT);
  }
  // Wait to allow user time to see screen.
  Wait(10000);

新增function,由RS485 port接收來自Arduino web server傳送的指令,並轉換為控制值:

void ReadCommandFromRS485(char &pfData[])
{
  string strAction;
  long lastTick = CurrentTick();
  pfData[IR_LEFT]  = 0;
  pfData[IR_RIGHT] = 0;
  while((CurrentTick() - lastTick) < 1000)
  {
    if(RS485DataAvailable())
    {
      strAction = "" ;
      RS485Read(strAction);
      if(StrLen(strAction)>0)
      {
        for(int xii=0; xii         {
          if(SubStr(strAction,xii,1) == "@" ) break;
          else
          if(SubStr(strAction,xii,1) == "F" )
          {
            pfData[IR_LEFT]  =  100;
            pfData[IR_RIGHT] =  100;
            break;
          }
          else
          if(SubStr(strAction,xii,1) == "B" )
          {
            pfData[IR_LEFT]  = -100;
            pfData[IR_RIGHT] = -100;
            break;
          }
          else
          if(SubStr(strAction,xii,1) == "L" )
          {
            pfData[IR_LEFT]  =  100;
            break;
          }
          else
          if(SubStr(strAction,xii,1) == "R" )
          {
            pfData[IR_RIGHT] =  100;
            break;
          }
        } // for loop
        if((pfData[IR_LEFT] != 0) || (pfData[IR_RIGHT] != 0)) break;
      } // if(StrLen(strAction)>0)
    } // if(RS485DataAvailable())
    Wait(100);
  } // while loop}

Arduino Web server傳送內嵌圖片給瀏覽器
前一篇Web page的控制介面使用HTML form tagSubmit button
本篇則是以四個箭頭圖像作為控制HTWay前進、後退以及左、右轉向的圖形介面。
此外,再加上NXTArduino兩個Icons
(HTWay control panel)

因此在每次Arduino Web server回覆HTTP Response時,即需要傳送共六個圖像資料給瀏覽器顯示。然而因為Arduino無法處理內嵌式圖片物件,所以就需要先編碼成mime Base64格式字串,再以字元串流方式下載到瀏覽器顯示。
線上編碼轉換網址:http://www.motobit.com/util/base64-decoder-encoder.asp
以向左箭頭圖像為submit buttonArduino程式碼為例,紅字部分為編碼後的字串:
P(left_arrow) =

"form action='/' method='POST'"
"
input type='hidden' name='nxtControl' value='R'"
"
input type='image' src='data:image/jpg;base64,"
"
iVBORw0KGgoAAAANSUhEUgAAAD0AAAA3CAIAAAAwm9XYAAAAAXNSR0IArs4c6QAAAARnQU1BAACx"
"
jwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAgNJREFU"
"
aEPVmqGywjAQRSuRSD4BiUQikUgkn4DEIZFIJBKJRCKRSCQSiUTuu2/SCR2aNtmk090wVUwpJ2c2"
"
zc22BYl/Ph/abun1YoEUrLO7P/lyofGYioKeT9bF5bh3OxoM/onNkQH39Vo6ttAZcKOOq7h5+N7v"
"
aTjMh/v9drOqrpPDodGxUu7bjaZTv2ld95OQ2lDn+3ik0SjUtLxvrmMVvs9ntmNh7seD5nNeVdSX"
"
nr7XeaS5asxwroWdf0kUm6ugJ91x9HgiuUUcVwcZw20Tc7St9B/yuBHlFovU+ZcOjSuEcmPFNrsS"
"
JYefG45XKy241pqfuykuy4pv42aluZ6H4ebW6bjtPni/MxJzz47d3Ihy67W6+dek5lsn3LgsKLu8"
"
fwfu/2RBf/699J2S90XG860T3PUmkwzr2zQVW/oyIl7989I2Q5v6YNq57QDQL1W7AHnyiVr3/lyl"
"
YZdQL1E/N8oGu7KfHrt4rQdx24qHeyXLKo/buN9sBBoP7vWS9UQIJ6PRI1sqbN92hKeTZM3Ec9sB"
"
iLjvgBsDiOgay/cHjfj0bUfffc3qnEaojJ6vktzWfUTLRZ7b0HPda+EGOitRKuIGOhLlchlU9Lq4"
"
Tc3gRQLvfNXIbejb29B6uQ09QqXTvXZuoOOtpPqjrAy4gV5/rJUHt11lbZrPjNuk+dmM+37VH7L/"
"
WySjImoPAAAAAElFTkSuQmCC' width='300' height='300' border='0'"
"
/form";

HTML完整內容WebPage_HTWayControlPanelHTML.html

Program Memory(Flash memory)存放大量資料

因為在Arduino程式中有六個圖像編碼後的大量字串資料,可能會超過ATMmega328可用的2K SRAM容量,所以需要預先將資料存放到32KFlash記憶體中,等到要使用時再讀取至SRAM
Arduino完整程式碼WebServer_NXT_ControlPanel.ino

處理HTTP request的參考資料HTTP Headers for Dummies

非常實用的工具書Arduino Cookbook, 2nd Edition

沒有留言:

張貼留言