How to control Wifi.client from PC

Hello all,

I am working on a school project in which I am using an MKR1000 as a high speed data acquisition device wirelessly. The application is to get sensor readings inside a tire as it is spinning.

I have gotten it to a point where I can reliably read sensors at the desired sampling rate, and then send the data to a mySQL database that runs on my computer. This has been working great, and I used a lot of the methodology given here. This has gotten me 95% of the way, but my problem is that I would like a way to control when the Arduino decides to record and send a sample. Currently I've only been getting it started running, and then just using a delay to have it run every 60 seconds or so.

I have been researching for a few hours this evening and I either am too out of my comfort zone to realize what is applicable to me, or there is not many resources out there that have done this.

A summary of the system is this:

MKR1000 running a Wifi101 client that reads sensor data, than sends it to a XAMPP server that is running on a pc in the same network. That uses a PHP script to then put the sensor data in a MySQL database.

MKR1000 Code:

#include <SPI.h>
#include <WiFi101.h>

//Wifi Connection
char ssid[] = "NathanE" ;
char pass[] = "Arduino1" ;
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 0, 103) ;
WiFiClient client;

//Sensor and Time Data

float timeSent ;

int interval = 1000 ;
int sampleSize = 2000 ;
float voltage [2000];
unsigned long timestamp [2000];
unsigned long previousTime = 0 ;
unsigned long currentTime = 0 ;
String message ;
float sensorToVoltage = (1.0 / (7.5 / (7.5 + 30.0)) * (3.3 / 4095.0)) ;
bool recordAndSend = true ;

void setup()
{
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for USB port only serial communications get rid of when running experiment
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // 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);
  }
  Serial.println("Connected to wifi");
  printWiFiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server and ready to sense");
    // Make a HTTP request:

  }

}
//------------------------------------------------------------------------------


/* Infinite Loop */
void loop()
{

  //Read the sensors locally and save readings to Arduino
  read_sensors() ;

  //Create packets and send to server database
  Sending_To_phpmyadmindatabase();


  delay(60000);
}


void read_sensors()
{
  Serial.println("Beginning of read sensors") ;
  for (int i = 0 ; i < sampleSize;)
  {
    analogReadResolution(12) ;
    currentTime = micros() ;
    Serial.println("In read sensors for") ;
    if (currentTime - previousTime >= interval)
    {
      Serial.println("In the sensors if") ;
      timestamp[i] = currentTime ;
      voltage[i] = analogRead(A0) ;
      previousTime = currentTime ;
      i = i + 1 ;
    }
  }
}



void Sending_To_phpmyadmindatabase()   //CONNECTING WITH MYSQL
{
  Serial.println("In send to db") ;
  if (client.connect(server, 80))
  {
    Serial.print("Sending to database") ;
    for (int z = 0 ; z < sampleSize ; z++)
    {
      client.connect(server, 80) ;
      voltage[z] = voltage[z] * sensorToVoltage ;
      timeSent = timestamp[z] / 1000000.0 ;
      message = "GET /testcode/dht.php?temperature=" + String(voltage[z], 4) + "&humidity=" + String(timeSent, 3)
                + " HTTP/1.1\r\n" + ("Host: 192.168.0.101\r\n") + ("Connection: close\r\n\r\n") ;
      client.print(message) ;
      Serial.println(message) ;

    }

  }


  else
  {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}


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

  // print your WiFi shield'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");
}

PHP Code

<?php
class dht11
{
 public $link='';
 function __construct($temperature,$humidity)
 {
  $this->connect();
  $this->storeInDB($temperature,$humidity);
 }
 
 function connect()
 {
  $this->link = mysqli_connect('localhost','root','') or die('Cannot connect to the DB');
  mysqli_select_db($this->link,'tester') or die('Cannot select the DB');
 }
 
 function storeInDB($temperature, $humidity)
 {
  $query = "insert into test123 set Timer='".$humidity."', Test='".$temperature."'";
  $result = mysqli_query($this->link,$query) or die('Errant query:  '.$query);
 }
 
}
if($_GET['temperature'] != '' and  $_GET['humidity'] != '')
{
 $dht11=new dht11($_GET['temperature'],$_GET['humidity']);
}

?>

