Tom
Tom

Reputation: 1030

Arduino connection failed loop after random period of time

I have recently started working with arduino and coding in C and have stumbled upon an issue.

Everything is working as it should be :

Read NFC tag > send POST to Laravel API > Recieve body response to display on LCD

However the program is very inconsistent meaning that after an unknown period of time (this is a random period of time) the program returns a connection failed as shown in the monitor returns.

After this connection failed the program will not return back to it's connection and will keep returning connection failed until you restart the program.

I myself am not able to solve this after hours of googling, and therefor I am asking assistance from you guys.

(Do not give me plain code as an answer, but give me explanation on the side as I am learning and want to learn from this.)

Hardware:

Arduino MKR1000

Adafruit PN532 NFC/RFID Controller Shield (SPI)

Monitor returns:

Found chip PN532
Firmware ver. 1.6
Waiting for an ISO14443A card/n
Attempting to connect to SSID: ****
Connected to wifi
SSID: ****
IP Address: ****
signal strength (RSSI):-66 dBm

Starting connection to server...

================= START PROGRAM =======================

Found a card!
UID Length: 4 bytes
UID Value HEX: 67D667E
UID Value Decimal: 6125102126
{"Druppel": "6125102126"}
Connected!
Response:
Tom 
Welcome

Succesfull sign in

Found a card!
UID Length: 4 bytes
UID Value HEX: C9DDCA35
UID Value Decimal: 20122120253
{"Druppel": "20122120253"}
Connection failed

Code

#include <SPI.h>
#include <WiFi101.h>
#include <Wire.h>
#include <LiquidCrystal.h> 
#include <ArduinoJson.h>
#include <Adafruit_PN532.h>

#define PN532_SCK   (9)
#define PN532_MOSI  (8)
#define PN532_SS    (6)
#define PN532_MISO  (10)
#define PN532_IRQ   (2)
#define PN532_RESET (7)
#define TIMEOUT     500

  Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);  

    const int rs = 12, en = 11, d4 = 2, d5 = 3, d6 = 4, d7 = 5;  
    LiquidCrystal lcd(rs, en, d4, d5, d6, d7);   

    const int ledPin =  1; 
    const int errorLedPin =  13;         
    const int buzzerPin =  0;
    int sensorPin = 0;

    char SSID_NAME[] = "****";        
    char SSID_PASS[] = "****";  

    WiFiClient client;
    int status = WL_IDLE_STATUS;
    int keyIndex = 0;

    char SERVER[] = "****.*****.nl";
    char TOKEN[] = "******************"; 
    char API[] = "********";

void printWiFiStatus() {
  Serial.print("SSID: "); 
  Serial.println(WiFi.SSID());

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");

  lcd.setCursor(0, 0);
  lcd.print("SSID: ");
  lcd.print(WiFi.SSID());

  lcd.setCursor(0, 2);
  lcd.print("IP: ");
  lcd.print(WiFi.localIP());
}


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

    Serial.println("Serial ready");

    analogWrite(A3, 0);                              
    lcd.begin(16, 2); 

    pinMode(ledPin, OUTPUT);
    pinMode(errorLedPin, OUTPUT);
    pinMode(buzzerPin, OUTPUT);

    tone(buzzerPin, 60);

    nfc.begin();

    uint32_t versiondata = nfc.getFirmwareVersion();
    if (! versiondata) {
      Serial.print("Didn't find PN53x board");
      while (1);                                     
    }

    Serial.print("Found chip PN5");Serial.println((versiondata>>24) & 0xFF, HEX);                
    Serial.print("Firmware ver. ");Serial.print((versiondata>>16) & 0xFF, DEC);Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 



    nfc.setPassiveActivationRetries(0xFF);

    nfc.SAMConfig();                                

    Serial.print("Waiting for an ISO14443A card"); Serial.println("/n");


    if (WiFi.status() == WL_NO_SHIELD) {            
      Serial.println("WiFi shield not present");
      while (true);                                 
    }
    noTone(buzzerPin);



    tone(buzzerPin, 50);

    while (status != WL_CONNECTED) {
      Serial.print("Attempting to connect to SSID: ");
      Serial.println(SSID_NAME);

      status = WiFi.begin(SSID_NAME, SSID_PASS);

      delay(100);
    }
    Serial.println("Connected to wifi");
    printWiFiStatus();


    Serial.println("\nStarting connection to server...");
    Serial.println("\n================= START PROGRAM =======================");

    noTone(buzzerPin);
}

