Switching a relay on and off using "millis()" without interfering with the runtime of the other piece of code

Turning on a relay 5 seconds after the analog voltage is read from the analog pin, and closing it again 5 seconds after opening it, but while doing this, it should not interfere with the operation of the other code. I wanted to use "millis ( )" for this but failed. Everything works fine but the relay opens immediately before 5 seconds is up but the closing time is correct.
note:(the working method is like a momentary button. The voltage is not constantly on the arduino)
The code is as follows.

#include <SPI.h>
#include "SdFat.h"
#include "RTClib.h"
#include "HX711.h"//XFW-HX711 amplifier 80Hz


#define calibration_factor -7090.0 
int LOADCELL_DOUT_PIN = 7;
int LOADCELL_SCK_PIN = 6;

int LOADCELL_DOUT_PIN_1 = 5;
int LOADCELL_SCK_PIN_1 = 4;                     

int LOADCELL_DOUT_PIN_2 = 3;
int LOADCELL_SCK_PIN_2 = 2;
HX711 scale;
HX711 scale1;
HX711 scale2;
int navoser;
int sensorPin = A0;        
int relay1 = 8;
int relay2 = 9;

unsigned long previousMillis = 0;
long OnTime = 5000;
long OffTime = 500;
int relay2State = LOW;
boolean alreadyRun = false;

int sensorValue = 0;
float voltage;
RTC_DS1307 RTC;//using RTClib
DateTime now;

bool enableDataLogging = false;
String receivedChar;
boolean newData = false;

const uint8_t chipSelect = 10;



const uint32_t SAMPLE_INTERVAL_MS = 1;



#define FILE_BASE_NAME "Result"  
#define error(msg) sd.errorHalt(F(msg))
//------------------------------------------------------------------------------

SdFat sd;

SdFile file;// Log file.

uint32_t logTime;

//==============================================================================


int Date_count = 1;
int Time_count = 1;
int Load_Cell1 = 1;
int Load_Cell2 = 1;
int Load_Cell3 = 1;
//------------------------------------------------------------------------------

void load_cell () {

  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.print("t3.txt=");
  Serial.write(0x22);
  Serial.print(scale.get_units(), 1);
  Serial.write(0x22);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.print("t4.txt=");
  Serial.write(0x22);
  Serial.print(scale1.get_units(), 1);
  Serial.write(0x22);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.print("t5.txt=");
  Serial.write(0x22);
  Serial.print(scale2.get_units(), 1);
  Serial.write(0x22);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  navoser = (scale.get_units() + scale1.get_units() + scale2.get_units() / 3);
  Serial.print("t8.txt=");
  Serial.write(0x22);
  Serial.print(navoser);
  Serial.write(0x22);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);





  /*
    Serial.print("Reading: ");
    Serial.print(scale.get_units(), 1);
    // Serial.print(" kg");
    Serial.print("\t");
    Serial.print(scale1.get_units(), 1);
    Serial.print("\t");
    Serial.print(scale2.get_units(), 1);
    Serial.print(" kg");
    Serial.println();
  */

}


void setup() {
  pinMode(sensorPin, INPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  Serial.begin(9600);//

  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  scale1.begin(LOADCELL_DOUT_PIN_1, LOADCELL_SCK_PIN_1);
  scale2.begin(LOADCELL_DOUT_PIN_2, LOADCELL_SCK_PIN_2);

  scale.set_scale(calibration_factor);
  scale.tare();

  scale1.set_scale(calibration_factor);
  scale1.tare();

  scale2.set_scale(calibration_factor);
  scale2.tare();


  RTC.begin();


}
void creat_file() {
  const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
  char fileName[13] = FILE_BASE_NAME "00.csv";
  if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
    sd.initErrorHalt();
  }

  // Find an unused file name.

  if (BASE_NAME_SIZE > 7) {
    error("FILE_BASE_NAME long");
  }
  while (sd.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } else {
      error("filename not created");
    }
  }
  if (!file.open(fileName, O_WRONLY | O_CREAT | O_EXCL)) {
    error("file.open");
  }
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.print("page 4");
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.print("g1.txt=");
  Serial.write(0x22);
  Serial.print(fileName);
  Serial.write(0x22);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

  //Serial.print(F("Recording: "));
  //Serial.println(fileName);
  //Serial.println(F("enter any character to stop"));
  writeHeader();

}
//------------------------------------------------------------------------------
void loop() {

  recvOneChar();   
  useNewData();    
  if (enableDataLogging) {

    logTime += SAMPLE_INTERVAL_MS;
    logData();


    if (!file.sync() || file.getWriteError()) {
      error("error write");
    }
  } else {
    load_cell();
  }
}
void recvOneChar()  
{

  sensorValue = analogRead(sensorPin);
  voltage = sensorValue * (5.0 / 1023.0);
  if (Serial.available() > 0 || voltage > 2 ) { 
    receivedChar = Serial.readStringUntil('#');  


    newData = true;   

  }
}//recvOneChar
void useNewData()
{
  if (newData == true)
  {
    //Serial.print("This just in ... ");
    Serial.println(receivedChar);

    if (receivedChar.indexOf("2") > -1 || voltage > 2 )
    {
      creat_file(); 
      enableDataLogging = true;
      
      //Serial.println("Data logging enabled");
      //digitalWrite(LED_BUILTIN, HIGH);
    }
    if (receivedChar.indexOf("5") > -1)
    {
      enableDataLogging = false;
      //Serial.println("   Data logging disabled");
      //digitalWrite(LED_BUILTIN, LOW);

      if (file) file.close();
      //SysCall::halt();
    }
    newData = false;
  }
}//useNewData


void writeHeader() {

  file.print(F("time(us)"));
  for (int c = 0; c < Load_Cell1; c++) {
    file.print(F(",load1"));
    //file.print(c, DEC);
  } for (int d = 0; d < Load_Cell2; d++) {
    file.print(F(",load2"));
    //file.print(d, DEC);
  } for (int e = 0; e < Load_Cell3; e++) {
    file.print(F(",load3"));
    //file.print(e, DEC);
  }
  for (int a = 0; a < Date_count; a++) {
    now = RTC.now();
    file.print(F(",date:"));
    file.print(now.day(), DEC);
    file.print('/');
    file.print(now.month(), DEC);
    file.print('/');
    file.print(now.year(), DEC);

  } for (int b = 0; b < Time_count; b++) {
    file.print(F(",time(hour-minute-second)"));

  }
  file.println();
}
//------------------------------------------------------------------------------


void logData() {

  file.print(logTime);
  for (int c = 0; c < Load_Cell1; c++) {
    file.write(',');
    file.print(scale.get_units());
  } for (int d = 0; d < Load_Cell2; d++) {
    file.write(',');
    file.print(scale1.get_units());
  } for (int e = 0; e < Load_Cell3; e++) {
    file.write(',');
    file.print(scale2.get_units());//file.print(scale2.get_units(),DEC);
  }
  for (int a = 0; a < Date_count; a++) {
    file.write(',');
    //file.print("test");
  } for (int b = 0; b < Time_count; b++) {
    file.write(',');
    file.print(now.hour(), DEC);
    file.print(":");
    file.print(now.minute(), DEC);
    file.print(":");
    file.print(now.second(), DEC);
    file.print(":");
    file.print(micros(), DEC);
  }
  file.println();
relay ();
}
//==============================================================================
void relay () {
  if(alreadyRun==false){
  unsigned long currentMillis = millis();
  if ((relay2State == LOW) && (currentMillis - previousMillis >= OnTime) ) {

    relay2State = HIGH;  // Turn it off
    previousMillis = currentMillis;  // Remember the time
    digitalWrite(relay2, relay2State);  // Update the actual LED
  }
  else if ((relay2State == HIGH) && (currentMillis - previousMillis >= OffTime) ) {

    relay2State = LOW;  // Turn it off
    previousMillis = currentMillis;  // Remember the time
    digitalWrite(relay2, relay2State);  // Update the actual LED
    alreadyRun = true;
  }
  }
}


please help a little with this
every opinion given is worthy of respect

I believe you posted your question in the wrong forum section.

You could ask a mod to move it for you.

sorry.yes, thank you wrong section

You should make the following unsigned long. Also, didn't you want both the on and off times to be 5 seconds?

long OnTime = 5000;
long OffTime = 500;