Again, I have no problems currently with how the code above works, in fact it works better than I was expecting to get. What I am trying to figure out, is a way to be at my computer, and send a "flag" if you will, that tells the Arduino, okay lets take 2000 more sensor readings and send it. In my head it is simple, but I am really struggling to find a way to get the Arduino to actually read that message I'm trying to send. My base idea was this:

  if (recordAndSend == true)
  {
    //Read the sensors locally and save readings to Arduino
    read_sensors() ;

    //Create packets and send to server database
    Sending_To_phpmyadmindatabase();

    recordAndSend = false ; 
  }

and then the main loop waits for something to change "recordAndSend" back to true. I just need to understand how to actually send a message that prompts the arduino to change recordAndSend. Any help is appreciated, let me know if I can provide any more information :slight_smile: Thanks so much for your time.

" What I am trying to figure out, is a way to be at my computer, and send a "flag" if you will, that tells the Arduino, okay lets take 2000 more sensor readings and send it."

Probably pretty simple, in the loop, check the serial buffer for a character, like "s" for send, and if the character is there, send the data. Just open the serial monitor and send an s to have the data sent.

first see the BlinkWithouDelay example on how to not block the sketch for a minute. because if it is in delay() it will not receive any command.

then you could have a telnet server to receive commands from a telnet client. see the ChatServer example

To zoomkat:

The system will be unable to take serial messages, because it will be inside a tire so I don't think that will work, but the idea of 's' to indicate send is very much what I'm going for.

To Juraj:

I have actually used that example already for my timing of when I take sensor readings, but noted, I will definitely fix that once I'm implementing looking for my flag.

I will look into the chat server and see what I can do. My preliminary question for that is, will the telnet server and my xampp server work in tandem?

Thank you guys for your help

"The system will be unable to take serial messages, because it will be inside a tire so I don't think that will work, but the idea of 's' to indicate send is very much what I'm going for."

I haven't tried it on my WeMOS 8266 board, but you should be able to run both client and server code at the same time. The server would serve to receive the flag from a client out there somewhere (ie. web page in a browser), which would then trigger the board to run client code to upload data to another server out there somewhere.

Hello all,

So I was able to try and implement both server and client code at the same time. If I tried to activate client and server things at the same time during setup, my code would not compile. So for fun I threw the server setup lines in a function, and to my surprise it seemed to work. I essentially ripped off this script, and plugged in into a function at the bottom of my code and tried to modify it to my purpose.

To summarize, my main loop looks for the recordAndSend boolean, if it's true, it takes readings and then sends them to my database. Once it has sent to the database it sets recordAndSend to be false, and then waits for the "serverChecking()" function to change recordAndSend back to true, indicating it's time to read the sensors again.

The way I have it written currently appears to work flawlessly at first. The Arduino starts, it takes its first batch of readings, and then opens up the serverChecking function and waits for my interaction with the web address to hit the flag. Once I interact and send the "Collect" command it then starts looping back through the original loop, taking sensor readings and then opens up my function that sends data back to the database.

This is where it all goes wrong. I get serial readings indicating that it is able to reconnect back to my server, but it seems to freeze. I have identified that the client.print line is what freezes it within my Sending_To_phpmyadmindatabase();. So due to that fact, I can only assume that I have broken my client relationship with my server and database by using code that turned it into a server to handle web commands. Does this seem correct?

Here is my code:

#include <SPI.h>
#include <WiFi101.h>

//Wifi Connection
char ssid[] = "******" ;
char pass[] = "Arduino1" ;
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 0, 103) ;
WiFiClient client;

//Time Variables
float timeSent ;
int interval = 2000 ;  //in microseconds, aka every 2000 microseconds, take a reading
int sampleSize = 100 ;
unsigned long timestamp [1000];
unsigned long initialTime = 0 ;
unsigned long previousTime = 0 ;
unsigned long currentTime = 0 ;

//Sensor Variables
float voltage [1000];
float current [1000] ;
float strain1 [1000];
float strain2 [1000];
float strain3 [1000];
float sensorToCurrent = 3.3 / 4095.0 ;
float sensorToStrain1 = 3.3 / 4095.0 ;
float sensorToStrain2 = 3.3 / 4095.0 ;
float sensorToStrain3 = 3.3 / 4095.0 ;
float sensorToVoltage = (1.0 / (7.5 / (7.5 + 30.0)) * (3.3 / 4095.0)) ;

