1

我现在正在使用 Arduino + WiFiShield 创建一个门锁,它可以通过带有浏览器的便携式设备远程控制门锁。但似乎我的程序有一个错误,我不知道它为什么会发生。

以下是我的错误。

我的 Arduino 多次执行从 Web 浏览器发送的相同命令。换句话说,如果我按下出现在网络浏览器上的按钮,我的 Arduino 将执行我在 Arduino 中编写的相应功能,不仅一次而且多次(通常是 3 次,有时只有两次......)。

以我的代码为例,如果我在网络浏览器上按下 FORWARD 按钮,我的 Arduino 将运行子函数“closedoor();” 3次。串行监视器返回日志如下:

Server connected
Processing request for /?V=C
STOP : 
closingdoor : 
TX 329 bytes
STOP : 
closingdoor : 
TX 329 bytes
STOP : 
closingdoor : 
TX 174 bytes
Server connection closed
Server connected
Processing request for /favicon.ico
TX 19 bytes
Server connection closed

如果我取消注释“Serial.println(URL);”,我将从串行监视器获得以下日志:

Server connected
Processing request for /?V=C
/?V=C
STOP : 
closingdoor : 
TX 329 bytes
/?V=C
STOP : 
closingdoor : 
TX 329 bytes
/?V=C
STOP : 
closingdoor : 
TX 174 bytes
Server connection closed
Server connected
Processing request for /favicon.ico
/favicon.ico
TX 19 bytes
Server connection closed

如果有人知道什么,请给我一个建议。我真的需要弄清楚。

以下是我的代码。请看一看!!

#include <WiServer.h>

const int LMD18245_Brake = 4; // Pin 4 of Motoduino     
const int LMD18245_Direction = 5;  // Pin 5 of Motoduino   

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[]    = {192,168,1,5};   // IP address of WiShield
unsigned char gateway_ip[]  = {192,168,1,1};   // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
char ssid[]                 = {"Johnny"};   // max 32 bytes
unsigned char security_type = 2;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"xxxxxxxx"};   // max 64 characters

byte sampledata=50;
char link[]="http://motoduino.com/"; //link data

// WEP 128-bit keys
prog_uchar wep_keys[] PROGMEM = { 
    0x61, 0x62, 0x63, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 0
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 1
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 2
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00    // Key 3
};

// setup the wireless mode; infrastructure - connect to AP; adhoc - connect to another WiFi device
#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2
unsigned char wireless_mode = WIRELESS_MODE_INFRA;
unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------

boolean mainpage()
{
          WiServer.print("<html><head></head>");
          WiServer.print("<body>");
          WiServer.print("<table border= 0>");
          WiServer.print("<tr>");
          WiServer.print("<th>  </th>");
          WiServer.print("<th>");
          WiServer.print("<form  method=get>");
          WiServer.print("<input type=hidden name=V value=C /><br />");
          WiServer.print("<input type=submit value=FORWARD>");
          WiServer.print("</form>");
          WiServer.print("</th><th> </th>");
          WiServer.print("</tr>");
          WiServer.print("<tr><th>");
          WiServer.print("<form  method=get >");
          WiServer.print("<input type=hidden name=V value=O /><br />");
          WiServer.print("<input type=submit value=LEFT>");
          WiServer.print("</form>");
          WiServer.print("</th><th>");
          WiServer.print("<form  method=get >");
          WiServer.print("<input type=hidden name=V value=S /><br />");
          WiServer.print("<input type=submit value=STOP>");
          WiServer.print("</form>");
          WiServer.print("</th><th> ");
          WiServer.print("<form  method=get >");
          WiServer.print("<input type=hidden name=V value=R /><br />");
          WiServer.print("<input type=submit value=RIGHT>");
          WiServer.print("</form>");
          WiServer.print("</th></tr> <tr> <th>  </th> <th> ");
          WiServer.print("<form  method=get >");
          WiServer.print("<input type=hidden name=V value=B /><br />");
          WiServer.print("<input type=submit value=BACKWARD>");
          WiServer.print("</form>");
          WiServer.print(" </th> <th> </th> </tr>");
          WiServer.print("</table>");
          WiServer.print("<br/>");
          WiServer.print("<font color=#888888 size=1>Project_Test</font><font size=3>");
          WiServer.print("<br /></font><font size=3> Johnny</font><br />");
          WiServer.print("</body>");
          WiServer.print("</html>");

          return true; 
}