You initialize alreadyRun to false. Then you set it to true when you turn the relay off. However, you never set alreadyRun back to false and therefore the following code only gets executed once!

  if (alreadyRun == false) {
    unsigned long currentMillis = millis();
    if ((relay2State == LOW) && (currentMillis - previousMillis >= OnTime) ) {

      relay2State = HIGH;  // Turn it off
      previousMillis = currentMillis;  // Remember the time
      digitalWrite(relay2, relay2State);  // Update the actual LED
    }
    else if ((relay2State == HIGH) && (currentMillis - previousMillis >= OffTime) ) {

      relay2State = LOW;  // Turn it off
      previousMillis = currentMillis;  // Remember the time
      digitalWrite(relay2, relay2State);  // Update the actual LED
      alreadyRun = true;
    }
  }

I want the relay to work once. When the voltage comes, the whole program starts running and after 5 seconds the relay goes "high". After being on for 5 seconds, it becomes “LOW” again and the relay ends, but the other program continues to run. If recording ends and re-recording is started, relays have to repeat the set task 1 time. I need help to make it work this way.

Also, I don't fully understand your suggestion.
Could you please explain a little more?``

unsigned long OnTime = 5000;
unsgined long OffTime = 5000;

I set it like this, still nothing changed

If none of the sketch hogs cycles, no delay()s or loops that run much longer than a default analog read (105 micros) will give you smooth responsive automation and the ability to write co-operative tasks.

  • Each task can be made into a function.
  • Each function runs in void loop() every time that void loop() runs even if just to check trigger conditions to run the rest or (most often) not.

Write tasks for inputs that read them and update status and messages in RAM for other tasks to read. My contact switch button task handles the button only, it makes it easier to swap with other inputs like capacitive touch or handling a button matrix one button per void loop() cycle. Collect tasks to read inputs to use in future code.

Write output tasks to handle different outputs for the same reasons.

Write process tasks to read sensor/input status and data and decide what to do, all that do something code. Write process tasks that control other process tasks rather than having a bigger block of code do everything and your code will be more flexible, easier to change.

unsigned long msStart, msLength;

//..... snip

// a 1-shot timed trigger task
  if ( msLength > 0 )
  {
    if ( millis() - msStart >= msLength )
    {
      // do something ------- the wait is over, a led blinker toggles the pin
      msLength = 0;     // finished
    }
    else
    {
      // perhaps check for a halt signal to act on right up to the blink?
    }
  }
// end of timed trigger

Here is a task that tells you how fast your sketch is running as void loop()s per second.
Copy the #define, the function and the line in loop() that runs it. Light work should run loop() at 67KHz. The counter is like a sketch response meter.

// add-a-sketch_loop_counter 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 29/2018 by GFS. Compiled on Arduino IDE 1.6.9.
// This sketch counts times that loop has run each second and prints it.
// It uses the void LoopCounter() function that does not block other code.

#define microsInOneSecond 1000000UL

void setup()
{
  Serial.begin( 115200 );
  Serial.println( F( "\n\n\n  Loop Counter, free by GoForSmoke\n" ));
  Serial.println( F( "This sketch counts times that loop has run each second and prints it." ));
}

void LoopCounter() // tells the average response speed of void loop()
{ // inside a function, static variables keep their value from run to run
  static unsigned long count, countStartMicros; // only this function sees these

  count++; // adds 1 to count after any use in an expression, here it just adds 1.
  if ( micros() - countStartMicros >= microsInOneSecond ) // 1 second
  {
    countStartMicros += microsInOneSecond; // for a regular second
    Serial.println( count ); // 32-bit binary into decimal text = many micros
    count = 0; // don't forget to reset the counter 
  }
}

void loop()  // runs over and over, see how often with LoopCounter()
{
  LoopCounter(); // the function runs as a task, the optimizer will inline the code.
}

mr. GoForSmoke
With analog reading, other code parts of the program other than the relays work. Analog voltage can be read without problems, this analog readout acts as a button.

Thanks for your suggestion. But .I don't quite understand how to implement your suggestion.

Here is a sketch that uses a finite state machine with a timer in front to blink leds without blocking as a dead-simple demo task.

The state machine is a technique to let the same function act differently according to conditions. Between state machines and timers you can automate most things.

