Electronic – arduino – How to fully turn off the Arduino WiFi shield

arduino

I'm using the WiFi shield on an Arduino Uno but I do not think the shield is fully disconnecting. I have a loop that checks a sensor for input. If the sensor hits the threshold, it connects with te WiFi shield to download some data, sleeps for a few seconds, then enters the loop again.

The function that I have to connect to the network, in it's simplest form, performs a WiFi.begin(), client.connect(), send message, client.stop() and WiFi.disconnect().

However, as I enter the main loop (after what I believe to be disconnecting form the network) the LINK light on the shield remains on. Furthermore if I loop through the loop after quite some time the Uno eventually halts. This is suggestive of a memory leak.

With the green light on am I REALLY disconnected from the network despite me running client.stop() and WiFi.disconnect()?
Has anyone else seen memory leak issues with the WiFi Shield?

I am also using the SD card and I've heard that there used to be memory leaks with that, but if I am not using strings to interface with the SD card I should be good, right? I am referring to this link about the SD card memory leak: https://stackoverflow.com/questions/11690647/arduino-memory-leaks-sd-card-strings I am executing a close() each time I reference the SD card…

EDIT: Attaching code…. (I believe this was the last working version. I've since removed the WiFi portions as I could never make it work, but you should get the gist of what I was trying to do….

#include <SD.h>
#include <WiFi.h>
#include <Time.h>

//#include <MemoryFree.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/
//system wide params
boolean DEBUG = true;        // flag to print out data or not
unsigned long timeBuf = 0;   // time marker for motion, number is in milliseconds that have passed sine system boot
char GPSString[100];
boolean weMoved = false;     // boolean to indicate that we moved.  We may or may not gather data depending on that...
boolean timeLapse = false;   // boolean to inicate that we sat in one common place for an extended period of time.





void setup()
{
int total;
int average;

      // this is the pin the GPS unit is plugged into.
      // Need to set it up for voltage output
      pinMode(8, OUTPUT);
      // but we have it turned off to start
      digitalWrite(8, LOW);



  //set accelerometer pins as inut pins
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  Serial.begin(57600);

  initializeSD();


}

void loop()
{
    // Check if we MOVE or time lapses and we need another data query.  
    {
    Serial.println("monitoring");
    int xreadings[8];
    int yreadings[8];
    int zreadings[8];
    initReadings(xreadings, yreadings, zreadings);

    int index = 0;
    while(1) {

      // turn on GPS unit if we sit for a while a minute before data gathering
      if((millis() - timeBuf > 299900)) digitalWrite(8, HIGH);

       // break if we have elapsed the time
       if((millis() - timeBuf) > 300000) 
       {
         timeLapse = true;
         break;
       }

       // time ok, so get new readings and check for movement threshold.  Break if we move
       if(index >= 8) index = 0;       
       xreadings[index] = analogRead(1);
       yreadings[index] = analogRead(2);
       zreadings[index] = analogRead(3);

       if(moved(xreadings, yreadings, zreadings))
       {
         digitalWrite(8, HIGH);
         weMoved = true;
         break; 
       }
    }
  }

     // get WiFi Positioning....
     checkWiFiPosition();

     delay(6000);

     // get GPS string and then send off to location server
     processGPS();
     sendGPS();
     delay(5000);


   {
     float temperature = getLocalTemp();
     Serial.print("Temp is ");
     Serial.println(temperature);
   }

    delay(1000);


    writeToSD();

    // now turn off GPS unit as we are about to go back into our loop
    digitalWrite(8, LOW);

    // and update timeLapse to be the current time
    timeBuf = millis();

}

// function to load up accelerometer array
void initReadings(int* xr, int* yr, int* zr){
   for (int thisReading = 0; thisReading < 8; thisReading++)
   {
     xr[thisReading] = analogRead(1);   
     delay(1);
     yr[thisReading] = analogRead(2);
     delay(1);
     zr[thisReading] = analogRead(3);    
   } 
}


// function to check if the accelerometer has detected movement
boolean moved(int* xr, int* yr, int* zr){
  int delta = 0;

  for (int i = 0; i < 7; i++)
  {
     // add x deltas
     if (xr[i] >= xr[i+1]) delta = delta + (xr[i] - xr[i+1]);
     else delta = delta + (xr[i+1] - xr[i]);

     // add y deltas
     if (yr[i] >= yr[i+1]) delta = delta + (yr[i] - yr[i+1]);
     else delta = delta + (yr[i+1] - yr[i]);

     // add z deltas
     if (zr[i] >= zr[i+1]) delta = delta + (zr[i] - zr[i+1]);
     else delta = delta + (zr[i+1] - zr[i]);

  }  
     if (delta > 100) return true;
     else return false;
}


float getLocalTemp(){

 int reading = analogRead(A0);
 return (reading - 500) / 10;

}


// function that write the GPS, baraometer and other data information to the SD card
static void writeToSD()
{

  String logEntry;
  logEntry += GPSString;

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(logEntry);
    dataFile.close();
    Serial.println("Closed");
    // print to the serial port too:
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }   

}


