How to add to existing Arduino sketch

I am connecting to Cayenne with Arduino MEGA and ESP 8266.
I’d like to do an existing Arduino sketch and finally upload and download Cayenne.
So I blinked LED (A) at Arduino, uploaded the startup period to Cayenne, and created a sketch to manipulate the brightness of LED (B) from the slider widget.
However, although it was possible to flash the LED (A) and upload the startup time to Cayenne, it is not possible to dim the LED (B) slider widget.
The serial monitor displays as follows.

[6586] Connected to WiFi
[6587] Connecting to mqtt.mydevices.com:1883
[7793] Connected
[8546] Publish: topic 4, channel 65534, value Arduino Mega, subkey , key
[9245] Publish: topic 6, channel 65534, value ATmega2560, subkey , key
[9911] Publish: topic 7, channel 65534, value 16000000, subkey , key
[10570] Publish: topic 5, channel 65534, value 1.2.0, subkey , key
[11230] Publish: topic 8, channel 65534, value ESP8266Shield, subkey , key
[27302] Publish: topic 1, channel 0, value 27302, subkey , key
[44288] Publish: topic 1, channel 0, value 44288, subkey , key
[44944] Connection ok
[61307] Publish: topic 1, channel 0, value 61307, subkey , key
[61965] Connection ok
[83298] Timeout reading data
[83544] Publish: topic 1, channel 0, value 83544, subkey , key
[84240] Connection ok

By deleting the sketch of the blinking part of the LED (A), dimming with the slider widget of LED (B) can be executed.
How can I add sending and receiving to Cayenne to an existing Arduino sketch?

Sorry for my poor English.
I am glad if you give me advice.

Below is the Arduino sketch we created.

#define CAYENNE_DEBUG       // Uncomment to show debug messages
#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <CayenneMQTTESP8266Shield.h>

// WiFi network info.
char ssid[] = "XXXXXX;
char wifiPassword[] = "XXXXXX";

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "XXXXXX";
char password[] = "XXXXXX";
char clientID[] = "XXXXXX";

// Set ESP8266 Serial object. In this example we use the Serial1 hardware serial which is available on boards like the Arduino Mega.
#define EspSerial Serial1

ESP8266 wifi(&EspSerial);
//LED (MEGA)
int LED=7;
//LED slider ch setting
#define VIRTUAL_CHANNEL 1
#define ACTUATOR_PIN 2

void setup()
{
  Serial.begin(9600);
  delay(10);
  //LED (MEGA)setting
pinMode(LED, OUTPUT);
  // Set ESP8266 baud rate
  EspSerial.begin(115200);
  delay(10);

  Cayenne.begin(username, password, clientID, wifi, ssid, wifiPassword);
}

void loop()
{
  digitalWrite(LED, HIGH);
  delay(1000);
  digitalWrite(LED, LOW);
  delay(15000);
  
  Cayenne.loop();
}

// This function is called when data is sent from Cayenne.
CAYENNE_IN(VIRTUAL_CHANNEL)
{
 float value = getValue.asInt(); // 0 to 255
  CAYENNE_LOG("Channel %d, pin %d, value %d", VIRTUAL_CHANNEL, ACTUATOR_PIN, value);
  // Write the value received to the PWM pin. analogWrite accepts a value from 0 to 255.
  analogWrite(ACTUATOR_PIN, value);
}

// You can also use functions for specific channels, e.g CAYENNE_OUT(1) for sending channel 1 data.
CAYENNE_OUT(VIRTUAL_CHANNEL)
{
  // Write data to Cayenne here. This example just sends the current uptime in milliseconds on virtual channel 0.
  Cayenne.virtualWrite(0, millis());
  // Some examples of other functions you can use to send data.
  //Cayenne.celsiusWrite(1, 22.0);
  //Cayenne.luxWrite(2, 700);
  //Cayenne.virtualWrite(3, 50, TYPE_PROXIMITY, UNIT_CENTIMETER);
}

// Default function for processing actuator commands from the Cayenne Dashboard.
// You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
  CAYENNE_LOG("Channel %u, value %s", request.channel, getValue.asString());
  //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

Welcome to the cayenne community @negishi_s0904.
First delete the delay from main loop, use millis() instead. the code you posted works for slider ?

Yes. I can adjust the LED (B) brightness with the slider from Virtual Canyonne’s Virtual Channel 1.

I corrected sketch according to the advice as below and I was able to do what I wanted. Thank you very much.

It is a pity that (delay) can not be used in the main loop because Arduno sketch I had already created contains a lot of (delay).

Here is the corrected sketch.

#define CAYENNE_DEBUG       // Uncomment to show debug messages
#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <CayenneMQTTESP8266Shield.h>

// WiFi network info.
char ssid[] = "";
char wifiPassword[] = "";

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "";
char password[] = "";
char clientID[] = "";

// Set ESP8266 Serial object. In this example we use the Serial1 hardware serial which is available on boards like the Arduino Mega.
#define EspSerial Serial1

ESP8266 wifi(&EspSerial);
//LED (MEGA)
int LED=7;
int LedState = LOW;
unsigned long preMillis = 0;  
unsigned long interval = 15000;

//LED slider ch setting
#define VIRTUAL_CHANNEL 1
#define ACTUATOR_PIN 2

void setup()
{
  Serial.begin(9600);
  delay(10);
  //LED (MEGA)setting
pinMode(LED, OUTPUT);
  // Set ESP8266 baud rate
  EspSerial.begin(115200);
  delay(10);

  Cayenne.begin(username, password, clientID, wifi, ssid, wifiPassword);
}

void loop()
{
    unsigned long curMillis = millis();

  if(curMillis - preMillis > interval) {
    if (LedState == LOW) {
       digitalWrite(LED, HIGH);
       LedState = HIGH;
    }
    else {
       digitalWrite(LED, LOW);
       LedState = LOW;
    }
    preMillis = curMillis;   
  }
  
  Cayenne.loop();
}

// This function is called when data is sent from Cayenne.
CAYENNE_IN(VIRTUAL_CHANNEL)
{
 float value = getValue.asInt(); // 0 to 255
  CAYENNE_LOG("Channel %d, pin %d, value %d", VIRTUAL_CHANNEL, ACTUATOR_PIN, value);
  // Write the value received to the PWM pin. analogWrite accepts a value from 0 to 255.
  analogWrite(ACTUATOR_PIN, value);
}

// You can also use functions for specific channels, e.g CAYENNE_OUT(1) for sending channel 1 data.
CAYENNE_OUT(VIRTUAL_CHANNEL)
{
  // Write data to Cayenne here. This example just sends the current uptime in milliseconds on virtual channel 0.
  Cayenne.virtualWrite(0, millis());
  // Some examples of other functions you can use to send data.
  //Cayenne.celsiusWrite(1, 22.0);
  //Cayenne.luxWrite(2, 700);
  //Cayenne.virtualWrite(3, 50, TYPE_PROXIMITY, UNIT_CENTIMETER);
}

// Default function for processing actuator commands from the Cayenne Dashboard.
// You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
  CAYENNE_LOG("Channel %u, value %s", request.channel, getValue.asString());
  //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

so what problem are facing beside delay. both the codes looks same. what changes you made?

The problem is that my technology is very low.
Because I am not treated as millis, it is difficult to correct sketch which is currently being used (delay) frequently.

Arduino I’m a beginner, even with IOT, Cayenne is a wonderful service.

I will study more so that I can master cayenne.

Thank you for your advice.

can you share the code you are having trouble with. i can try to help you out.

