Arduino UNO + SIM800L-向服务器发送数据

问题描述 投票:1回答:1

我正在使用带有调制解调器sim800l的arduino UNO板。我想用它每10秒将数据发送到服务器mysql。当我在arduino IDE中打开了串行监视器(数据已保存到mysql数据库中)时,一切工作正常,但是当串行监视器关闭时,则不起作用。

我想使用我的系统远程连接到移动电源。但是它仅在我打开arduino IDE串行监视器时才有效。

如何编辑代码,使微控制器在不连接计算机和开放式串行监视器的情况下工作?

#include <SoftwareSerial.h>
SoftwareSerial gprsSerial(7, 8);

void setup()
{
  gprsSerial.begin(19200);
  Serial.begin(19200);

  Serial.println("Config SIM900...");
  delay(2000);
  Serial.println("Done!...");
  gprsSerial.flush();
  Serial.flush();

  // attach or detach from GPRS service 
  gprsSerial.println("AT+CGATT?");
  delay(100);
  toSerial();


  // bearer settings
  gprsSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
  delay(2000);
  toSerial();

  // bearer settings
  gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"internet\"");
  delay(2000);
  toSerial();

  // bearer settings
  gprsSerial.println("AT+SAPBR=1,1");
  delay(2000);
  toSerial();
}


void loop()
{
   // initialize http service
   gprsSerial.println("AT+HTTPINIT");
   delay(2000); 
   toSerial();

   // set http param value
   gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://server.net/test.php?data1=2&data2=3\""); 
   delay(2000);
   toSerial();

   // set http action type 0 = GET, 1 = POST, 2 = HEAD
   gprsSerial.println("AT+HTTPACTION=0");
   delay(6000);
   toSerial();

   // read server response
   gprsSerial.println("AT+HTTPREAD"); 
   delay(1000);
   toSerial();

   gprsSerial.println("");
   gprsSerial.println("AT+HTTPTERM");
   toSerial();
   delay(300);

   gprsSerial.println("");
   delay(10000);
}

void toSerial()
{
  while(gprsSerial.available()!=0)
  {
    Serial.write(gprsSerial.read());
  }
}
c++ arduino at-command arduino-c++ sim800
1个回答
0
投票

我不确定Serial的基本实现,但是可能会无限期地等待Serial.println()的发生。

因为Serial.println()似乎使用Serial.write()功能来完成其工作,所以我想如果某个时刻没有设备从串行端口读取数据,则写缓冲区将变满并导致Serial.println()阻塞。

我将在使用Serial.availableForWrite()进行任何输出之前使用Serial.println()函数,并且如果可用字节数指示写缓冲区已满,则跳过输出。

[也许最好的方法是作为Setup()函数的一部分,在执行Serial.begin()之后检查写缓冲区的大小,并将其存储在全局变量中,然后使用该全局变量检查写缓冲区是否被清空是否。

请参见https://www.instructables.com/id/Arduino-Serial/,其中有这句话:

步骤3:命令:

说明

获取可用于写入的字节数(字符)串行缓冲区,而不会阻止写操作。

语法

Serial.availableForWrite()

另请参阅https://www.arduino.cc/reference/en/language/functions/communication/serial/availableforwrite/

还有if (Serial)可用于检查端口是否可用。 https://www.arduino.cc/reference/en/language/functions/communication/serial/ifserial/但是我怀疑这更多是检查所请求的端口是否可用,而不是该端口是否实际上与链接另一端的设备一起工作。

还有Serial.available() https://www.arduino.cc/reference/en/language/functions/communication/serial/available/

Serial.available()

说明

获取可从中读取的字节数(字符)串行端口。这是已经到达并存储在串行接收缓冲区(保存64个字节)。

Serial.available()从Stream实用程序类继承。

语法

Serial.available()

参数

Serial:串行端口对象。请参阅可用串行端口列表,以了解串行主页上的每个板。

返回

可读取的字节数。

我的建议是,对于每行Serial.println(),首先检查Serial.availableForWrite()可用的缓冲区字节数,如下所示:

int firstAvailableForWrite = 0;

void Setup ()
{
    // set up everything you do then add the following statement
    firstAvailableForWrite = Serial.availableForWrite();
}

然后您将在哪里进行写操作,并使用类似于下面示例的if语句进行修改:

if (Serial.availableForWrite() >= firstAvailableForWrite) Serial.println("Config SIM900...");

或者您也可以创建类似以下的函数:

int serialPrintLineIfAvailable (char *aszLine)
{
    int iCount = 0;
    if (Serial.availableForWrite() >= firstAvailableForWrite) iCount = Serial.println(aszLine);

    return iCount;
}

然后,无论您想在何处使用Serial.println(),都应像在serialPrintLineIfAvailable()中一样使用serialPrintLineIfAvailable("Config SIM900...");

© www.soinside.com 2019 - 2024. All rights reserved.