Go Down

Topic: Skip a slow function (Read 811 times) previous topic - next topic


Hi everyone.

Im currently building a wireless multimeter and i'm having trouble with my web server not responding sometimes.

This is where i send my information and gets stuck sometimes:
Code: [Select]
   

// Function to send a TCP request and get the result as a string
void send_request (String request) {
     
    // Connect   
    Serial.println("Starting connection to server...");
   
   
    Adafruit_CC3000_Client client = cc3000.connectTCP(ip, port); //Here is my problem!!
   
    //int time = millis()-now;
    //Serial.println("time:    ");
    //Serial.print(time);
    //Serial.println("");
   
    // Send request
    if (client.connected()) {
      client.println(request);     
      client.println(F(""));
     
   
     
      Serial.println("Connected & Data sent");
    }
                                                       
                                                       
    else {
      Serial.println(F("Connection failed"));   
     
    }
   
   
     while (client.connected()) {
      while (client.available()) {

      // Read answer
      char c = client.read();
      }
     }

    Serial.println("Closing connection");
    Serial.println("");
    client.close();

   
}


Sometimes the web server is not responding when im sending my information to it.
I'm updating my values on the webserver twice per secound so i don't need exactly every value either.

So i'm trying to think of some way to skip this function and continue with the next value if it takes to much time. It gets stuck for up to 20 seconds sometimes and the server is responding fine for most of the time.

I would very much appreciate some help!

Regards
Victor

PaulS

The cc3000.connectTCP() method appears to be a blocking fundtion. Unless you go to http://www.crystalball.com, and get a crystal ball, you won't be able to tell, prior to that call, whether it will block. Once it does, there is no way for you to say "Hey, never mind, let's skip that this time".

Of course, since that is not a standard library, and you didn't post a link to it, I could be all wrong. Perhaps that library includes a useTheCrystalBallToDetermineIfConnectingIsGoingToBlock() method. I have my doubts, though.

robtillaart

Hi PaulS,

That website -  http://www.crystalball.com - brings you really to the Oracle ;) 
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

PaulS

I had no idea that was a real web site.


Hi again and sorry if i was unclear.

This is my entire code as of now:

Code: [Select]



// Voltage divider VDC: Vout = Vin*(R2/(R1+R2)) R1=1MOhm ,R2=100kOhm(Mot jord)
// Resistance measure: 5V -10KOhm------PinA1-----Resistor-GROUND


// Include required libraries
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
//#include "utility/debug.h"
#include<stdlib.h>


// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

// Define Sensor pins
#define SensorPin1 A0
#define SensorPin2 A1

#define filterSamples   21              // filterSamples should  be an odd number, no smaller than 3



// WiFi network (change with your settings !)
#define WLAN_SSID       "Viktor Nordmark iPhone"        // cannot be longer than 32 characters!
#define WLAN_PASS       "hacker7777"
//#define WLAN_SSID       "AndroidAP_nexus"        // cannot be longer than 32 characters!
//#define WLAN_PASS       "pumbatimon"
#define WLAN_SECURITY   WLAN_SEC_WPA2 // This can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2


int led = 8;
//--------------------------------------------Initiation for filtering---------------------
int sensSmoothArray1 [filterSamples];   // array for holding raw sensor values for sensor1
int rawData1, smoothData1;  // variables for sensor1 data
char buffer[6];

//--------------------------------------------Initiation for VDC Measure--------------------
double voltDiv = 0.0948044;
String rawOutputVoltage=" ";
String smoothOutputVoltage=" ";
double voltage0_50 = 0;
double voltage0_50_0 = 0;

//--------------------------------------------Initiation for Resistance Measure-----------
String Resistance = "";
int Rraw = 0;           // variable to store the raw input value
int RVin = 5;           // variable to store the input voltage
float RVout = 0;        // variable to store the output voltage
float R1 = 10;         // variable to store the R1 value
float Res = 0;          // variable to store the R2 value
float Rbuffer = 0;      // buffer variable for calculation

//--------------------------------------------Initiation for wifi chip---------------------
// Create CC3000 instance
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIV2);
                                         
// Local server IP, port, and repository (change with your settings !)
uint32_t ip = cc3000.IP2U32(172,20,10,3);
//uint32_t ip = cc3000.IP2U32(192,168,43,136);
int port = 80;
String repository = "/multimeter/";

