簡體   English   中英

Arduino UNO + SIM800L - 向服務器發送數據

[英]Arduino UNO + SIM800L - sending data to server

我正在使用帶有調制解調器 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() 的調用,您可以首先使用 availableForWrite() 檢查傳輸緩沖區中的可用空間量。

請參閱Serial.flush()函數https://www.arduino.cc/reference/en/language/functions/communication/serial/flush/ 的說明,其中指出:

序列號.flush()

描述

等待傳出串行數據的傳輸完成。 (在 Arduino 1.0 之前,這會刪除任何緩沖的傳入串行數據。)

flush() 繼承自 Stream 實用程序類。

並看到這篇文章, https : //www.baldengineer.com/when-do-you-use-the-arduinos-to-use-serial-flush.html說“

Serial.flush() 有什么作用?

來自 Serial.flush 的 Arduino 參考(可在此頁面上找到):

等待傳出串行數據的傳輸完成。

該聲明的關鍵是“外向”。 Serial.flush() 並沒有像許多人認為的那樣清空“傳入”緩沖區。 它會在刷新傳輸緩沖區時暫停您的程序。

我會用Serial.availableForWrite()函數之前做使用任何輸出Serial.println() ,如果可用的字節數指示寫入緩沖區已滿越來越然后跳過輸出。

可能最好的方法是作為Setup()函數的一部分,在執行Serial.begin()之后檢查寫入緩沖區大小並將其存儲在一個全局變量中,然后您可以使用該變量來檢查寫入緩沖區是否被清空或不。

參見https://www.instructables.com/id/Arduino-Serial/有這樣的說法:

第 3 步:命令: AvailableForWrite()

描述

在不阻塞寫操作的情況下獲取可用於寫入串行緩沖區的字節(字符)數。

句法

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/

串行可用()

描述

獲取可用於從串行端口讀取的字節數(字符)。 這是已經到達並存儲在串行接收緩沖區(保存 64 個字節)中的數據。

Serial.available() 繼承自 Stream 實用程序類。

句法

串行可用()

參數

Serial:串口對象。 請參閱串行主頁上每個板的可用串行端口列表。

退貨

可供讀取的字節數。

建議的行動方案

首先,我不認為Setup()函數中的Serial.flush()是必要的,可以安全地刪除它。 雖然這使控制台輸出在Setup()期間立即輸出,但它確實引入了對遠程情況的等待,在這種情況下,沒有設備從串行線路讀取以清空輸出緩沖區。

我還建議,對於您執行Serial.println()每一行,您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...");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM