Aduino pin. 2 things at once???????

Hello everyone.

If someone could take the time to have a look at this and point me in the right direction. I am using an rc receiver for ch4, ch5, ch6. I am trying to make it so if ch6 switch is on. Pin is high but if my voltage divider is telling it that it is between 24 and 25 volt it will go low and high(delayed). Also if ch5 switch is on and voltage is above 24 volts pin will be high. As of now everything works just not as its supposed to. How would i code this so if it is between 24 and 25 volts pin will delay but if i turn ch6 switch off pin goes low. Ch5 works properly except if ch5 is delayed ch6 switch wont switch off until it is in the 2 sec delay.
I’m sure i am making a noobish mistake but I am stuck and any help would be greatly appreciated.

ch4 = pulseIn(servo4, HIGH, 20000); // Read the pulse width of each channel
ch5 = pulseIn(servo5, HIGH, 20000);
ch6 = pulseIn(servo6, HIGH, 20000);

// Channel 6 mower switch. If voltage is between 24 and 25 volts mowerpin will turn off and on.

if(voltage >= 24 && voltage <=25){ //If voltage between 24 and 25 volts
digitalWrite(mowerpin, HIGH);
delay(10000); //Mowerpin will be High for 10 sec
digitalWrite(mowerpin, LOW);
delay(2000); //Mowerpin will be low for 2 sec
}
else if(ch6 >= 1900 && ch6 <= 2200){ //If channel 6 is between 1900 and 2200 mowerpin will be on
digitalWrite(mowerpin, HIGH);
}

else {
digitalWrite(mowerpin, LOW); //If channel 6 is under 1900 mowerpin will be off
}

// channel 5 disconnect switch with shut off if voltage falls below 24 volts

if(ch5 >= 1900 && ch5 <= 2200 && voltage > 24){ //If channel 5 is between 1900 and 2200 disconnectpin will be off
digitalWrite(disconnectpin, HIGH); //Also if voltage is above 24 volts
}

else {
digitalWrite(disconnectpin, LOW); //If channel 5 is below 1900 or voltage is below 24 volts. disconnectpin will be on
}

Ok so I just read that delay can't do two things at once. Is there a way around this or should i just digitalWrite pin LOW when it gets to say 24.5 volts

Need to use millis(). See the Blink without Delay in the Playground.
Basically, read the "time" every pass thru void loop, store the time when your event starts, and when enough time has elapsed you stop your event.
Then you can have multiple events running in parallel, each with its own start & stop times, none holding another one up like delay would.

I was just reading about millis(). I will try and see if i can implement it for my application. If delay stops the program would that mean if im delay(100) for serial monitor will that affect my sketch as well?

How about a serial display with a big buffer... pass the data and let the display take it's own time... Liudr sold a serial backpack with a 64 byte buffer... I think I still have one...

Doc

Honestly it would be easier for me to use a buffer but I am trying to learn also teach my self and kids some code. I have read the BlinkWithoutDelay. I don’t understand how i would include it with my application. Not looking for the answer as i learn by doing. Just looking for a push in the right direction. Thanks CrossRoads for pushing it just wasn’t hard enough.

I have read the BlinkWithoutDelay. I don't understand how i would include it with my application.

Don't just read the code. You maybe need to play with the example perhaps to understand how/why it works. Perhaps add some print statements to show what your variables hold at critical points like inside if statements. Anything you're not sure of, make it show you. Learn by doing, by stretching.

Once you understand, then you can apply that timing to your much more complicated project.

It wasn’t complicated till i had to learn millis() LOL. I understand how the BlinkWithoutDelay sketch works just don’t how to include my between statements. Where would I put my
if(voltage >= 24 && voltage <=25); statement that would be the push I need.

If the voltage is in the range you want, do two things:
if (voltage == 24 || voltage == 25){
//capture the time:
start1Time = millis();
set a flag:
event1Running = 1;
// start whatever it was you wanted to do
}
next pass thru void loop, checkif event1 is running:
if (event1Running == 1){
// see if enough time passed
if ( ( millis ( ) - start1Time ) >= event1Duration){
// clear the flag
event1Running = 0;
// and stop whatever it was you started
}
}
Make sense?