void loop() {
  digitalWrite(errorLedPin, LOW);

  boolean success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
  uint8_t uidLength;

  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
  if (success) {
    lcd.clear();


      Serial.println("");
      Serial.print("Found a card!");
      Serial.println("");
      Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
      Serial.print("UID Value HEX: ");

      String data;
      for (uint8_t i=0; i < uidLength; i++) 
      {
        Serial.print(uid[i], HEX); 
        data =  String(data + uid[i]);
      }
      Serial.println("");
      Serial.print("UID Value Decimal: ");
      Serial.print(data); 
      Serial.println("");

      lcd.print(data);

    delay(100);

    digitalWrite(ledPin, HIGH);  

    tone(buzzerPin, 50);
    String PostData = "{\"Druppel\": \"";
    PostData = String(PostData + data);
    PostData = String(PostData + "\"}");
    int PostDataLength = PostData.length() + 1;
    delay(100);
    noTone(buzzerPin);

    char char_array[PostDataLength];

    PostData.toCharArray(char_array, PostDataLength);

    Serial.println(PostData);

    delay(500);
    if(!client.connect(SERVER, 80)) {   
      Serial.println(F("Connection failed"));
      digitalWrite(errorLedPin, HIGH);
      return;
    }

    Serial.println(F("Connected!"));
      client.println("POST /api/******?api_token=****************** HTTP/1.1");
      client.println("Host: ****.*****.nl"); 
      client.println("Cache-Control: no-cache");
      client.println("Content-Type: application/json");
      client.print("Content-Length: ");
      client.println(PostDataLength);
      client.println();
      client.println(PostData);

    client.println(F("Connection: close"));


    if (client.println() == 0) {
      Serial.println(F("Failed to send request"));  
      return;
    }

    char status[32] = {0};
    client.readBytesUntil('\r', status, sizeof(status));
    if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
      Serial.print(F("Unexpected response: "));
      Serial.println(status);
      return;
    }

    char endOfHeaders[] = "\r\n\r\n";
    if (!client.find(endOfHeaders)) {
      Serial.println(F("Invalid response"));
      return;
    }

    const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
    DynamicJsonBuffer jsonBuffer(capacity);

    JsonObject& root = jsonBuffer.parseObject(client);
    if (!root.success()) {
      Serial.println(F("Parsing failed!"));
      return;
    }

    Serial.println(F("Response:"));
    Serial.println(root["User"].as<char*>());
    Serial.println(root["Status"].as<char*>());

    lcd.setCursor(0, 2);
    lcd.print(root["User"].as<char*>());
    lcd.setCursor(0, 0);
    lcd.print(root["Status"].as<char*>());

    client.stop();

    digitalWrite(ledPin, LOW);   

    digitalWrite(errorLedPin, HIGH);
    Serial.println("");
    Serial.println("Succesfull sign in");

    delay(3000);
    lcd.clear();
  } else
  {
    Serial.println("Timed out waiting for a card");
  }
}

Upvotes: 2

Views: 196

Answers (1)

Juraj
Juraj

Reputation: 3736

Don't use the String class. It fragments the memory heap, which leads to crash. Use C strings (zero terminated char array). If you are not experienced with strcat and sprintf functions, you can use CStringBuilder from my StreamLib library. The library is available in Library Manager in Arduino IDE.

char PostData[200];
CStringBuilder sb(PostData, sizeof(PostData));

sb.print("{\"Druppel\": \"");
for (uint8_t i=0; i < uidLength; i++)
{
  sb.print(uid[i]);
  //sb.printf("%02x", uid[i]); // for hex aligned with 0
}
sb.print("\"}");

Serial.println(sb.length());
Serial.println(PostData);

Upvotes: 2

Related Questions