I have not been able to change existing sketches for cayenne yet.
I made an automatic fertilizer of hydroponic culture with Arduino.
I’d like to upload the value (loggingData ():wink: saved on the SD card in the sketch to cayenne. And I would like to be able to change the fertilizer concentration setting (ECvalu) from the Cayenne slider widget.

Thank you very much for your kind guidance.
Try changing sketch based on what you taught.

Here is the existing sketch.

#include <Wire.h>
#include "GravityRtc.h" 
#include <BH1750.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <OneWire.h>
//EC設定値
//トマト参考値 育苗期1.2 定植初期1.2-1.5 中期(交配期)1.2-1.8 収穫期~後期2.0-2.8
//X500 dil. HyponicaはEC 1.4程度だった
//設定可能範囲はEC1.1mS/cm以上から
//ECvalu=X-0.05 Xに設定したいEC値を入力 0.05は補正値
float ECvalu=1.3-0.05;

//補水量閾値以下カウント数格納
int WLvCt=0;
//補水量(一回分)
int W_add_vol=250;
//水位測定繰り返し回数
int WLvVar=0;
// EC閾値以下カウント数格納
int EC_val=0; 
//EC測定繰り返し回数
int ECvar=0;
//液肥追加量(一回分)
int F_add_vol=2;
//スイッチ設定
int P_pin = 7;   // Primeスイッチ入力ピン番号
int P_state = 0;   // Primeスイッチより取得したデータ格納用
int T_pin = 9;   // Testスイッチ入力ピン番号
int T_state = 0;   // Testスイッチより取得したデータ格納用

//EC設定
// # Connection:
// #        EC meter output     -> Analog pin 1
// #        DS18B20 digital pin -> Digital pin 2
// #


#define StartConvert 0
#define ReadTemperature 1

const byte numReadings = 20;     //the number of sample times
byte ECsensorPin = A1;  //EC Meter analog output,pin on analog 1
byte DS18B20_Pin = 2; //DS18B20 signal, pin on digital 2
unsigned int AnalogSampleInterval=25,printInterval=700,tempSampleInterval=850;  //analog sample interval;serial print interval;temperature sample interval
unsigned int readings[numReadings];      // the readings from the analog input
byte index = 0;                  // the index of the current reading
unsigned long AnalogValueTotal = 0;                  // the running total
unsigned int AnalogAverage = 0,averageVoltage=0;                // the average
unsigned long AnalogSampleTime,printTime,tempSampleTime;
float temperature,ECcurrent; 


//Temperature chip i/o
OneWire ds(DS18B20_Pin);  // on digital pin 2
float TempProcess(bool ch)
{
  //returns the temperature from one DS18B20 in DEG Celsius
  static byte data[12];
  static byte addr[8];
  static float TemperatureSum;
  if(!ch){
          if ( !ds.search(addr)) {
              Serial.println( F("no more sensors on chain, reset search!") );
              ds.reset_search();
              return 0;
          }      
          if ( OneWire::crc8( addr, 7) != addr[7]) {
              Serial.println( F("CRC is not valid!") );
              return 0;
          }        
          if ( addr[0] != 0x10 && addr[0] != 0x28) {
              Serial.print( F("Device is not recognized!") );
              return 0;
          }      
          ds.reset();
          ds.select(addr);
          ds.write(0x44,1); // start conversion, with parasite power on at the end
  }
  else{  
          byte present = ds.reset();
          ds.select(addr);    
          ds.write(0xBE); // Read Scratchpad            
          for (int i = 0; i < 9; i++) { // we need 9 bytes
            data[i] = ds.read();
          }         
          ds.reset_search();           
          byte MSB = data[1];
          byte LSB = data[0];        
          float tempRead = ((MSB << 8) | LSB); //using two's compliment
          TemperatureSum = tempRead / 16;
    }
          return TemperatureSum;  
}

//水位測定設定
const int WLvPin=8; 
int WLvVal = HIGH; //水位初期値

//SD設定
char timestamp[30];
const int chipSelect =4;         //pin for chipselect SD card
// Create a file to store the data
File dataFile;             

//モーター制御セットアップ

int WLv_motorPin = 10; // The pin connected to the transistor base
int WLv_Mvol=0; //モーターカウンター

 //EC-A調整モーター
int EC_A_motorPin = 5; // The pin connected to the transistor base
int EC_A_Mvol=0; //モーターカウンター


//RTC設定
GravityRtc rtc;     //RTC Initialization

//光センサーアドレス
BH1750 lightMeter(0x23); 
  int Lval=0; // lux値格納
  
  //LCT設定
  LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x3F for a 20 chars and 4 line display
  
  
  //Function 
  
   //EC測定
    void EC_mesure() {
    /*
     Every once in a while,sample the analog value and calculate the average.
  */
    if(millis()-AnalogSampleTime>=AnalogSampleInterval)  
  {
    AnalogSampleTime=millis();
     // subtract the last reading:
    AnalogValueTotal = AnalogValueTotal - readings[index];
    // read from the sensor:
    readings[index] = analogRead(ECsensorPin);
    // add the reading to the total:
    AnalogValueTotal = AnalogValueTotal + readings[index];
    // advance to the next position in the array:
    index = index + 1;
    // if we're at the end of the array...
    if (index >= numReadings)
    // ...wrap around to the beginning:
    index = 0;
    // calculate the average:
    AnalogAverage = AnalogValueTotal / numReadings;
  }
  /*
   Every once in a while,MCU read the temperature from the DS18B20 and then let the DS18B20 start the convert.
   Attention:The interval between start the convert and read the temperature should be greater than 750 millisecond,or the temperature is not accurate!
  */
   if(millis()-tempSampleTime>=tempSampleInterval) 
  {
    tempSampleTime=millis();
    temperature = TempProcess(ReadTemperature);  // read the current temperature from the  DS18B20
    TempProcess(StartConvert);                   //after the reading,start the convert for next reading
  }
   /*
   Every once in a while,print the information on the serial monitor.
  */
  if(millis()-printTime>=printInterval)
  {
    printTime=millis();
    averageVoltage=AnalogAverage*(float)5000/1024;
    
    float TempCoefficient=1.0+0.0185*(temperature-25.0);    //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.0185*(fTP-25.0));
    float CoefficientVolatge=(float)averageVoltage/TempCoefficient;   
    if(CoefficientVolatge<150)Serial.println( F("No solution!") );   //25^C 1413us/cm<-->about 216mv  if the voltage(compensate)<150,that is <1ms/cm,out of the range
    else if(CoefficientVolatge>3300)Serial.println( F("Out of the range!") );  //>20ms/cm,out of the range
    else
    { 
      if(CoefficientVolatge<=448)ECcurrent=6.84*CoefficientVolatge-64.32;   //1ms/cm<EC<=3ms/cm
      else if(CoefficientVolatge<=1457)ECcurrent=6.98*CoefficientVolatge-127;  //3ms/cm<EC<=10ms/cm
      else ECcurrent=5.3*CoefficientVolatge+2278;                           //10ms/cm<EC<20ms/cm
      ECcurrent/=1000;    //convert us/cm to ms/cm
      Serial.print(ECcurrent,2);  //two decimal
      Serial.println( F("ms/cm") );
    }
  }
if (ECcurrent < ECvalu){
EC_val++; //ECが指定値より低かった回数をカウント
}
else{
EC_val =0; //EC_valリセット
}
}
/*
ch=0,let the DS18B20 start the convert;ch=1,MCU read the current temperature from the DS18B20.
*/

  //水位測定
  void WLv_mesure() {
   //read the switch value into a variable
 WLvVal = digitalRead(WLvPin);
  //print out the value of the liquid level
  Serial.println(WLvVal);
  if (WLvVal== LOW){
  WLvCt++; //水位が指定値より低かった回数をカウント
}
else{
WLvCt =0; //WLvCtリセット
}
  }
   //LCDへ測定結果を表示
  void LCD()
  {
    rtc.read();
    lcd.clear();
    lcd.print(rtc.year);
    lcd.print( F("/") );
    lcd.print(rtc.month);
    lcd.print( F("/") );
    lcd.print(rtc.day);
    lcd.print(" ");
    lcd.print(rtc.hour);
    lcd.print( F(":") );
    lcd.print(rtc.minute);
    lcd.print( F(":") );
    lcd.print(rtc.second);
    lcd.setCursor(0,1);
    lcd.print( F("EC: ") );
    lcd.print(ECcurrent,2);
    lcd.print( F("ms/cm") );
    lcd.setCursor(0,2); 
    lcd.print( F("Temp:  ") );
    lcd.print(temperature);
    lcd.print( F(" ^C ") );
    lcd.setCursor(0,3); 
    lcd.print( F("Lux:  ") );
    lcd.print(Lval); 
    lcd.print(" ");
    lcd.print( F("Low: ") );
    lcd.print(WLvCt); 
    lcd.print(" ");
    lcd.print( EC_val); 
          }
      
   void Lux_mesure(){ //Lux測定テンプレート
   uint16_t lux = lightMeter.readLightLevel();
   Lval=lux*2;
   }

// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
 rtc.read();
 sprintf(timestamp, "%02d:%02d:%02d %2d/%2d/%2d \n", rtc.hour,rtc.minute,rtc.second,rtc.month,rtc.day,rtc.year-2000);
 Serial.println("yy");
 Serial.println(timestamp);
 // return date using FAT_DATE macro to format fields
 *date = FAT_DATE(rtc.year, rtc.month, rtc.day);

 // return time using FAT_TIME macro to format fields
 *time = FAT_TIME(rtc.hour, rtc.minute, rtc.second);
}
   
 //SD使用中警告
  void SDalert()
  {
    lcd.clear();
    lcd.print( F("The SD card is busy.") );
    lcd.setCursor(0,1);
    lcd.print( F("Do not turn off ") );
    lcd.setCursor(0,2); 
    lcd.print( F("the power or ") );
    lcd.setCursor(0,3); 
    lcd.print( F("remove the SD card.") );
          }