You need to do a lot of restructuring, but maybe not all that much. Here’s a light-flashing sketch that you run a function to turn a led (or other simple device) on and give it however long before it turns off at the same time. It does require some control variables per device used and it does tell when a device has been turned off.

So where you have

    digitalWrite(mowerpin, HIGH);
    delay(10000);                                                       //Mowerpin will be High for 10 sec
    digitalWrite(mowerpin, LOW);

the blink() function will do that but the next line, delay(2000), will take a bit more code.

Note that blinkcheck() has to run inside loop() to catch timeouts.

// Led On Then Off -- Rippling leds demo
unsigned long  blinkOnTime =  50UL;

// this needs 4 leds and resistors, one each on pins 4, 5, 6, 7, all to ground
#define         LEDS  4
byte            ledPin[ LEDS ] = { 
  4, 5, 6, 7 };
unsigned long   ledTime[ LEDS ][ 2 ]; // start and duration 

// blink() must be run first thing in loop(), it checks the time as well as sets blinks
byte  blinkCheck( byte led )
{
  static unsigned long  lastTime = 0UL;
  byte    turnOff = 0;

  if ( millis() != lastTime ) // only check once per milli because......
  {
    lastTime = millis();

    if ( lastTime - ledTime[ led ][ 0 ] > ledTime[ led ][ 1 ])  // duration ran out 
    {
      digitalWrite( ledPin[ led ], LOW );  
      turnOff = 1;  
//      Serial.print( led, DEC );
//      Serial.println( " off" );    
    }
  }

  return  turnOff;
}

void  blink( byte led, unsigned long time )
{
  if ( led < LEDS )
  {
    ledTime[ led ][ 0 ] = millis();
    ledTime[ led ][ 1 ] = time;
    digitalWrite( ledPin[ led ], HIGH );
//    Serial.print( led, DEC );
//    Serial.println( " on" );    
  }
}

void setup( void )
{
//  Serial.begin( 9600 );
  for ( byte i = 0; i < LEDS; i++ )
  {
    pinMode( ledPin[ i ], OUTPUT );
    digitalWrite( ledPin[ i ], LOW );
  }
  blink( 0, blinkOnTime );
}

void loop( void )
{
  static byte  led = 0;

  if ( blinkCheck( led )) // return > 0 means led turned off
  {
    led = (( led + 1 ) & 3 );
    blink( led, blinkOnTime );
  }  
}

Thanks CrossRoads that what i was looking for. I will change my code and see if I can get it to work. Appreciate your replies.

http://www.gammon.com.au/blink

Ok this is part of my main sketch. millis() works well. the jist of the code is when I turn on switches on my remote 5 and 6. everything works like its suppose to unless voltage divider is reading between 24 and 25 volts then mowerpin will shut off and on to tell me the battery is getting low. when channel 5 reads to voltage is under 24 volts the diconnectpin will shut off Question is? Is there a way to adjust the delay times? its set for 1000 what if I wanted to have 2 secs off 10 sec on? Also when the millis() is working my test led on disconnectpin was fantly flashing when the ch5 switch is off. Any thoughts as to why it would do that. I tried to trouble shoot and fried my 328 when i turn on the internal pull up (not wise to do if you already have a external pull down doh).

Thanks

const int voltPin = 0;  //Analog volt read pin

float denominator;      //Variables for voltage divider
int resistor1 = 10000;  //Check resistors with ohm meter and adjust according
int resistor2 = 1870;

int disconnectpin = 4;  // Main disconnect
int mowerpin = 7;       // Mower motor
int mowerstate= LOW;
long previousMillis = 0;// will store last time mowerpin was updated
long interval = 1000;   // interval at which to delay (milliseconds)

int servo5 = 11;        // r/c channel 5
int servo6 = 12;        // r/c channel 6
int(ch5);
int(ch6);
void setup(){

Serial.begin(9600);
  
  //Convert resistor values to division value
  //  R2 / (R1 + R2)
  denominator = (float)resistor2 / (resistor1 + resistor2);
  
  pinMode(servo5, INPUT);      //Pin 5 as input
  pinMode(servo6, INPUT);      //Pin 6 as input
 
  pinMode(disconnectpin, OUTPUT); //Pin 4 as output
  pinMode(mowerpin, OUTPUT);      //Pin 7 as output
  analogWrite(disconnectpin, 0);  
  analogWrite(mowerpin, 0); 
}
  void loop() {

  float voltage;
  //Obtain RAW voltage data
  voltage = analogRead(voltPin);

  //Convert to actual voltage (0 - 5 Vdc)
  voltage = (voltage / 1024) * 5.0;

  //Convert to voltage before divider
  //  Divide by divider = multiply
  //  Divide by 1/5 = multiply by 5
  voltage = voltage / denominator;
  
                       
  ch5 = pulseIn(servo5, HIGH, 20000); // Read the pulse width of each channel 
  ch6 = pulseIn(servo6, HIGH, 20000);
 
  // Channel 6 mower switch. If voltage is between 24 and 25 volts mowerpin will turn off and on.  
  
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval && voltage >= 24 && voltage <= 25) {
  // save the last time checked state
    previousMillis = currentMillis;  

  if  (mowerstate == LOW)
      (mowerstate = HIGH);
  if
      (mowerstate = LOW);{
      digitalWrite(mowerpin, mowerstate);
  
   }    
 }
  else if (ch6 >= 1900 && ch6 <= 2200){
    digitalWrite(mowerpin, HIGH);                 //Also if voltage is above 24 volts 
  }
   
  else  {
    digitalWrite(mowerpin, LOW);                  //If channel 5 is below 1900 or voltage is below 24 volts. disconnectpin will be on
  }
  


   
    // channel 5 disconnect switch with shut off if voltage falls below 24 volts
    
    if(ch5 >= 1900 && ch5 <= 2200 && voltage > 24){    //If channel 5 is between 1900 and 2200 disconnectpin will be off
    digitalWrite(disconnectpin, HIGH);                 //Also if voltage is above 24 volts 
  }
   
  else  {
    digitalWrite(disconnectpin, LOW);                  //If channel 5 is below 1900 or voltage is below 24 volts. disconnectpin will be on
  }
}

Internal pullup goes through a lot of resistor. It is OUTPUT to too low resistance (like ground) that burns pins. Don't be afraid to use the pullups.

what ever i did its dead. Good thing I stock up for these frequent occasions :grin:

mhastie1234:
Question is? Is there a way to adjust the delay times? its set for 1000 what if I wanted to have 2 secs off 10 sec on?

Didn't you write the code, compile and download it to the board?
Didn't you set it to 1000?

I think I must not understand what you mean from your words.
To me there are at least two answers:

  1. change the hard-coded 1000 to another number, compile and load the new sketch.
  2. add user I/O via serial monitor and allow the delay to be changed dynamic.
  3. buttons/switches/sensor input control of the delay
  4. control through program on the PC (besides serial monitor)

Also when the millis() is working my test led on disconnectpin was fantly flashing when the ch5 switch is off. Any thoughts as to why it would do that.

Probably something about how it's wired?

Questions like that and burned chips suggests taking the project down to pieces and troubleshooting each one before seeing about reassembling the pieces while including fixes.

Yes it is set for 1000. Can you use two variables with millis().1000 on 500 off. like the code but with millis(). I have fixed the led problem. Cant have sucess without some sacrifice.

digitalWrite ledPin, HIGH);
          delay(1000);
          digitalWrite ledPin, LOW);
          delay(500)

Like

unsigned long startTime;
unsigned long duration;

// code .. code .. code

duration = 1000UL;
startTime = millis();

// code .. code .. code

if ( millis() - startTime > duration ) // the unsigned subtraction avoids rollover problems
{
// do whatever, duration is up!
}

And then make duration whatever you want?