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

Arduino UNO + SIM800L - sending data to server

本文关键字:数据 服务器 UNO+SIM800L- Arduino      更新时间:2023-10-16

我使用的是带有调制解调器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());
}
}

我不确定Serial的底层实现,但可能会有某种对Serial.println()的无限等待。

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

由于Serial.println()似乎使用Serial.write()功能来完成它的任务,我认为如果在某个时刻没有设备从串行端口读取,则写缓冲区会变满,并导致Serial.println()阻塞。看见https://www.arduino.cc/reference/en/language/functions/communication/serial/write/

注意和警告

从Arduino IDE 1.0开始,串行传输是异步的。如果有传输缓冲区中有足够的空空间,Serial.write()将在通过串行传输任何字符之前返回。如果传输缓冲区已满,则Serial.write()将被阻止,直到缓冲区中有足够的空间。为了避免阻塞对Serial.write()的调用,您可以首先检查传输缓冲区中的可用空间量使用available ForWrite()。

请参阅Serial.flush()函数的解释https://www.arduino.cc/reference/en/language/functions/communication/serial/flush/注意事项:

Serial.flush()

说明

等待传出串行数据的传输完成。(之前对于Arduino 1.0,这反而删除了任何缓冲的传入串行数据。)

flush()继承自Stream实用程序类。

请参阅本文,https://www.baldengineer.com/when-do-you-use-the-arduinos-to-use-serial-flush.html上面写着">

Serial.flush()做什么?

来自Arduino的Serial.flush参考(在本页上找到):

等待传出串行数据的传输完成。

该语句的关键是"传出"。Serial.flush()没有正如许多人所想的那样清空"传入"缓冲区。它会暂停您的程序,同时刷新传输缓冲区。

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

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

请参阅https://www.instructables.com/id/Arduino-Serial/也就是说:

步骤3:命令:​可用于写入()

说明

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

语法

Serial.available ForWrite()

另请参阅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主页上的每个板。

返回

可读取的字节数。

建议的行动方案

首先,我不认为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("Config SIM900...");中一样使用serialPrintLineIfAvailable()

相关文章: