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.");}
}
malloc()
on the AVR (or at least there shouldn't be). Everything should be statically allocated. \$\endgroup\$malloc()
has been implemented on the Arduino in a few different ways. Some libraries for peripherals / shields implement their own private version as well - though that should be consideredprivateLocalAlloc()
or something. \$\endgroup\$malloc()
with 2 KB SRAM? That's a horrible idea. \$\endgroup\$