//Database Variables
String message ;
bool recordAndSend = true ;
bool waitingForCommand = true ; 

void setup()
{


[b]wifi connection and serial code removed for character count[/b]

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server and ready to sense");


  }

}
//------------------------------------------------------------------------------


/* Infinite Loop */
void loop()
{

  if (recordAndSend)
  {
    //Read the sensors locally and save readings to Arduino
    read_sensors() ;
    
      if (client.connect(server, 80)) {
    Serial.println("connected to server and ready to send");
      }

    //Create packets and send to server database
    Sending_To_phpmyadmindatabase();

    recordAndSend = false ;
  }


  serverChecking();


}

void read_sensors()
{
  Serial.println("Beginning of read sensors") ;
  for (int i = 0 ; i <= sampleSize;)
  {
    analogReadResolution(12) ;
    currentTime = micros() ;

    if (currentTime - previousTime >= interval)
    {

      timestamp[i] = currentTime ;
      previousTime = currentTime ;
      if (i == 0)
      {
        initialTime = timestamp[i] ;
      }

      voltage[i] = analogRead(A0) ;
      current[i] = analogRead(A1) ;
      strain1[i] = analogRead(A2) ;
      strain2[i] = analogRead(A3) ;
      strain3[i] = analogRead(A4) ;

      i = i + 1 ;
    }
  }
}



