Need help. My sketch stops working after 10~20min.

Hi!

Im using my Uno(R3) to controll a wifi watering system, using the adafruit wifi- and motorshield and a mux/mosfet setup and some other stuff. It works great for about 10 to 20 min, but then it stops sending data to my local xampp-server. So im thinking it might be some memory problem or? If anyone could take a quick look code and give me a tip or improvement i would appreciate it immensely :grinning: (And just ask if my clumsy code isnt understandable!)

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

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *pumpMotorA = AFMS.getMotor(1);
Adafruit_DCMotor *pumpMotorB = AFMS.getMotor(2);
Adafruit_StepperMotor *stepMotor = AFMS.getStepper(200, 2);

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

// WiFi network (change with your settings !)
#define WLAN_SSID "559HardangerNett2" // cannot be longer than 32 characters!
#define WLAN_PASS "5en9ruwr"
#define WLAN_SECURITY WLAN_SEC_WPA2 // This can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2

// Load Cell and soil sensor
int loadSensorPin = A0;
int loadSensorValue;
int loadSensSetpoint;

int soilHumPin = A1;
int soilHumValue;

int dispPosSensorPin = A2;
int dispPosVal;

const uint8_t dataPin = 6;
const uint8_t clockPin = 7;
Sensirion airSensor = Sensirion(dataPin, clockPin);

// settingsArray/wateringArr tells how much to water at each position, and the two last chars are time delay between loop and if the array should be changed
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
char settingsArray[36];// = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 0";
float temp_air;
float hum_air;
float dewpoint;
int nonCnc = 0;

// Create CC3000 instances
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER);

// Local server IP, port, and repository (change with your settings !)
String repository = "/greenHouseApp/";
uint32_t ip = cc3000.IP2U32(192,168,1,20);
int port = 80;

uint8_t motor0 = 0; //Stepmotor
uint8_t motor1 = 0; //PumpmotorA
uint8_t motor2 = 0; //PumpmotorB

// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
int wateringArr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0};
int dispPosSteps[] = { 2, 10, 19, 28, 37, 46, 55, 63, 72, 81, 90, 99,107,116,125,133,142};
//int dispPosVals[] = { 1,276,289,300,315,333,348,366,387,409,435,464,495,532,575,626,685}; // The potentiometer value at each position, not used
int curStep = 0;
int curPos = 16;

// MUX pins settings
int muxPinA = 2;
int muxPinB = 4;
int muxPinD = 9;

// Time control
unsigned long startTime = millis ();
unsigned long timeBase = 3600000;
unsigned long timeLimit = 3600000;
unsigned long runTime = 0;
unsigned long wateringTime = 0;
int refillWaterInt = 0;
boolean internettUpd = false;
int waterCntDown = 0;
boolean firstTime = true;

void setup(void)
{
if (!cc3000.begin())
{
while(1);
}

// Connect to WiFi network
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);

// Check DHCP
while (!cc3000.checkDHCP())
{
delay(100);
}
// Set the speed to start, from 0 (off) to 255 (max speed)
AFMS.begin();
pumpMotorA->setSpeed(1);
pumpMotorA->run(RELEASE);
pumpMotorB->setSpeed(1);
pumpMotorB->run(RELEASE);
stepMotor->setSpeed(1);

pinMode(muxPinA, OUTPUT);
pinMode(muxPinB, OUTPUT);
pinMode(muxPinD, OUTPUT);

delay(1000);

setMUX(0);
loadSensSetpoint = analogRead(loadSensorPin);
setMUX(-1);

calibratePosSensor();
}

void loop(void) {

//Checking time controll
long timeDiff = millis() - startTime;
startTime = millis();
runTime += timeDiff;
if (runTime > timeLimit && curPos <= 0) {
// Restart timeloop and other sequences
curPos = 16;
runTime = 0;
}
//If step and pump motors are not moving, check for next POSITION to water
if (motor0 == 0 && motor1 == 0 && waterCntDown == 0 && !firstTime) {
int a = curPos;
//Refill bucket when all watering is done
if (a<=0 && waterCntDown==0 && refillWaterInt>0) {
wateringTime = millis();
long time = 0;
while (time < 6000) {
long timeDiff = millis() - wateringTime;
wateringTime = millis();
time += timeDiff;
//refilling bucket
pumpMotorB->run(FORWARD);
pumpMotorB->setSpeed(255);
delay(1000);
}
refillWaterInt--;
pumpMotorB->setSpeed(0);
pumpMotorB->run(RELEASE);
motor2 = 0;
}
while (a>=0 && motor0==0) {
if (wateringArr[a] == 0) {
a--;
} else {
waterCntDown = wateringArr[a];
motor0 = 1;
}
}
//Update serverside that refilling will comence
if (a<=0 && waterCntDown==0 && refillWaterInt>0) {
motor2 = 1;
}
curPos = a;
}

// Measure the humidity & temperature
setMUX(1);
airSensor.measure(&temp_air, &hum_air, &dewpoint);
setMUX(-1);

setMUX(0);
loadSensorValue = analogRead(loadSensorPin);
setMUX(-1);

setMUX(2);
soilHumValue = analogRead(soilHumPin);
setMUX(-1);

setMUX(3);
int rPin = analogRead(dispPosSensorPin);
setMUX(-1);
//calibratePosSensor();

// Send request
String delimiter = "g";

String dA = String(int(temp_air100));
dA += delimiter + String(int(hum_air
100));
dA += delimiter + String(int(soilHumValue));
dA += delimiter + String(loadSensorValue);
dA += delimiter + String(curPos);
dA += delimiter + String(rPin);
dA += delimiter + String(motor0);
dA += String(motor1);
dA += String(motor2);
String request = "GET "+ repository + "arduinoDataHandler.php?data=x" + dA + " HTTP/1.0";
send_request(request);

// If settings changes have been made from serverside and succefull internett update has been conducted
if ((settingsArray[35] == '1' || firstTime) && internettUpd) {
for(int i=0; i<17; i++) {
wateringArr = (settingsArray[i*2] - '0')*10 + (settingsArray[i*2 + 1] - '0');

  • }*
    _ timeLimit = timeBase * (settingsArray[34] - '0');_

  • firstTime = false;*

  • internettUpd = false;*

  • }*

  • if (motor0 == 1) {*

  • //Go to new pos*

  • gotoNewPos();*

  • motor0 = 0;*

  • motor1 = 1;*

  • } else if (motor1 == 1) {*

  • //Check if unwanted movement has accured*

  • int err=5;*

  • if (rPin > 630) {*

  • err = 11;*

  • }*

  • if (abs(dispPosVal-rPin) > err) {*

  • calibratePosSensor(); *

  • } else {*

  • dispPosVal = rPin;*

  • }*

  • //Watering at the new POS*

  • wateringTime = millis();*

  • long time = 0;*

  • boolean watering = false;*

  • while (time < 6000) {*

  • long timeDiff = millis() - wateringTime;*

  • wateringTime = millis();*

  • time += timeDiff;*

  • if(!watering) {*

  • // Watering plant and refilling bucket simultaneous*

  • pumpMotorA->run(FORWARD);*

  • pumpMotorA->setSpeed(255);*

  • watering = true;*

  • refillWaterInt++;*

  • }*

  • delay(1000);*

  • } *

  • pumpMotorA->setSpeed(0);*

  • pumpMotorA->run(RELEASE);*

  • waterCntDown--;*

  • if (waterCntDown == 0) {*

  • motor1 = 0;*

  • curPos--;*

  • }*

  • }*

  • delay(5000);*
    }
    [/quote]
    wifi_green_house_2015_mai.ino (11.2 KB)

The other function used in the sketch (wasnt room for it in my first comment)

// Function to send a TCP request and get the result as a string/////////
void send_request (String request) {
internettUpd = false;
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, port);
if (client.connected()) {
client.println(request);
client.println(F(""));
nonCnc = 0;
}
else {
nonCnc++;
}