//データ保存タイムスタンプ
void loggingTime() {
  rtc.read();
  SDalert();
  dataFile=SD.open(( F("datalog.csv") ) , FILE_WRITE);
  if (dataFile) {
  dataFile.print(rtc.year);
  dataFile.print( F("/") );
  dataFile.print(rtc.month);
  dataFile.print( F("/") );
  dataFile.print(rtc.day);
  dataFile.print(", ");
  dataFile.print(rtc.hour);
  dataFile.print( F(":") );
  dataFile.print(rtc.minute);
  dataFile.print( F(":") );
  dataFile.print(rtc.second);
  dataFile.print(", ");
  }
  dataFile.close();
  delay(1000);  
}
 //データ保存
   void loggingData() {
        dataFile=SD.open(( F("datalog.csv") ) , FILE_WRITE);    
        if (dataFile) {
        dataFile.print( F("Date Log: ") );
        dataFile.print(", ");
        dataFile.print( F("EC: ") );
        dataFile.print(", ");
        dataFile.print(ECcurrent,2);
        dataFile.print(", ");
        dataFile.print( F("ms/cm") );
        dataFile.print(", ");
        dataFile.print( F("temp:") );
        dataFile.print(", ");
        dataFile.print(temperature);  
        dataFile.print(", ");
        dataFile.print( F("^C ") );
        dataFile.print(", ");
        dataFile.print( F("Light: ") );
        dataFile.print(", ");
        dataFile.print(Lval);
        dataFile.print(", ");
        dataFile.print( F("lx") );
        dataFile.print(", ");
        dataFile.print( F("Water level: ") );
        dataFile.print(", ");
        dataFile.print(WLvVal);
        dataFile.println(",");
       }
        dataFile.close();
        delay(3000);
        LCD();
        
}

