1. Home
  2. RG Guides
  3. RG Arduino Guide
  4. Access The Rain Gauge Through WiFi

Access The Rain Gauge Through WiFi

Taking the data manually out of the arduino is slow and tedious. With a WiFi enabled Arduino this process can be simplified. The device can create a local web server that sends all data in a matter of seconds just by opening a web link.

This example is build upon the microSD card tutorial and assumes you have completed it.

Materials

  • RG-15
  • MicroSD Card with a Reader
  • WiFi enabled Arduino (Example uses Arduino RP2040 connect)

Keep in mind this example does not use the same Arduino from previous examples.

Code

After initializing the SD card Wifi code should be added to connect and start our web server:

while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();
  // you're connected now, so print out the status:
  printWifiStatus();

A helper function is provided to print important information about the wifi connection. This method is used in the last line of above code but this code is all optional:

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

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

It is recommended to keep the wifi ssid and password on seperate file. In the tutorial, arduino_secrtets.h Is created which holds two values:

#define SECRET_SSID "wifi name"
#define SECRET_PASS "wifi password"

In the loop the Arduino continuously checks for a new connection and if found we send the data file. Sending data through http is trivial, the first step is to send a http header:

   client.println("HTTP/1.1 200 OK");
   client.println("Content-Disposition: attachment; filename=log.csv");
   client.println("Connection: close");  // the connection will be closed after completion of the response
   client.println();

This http request tells the client we want to send it a file with the name log.csv. Before sending this we must ensure that the client is ready to receive a response. To do this the client incoming text is read until a ‘\n’ is found:

while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the HTTP request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard HTTP response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Disposition: attachment; filename=log.csv");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println();
...     }
      }
}

At this stage the client knows about the incoming file and awaits for data of bytes. We have to continuously read the SD file and send it in chunks as to not overwhelm the stream:

 byte buf[64];
 int bufIdx = 0;

 File file = SD.open("LOG.csv");
 while (file.available()) {
    buf[bufIdx] = file.read();
    bufIdx++;
    if (bufIdx > 63) {
       client.write(buf, 64);
       bufIdx = 0;
       }
    }
 client.write(buf, bufIdx);
 file.close();
 break;

Note: The second client.write line is important. This writes any left over data that did not fit into a final buffer.

Make sure to close the file and client after sending data:

 delay(3);

 // close the connection:
 client.stop();
 Serial.println("client disconnected");

Usage

When running the code, the serial monitor should display an IP address that you can connect to. Open a web browser and type that IP in the address bar. If all things are properly set up a log.csv file should download.

When this device is being used without a computer directly connected, It is recommended to remove all Serial.print commands and this snippet of code:


while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

The above code is helpful for creating and making sure it is running properly. It also blocks the Arduino from running if it can’t find a serial monitor (your computer). So do not use it when not developing it.

Full Code

WifiWebServer.h

#include <SPI.h>
#include <WiFiNINA.h>
#include <SD.h>

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;                 // your network key index number (needed only for WEP)

int status = WL_IDLE_STATUS;
int chipSelect = 10;

WiFiServer server(80);

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial1.write('c');
  Serial1.write('\n');
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed or not present");
  }

  Serial.println("Card Initialized.");

  if (!SD.exists("log.csv")) {
    Serial.println("Creating new file.");
    File dataFile = SD.open("log.csv", FILE_WRITE);
    dataFile.println("Acc, eventAcc, totalAcc, rInt");
    dataFile.close();
  }
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();
  // you're connected now, so print out the status:
  printWifiStatus();
}


void loop() {
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an HTTP request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the HTTP request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard HTTP response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Disposition: attachment; filename=log.csv");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println();

          byte buf[64];
          int bufIdx = 0;

          File file = SD.open("LOG.csv");
          while (file.available()) {
            buf[bufIdx] = file.read();
            bufIdx++;
            if (bufIdx > 63) {
              client.write(buf, 64);
              bufIdx = 0;
            }
          }
          client.write(buf, bufIdx);
          file.close();
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(3);

    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }


  String response = Serial1.readStringUntil('\n');
  if (response.startsWith("Acc")) {
    char acc[7], eventAcc[7], totalAcc[7], rInt[7], unit[4];
    sscanf (response.c_str(), "%*s %s %[^,] , %*s %s %*s %*s %s %*s %*s %s", &acc, &unit, &eventAcc, &totalAcc, &rInt);
    if (SD.exists("log.csv")) {


    File dataFile = SD.open("log.csv", FILE_WRITE);

      if (dataFile) {
        dataFile.print(atof(acc), 3);
        dataFile.print(",");
        dataFile.print(atof(eventAcc), 3);
        dataFile.print(",");
        dataFile.print(atof(totalAcc), 3);
        dataFile.print(",");
        dataFile.println(atof(rInt), 3);
        dataFile.close();
        Serial.println("success");
      } else {
        Serial.println("Error trying to open log.csv");
      }
    }
  }
  delay(3000);
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

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

arduino_secrets.h

#define SECRET_SSID "wifi name"
#define SECRET_PASS "wifi password"
Was this article helpful to you? Yes No

How can we help?