Arduino keeps losing connection after a few seconds

Hello, I am new to Pi, Arduino, and coding and am trying to get code to work in Cayenne. I have a Raspberry Pi(WiFi) and 2 Arduinos(Serial) I am trying to interface with Cayenne but every time I get the Arduino to connect it goes offline after about 10 to 15 seconds. I am pretty sure it has something to do with my code but am not sure what is wrong. I have been trying to configure existing code to work with Cayenne but haven’t succeeded yet. If anyone has any ideas on what I’m doing wrong, I would greatly appreciate any help I can get.

#include <CayenneMQTTSerial.h>
#include <DallasTemperature.h>
#include <farmBot.h>
#include <OneWire.h>
#include <EEPROM.h>
#define CAYENNE_PRINT Serial



/* I2C interface requirements */
#include <Wire.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "xxxxx";
char password[] = "xxxxx";
char clientID[] = "xxxxx";
 
/* allowcation of 1024 EEPROM  */
const byte I2CID = 0;  

int number = 0;
int state = 0;
double temp;
/* end I2C interface requirements */

// Pin assignment
const int ONE_WIRE_BUS = 3;        // air temperature pin in
const int lightsPin = 4;          // lights pin out
const int circulationFanPin = 13;  // circulation fan pin out

#define VIRTUAL_CHANNEL 0
#define VIRTUAL_CHANNEL 1
#define VIRTUAL_CHANNEL 2

const int NORMAL = 1;             // processing state
const int SPECIAL = 2;           // processing state
const int OFF = 0;                // device mode
const int ON = 1;                 // device mode
const int AUTO = 3;               // device mode

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress airThermometer = { 0x28, 0x98, 0x01, 0x94, 0x97, 0x0E, 0x03, 0x40 };
//DeviceAddress outsideThermometer = { 0x28, 0x6B, 0xDF, 0xDF, 0x02, 0x00, 0x00, 0xC0 };
//DeviceAddress dogHouseThermometer = { 0x28, 0x59, 0xBE, 0xDF, 0x02, 0x00, 0x00, 0x9F };

int systemMode = NORMAL;          // processing state (NORMAL, FILLTANK)

int lightsMode = AUTO;            // lights mode
int lightsState = LOW;            // lights current state
int lightsOnTime = 1080;          // minutes that lights are ON
int lightsOffTime = 360;         // minutes that lights are OFF
unsigned long lightsTimer = 0;    // clock time when lights state should toggle

int circulationFanMode = AUTO;               // circulation fan mode
int circulationFanState = LOW;               // circulation fan current state
int circulationFanOnTime = 1;             // minutes that fan is ON
int circulationFanOffTime = 2;            // minutes that fan is OFF
unsigned long circulationFanTimer = 5000;       // clock time when fan state should toggle

byte airTempMSB = 80;            // thermometer integer full units ie. 93
byte airTempLSB = 2;            // thermometer rounded to one decimal place to the right ie. .2 so together 93.2
byte airTempTarget = 82;
byte airTempDelta = 5;
int airTempSampleRate = 3;      // seconds between samples
unsigned long airTempTimer = 0;

byte cmdRecieved = 0;
int cmdCnt;
int command;

void setup() {
  Serial.begin(9600);
  Cayenne.begin(username, password, clientID);
  
  
  pinMode(lightsPin, OUTPUT);   
  digitalWrite(lightsPin, lightsState);      // set initial lights state 
  
  pinMode(circulationFanPin, OUTPUT);   
  digitalWrite(circulationFanPin, circulationFanState);            // set initial fan state 

  i2cSetup();
  oneWireSetup();
//  flowSetup();

} // setup

void loop() {
 
  switch (systemMode) {
     case NORMAL: normalMode(); break;
     case SPECIAL: specialMode(); break;
     default: normalMode(); break;
  }
  Cayenne.loop();  
  
} // loop

void normalMode()
{
  if (circulationFanMode == AUTO) circulationFanControl();
  if (lightsMode == AUTO) lightsControl();
 
} // normalMode

void circulationFanControl()
{
  if (checkTimer(airTempTimer) == HIGH) {
    getAirTemp();
    airTempTimer = setSecondsTimer(airTempSampleRate);    // change value to mean seconds
//    Serial.print("sample temp \n");
  }

  if (airTempMSB >= airTempTarget)  // turn fan on
  { 
    circulationFanState = HIGH;
  }
  if (airTempMSB < airTempTarget - airTempDelta)  // turn fan off
  { 
    circulationFanState = LOW;
  }
  digitalWrite(circulationFanPin, circulationFanState);  
}  // circulationFanControl

void lightsControl()
{
  if (checkTimer(lightsTimer) == HIGH) {
    lightsState = !lightsState;
    digitalWrite(lightsPin, lightsState);
    if (lightsState == HIGH) {
      lightsTimer = setMinutesTimer(lightsOnTime);
    } else {
     lightsTimer = setMinutesTimer(lightsOffTime);
    }
  }
} // end lightsControl

void specialMode()
{
  systemMode = NORMAL;
} // specialMode

unsigned long setMinutesTimer(int waitTime)
{ 
  unsigned long endTime;

   endTime = millis() + (waitTime * 60000);  // convert back to milliseconds from minutes
   return endTime;
} // setMinutesTimer

unsigned long setSecondsTimer(int waitTime)
{ 
  unsigned long endTime;

   endTime = millis() + (waitTime * 1000);  // convert back to milliseconds from seconds
   return endTime;
} // setSecondsTimer

int checkTimer(unsigned long timer)
{
   if (millis() > timer) {return HIGH;}
   else {return LOW;}
} // checkTimer

void debouncePin(DEBOUNCE_DEF& target) {
  long debounceDelay = 50;    // the debounce time; increase if the output flickers

   // read the state of the pin into a local variable:
  int reading = digitalRead(target.pin);

  // check to see if pin state has changed and you've waited
  // long enough since the last test to ignore any noise:  
  if (reading != target.pinState) {
    // reset the debouncing timer
    target.lastDebounceTime = millis();
    target.pinStable = LOW;
        if (target.pinOldState == LOW) {target.pinOldState = HIGH;} else {target.pinOldState = LOW;}
 } 
  
  if ((millis() - target.lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
	  target.pinStable = HIGH;
   }
  target.pinState = reading;
} // debouncePin

/* IC2 support */

void i2cSetup() {
  EEPROM.write(I2CID, 0x06);
  // set default i2c ID if not yet defined
 // if (EEPROM.read(I2CID)==0) { EEPROM.write(I2CID, 0x4); }
 
 // initialize i2c as slave
 Wire.begin(EEPROM.read(I2CID));
 
 // define callbacks for i2c communication
 Wire.onReceive(i2cCommand);
 Wire.onRequest(i2cRequest);
} // i2cSetup
  
void i2cCommand(int byteCount){ // callback for received data
  unsigned char received;
//  int cmdCnt;
//  int command;
  int output;
 
  cmdCnt = Wire.available();
  if (cmdCnt > 0 ) {
    cmdRecieved++;
    command = Wire.read();      // first byte is the command
    switch (command)
    {              
      case 1:    // set Lights Mode (Off, On, Auto)
        if (cmdCnt == 2 ) {    // next byte is the mode
          lightsMode = Wire.read();      
          switch (lightsMode) {
            case ON: lightsState = HIGH; break;
            case OFF: lightsState = LOW; break;
          }
          digitalWrite(lightsPin, lightsState);
          Serial.print("Lights state = ");
          Serial.println(lightsState);
          Serial.print("Lights Mode = ");
          Serial.println(lightsMode);
       }
        break;
        
      case 2:    // set Lights auto ON time
        if (cmdCnt == 3 ) {    // next 2 bytes is the time
          received = Wire.read();
          output = (received << 8);  // shift to high byte
          received = Wire.read();
          output = output + received; // add in low byte
          lightsOnTime = output;      // ON time in seconds
        }
         break;
        
      case 3:    // set Lights auto OFF time
        if (cmdCnt == 3 ) {    // next 2 bytes is the time
          received = Wire.read();
          output = (received << 8);    // shift to high byte
          received = Wire.read();
          output = output + received;  // add in low byte
          lightsOffTime = output;      // OFF time in seconds
        }
        break;
        
      case 4:    // set Circulation Fan (Off, On, Auto)
        if (cmdCnt == 2 ) {    // next byte is the mode
          circulationFanMode = Wire.read();      
          switch (circulationFanMode) {
            case ON: circulationFanState = HIGH; break;
            case OFF: circulationFanState = LOW; break;
          }
            digitalWrite(circulationFanPin, circulationFanState);
            Serial.print("Fan state = ");
            Serial.println(circulationFanState);
        }
        break;
           
      case 5:    // set Circulation Fan auto ON time
        if (cmdCnt == 3 ) {    // next 2 bytes is the time
          received = Wire.read();
          output = (received << 8);    // shift to high byte
          received = Wire.read();
          output = output + received;  // add in low byte
          circulationFanOnTime = output;          // ON time in seconds
        }
        break;
      
      case 6:    // set Circulation Fan auto OFF time
           circulationFanOffTime = 6001;         // OFF time in seconds
//       if (cmdCnt == 3 ) {    // next 2 bytes is the time
//          received = Wire.read();
//          output = (received << 8);    // shift to high byte
//          received = Wire.read();
//          output = output + received;  // add in low byte
//          circulationFanOffTime = 6001;         // OFF time in seconds
//        }
        break;
       
       default:
         Serial.print("Unhandled command # ");
         Serial.print(command);
         Serial.print("\n");;
         break;
   } // end switch 
  } // end if cmdCnt
  
} // ic2Command
 

void i2cRequest() {    // callback for sending data
  byte i2cResponse[32];
  byte i2cResponseLen = 1;                 // response length
  unsigned long currentTime = millis();
  unsigned long transitionTime = 0;
  byte lightsStatus = 0;
  byte circulationFanStatus = 0;
  String outString = "Hello";
  
  
  
/*    
    i2cResponse[i2cResponseLen] = (byte)11;  // left of decimal byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)airTempLSB;  // right if decimal byte
    i2cResponseLen++;
    Serial.print("air temp msb = ");
    Serial.println(airTempLSB);
    
    i2cResponse[i2cResponseLen] = airTempTarget;  // byte
    i2cResponseLen++;  
    Serial.print("air temp Target = ");
    Serial.println(airTempTarget);

    i2cResponse[i2cResponseLen] = airTempDelta;  // byte
    i2cResponseLen++;  
    Serial.print("air temp Delta = ");
    Serial.println(airTempDelta);
 
    lightsStatus = (lightsMode << 6) | (lightsState << 5 );
    circulationFanStatus = (circulationFanMode << 3) | circulationFanState << 2;
    i2cResponse[i2cResponseLen] = lightsStatus | circulationFanStatus;      //  lights, circulation fan mode and status
    i2cResponseLen++;

    if (currentTime < lightsTimer) {transitionTime = lightsTimer - currentTime;} else {transitionTime = 0;}
    transitionTime = transitionTime / 60000;  // convert to minutes
    i2cResponse[i2cResponseLen] = (byte)(transitionTime >> 8); // high byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)transitionTime; // low byte
    i2cResponseLen++;
    Serial.print("lights transitionTime = ");
    Serial.println(transitionTime);
    
    i2cResponse[i2cResponseLen] = (byte)(lightsOnTime >> 8); // high byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)lightsOnTime; // low byte
    i2cResponseLen++;
    Serial.print("lights on duration = ");
    Serial.println(lightsOnTime);

    i2cResponse[i2cResponseLen] = (byte)(lightsOffTime >> 8); // high byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)lightsOffTime; // low byte 17
    i2cResponseLen++;
    Serial.print("lights off duration = ");
    Serial.println(lightsOffTime);
    
    if (currentTime < circulationFanTimer) {transitionTime = circulationFanTimer - currentTime;} else {transitionTime = 0;}
    transitionTime = transitionTime / 60000;  // convert to minutes
    i2cResponse[i2cResponseLen] = (byte)(transitionTime >> 8); // high byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)transitionTime; // low byte
    i2cResponseLen++;
    Serial.print("fan transitionTime = ");
    Serial.println(transitionTime);

    i2cResponse[i2cResponseLen] = (byte)(circulationFanOnTime >> 8); // high byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)circulationFanOnTime; // low byte
    i2cResponseLen++;
    Serial.print("fan on duration = ");
    Serial.println(circulationFanOnTime);
    
    i2cResponse[i2cResponseLen] = (byte)(circulationFanOffTime >> 8); // high byte
    i2cResponseLen++;
    i2cResponse[i2cResponseLen] = (byte)circulationFanOffTime; // low byte 22
    i2cResponseLen++;    // compensate for zero based array 24
    Serial.print("fan off duration = ");
    Serial.println(circulationFanOffTime);
 
    Serial.print("message length = ");
    Serial.println(i2cResponseLen);
    Wire.write(i2cResponse, i2cResponseLen);
 */
  
   
} // i2cRequest
 
double GetChipTemp(void)
{  // Get the internal temperature of the arduino
  unsigned int wADC;
  double t;
  ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
  ADCSRA |= _BV(ADEN); // enable the ADC
  delay(20); // wait for voltages to become stable.
  ADCSRA |= _BV(ADSC); // Start the ADC
  while (bit_is_set(ADCSRA,ADSC));
  wADC = ADCW;
  t = (wADC - 324.31 ) / 1.22;
  return (t);
} // GetChipTemp

// end I2C support
// git clone http://github.com/jrowberg/i2cdevlib

// Reads DS18B20 "1-Wire" digital temperature sensors.
// Tutorial: http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html

void oneWireSetup()
{
  // Start up the library
  sensors.begin();
  sensors.setResolution(airThermometer, 10); // set the resolution to 10 bit (good enough?)
//  sensors.setResolution(outsideThermometer, 10);
//  sensors.setResolution(dogHouseThermometer, 10);
} // oneWireSetup

float getTemperature(DeviceAddress deviceAddress)
{
  float tempF = 70;
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
 //   Serial.print("Error getting temperature");
  } else {
    tempF = DallasTemperature::toFahrenheit(tempC);
//    Serial.print("C: ");
//    Serial.print(tempC);
//    Serial.print(" F: ");
//    Serial.print(DallasTemperature::toFahrenheit(tempC));
//    Serial.print("\n");;
  }
  return tempF;
}