//水位 EC調整
void Adjust_WLv_EC()
{

  for (WLvVar=0; WLvVar <= 10; WLvVar++){
    WLv_mesure();
    delay(3000);
   }
  while
    (WLvVal ==  LOW && WLv_Mvol < 4 && WLvCt > 5 ){ //指定水位以下で、添加数4回以下 のときかつ5回水位が閾値を下回ったとき
    digitalWrite(WLv_motorPin,LOW);
    delay(W_add_vol*844UL); //1mL添加に844msec 
    digitalWrite(WLv_motorPin,HIGH);
    WLv_Mvol++; //モーターを回したら、添加数+1
    delay(3000); //3秒安定化させる
    //WLv 次回ループのための測定(10回)
     for (WLvVar=0; WLvVar <= 10; WLvVar++){
    WLv_mesure();
    delay(3000);
   }
    }
     //補水量SD保存 
    if (WLv_Mvol!=0){
  loggingTime();
  dataFile=SD.open(( F("datalog.csv") ) , FILE_WRITE);    
        if (dataFile) {
        dataFile.print( F("Action Log: ") );
        dataFile.print(", ");
        dataFile.print( F("Add") );
        dataFile.print(", ");
        dataFile.print(WLv_Mvol*W_add_vol);
        dataFile.print(", ");
        dataFile.print( F("mL of water, ") );
        dataFile.println(",");
       }
        dataFile.close();
        delay(3000);
        LCD();
  
    WLv_Mvol =0; //モータカウントリセット
    delay(3000);
}
    
    for (ECvar=0; ECvar <= 10; ECvar++){
    EC_mesure(); 
    delay(3000);
   }
     while
    (ECcurrent < ECvalu && EC_A_Mvol < 5 && EC_val > 5 ){ //EC指定値以下の時(333倍希釈ハイポニカのEC値が1.2)で、添加数5回以下かつ5回ECが閾値を下回ったとき
    digitalWrite(EC_A_motorPin ,LOW);
    delay(F_add_vol*4191UL); //1mL添加に4191msec 
    digitalWrite(EC_A_motorPin,HIGH);
    EC_A_Mvol++; //モーターを回したら、添加数+1
    delay(900000UL); //15分安定化させる
   //WLv 次回ループのための測定(10回)
    for (ECvar=0; ECvar <= 10; ECvar++){
    EC_mesure(); 
    delay(3000);
   }
    }
  //Hyponica添加量SD保存  
    if ( EC_A_Mvol!=0){
        loggingTime();
        dataFile=SD.open(( F("datalog.csv") ) , FILE_WRITE);    
        if (dataFile) {
        dataFile.print( F("Action Log: ") );
        dataFile.print(", ");
        dataFile.print( F("Add") );
        dataFile.print(", ");
        dataFile.print(EC_A_Mvol*F_add_vol);
        dataFile.print(", ");
        dataFile.print( F("mL of x500 Hyponica, ") );
        dataFile.println(",");
       }
        dataFile.close();
        delay(3000);
        LCD();
  
     EC_A_Mvol =0; //モータカウントリセット
    delay(300);
}
    }

    