//----------------------------------------SETUP-----------------------------------------         

void setup(void){
 
  pinMode(led,OUTPUT);

  Serial.begin(115200);
   
  // Initialise the CC3000 module
  if (!cc3000.begin()) {while(1);}

  // Connect to  WiFi network
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println("Connected to WiFi network!");
   
  // Check DHCP
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP()) {delay(100);}
 
                }
//-----------------------------------LOOP------------------------------------------------

void loop(void)
{

    digitalWrite(led,LOW);
    VDCMeasure(); //String = smoothOutputVoltage
    RMeasure();   //String = Resistance
   
    // Send request
      String request = "GET "+ repository + "sensor.php?temp=" + smoothOutputVoltage + "&hum=" + Resistance + " HTTP/1.0";
    //String request = "GET "+ repository + "sensor.php?temp=" + temperature + "&hum=" + humidity + " HTTP/1.0";
   
    Serial.println(request);
   
    send_request(request);
    digitalWrite(led,HIGH);
   
    // Update every 370 ms
    delay(370);
     
}





// Function to send a TCP request and get the result as a string
void send_request (String request) {
     
    // Connect   
    Serial.println("Starting connection to server...");
   
   
    Adafruit_CC3000_Client client = cc3000.connectTCP(ip, port);
   
    //int time = millis()-now;
    //Serial.println("time:    ");
    //Serial.print(time);
    //Serial.println("");
   
    // Send request
    if (client.connected()) {
      client.println(request);     
      client.println(F(""));
     
      Serial.println("Connected & Data sent");
    }
                                                       
                                                       
    else {
      Serial.println(F("Connection failed"));   
     
    }
   
   
     while (client.connected()) {
      while (client.available()) {

      // Read answer
      char c = client.read();
      }
     }

    Serial.println("Closing connection");
    Serial.println("");
    client.close();

   
}





int digitalSmooth(int rawIn, int *sensSmoothArray){     // "int *sensSmoothArray" passes an array to the function - the asterisk indicates the array name is a pointer
  int j, k, temp, top, bottom;
  long total;
  static int i;
// static int raw[filterSamples];
  static int sorted[filterSamples];
  boolean done;

  i = (i + 1) % filterSamples;    // increment counter and roll over if necc. -  % (modulo operator) rolls over variable
  sensSmoothArray[i] = rawIn;                 // input new data into the oldest slot

  // Serial.print("raw = ");

  for (j=0; j<filterSamples; j++){     // transfer data array into anther array for sorting and averaging
    sorted[j] = sensSmoothArray[j];
  }

  done = 0;                // flag to know when we're done sorting             
  while(done != 1){        // simple swap sort, sorts numbers from lowest to highest
    done = 1;
    for (j = 0; j < (filterSamples - 1); j++){
      if (sorted[j] > sorted[j + 1]){     // numbers are out of order - swap
        temp = sorted[j + 1];
        sorted [j+1] =  sorted[j] ;
        sorted [j] = temp;
        done = 0;
      }
    }
  }

/*
  for (j = 0; j < (filterSamples); j++){    // print the array to debug
    Serial.print(sorted[j]);
    Serial.print("   ");
  }
  Serial.println();
*/

  // throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom
  bottom = max(((filterSamples * 15)  / 100), 1);
  top = min((((filterSamples * 85) / 100) + 1  ), (filterSamples - 1));   // the + 1 is to make up for asymmetry caused by integer rounding
  k = 0;
  total = 0;
  for ( j = bottom; j< top; j++){
    total += sorted[j];  // total remaining indices
    k++;
    // Serial.print(sorted[j]);
    // Serial.print("   ");
  }

//  Serial.println();
//  Serial.print("average = ");
//  Serial.println(total/k);
  return total / k;    // divide by number of samples
}