void getAirTemp()
{ 
  float tempF = 0;
  double leftPart;
  double rightPart;
  double newRight;
  sensors.requestTemperatures();
  tempF = getTemperature(airThermometer);
 
  rightPart = modf(tempF, &leftPart);
  airTempMSB = (byte)leftPart;
  newRight = rightPart*10;
  rightPart = modf(newRight, &leftPart);
  airTempLSB = (byte)leftPart;
  Serial.print("Air Temp: ");;
  Serial.println(airTempMSB);

}

// This function is called at intervals to send sensor data to Cayenne.
CAYENNE_OUT(V0)
{
  // Send the command to get temperatures.
  sensors.requestTemperatures();
  // This command writes the temperature in Celsius to the Virtual Channel.
  //Cayenne.celsiusWrite(VIRTUAL_CHANNEL, sensors.getTempCByIndex(0));
  // To send the temperature in Fahrenheit use the corresponding code below.
  Cayenne.fahrenheitWrite(V0, sensors.getTempFByIndex(0));
}

// This function is called when data is sent from Cayenne.
CAYENNE_IN(V1)
{
  // Write value to turn the relay switch on or off. This code assumes you wire your relay as normally open.
  if (getValue.asInt() == 0) {
    digitalWrite(lightsPin, HIGH);
  }
  else {
    digitalWrite(lightsPin, LOW);
  }
}

// This function is called when data is sent from Cayenne.
CAYENNE_IN(V2)
{
  // Write value to turn the relay switch on or off. This code assumes you wire your relay as normally open.
  if (getValue.asInt() == 0) {
    digitalWrite(circulationFanPin, HIGH);
  }
  else {
    digitalWrite(circulationFanPin, LOW);
  }
}


// end DS18B20 support

for such extreme code, I would suggest not using the serial connection as it is difficult to debug the issue. You can try to use a basic code and see if the issue occurs.

Like Shramik said, could be a lot of things. If you have an ethernet shield hook that up and turn debug on to see if it’s a code issue or hardware. If you don’t have an ethernet shield, do you get any errors in the console when you run the .sh file on the pi?

I haven’t gotten any errors on the pi. I have run the arduinos both from the pi and from my pc and get the same result, but no errors. This has been driving me crazy. I just got some esp8266 boards that I am going to configure and add to my project. Now that I have these I will probably eliminate the Pi at least for now and just run the arduino’s. I hate having to disconnect them everytime I need to change the code, so the wifi should make my life a lot easier. I appreciate your help. I will update this with anything I find.

1 Like

Thanks for your help, I am going to try a different connection and the basic code you suggested.

using an esp8266 dev board is a better option than the current setup for your project.