boolean processGPS()
{
     char buf[100];
     int iter = 0;
     int d = 0;
     char thisChar; 
     unsigned long startTime = millis();

     Serial.println("GPS");
     while((millis() - startTime) < 2000){
     if (Serial.available()) {
       #if ARDUINO >= 100 //For Arduino v1.0+
       {
         thisChar = Serial.read();
         if(thisChar == '$') iter = 0;
         buf[iter] = thisChar;
         buf[iter+1] = '\0';
         iter++;
       }  
       #else //For Arduino v0023 or earlier
         thisChar = Serial.read();
       #endif
     }
       if(thisChar == '*'){

        if(buf[1] == 'G' && buf[2] == 'P' && buf[3] == 'G' && buf[4] == 'G' && buf[5] == 'A'){
           int commaCount = 0;

           // cycle through all characters contained in the string, noting commas
             for(int i = 0; i < iter; i++){

                if(buf[i] == ','){
                 commaCount++; 
              }
           } // for loop      
         // Only return true if we reach the 9th comma on the GPGGA line.  This indicates we
         //    gathered all necessary data fields from the GPGGA line we need: fields 2 - 8
         if(commaCount >= 9){     
             for(int i = 0; i < iter; i++)
             {
                GPSString[i] = buf[i];
             }    
             GPSString[iter] = '\0';
             return true;
         }
         iter = 0;
       } // If we found GPGGA in the string      
       else{
           iter = 0;
       }
       d=0;
     }
   }   
     return false;
}





//###################################################################################
void sendGPS(){
  int status = WL_IDLE_STATUS; // the Wifi radio's status

  WiFiClient client;  

  char* ssids[]={"linksys"};
  char* passwds[]={"xxxx"};
   for (int i = 0; i < 1; i++){
     Serial.print("Attempting to connect to: ");
     Serial.print(ssids[i]);
     status = WiFi.begin(ssids[i],passwds[i]);
     if ( status != WL_CONNECTED) { 
      WiFi.disconnect();
      Serial.println("No connection");
      continue;
    } else {

      break;
    }
  }

  byte server[] = { 1,2,3,4 }; // Test server
  if (client.connect(server, 8080)) {
  Serial.println("Connected to Lo ");
  byte wifimac[6];                    
  WiFi.macAddress(wifimac);
  char c1[17]="";
  byte b1;  
  for(int y=5, x=0; y>=0, x<=16; y--, ++x) {
       b1=((byte)(wifimac[y]>>4));
       c1[x]=(char)(b1>9 ? b1+0x37 : b1+0x30);
       b1=((byte)(wifimac[y]&0xF));
       c1[++x]=(char)(b1>9 ? b1+0x37 : b1+0x30);
       if(x<16) {
         c1[++x]=':';
       }
  }
  String wifim = "";
  for(int z=0; z<17;z++)
  {
    wifim += c1[z];
  } 

  client.println("POST /MACServer/LocateMe?id="+wifim+"&latlong="+GPSString);

  }
  Serial.println("disconnected");
  client.stop(); 
  WiFi.disconnect();
}


void checkWiFiPosition(){
  int status = WL_IDLE_STATUS; // the Wifi radio's status

  WiFiClient client; 

  char* ssids[]={"linksys"};
  char* passwds[]={"xxxxxx"};
   for (int i = 0; i < 1; i++){
     Serial.print("Attempting to connect to: ");
     Serial.print(ssids[i]);
     status = WiFi.begin(ssids[i],passwds[i]);
     if ( status != WL_CONNECTED) { 
      WiFi.disconnect();
      Serial.println("No connection");
      continue;
    } else {
      break;
    }
  }

  byte server[] = { 1,2,3,4 }; // Test server
  if (client.connect(server, 8080)) {
  Serial.println("Connected to Lo ");
  byte wifimac[6];                    
  WiFi.macAddress(wifimac);
  char c1[17]="";
  byte b1;  
  for(int y=5, x=0; y>=0, x<=16; y--, ++x) {
       b1=((byte)(wifimac[y]>>4));
       c1[x]=(char)(b1>9 ? b1+0x37 : b1+0x30);
       b1=((byte)(wifimac[y]&0xF));
       c1[++x]=(char)(b1>9 ? b1+0x37 : b1+0x30);
       if(x<16) {
         c1[++x]=':';
       }
  }
  String wifim = "";
  for(int z=0; z<17;z++)
  {
    wifim += c1[z];
    //Serial.print(c1[z]);
  } 


  //Serial.println("WIFI shield MAC " + wifim);
  //Serial.print("RSSI: ");
  //Serial.println(WiFi.RSSI());

  byte bssid[6];
  WiFi.BSSID(bssid);
  char c[17]="";
  byte b;
  for(int y=5, x=0; y>=0, x<=16; y--, ++x) {
       b=((byte)(bssid[y]>>4));
       c[x]=(char)(b>9 ? b+0x37 : b+0x30);
       b=((byte)(bssid[y]&0xF));
       c[++x]=(char)(b>9 ? b+0x37 : b+0x30);
       if(x<16) {
         c[++x]=':';
       }
  }
  String mac = ""; 
   for(int z=0; z<17;z++)
  {
    mac += c[z];
    Serial.print(c[z]);
  }

  client.println("POST /MACServer/LocateMe?id="+wifim+"&m=" + mac);
  boolean startRead=false;


  Serial.println("Rd");
  while (client.connected()) {

      char c = client.read();

      if(c=='<')
        startRead=true;

      if(startRead==true)
          Serial.print(c);
      if(c=='>') startRead=false;
    }


  client.stop(); 
  WiFi.disconnect();
  }
  delay(1000);  

}



//function that initializes the SD card
void initializeSD()
{
  analogWrite(8, 170);
  delay(5000);
  analogWrite(8, 0);
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  //pinMode(10, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(4)) {
    // don't do anything more:
    return;
  }
  if(DEBUG) {Serial.println("card initialized.");}
}

Best Answer

You can use analog switches like CD4066 or MOSFET in series to power the shield. This can power off the shield completely. If using analog switch, make sure to check the current handling capability of the switch.

Hope this helps.