char c = 'null';
byte i = 0;
while (client.connected()) {
while (client.available()) {
// Read answer
c = client.read();

if ((c == 'g') && (i < 4)) {
i++;
} else if ((i < 4) && (c != 'g')) {
i = 0;
} else if (i >= 4) {
settingsArray[i-4] = c;
i++;
if (i==35) {
internettUpd = true;
}
}
}
}
//(IF) Internett update succefull, maybe implement better check
//internettUpd = true;
//int val = c - '0';
client.close();
}

void gotoNewPos() {
//Check for unwanted movement here also
setMUX(3);
int rPin = analogRead(dispPosSensorPin);
setMUX(-1);
int err=5;
if (rPin > 630) {
err = 11;
}
if (abs(dispPosVal-rPin) > err) {
calibratePosSensor();
} else {
dispPosVal = rPin;
}

// Goes to new POS
if(curStep > dispPosSteps[curPos]) {
stepMotor->step(curStep - dispPosSteps[curPos], BACKWARD, DOUBLE);
curStep -= curStep - dispPosSteps[curPos];
}
if(curStep < dispPosSteps[curPos]) {
stepMotor->step(dispPosSteps[curPos] - curStep, FORWARD, DOUBLE);
curStep += dispPosSteps[curPos] - curStep;
}
stepMotor->release();
//stores new dispPosVal to be able to detect changes
setMUX(3);
dispPosVal = analogRead(dispPosSensorPin);
setMUX(-1);
}

void calibratePosSensor() {
setMUX(3);
int rPin = analogRead(dispPosSensorPin);
setMUX(-1);
while (rPin > 720) {
stepMotor->step(1, BACKWARD, DOUBLE);

setMUX(3);
rPin = analogRead(dispPosSensorPin);
setMUX(-1);
}
while (rPin < 720) {
stepMotor->step(1, FORWARD, DOUBLE);

setMUX(3);
rPin = analogRead(dispPosSensorPin);
setMUX(-1);
}

int first = rPin;
int second = 0;
boolean bol = false;

int steps = 9;
while (!bol) {
stepMotor->step(1, FORWARD, DOUBLE);

setMUX(3);
rPin = analogRead(dispPosSensorPin);
setMUX(-1);

if (rPin > second + 6) {
second = first;
first = rPin;
} else {
bol = true;
if (rPin<first - 4) {
steps = 6;
}
}
}

curStep = 142;
stepMotor->step(steps, BACKWARD, DOUBLE);
delay(1000);
setMUX(3);
dispPosVal = analogRead(dispPosSensorPin);
setMUX(-1);
gotoNewPos();
}

void setMUX (int channel) {
if (channel < 0) {
digitalWrite(muxPinD, HIGH);
digitalWrite(muxPinA, LOW);
digitalWrite(muxPinB, LOW);
} else if (channel == 0) {
digitalWrite(muxPinD, LOW);
digitalWrite(muxPinA, LOW);
digitalWrite(muxPinB, LOW);
} else if (channel == 1) {
digitalWrite(muxPinD, LOW);
digitalWrite(muxPinA, HIGH);
digitalWrite(muxPinB, LOW);
} else if (channel == 2) {
digitalWrite(muxPinD, LOW);
digitalWrite(muxPinA, LOW);
digitalWrite(muxPinB, HIGH);
} else if (channel == 3) {
digitalWrite(muxPinD, LOW);
digitalWrite(muxPinA, HIGH);
digitalWrite(muxPinB, HIGH);
}
delay(100);
}

check the size of your array's, if you really want to put such string in the settingsArray it will overflow.

settingsArray[36];// = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 0";

Second I would add Serial print statements to see where it blocks.

Third, if you think memory is the problem you can use this function to check it runtime (you need to print it to see effects

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

In your code I see

long timeDiff = millis() - wateringTime;

Note that all timestamps should preferably unsigned long (millis and micros do return that).

Thx alot for the reply :slight_smile: So do u have any suggestion on how to retrieving the settingsarray differently? As u see from the "send_request (String request)" function (made by adafruit), all i get is a bounch of chars that i store in the settingsArray. Would making two or more shorter string arrays instead one long one help maybe?