boolean  controlpage(char* URL)
{
//    Serial.println(URL);
    if (strcmp(URL, "/") == 0)
    {
          mainpage();  
         return true;
    }
    else
    {
         if(URL[1] == '?')
         {
           if((URL[2] == 'V') && (URL[3] == '='))
           {
              switch(URL[4])
              {

                 case 'C': 
                           closedoor(); 
                          break;
                 case 'O': 
                           opendoor(); 
                          break;
                 case 'S': 
                           stopmode(); 
                          break;   
                 default:
                 //Do nothing
                          break;            
              }
           mainpage();  
           return true;    
           }
          mainpage();  
          return true;          
         }      

    }
}

void opendoor()
{
  digitalWrite( LMD18245_Brake, 0);
  digitalWrite( LMD18245_Direction, 1);
  delay(200);
  stopmode();

  Serial.println("openingdoor : ");
}

void closedoor()
{
  digitalWrite( LMD18245_Brake, 0);
  digitalWrite( LMD18245_Direction, 0);
  delay(200);
  stopmode();

  Serial.println("closingdoor : ");
}

void stopmode()
{
  digitalWrite( LMD18245_Brake, 1);
  digitalWrite( LMD18245_Direction, 0);

  Serial.println("STOP : ");
}

void setup() {
  Serial.begin(9600);

  // set all color leds as output pins
  pinMode(LMD18245_Brake, OUTPUT);
  pinMode(LMD18245_Direction, OUTPUT);

  WiServer.init(controlpage);
  digitalWrite( LMD18245_Brake, 1);
  // Enable Serial output and ask WiServer to generate log messages (optional)
  WiServer.enableVerboseMode(true);
}

void loop(){

  // Run WiServer
  WiServer.server_task();

  delay(10);
}
4

1 回答 1

1

这是因为创建 wishield 库的 atmega328(或类似设备)上的缓冲区很小。

atmega328 的 RAM 非常有限,因此它们被迫使用一个小的缓冲区。如果您在库中“grep”了 SIZE,我相信这是定义它的行:

uipopt.h:#define UIP_BUFSIZE 400

因此,一旦 IP 数据包的标头进入,似乎还有大约 329 个字节留给有效负载。

那么,如果您的页面包含更多内容,会发生什么?

该库只是一遍又一遍地调用您的页面,并记住上次的时间,下一次,它传输下一个 329 字节的段,直到最后的段适合 329 字节,然后它就完成了。

我没有看到任何其他的方法,但如果你不每次都传输相同的东西,它可能会产生烦人的副作用。您必须每次都传输相同的内容,直到完成为止。

他们似乎计划实现一种方法来告诉您它“正在进行中”,但代码不存在:

boolean Server::sendInProgress() {
        return false; // FIX ME
}

因此,简而言之,这很正常,但请确保每次传输相同的内容,并且对于给定页面,您传输的内容的大小永远不会改变。

不用说,这是为了传输静态页面而设计的,而不是运行动态创建的动态内容太花哨的东西,尽管在一定程度上可以做到,如果你小心的话。

顺便说一句,我不会尝试在那里更改#define 的大小,因为那样你会在不知不觉中耗尽堆栈空间,这可能很难调试。

如果您真的只需要被调用一次,那么您必须削减您为该给定 URL 传输的一些内容,直到它小于 329 字节(根据您的日志)。那么它应该只给你打电话一次。

于 2013-11-12T04:36:11.400 回答