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

标签 c++ arduino at-command arduino-c++ sim800

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

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

如何编辑代码,使微 Controller 在不连接计算机和打开串口监视器的情况下工作?

#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());
  }
}

最佳答案

我不确定 Serial 的底层实现,但是可能会无限等待正在发生的 Serial.println()

阅读有关 Serial.flush() 的文档,它似乎也可能是在返回之前无限等待串行输出完成的原因。

因为 Serial.println() 似乎使用 Serial.write() 功能来做它的事情我想如果你没有设备从串行读取port 在某个时候写入缓冲区变满并导致 Serial.println() 阻塞。参见 https://www.arduino.cc/reference/en/language/functions/communication/serial/write/

Notes and Warnings

As of Arduino IDE 1.0, serial transmission is asynchronous. If there is enough empty space in the transmit buffer, Serial.write() will return before any characters are transmitted over serial. If the transmit buffer is full then Serial.write() will block until there is enough space in the buffer. To avoid blocking calls to Serial.write(), you can first check the amount of free space in the transmit buffer using availableForWrite().

查看 Serial.flush() 函数的解释 https://www.arduino.cc/reference/en/language/functions/communication/serial/flush/其中指出:

Serial.flush()

Description

Waits for the transmission of outgoing serial data to complete. (Prior to Arduino 1.0, this instead removed any buffered incoming serial data.)

flush() inherits from the Stream utility class.

并查看这篇文章,https://www.baldengineer.com/when-do-you-use-the-arduinos-to-use-serial-flush.html上面写着“

What does Serial.flush() do?

From the Arduino reference for Serial.flush (found on this page):

Waits for the transmission of outgoing serial data to complete.

这句话的关键是“外向”。 Serial.flush() 没有 正如许多人所想的那样清空“传入”缓冲区。它暂停你的 在刷新传输缓冲区时进行编程。

我会在使用 Serial.println() 进行任何输出之前使用 Serial.availableForWrite() 函数,如果可用字节数表明写入缓冲区是变满然后跳过输出。

可能最好的方法是作为 Setup() 函数的一部分,在执行 Serial.begin() 后检查写入缓冲区大小并将其存储在全局变量,然后您可以使用它来检查写入缓冲区是否已清空。

参见 https://www.instructables.com/id/Arduino-Serial/有这样的话:

Step 3: Command : ​ AvailableForWrite()

Description

Get the number of bytes (characters) available for writing in the serial buffer without blocking the write operation.

Syntax

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()

Description

Get the number of bytes (characters) available for reading from the serial port. This is data that’s already arrived and stored in the serial receive buffer (which holds 64 bytes).

Serial.available() inherits from the Stream utility class.

Syntax

Serial.available()

Parameters

Serial: serial port object. See the list of available serial ports for each board on the Serial main page.

Returns

The number of bytes available to read.

建议的行动方案

首先,我没有看到 Setup() 函数中的 Serial.flush() 是必需的,可以安全地删除它。虽然这使得控制台在 Setup() 期间立即输出,但它确实引入了一个等待远程情况的过程,在这种情况下没有设备从串行线路读取以清空输出缓冲区。

我还建议,对于执行 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...") ;

关于c++ - Arduino UNO + SIM800L - 向服务器发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59911634/

相关文章:

arduino - 使用 SD 卡和 arduino 的单位模式

C++ 从 'const char*' 到 'char' 的无效转换

excel - 从 Matlab 发送短信并确保所有收件人都收到短信

java - 使用 AT 命令发送短信的名称而不是号码

c++ - 线程在检查数据库时抛出错误

C++ 使用 qsort 对类数组进行排序

C++从istream读取int,检测溢出

java - 将数据从 Java 文件传递​​到 cpp

c++ - Arduino SIM800L : converting String to char* error

java - 当短信再次发送时,命令显示忙(在java中)