void VDCMeasure(){
 
   //int now = millis();
   

int total = 0;

for(int i=0; i<filterSamples; i++)  {
   
  rawData1 = analogRead(SensorPin1);                        // read DC-voltage sensor
  smoothData1 = digitalSmooth(rawData1, sensSmoothArray1);  // Send raw data to filter and place in array
 
  double voltage0_5 = (smoothData1 * (5.0 / 1023.0));        //Filtered
  voltage0_50 = voltage0_5/voltDiv;
 
  double voltage0_5_0 = (rawData1 * (5.0 / 1023.0));         //Unfiltered
  voltage0_50_0 = voltage0_5_0/voltDiv;
 
  total +=rawData1;                                          //Total value 
                                    }
 
 
 
   smoothOutputVoltage = dtostrf(voltage0_50, 4, 2, buffer); //Convert to string
   rawOutputVoltage = dtostrf(voltage0_50_0, 4, 2, buffer);


    int avg = total/filterSamples;
    double voltage0_5_1 = (avg * (5.0 / 1023.0));
    double voltage0_50_1 = voltage0_5_1/voltDiv;

   /* Serial.println("Raw Datafrom sensor:       ");
    Serial.print(rawOutputVoltage);
   
    Serial.println(" ");
   
    Serial.println("Smoothed Data:    ");
    Serial.print(smoothOutputVoltage);
    Serial.println(" ");
   
    Serial.println("Average:    ");
    Serial.print(voltage0_50_1);
    Serial.println(" ");*/


    //int time = millis()-now;
   
    //Serial.println(time);

}

void RMeasure(){

  Rraw = analogRead(SensorPin2);    // Reads the Input PIN
  RVout = (5.0 / 1023.0) * Rraw;    // Calculates the Voltage on th Input PIN
  Rbuffer = (RVin / RVout) - 1;
  Res = R1 / Rbuffer;
  if(Res>1000){Resistance="INFINITY";}
    else {Resistance = dtostrf(Res, 3, 1, buffer);} //Convert to string
 
  /*Serial.print("Voltage: ");      //
  Serial.println(RVout);           // Outputs the information
  Serial.print("R2: ");           //
  Serial.println(Resistance);             //*/

}





Is there really no way of saying "If this part takes more than 2 second ->  Skip it"
I'm using the Adafruit CC3000 wifi breakout chip. The libary can be found here: https://github.com/adafruit/Adafruit_CC3000_Library

liomry

I think you'd need multithreading with a timed interrupt which, afaik , arduino does not support


I added this:

Code: [Select]

// Function to send a TCP request and get the result as a string
void send_request (String request) {
     
    unsigned long startTime;
 
    // Connect   
    Serial.println("Starting connection to server...");
   
     startTime = millis();
     
    do  {
    client = cc3000.connectTCP(ip, port);
        }
    while((!client.connected()) && ((millis() - startTime) < connectTimeout));
     
    // Send request
    if (client.connected())
    {
      client.println(request);     
      client.println(F(""));
      Serial.println("Connected & Data sent");
    }                                                 
    else {
        Serial.println(F("Connection failed"));
         }
   
    while (client.connected()){
      while (client.available()) {char c = client.read();}
     }

    Serial.println("Closing connection");
    Serial.println("");
    client.close();
}


But i still freezes sometimes. Any ideas?

int2str

Switch to UDP. Since you don't need reliable delivery, it's perfect for the job!

Thanks for your reply!

I've tried changing the TCP to UDP

Code: [Select]

// Include required libraries
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#include<stdlib.h>

// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

//const int relay_pin = 8; // Relay pin
//char relayBuffer[1]; // Relay buffer

#define SensorPin1 A0
#define SensorPin2 A1

#define filterSamples   21              // filterSamples should  be an odd number, no smaller than 3

const unsigned long
  dhcpTimeout     = 60L * 1000L, // Max time to wait for address from DHCP
  connectTimeout  = 15L * 1000L, // Max time to wait for server connection
  responseTimeout = 15L * 1000L; // Max time to wait for data from server
uint32_t t;

// WiFi network (change with your settings !)
#define WLAN_SSID       "Viktor Nordmark iPhone"        // cannot be longer than 32 characters!
#define WLAN_PASS       "hacker7777"
#define WLAN_SECURITY   WLAN_SEC_WPA2 // This can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2


int led = 8;
//--------------------------------------------Initiation for filtering---------------------
int sensSmoothArray1 [filterSamples];   // array for holding raw sensor values for sensor1
int rawData1, smoothData1;  // variables for sensor1 data
char buffer[6];