void Sending_To_phpmyadmindatabase()   //CONNECTING WITH MYSQL
{
  Serial.println("In send to db") ;
  //WiFiClient client;
  //IPAddress server(192, 168, 0, 103) ;
  if (client.connect(server, 80))
  {
    
    Serial.print("Sending to database") ;
    for (int z = 0 ; z <= sampleSize ; z++)
    {
      //client.connect(server, 80) ;

      voltage[z] = voltage[z] * sensorToVoltage ;
      current[z] = current[z] * sensorToCurrent ;
      strain1[z] = strain1[z] * sensorToStrain1 ;
      strain2[z] = strain2[z] * sensorToStrain2 ;
      strain3[z] = strain3[z] * sensorToStrain3 ;


      timeSent = (timestamp[z] - initialTime) / 1000000.0 ;

      message = "GET /testcode/dht.php?time=" + String(timeSent, 3) + "&voltage=" + String(voltage[z], 4) + "&current=" +
                String(current[z], 4) + "&strain1=" + String(strain1[z], 4) + "&strain2=" + String(strain2[z], 4) + "&strain3=" + String(strain3[z], 4)
                + " HTTP/1.1\r\n" + ("Host: 192.168.0.101\r\n") + ("Connection: close\r\n\r\n") ;
      //client.print(message) ;
      Serial.println(message) ;

    }


  }


  else
  {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}


void printWiFiStatus() {
[b]removed for character count[/b]

}


void serverChecking()
{
  WiFiServer server(80);
  server.begin();
  Serial.println("Server should be on?") ;
  
  while (!recordAndSend)
  {
  WiFiClient client = server.available();   // listen for incoming clients


    if (client)
    { // if you get a client,
      Serial.println("new client");           // print a message out the serial port
      String currentLine = "";                // make a String to hold incoming data from the client
      while (client.connected()) {            // loop while the client's connected
        if (client.available()) {             // if there's bytes to read from the client,
          char c = client.read();             // read a byte, then
          Serial.write(c);                    // print it out the serial monitor
          if (c == '\n') {                    // if the byte is a newline character

            // if the current line is blank, you got two newline characters in a row.
            // that's the end of the client HTTP request, so send a response:
            if (currentLine.length() == 0) {
              // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
              // and a content-type so the client knows what's coming, then a blank line:
              client.println("HTTP/1.1 200 OK");
              client.println("Content-type:text/html");
              client.println();

              // the content of the HTTP response follows the header:
              client.print("Click <a href=\"/Collect\">here</a> to take a reading
");

              // The HTTP response ends with another blank line:
              client.println();
              // break out of the while loop:
              break;
            }
            else {      // if you got a newline, then clear currentLine:
              currentLine = "";
            }
          }
          else if (c != '\r') {    // if you got anything else but a carriage return character,
            currentLine += c;      // add it to the end of the currentLine
          }

          // Check to see if the client request was "GET /H" or "GET /L":
          if (currentLine.endsWith("GET /Collect")) {
            recordAndSend = true ;               // GET /H triggers data collection
            break;
          }

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


}

The freezing looks like this in the serial monitor:

00:24:46.029 -> client disonnected
00:24:48.295 -> new client
00:24:48.295 -> GET /Collectclient disonnected
00:24:48.295 -> Beginning of read sensors
00:24:48.749 -> connected to server and ready to send
00:24:48.749 -> In send to db
00:24:48.749 -> Sending to database

*Removed a bit of html account to be under character requirement

If anyone is able to provide guidance on how to have server and client commands running at the same time I would be eternally grateful :slight_smile: If that isn't possible and there is another way to do this, I am open to that as well. I apologize if some "rules" are broken in my code, I am a mechanical engineering student who is in a little over his head for this project that is just trying to make it work. Thanks for any help.

how should a client connect if you always restart the server?

"I have identified that the client.print line is what freezes it within my Sending_To_phpmyadmindatabase();"

The compounding operations in that function may have run you out of memory. Skinny that down to only one variable for a test and see if that works.

To Juraj:

I am completely okay with the client having to reconnect every time because it is simply just hit enter on the webpage and it has reconnected as far as I understand. I can only imagine how un-optimal that is, but if I can make it work for me then I would be thrilled. If there's a way to open and keep the connection, while also allowing my client code to run, then I would be open to that as well, I just get compilation errors every time I try to do both within the same function.

To zoomkat:

Trying that now, and it seemed to work? Kind of. Essentially it went down like this:

  1. Start the script, it ran and recorded data to the database successfully.

  2. It starts the web server, I connect to it, send the "Collect" flag

  3. It runs through, recorded and sent all the data to the database successfully

  4. It then says that it's in the server code, but I am no longer able to actually connect to it from my pc.

For fun, I added back all 5 variables and the same situation as above happened again. So it didn't seem to matter about the 5 variables being too much.

So it connects to db as client, starts up server well afterwards, takes command from pc, reconnects to database and sends data, and then fails to start the server up again.

I am not entirely sure what I changed to make this happen. I've posted the updated code in which this is happening below if that's needed at all.

#include <SPI.h>
#include <WiFi101.h>

//Wifi Connection
char ssid[] = "NathanE" ;
char pass[] = "Arduino1" ;
int status = WL_IDLE_STATUS;
IPAddress server(192, 168, 0, 103) ;
WiFiClient client;

//Time Variables
float timeSent ;
int interval = 2000 ;  //in microseconds, aka every 2000 microseconds, take a reading
int sampleSize = 100 ;
unsigned long timestamp [1000];
unsigned long initialTime = 0 ;
unsigned long previousTime = 0 ;
unsigned long currentTime = 0 ;

//Sensor Variables
float voltage [1000];
float current [1000] ;
float strain1 [1000];
float strain2 [1000];
float strain3 [1000];
float sensorToCurrent = 3.3 / 4095.0 ;
float sensorToStrain1 = 3.3 / 4095.0 ;
float sensorToStrain2 = 3.3 / 4095.0 ;
float sensorToStrain3 = 3.3 / 4095.0 ;
float sensorToVoltage = (1.0 / (7.5 / (7.5 + 30.0)) * (3.3 / 4095.0)) ;

//Database Variables
String message ;
bool recordAndSend = true ;
bool waitingForCommand = true ; 

void setup()
{
  //Initialize serial and wait for port to open:
  Serial.begin(9600);


  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {


  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWiFiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server and ready to sense");


  }

}
//------------------------------------------------------------------------------


/* Infinite Loop */
void loop()
{

  if (recordAndSend)
  {
    //Read the sensors locally and save readings to Arduino
    read_sensors() ;
    
      if (client.connect(server, 80)) {
    Serial.println("connected to server and ready to send");
      }

    //Create packets and send to server database
    Sending_To_phpmyadmindatabase();

    recordAndSend = false ;
  }


  serverChecking();


}

void read_sensors()
{
  Serial.println("Beginning of read sensors") ;
  for (int i = 0 ; i <= sampleSize;)
  {
    analogReadResolution(12) ;
    currentTime = micros() ;

    if (currentTime - previousTime >= interval)
    {

      timestamp[i] = currentTime ;
      previousTime = currentTime ;
      if (i == 0)
      {
        initialTime = timestamp[i] ;
      }

      voltage[i] = analogRead(A0) ;
      current[i] = analogRead(A1) ;
      strain1[i] = analogRead(A2) ;
      strain2[i] = analogRead(A3) ;
      strain3[i] = analogRead(A4) ;

      i = i + 1 ;
    }
  }
}



void Sending_To_phpmyadmindatabase()   //CONNECTING WITH MYSQL
{
  Serial.println("In send to db") ;
  //WiFiClient client;
  IPAddress server(192, 168, 0, 103) ;
  if (client.connect(server, 80))
  {
    
    Serial.print("Sending to database") ;
    for (int z = 0 ; z <= sampleSize ; z++)
    {
      client.connect(server, 80) ;

      voltage[z] = voltage[z] * sensorToVoltage ;
      current[z] = current[z] * sensorToCurrent ;
      strain1[z] = strain1[z] * sensorToStrain1 ;
      strain2[z] = strain2[z] * sensorToStrain2 ;
      strain3[z] = strain3[z] * sensorToStrain3 ;


      timeSent = (timestamp[z] - initialTime) / 1000000.0 ;

      message = "GET /testcode/dht.php?time=" + String(timeSent, 3) + "&voltage=" + String(voltage[z], 4) + "&current=" +
                String(current[z], 4) + "&strain1=" + String(strain1[z], 4) + "&strain2=" + String(strain2[z], 4) + "&strain3=" + String(strain3[z], 4)
                + " HTTP/1.1\r\n" + ("Host: 192.168.0.101\r\n") + ("Connection: close\r\n\r\n") ;
      client.print(message) ;
      Serial.println(message) ;

    }


  }


  else
  {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }

  
  client.stop() ;
}


void printWiFiStatus() {

}

void serverChecking()
{
  WiFiServer server(80);
  server.begin();
  Serial.println("Server should be on?") ;
  
  while (!recordAndSend)
  {
  WiFiClient client = server.available();   // listen for incoming clients


    if (client)
    { // if you get a client,
      Serial.println("new client");           // print a message out the serial port
      String currentLine = "";                // make a String to hold incoming data from the client
      while (client.connected()) {            // loop while the client's connected
        if (client.available()) {             // if there's bytes to read from the client,
          char c = client.read();             // read a byte, then
          Serial.write(c);                    // print it out the serial monitor
          if (c == '\n') {                    // if the byte is a newline character

            // if the current line is blank, you got two newline characters in a row.
            // that's the end of the client HTTP request, so send a response:
            if (currentLine.length() == 0) {
              // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
              // and a content-type so the client knows what's coming, then a blank line:
              client.println("HTTP/1.1 200 OK");
              client.println("Content-type:text/html");
              client.println();

              // the content of the HTTP response follows the header:
              client.print("Click <a href=\"/Collect\">here</a> to take a reading
");

              // The HTTP response ends with another blank line:
              client.println();
              // break out of the while loop:
              break;
            }
            else {      // if you got a newline, then clear currentLine:
              currentLine = "";
            }
          }
          else if (c != '\r') {    // if you got anything else but a carriage return character,
            currentLine += c;      // add it to the end of the currentLine
          }

          // Check to see if the client request was "GET /Collect":
          if (currentLine.endsWith("GET /Collect")) {
            recordAndSend = true ;               // GET /Collect triggers data collection
            break;
          }

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


}

My understanding/suspicion of what is going on is this:

I am opening client code, connecting to a server, and then disconnecting, and then I open up a server code, and I maybe don't close it the right way, so it gets stuck and isn't able to work again the next time? I am completely clueless as to what the right protocol is to keep everything completely clean and make sure I cut everything off when I should and start everything back up when I should. Does this seem like the correct line of thought, or is there maybe something else going on?

"Does this seem like the correct line of thought, or is there maybe something else going on?"

I looked at some old test code for an ethernet board and the way it was setup was the server code is in the main code loop and the client code is in a function. The way this code operates is after the setup (serial port and ethernet) there is a check to see if a client command is received from the serial monitor, and if so, the client function is called and the client function is performed. The server code listens for a client request and supplies a web page, or acts upon request from the web page. I don't know if this approach would be any better.

imagine you have a shop (server). you open the shop and look for the customers. there is nobody so you close the shop. a little later you again open and look for the customers. there is nobody so you close the shop. sometimes randomly a customer is there in the moment you open or someone is persistent and always returns, but it would so much better to let the shop open.