void setup() {

//LCDセットアップ
  // initialize the LCD
  lcd.begin();
  lcd.backlight();

//モーターピン初期値
pinMode(WLv_motorPin, OUTPUT);
digitalWrite(WLv_motorPin, HIGH);
pinMode(EC_A_motorPin, OUTPUT);
digitalWrite(EC_A_motorPin, HIGH);

//スイッチセットアップ
  pinMode(P_pin, INPUT);     // ボタンスイッチ用に入力に設定    
  pinMode(T_pin, INPUT);     // ボタンスイッチ用に入力に設定   

 //ECセットアップ
 // initialize serial communication with computer:
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (byte thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;
  TempProcess(StartConvert);   //let the DS18B20 start the convert
  AnalogSampleTime=millis();
  printTime=millis();
  tempSampleTime=millis();

//水位測定 セットアップ
  pinMode(WLvPin, INPUT);

//RCTセットアップ
rtc.setup();

//rtc.adjustRtcが有効になっていると、Arduino再起動時に時間がコンパイル時に戻ってしまうためコメントアウト
  //Set the RTC time automatically: Calibrate RTC time by your computer time
  //rtc.adjustRtc(F(__DATE__), F(__TIME__)); 
  
  //Set the RTC time manually
  //rtc.adjustRtc(2017,6,19,1,12,7,0);  //Set time: 2017/6/19, Monday, 12:07:00
     

//光センサーセットアップ
  // Initialize the I2C bus (BH1750 library doesn't do this automatically)
  Wire.begin();
  lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);

//センサテスト
 T_state = digitalRead(T_pin);  // ピンよりデータ取得
 
   
 while(T_state==1)
 {
WLv_mesure();
EC_mesure();
Lux_mesure();
LCD();

delay(3000);
T_state = digitalRead(T_pin); 
  }

// set date time callback function(SD time stamp)
 SdFile::dateTimeCallback(dateTime);
  rtc.read();
  sprintf(timestamp, "%02d:%02d:%02d %2d/%2d/%2d \n", rtc.hour,rtc.minute,rtc.second,rtc.month,rtc.day,rtc.year-2000);
  Serial.println("xx");
  Serial.println(timestamp);

//SD セットアップ
SDalert();
// setup for the SD card
  Serial.print( F("Initializing SD card...") );

  while(!SD.begin(chipSelect)) {
    Serial.println( F("initialization failed!") );
    lcd.clear();
    lcd.print( F("SD initialization") );
    lcd.setCursor(0,1);
    lcd.print( F("failed! ") );
    lcd.setCursor(0,2);
    lcd.print( F("Please check the SD") );
    lcd.setCursor(0,3);
    lcd.print( F("and reboot the syst.") );
    delay(5000);
     }
  Serial.println( F("initialization done.") );
    
  //reboot log
  loggingTime();
  dataFile=SD.open(( F("datalog.csv") ) , FILE_WRITE);    
        if (dataFile) {
        dataFile.print( F("Reboot Log: ") );
        dataFile.print(", ");
        dataFile.print( F("File opened ok") );
        dataFile.println(",");
        lcd.clear();
        lcd.print( F("SD File opened ok") );
       }
        dataFile.close();
        delay(5000);

  
//ポンププライミング
 P_state = digitalRead(P_pin);  // ピンよりデータ取得
 
   
 if(P_state==1)
 {
    digitalWrite(WLv_motorPin, LOW);
    delay(60000UL);
    digitalWrite(WLv_motorPin,HIGH);
    digitalWrite(EC_A_motorPin , LOW);
    delay(10000UL); 
    digitalWrite(EC_A_motorPin,HIGH);
    delay(60000UL);

 
  }
 }
 
  
  // put your setup code here, to run once:


void loop() {
 //測定
 WLv_mesure();
 EC_mesure();
 Lux_mesure();
 LCD();
 //記録
 loggingTime();
 loggingData();
 //補正
 Adjust_WLv_EC();
  //測定
 WLv_mesure();
 EC_mesure();
 Lux_mesure();
 LCD();
  //記録
 loggingTime();
 loggingData();
delay(900000UL);//15分間隔
  
}

@negishi_s0904 you are doing all this once in 15 minutes? so only a small change is required. just make sure that there is no infinite blockage in the main loop.

unsigned long lastmillis1 = 0;

 void loop(){
  Cayenne.loop();
  if (millis() - lastmillis1 > 900000) {
 //測定
 WLv_mesure();
 EC_mesure();
 Lux_mesure();
 LCD();
 //記録
 loggingTime();
 loggingData();
 //補正
 Adjust_WLv_EC();
  //測定
 WLv_mesure();
 EC_mesure();
 Lux_mesure();
 LCD();
  //記録
 loggingTime();
 loggingData();
    lastmillis1 = millis();
  }
}

Thank you for editing sketch.
Yes, I would like to run this sketch once every 15 minutes.
The function in the loop (for example, Adjust_WLv_EC ()) still contains “delay”, but is it correct as it is?

I am inserting “delay” to stabilize the sensor value, move the specified time motor according to the sensor value, and connect the two functions stably and operate.

what are you doing with this code?

Thank you for your reply.
In the above code, since the reading value of the sensor is blurred, I do not increase the amount of fertilizer addition too much.
Specifically, sensor reading is done 10 times every 3 seconds, and fertilizer is added by the motor when the value falls below the set value 5 times.
When the sensor reading value exceeds the set value, the number of times that it falls below the set value using the code of “EC_mesure ()” function is reset to 0.

Then, using “while”, measurement and fertilizer addition are repeated until the fertilizer concentration exceeds the set value, but the number of additions is set to a maximum of 5 times so that fertilizer is not added too much at once.
After adding the fertilizer with the motor, it takes time until the fertilizer concentration in the aquarium becomes constant, so we wait for the next measurement for 15 minutes.

what i would do:

if (millis() - lastmillis >  900000) // do this every 15 minutes
{
lastmillis = millis();
 // read concentration sensor measurent 
 if ( sensor value < set value)
{
//turn on motor 
delay();
//turn off motor
}
}