// add-a-sketch_un-delay 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 30/18 by GFS. Compiled on Arduino IDE 1.6.9.
// This sketch shows a general method to get rid of delays in code.
// You could upgrade code with delays to work with add-a-sketch.

#include <avr/io.h>
#include "Arduino.h"

const byte ledPin = 13;
unsigned long delayStart, delayWait;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( F( "\n\n\n  Un-Delay Example, free by GoForSmoke\n" ));
  Serial.println( F( "This sketch shows how to get rid of delays in code.\n" ));

  pinMode( ledPin, OUTPUT );
};


/* The section of the original sketch with delays:
 * 
 * digitalWrite( ledPin, HIGH );   --  0
 * delay( 500 );
 * digitalWrite( ledPin, LOW );    --  1
 * delay( 250 );
 * digitalWrite( ledPin, HIGH );   --  2
 * delay( 250 );
 * digitalWrite( ledPin, LOW );    --  3
 * delay( 250 );
 * digitalWrite( ledPin, HIGH );   --  4
 * delay( 1000 );
 * digitalWrite( ledPin, LOW );    --  5
 * delay( 1000 );
 */

byte blinkStep; // state tracking for BlinkPattern() below

void BlinkPattern()
{
  // This one-shot timer replaces every delay() removed in one spot.  
  // start of one-shot timer
  if ( delayWait > 0 ) // one-shot timer only runs when set
  {
    if ( millis() - delayStart < delayWait )
    {
      return; // instead of blocking, the undelayed function returns
    }
    else
    {
      delayWait = 0; // time's up! turn off the timer and run the blinkStep case
    }
  }
  // end of one-shot timer

  // here each case has a timed wait but cases could change Step on pin or serial events.
  switch( blinkStep )  // runs the case numbered in blinkStep
  {
    case 0 :
    digitalWrite( ledPin, HIGH );
    Serial.println( F( "Case 0 doing something unspecified here at " ));
    Serial.println( delayStart = millis()); // able to set a var to a value I pass to function
    delayWait = 500; // for the next half second, this function will return on entry.
    blinkStep = 1;   // when the switch-case runs again it will be case 1 that runs
    break; // exit switch-case

    case 1 :
    digitalWrite( ledPin, LOW );
    Serial.println( F( "Case 1 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 250;
    blinkStep = 2;
    break;

    case 2 :
    digitalWrite( ledPin, HIGH );
    Serial.println( F( "Case 2 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 250;
    blinkStep = 3;
    break;

    case 3 :
    digitalWrite( ledPin, LOW );
    Serial.println( F( "Case 3 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 250;
    blinkStep = 4;
    break;

    case 4 :
    digitalWrite( ledPin, HIGH );
    Serial.println( F( "Case 4 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 1000;
    blinkStep = 5;
    break;

    case 5 :
    digitalWrite( ledPin, LOW );
    Serial.print( F( "Case 5 doing something unspecified here at " ));
    Serial.println( delayStart = millis());
    delayWait = 1000;
    blinkStep = 0;
    break;
  }
}


void loop()  // runs over and over, see how often
{            
  BlinkPattern();
}

I can't say that I fully understand how this could be implemented as well.
Could you please explain a little more about this.

It takes 105 micros to get a default analog read, according to the datasheet.
That is a tiny bit of time but very long compared to a digital read.

I have no problems with this, I can start other loops of the code with analog reading. The voltage is waiting for a certain time on the analog pin, so I don't think it will be a problem.

Maybe have a look at this. It may not compile; I don't have all your libs and didn't feel like downloading them. But if it doesn't it might still give you an idea or two:

#include <SPI.h>
#include "SdFat.h"
#include "RTClib.h"
#include "HX711.h"//XFW-HX711 amplifier 80Hz

//"Turning on a relay 5 seconds after the analog voltage is read from the 
//analog pin, and closing it again 5 seconds after opening it
#define K_RELAY_DELAY_TIME  5000ul
#define K_RELAY_HOLD_TIME   5000ul
typedef enum
{
    RLY_IDLE=0,
    RLY_DELAY,
    RLY_HOLD
    
}e_statesRelay_t;

#define calibration_factor -7090.0 
int LOADCELL_DOUT_PIN = 7;
int LOADCELL_SCK_PIN = 6;

int LOADCELL_DOUT_PIN_1 = 5;
int LOADCELL_SCK_PIN_1 = 4;                     

int LOADCELL_DOUT_PIN_2 = 3;
int LOADCELL_SCK_PIN_2 = 2;
HX711 scale;
HX711 scale1;
HX711 scale2;
int navoser;
int sensorPin = A0;        
int relay1 = 8;
int relay2 = 9;

unsigned long previousMillis = 0;
long OnTime = 5000;
long OffTime = 500;
int relay2State = LOW;
boolean bRelay = false;

int sensorValue = 0;
float voltage;
RTC_DS1307 RTC;//using RTClib
DateTime now;

bool enableDataLogging = false;
String receivedChar;
boolean newData = false;

const uint8_t chipSelect = 10;



const uint32_t SAMPLE_INTERVAL_MS = 1;



#define FILE_BASE_NAME "Result"  
#define error(msg) sd.errorHalt(F(msg))
//------------------------------------------------------------------------------

SdFat sd;

SdFile file;// Log file.

uint32_t logTime;

//==============================================================================


int Date_count = 1;
int Time_count = 1;
int Load_Cell1 = 1;
int Load_Cell2 = 1;
int Load_Cell3 = 1;
//------------------------------------------------------------------------------

void load_cell () 
{
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.print("t3.txt=");
    Serial.write(0x22);
    Serial.print(scale.get_units(), 1);
    Serial.write(0x22);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.print("t4.txt=");
    Serial.write(0x22);
    Serial.print(scale1.get_units(), 1);
    Serial.write(0x22);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.print("t5.txt=");
    Serial.write(0x22);
    Serial.print(scale2.get_units(), 1);
    Serial.write(0x22);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    navoser = (scale.get_units() + scale1.get_units() + scale2.get_units() / 3);
    Serial.print("t8.txt=");
    Serial.write(0x22);
    Serial.print(navoser);
    Serial.write(0x22);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);

  /*
    Serial.print("Reading: ");
    Serial.print(scale.get_units(), 1);
    // Serial.print(" kg");
    Serial.print("\t");
    Serial.print(scale1.get_units(), 1);
    Serial.print("\t");
    Serial.print(scale2.get_units(), 1);
    Serial.print(" kg");
    Serial.println();
  */

}//load_cell

void setup() 
{
    pinMode(sensorPin, INPUT);
    pinMode(relay1, OUTPUT);
    pinMode(relay2, OUTPUT);
    Serial.begin(9600);//
    
    scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
    scale1.begin(LOADCELL_DOUT_PIN_1, LOADCELL_SCK_PIN_1);
    scale2.begin(LOADCELL_DOUT_PIN_2, LOADCELL_SCK_PIN_2);
    
    scale.set_scale(calibration_factor);
    scale.tare();
    
    scale1.set_scale(calibration_factor);
    scale1.tare();
    
    scale2.set_scale(calibration_factor);
    scale2.tare();
    
    
    RTC.begin();

}//setup

void creat_file() 
{
    const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
    char fileName[13] = FILE_BASE_NAME "00.csv";
    if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) 
    {
        sd.initErrorHalt();
    }
    
    // Find an unused file name.
    
    if (BASE_NAME_SIZE > 7) 
    {
        error("FILE_BASE_NAME long");
    }
    while (sd.exists(fileName)) 
    {
        if (fileName[BASE_NAME_SIZE + 1] != '9') 
        {
            fileName[BASE_NAME_SIZE + 1]++;
        } 
        else if (fileName[BASE_NAME_SIZE] != '9') 
        {
            fileName[BASE_NAME_SIZE + 1] = '0';
            fileName[BASE_NAME_SIZE]++;
        } 
        else 
        {
            error("filename not created");
        }
    }
    
    if (!file.open(fileName, O_WRONLY | O_CREAT | O_EXCL)) 
    {
        error("file.open");
    }
    
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.print("page 4");
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.print("g1.txt=");
    Serial.write(0x22);
    Serial.print(fileName);
    Serial.write(0x22);
    Serial.write(0xff);
    Serial.write(0xff);
    Serial.write(0xff);
    
    //Serial.print(F("Recording: "));
    //Serial.println(fileName);
    //Serial.println(F("enter any character to stop"));
    writeHeader();

}//creat_file

//------------------------------------------------------------------------------
void loop() 
{
    recvOneChar();   
    useNewData();
    relay();    
    if (enableDataLogging) 
    {
        logTime += SAMPLE_INTERVAL_MS;
        logData();

        if (!file.sync() || file.getWriteError()) 
        {
            error("error write");
        }
    } 
    else 
    {
        load_cell();
    }
    
}//loop

void recvOneChar()  
{
    sensorValue = analogRead(sensorPin);
    voltage = sensorValue * (5.0 / 1023.0);
    if (Serial.available() > 0 || voltage > 2 ) 
    { 
        receivedChar = Serial.readStringUntil('#');      
        newData = true; 

        bRelay = true;  //...after the analog voltage is read from the analog pin...
    }
    
}//recvOneChar

void useNewData()
{
    if (newData == true)
    {
        //Serial.print("This just in ... ");
        Serial.println(receivedChar);
        
        if (receivedChar.indexOf("2") > -1 || voltage > 2 )
        {
            creat_file(); 
            enableDataLogging = true;
            
            //Serial.println("Data logging enabled");
            //digitalWrite(LED_BUILTIN, HIGH);
        }
        if (receivedChar.indexOf("5") > -1)
        {
            enableDataLogging = false;
            //Serial.println("   Data logging disabled");
            //digitalWrite(LED_BUILTIN, LOW);
            
            if (file) 
                file.close();
                
            //SysCall::halt();
        }
        
        newData = false;
        
    }
    
}//useNewData


void writeHeader() 
{
    file.print(F("time(us)"));
    for (int c = 0; c < Load_Cell1; c++) 
    {
        file.print(F(",load1"));
        //file.print(c, DEC);
    } 
    
    for (int d = 0; d < Load_Cell2; d++) 
    {
        file.print(F(",load2"));
        //file.print(d, DEC);
    } 
    
    for (int e = 0; e < Load_Cell3; e++) 
    {
        file.print(F(",load3"));
        //file.print(e, DEC);
    }
    
    for (int a = 0; a < Date_count; a++) 
    {
        now = RTC.now();
        file.print(F(",date:"));
        file.print(now.day(), DEC);
        file.print('/');
        file.print(now.month(), DEC);
        file.print('/');
        file.print(now.year(), DEC);
    
    } 
    
    for (int b = 0; b < Time_count; b++) 
    {
        file.print(F(",time(hour-minute-second)"));
    
    }
    
    file.println();
    
}//writeHeader
//------------------------------------------------------------------------------


void logData() 
{
    file.print(logTime);
    for (int c = 0; c < Load_Cell1; c++) 
    {
        file.write(',');
        file.print(scale.get_units());
    } 
    
    for (int d = 0; d < Load_Cell2; d++) 
    {
        file.write(',');
        file.print(scale1.get_units());
    } 
    
    for (int e = 0; e < Load_Cell3; e++) 
    {
        file.write(',');
        file.print(scale2.get_units());//file.print(scale2.get_units(),DEC);
    }
    
    for (int a = 0; a < Date_count; a++) 
    {
        file.write(',');
        //file.print("test");
    } 
    
    for (int b = 0; b < Time_count; b++) 
    {
        file.write(',');
        file.print(now.hour(), DEC);
        file.print(":");
        file.print(now.minute(), DEC);
        file.print(":");
        file.print(now.second(), DEC);
        file.print(":");
        file.print(micros(), DEC);
    }
    
    file.println();
    
    //relay (); //relay() is called from loop now
    
}//logData

//==============================================================================
void relay( void ) 
{
    uint8_t
        stateRelay = RLY_OFF;
    static uint32_t
        timeRelay;
    uint32_t
        timeNow = millis();
        
    switch( stateRelay )
    {
        case    RLY_IDLE:
            //waiting for flag to indicate relay sequence
            if( bRelay == true )
            {
                bRelay = false;
                timeRelay = timeNow;
                stateRelay = RLY_ON;
                
            }//if
            
        break;

        case    RLY_DELAY:
            //delay before turning the relay on
            if( millis() - timeRelay >= K_RELAY_DELAY_TIME )
            {
                digitalWrite( relay2, LOW );   //relay on 
                timeRelay = timeNow;
                stateRelay = RLY_HOLD;
                    
            }//if
            
        break;

        case    RLY_HOLD:
            //relay on-timing
            if( millis() - timeRelay >= K_RELAY_HOLD_TIME )
            {
                digitalWrite( relay2, HIGH );    
                stateRelay = RLY_IDLE;
                    
            }//if
        
        break;
                
    }//switch

}//relay

thank you for the idea. There is a compile error.

    uint8_t
        stateRelay = RLY_OFF;
    static uint32_t
        timeRelay;

It appears that logging is enabled by the serial port and voltage being greater than 2. Since you initialize previousMillis to 0 then if the logging does not get enabled until 5 seconds or more have passed then the relay will immediately open. You need to set previousMillis = millis() when you enable logging.

mr.ToddL1962
What you're saying is, if I'm not mistaken, you're telling me to change this line like this?

void logData() {
 unsigned long currentMillis = millis();
  file.print(logTime);
  for (int c = 0; c < Load_Cell1; c++) {
    file.write(',');
    file.print(scale.get_units());
  } for (int d = 0; d < Load_Cell2; d++) {
    file.write(',');
    file.print(scale1.get_units());
  } for (int e = 0; e < Load_Cell3; e++) {
    file.write(',');
    file.print(scale2.get_units());//file.print(scale2.get_units(),DEC);
  }
  for (int a = 0; a < Date_count; a++) {
    file.write(',');
    //file.print("test");
  } for (int b = 0; b < Time_count; b++) {
    file.write(',');
    file.print(now.hour(), DEC);
    file.print(":");
    file.print(now.minute(), DEC);
    file.print(":");
    file.print(now.second(), DEC);
    file.print(":");
    file.print(micros(), DEC);
  }
  file.println();

}
//==============================================================================
void relay () {
  if (alreadyRun == false) {
   
    if ((relay2State == LOW) && (currentMillis - previousMillis >= OnTime) ) {

      relay2State = HIGH;  // Turn it off
      previousMillis = currentMillis;  // Remember the time
      digitalWrite(relay2, relay2State);  // Update the actual LED
    }
    else if ((relay2State == HIGH) && (currentMillis - previousMillis >= OffTime) ) {

      relay2State = LOW;  // Turn it off
      previousMillis = currentMillis;  // Remember the time
      digitalWrite(relay2, relay2State);  // Update the actual LED
      alreadyRun = true;
    }
  }
}


Oops. Sorry, in the line:

uint8_t
        stateRelay = RLY_OFF;

RLY_OFF should be RLY_IDLE like:

uint8_t
        stateRelay = RLY_IDLE;

mr.Blackfin
this way i called this function directly from void loop there was no relay wiggle

void relay( void )
{
  uint8_t
  stateRelay = RLY_IDLE;
  static uint32_t
  timeRelay;
  uint32_t
  timeNow = millis();

  switch ( stateRelay )
  {
    case    RLY_IDLE:
      //waiting for flag to indicate relay sequence
      if ( bRelay == true )
      {
        bRelay = false;
        timeRelay = timeNow;
        stateRelay = RLY_IDLE;

      }//if

      break;

    case    RLY_DELAY:
      //delay before turning the relay on
      if ( millis() - timeRelay >= K_RELAY_DELAY_TIME )
      {
        digitalWrite( relay2, LOW );   //relay on
        timeRelay = timeNow;
        stateRelay = RLY_HOLD;

      }//if

      break;

    case    RLY_HOLD:
      //relay on-timing
      if ( millis() - timeRelay >= K_RELAY_HOLD_TIME )
      {
        digitalWrite( relay2, HIGH );
        stateRelay = RLY_IDLE;

      }//if

      break;

  }//switch

}//relay

Read the datasheet. There is only 1 ADC, not 1 per analog pin. If that doesn't make sense it's because you don't know the chip as well as you think.

You can put while loops inside of void loop() at which point you stand a chance of interfering with your other code.

The only loop you need is a fast void loop(). I learned these things by 1985 after writing code for money since 1980.

GoForSmoke
forgive my ignorance I don't know how to do this please can you help me a bit?