//--------------------------------------------Initiation for VDC Measure--------------------
double voltDiv = 0.0948044;
String rawOutputVoltage=" ";
String smoothOutputVoltage=" ";
double voltage0_50 = 0;
double voltage0_50_0 = 0;

//--------------------------------------------Initiation for Resistance Measure-----------
String Resistance = "";
int Rraw = 0;           // variable to store the raw input value
int RVin = 5;           // variable to store the input voltage
float RVout = 0;        // variable to store the output voltage
float R1 = 10;         // variable to store the R1 value
float Res = 0;          // variable to store the R2 value
float Rbuffer = 0;      // buffer variable for calculation

// Create CC3000 instances
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIV2);                               
Adafruit_CC3000_Client client;
                                         
// Local server IP, port, and repository (change with your settings !)
uint32_t ip = cc3000.IP2U32(172,20,10,3);
int port = 80;
String repository = "/multimeter/";

void setup() {
   
 
  pinMode(led,OUTPUT);
  //pinMode(relay_pin,OUTPUT);
 
  Serial.begin(115200);
 
  // Initialise the CC3000 module
  if (!cc3000.begin()){while(1);}

  // Connect to  WiFi network
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println("Connected to WiFi network!");
   
  // Check DHCP
  Serial.print(F("Requesting address from DHCP server..."));
 
  for(t=millis(); !cc3000.checkDHCP() && ((millis() - t) < dhcpTimeout); delay(1000));
  if(cc3000.checkDHCP()) {
    Serial.println(F("OK"));
  } else {
    Serial.println(F("failed"));
    return;
  }

}

void loop() {
 
 
    digitalWrite(led,LOW);
    VDCMeasure(); //String = smoothOutputVoltage
    RMeasure();   //String = Resistance
   
    // Send request
      String request = "GET "+ repository + "sensor.php?temp=" + smoothOutputVoltage + "&hum=" + Resistance + " HTTP/1.0";
   
    Serial.println(request);
   
    send_request_udp(request);
    digitalWrite(led,HIGH);
   
    // Update every 370 ms
    delay(370);
 
 
}

// Function to send a UDP request and get the result as a string
 
void send_request_udp (String request) {

  unsigned long startTime;
   
  Serial.println(F("\r\nAttempting connection..."));
    startTime = millis();
    do {
        client = cc3000.connectUDP(ip, port);
       }
   while((!client.connected()) && ((millis() - startTime) < connectTimeout));

    if(client.connected()) {
     
      client.println(request);     
      client.println(F(""));
      Serial.print(F("connected!\r\nIssuing request..."));
     
    }
      else{Serial.println("FAIL!");}
     
      //Serial.print(F("\r\nAwaiting response..."));
     
      startTime = millis();
     
      while((!client.available()) && ((millis() - startTime) < responseTimeout));
      if(client.available()) {
         char c = client.read();
     
      }

      client.close();
   
   
    Serial.println("Time to connect, send & read:");
    Serial.println(millis() - startTime);
         
}





int digitalSmooth(int rawIn, int *sensSmoothArray){     // "int *sensSmoothArray" passes an array to the function - the asterisk indicates the array name is a pointer
  int j, k, temp, top, bottom;
  long total;
  static int i;
// static int raw[filterSamples];
  static int sorted[filterSamples];
  boolean done;

  i = (i + 1) % filterSamples;    // increment counter and roll over if necc. -  % (modulo operator) rolls over variable
  sensSmoothArray[i] = rawIn;                 // input new data into the oldest slot

  // Serial.print("raw = ");

  for (j=0; j<filterSamples; j++){     // transfer data array into anther array for sorting and averaging
    sorted[j] = sensSmoothArray[j];
  }

  done = 0;                // flag to know when we're done sorting             
  while(done != 1){        // simple swap sort, sorts numbers from lowest to highest
    done = 1;
    for (j = 0; j < (filterSamples - 1); j++){
      if (sorted[j] > sorted[j + 1]){     // numbers are out of order - swap
        temp = sorted[j + 1];
        sorted [j+1] =  sorted[j] ;
        sorted [j] = temp;
        done = 0;
      }
    }
  }

/*
  for (j = 0; j < (filterSamples); j++){    // print the array to debug
    Serial.print(sorted[j]);
    Serial.print("   ");
  }
  Serial.println();
*/

  // throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom
  bottom = max(((filterSamples * 15)  / 100), 1);
  top = min((((filterSamples * 85) / 100) + 1  ), (filterSamples - 1));   // the + 1 is to make up for asymmetry caused by integer rounding
  k = 0;
  total = 0;
  for ( j = bottom; j< top; j++){
    total += sorted[j];  // total remaining indices
    k++;
    // Serial.print(sorted[j]);
    // Serial.print("   ");
  }

//  Serial.println();
//  Serial.print("average = ");
//  Serial.println(total/k);
  return total / k;    // divide by number of samples
}

void VDCMeasure(){
 
   //int now = millis();
   

int total = 0;

for(int i=0; i<filterSamples; i++)  {
   
  rawData1 = analogRead(SensorPin1);                        // read DC-voltage sensor
  smoothData1 = digitalSmooth(rawData1, sensSmoothArray1);  // Send raw data to filter and place in array
 
  double voltage0_5 = (smoothData1 * (5.0 / 1023.0));        //Filtered
  voltage0_50 = voltage0_5/voltDiv;
 
  double voltage0_5_0 = (rawData1 * (5.0 / 1023.0));         //Unfiltered
  voltage0_50_0 = voltage0_5_0/voltDiv;
 
  total +=rawData1;                                          //Total value 
                                    }
 
 
 
   smoothOutputVoltage = dtostrf(voltage0_50, 4, 2, buffer); //Convert to string
   rawOutputVoltage = dtostrf(voltage0_50_0, 4, 2, buffer);


    int avg = total/filterSamples;
    double voltage0_5_1 = (avg * (5.0 / 1023.0));
    double voltage0_50_1 = voltage0_5_1/voltDiv;

   /* Serial.println("Raw Datafrom sensor:       ");
    Serial.print(rawOutputVoltage);
   
    Serial.println(" ");
   
    Serial.println("Smoothed Data:    ");
    Serial.print(smoothOutputVoltage);
    Serial.println(" ");
   
    Serial.println("Average:    ");
    Serial.print(voltage0_50_1);
    Serial.println(" ");*/


    //int time = millis()-now;
   
    //Serial.println(time);

}

void RMeasure(){

  Rraw = analogRead(SensorPin2);    // Reads the Input PIN
  RVout = (5.0 / 1023.0) * Rraw;    // Calculates the Voltage on th Input PIN
  Rbuffer = (RVin / RVout) - 1;
  Res = R1 / Rbuffer;
  if(Res>1000){Resistance="INFINITY";}
    else {Resistance = dtostrf(Res, 3, 1, buffer);} //Convert to string
 
  /*Serial.print("Voltage: ");      //
  Serial.println(RVout);           // Outputs the information
  Serial.print("R2: ");           //
  Serial.println(Resistance);             //*/

}
   


But i cant get the UDP connection working. Any ideas would be bery appreciated!

int2str


Thanks for your reply!
I've tried changing the TCP to UDP
...
But i cant get the UDP connection working. Any ideas would be bery appreciated!


Sorry. my assumption was that you have control over what's receiving the data.
Web servers don't usually listen to UDP packets. You'll have to write a little UDP server to receive the data.



Thanks for your reply!
I've tried changing the TCP to UDP
...
But i cant get the UDP connection working. Any ideas would be bery appreciated!


Sorry. my assumption was that you have control over what's receiving the data.
Web servers don't usually listen to UDP packets. You'll have to write a little UDP server to receive the data.



I do have control over the web server. But i haven't really done this before and have no idea of what i'm doing :P I'll read up a bit on how to set up a UDP web server and get back to you.
Thanks tough!

PaulS

Quote
But i still freezes sometimes. Any ideas?

You check the time before you call the function. When the function (eventually) returns you check the time again. If it took too long, you don't ask the function to do it again. I fail to see how you expected that to do anything.

That would be like wrapping a call to delay(600000000) in that while loop, and expecting delay() to return early.

Nick Gammon


Hi PaulS,

That website -  http://www.crystalball.com - brings you really to the Oracle ;) 


That's the Oracle?

Quote
There is no spoon.


I thought PaulS was a bit quiet today. Perhaps eating a lot of cake?

Quote
The cake is a lie.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up