Advanced delay from button push

So far the code I’m working with seems to sort of work, however instead of a linear gradient of delay, I want to have 10 distinct periods of delay. How would I best do this in the following sketch. I’m going to use a selector switch connected to a series of 1K resistors +5V → 1K → Selector 1 → 1K → Selector 2 → 1K → Selector 3 → 1K → Selector 4 … → A01

The trigger is a momentary contact closure and the output is actually going to trigger a relay which must have LOW to turn RELAY ON.

The sketch I have thus far is:

int sensorPin = A0;    // select the input pin for the potentiometer
int RelayPin = 13;      // select the pin for the Relay
int sensorValue = 0;  // variable to store the value coming from the sensor
int TriggerPin = 7;   // choose the input pin (for a pushbutton)
int val = 0;     // variable for reading the pin status


void setup() {
  // declare the RelayPin as an OUTPUT:
  pinMode(RelayPin, OUTPUT);  
  // declare pushbutton as input
  pinMode(TriggerPin, INPUT);

}

void loop() {
  // read Button Press value
  val = digitalRead(TriggerPin);
  if (val == HIGH) {         // check if the input is HIGH (button released)
    // read the value from the sensor
    sensorValue = analogRead(sensorPin);    
    // turn the RELAY ON
    digitalWrite(RelayPin, LOW); 
    // stop the program for <sensorValue> milliseconds
    delay(sensorValue);          
    // turn the RELAY OFF
    digitalWrite(RelayPin, HIGH);   
    // stop the program for for <sensorValue> milliseconds
    delay(sensorValue);                  
  } 
  else {
    digitalWrite(RelayPin, HIGH);  // turn RELAY OFF
  }
}

Thank you for your generous assistance!

Shawn

So far the code I'm working with seems to sort of work, however instead of a linear gradient of delay, I want to have 10 distinct periods of delay.

The values you read from the "sensor" pin are not going to be linear, are they? It's not clear what you want to do. If you want to use the value read from sensorPin to determine which "Selector n" was picked, that is possible. If you want to use the value of n to determine which of 10 delay periods to use, that is possible. Put the delay periods in an array, and use n (or n-1) as the array index.

Right, the values aren’t linear. Ideally it would be ranges ie (800-1200, 1800-2200, 2800-3200…)

Each range will be a “step” and each step will have an associated time for the relay to remain energized.

Does that make sense?

To clarify: Each position of the selector switch will engage the series of 1K resistors at the connecting points so the first position will be connected to the very end with no resistance and the last will be at the beginning of the series with the maximum. Each step will provide a more static reading so we can accurately calculate the delay period of the relay.

Do you have a recommendation on software to draw a diagram of the circuits and I can provide greater detail if necessary?

Thanks!

Shawn

Ideally it would be ranges ie (800-1200, 1800-2200, 2800-3200...)

How can a switch [u]position[/u] relate to a range of values? The switch position might select the range, but the delay() call wants ONE value from that range.

I understand you’ve got a ten-position rotary switch and you want to know which position is selected. Each position is connected to a different point in a resistor ladder so the voltage at the common terminal is different for each position, and you’re using an analog input to read the voltage at the common terminal.

The way I’d approach this is to define an array. Each element in the array contains the mid-point (average) of the analog readings for two adjacent switch positions (nine values in all).

For a given analog input value you can now iterate through the array until you find an element which is greater than your analog value (if they’re arranged in ascending order) or less than the analog value (if they’re in descending order). The array index of the element your found gives you your switch position. If you run off the end of the array you know the last position was selected. You could avoid having to write code to deal specially with that case by adding an extra element to the array and giving it a value bigger than the biggest possible input value.

Yes that is exactly the case. A ladder of resistors. That's a great idea to have a different value at the end so there is a clear end to the ladder.

Is it necessary to have the momentary switch use a resistor in series? I've read it both ways.

I'll keep digging, any recommendations on coding for it to pull values based on the array? The reason I was thinking of a range was because it would allow some flexibility with the variations in resistance of the individual resistors through the ladder. Is this possible?

Thanks again!

Shawn

It just needs a for loop to iterate through the array looking for the right value. Putting the mid-points in the array is conceptually similar to defining each position as a range but is better than defining the ranges separately because it eliminates redundancy and implicitly ensures that there are no gaps or overlaps between the ranges. Bear in mind that when the switch is moving you will get an extreme value which does not correspond to any of the switch positions. I'd treat this code as a slight variation of conventional debouncing and edge detection for a simple switch input, and implement it in a wrapper function analogous to digitalRead() which does the analog reads, range comparisons, debouncing and just returns the current position as a number 0 .. N.

shawnlevin:
Yes that is exactly the case. A ladder of resistors. That’s a great idea to have a different value at the end so there is a clear end to the ladder.

Is it necessary to have the momentary switch use a resistor in series? I’ve read it both ways.

I’ll keep digging, any recommendations on coding for it to pull values based on the array? The reason I was thinking of a range was because it would allow some flexibility with the variations in resistance of the individual resistors through the ladder. Is this possible?

Thanks again!

Shawn

“<” and (&&) “>”

Well it is coming along, thanks for the insight! I’m not sure if this is possible to do but I’m thinking the idea is there. I want to assign the value to the “DelayTime” variable by reading the value of the analog input. It should take on the value as defined in the array “SwitchVal”. This way if I want to change the values of the delays, I only have to change them in the setup. I’m fairly confident there is a more elegant way to do this, but it may work. I’m getting a compile error I don’t understand as well. Is it possible to run to “IF”'s in a single sketch?

This is the current sketch (non-working)

Thanks for the help…I’m learning as I go!

const int sensorPin = A0;    // select the input pin for the potentiometer
const int RelayPin = 13;      // select the pin for the Relay
const int TriggerPin = 7;   // choose the input pin (for a pushbutton)
int SwitchVal = 0;  // variable to store the value coming from the sensor
int TriggerState = 0;     // variable for reading the pin status
int DelayTime[] = {0, 125, 250, 375, 500, 750, 1000, 1500, 2000, 2500};  // array for time delay of relay

void setup() {
  // declare the RelayPin as an OUTPUT:
  pinMode(RelayPin, OUTPUT);  
  // declare pushbutton as input
  pinMode(TriggerPin, INPUT);
}

void loop() {
  if ( SwitchVal == 0 ) 
  {
    DelayTime = DelayTime[0];
  }
  else if ( SwitchVal >= 900 and SwtichVal <= 1100 )
  {
    DelayTime = DelayTime[1];
  }
  else if ( SwitchVal >= 1900 and SwtichVal <= 2100 )
  {
    DelayTime = DelayTime[2];
  }
  else if ( SwitchVal >= 2900 and SwtichVal <= 3100 )
  {
    DelayTime = DelayTime[3];
  }
  else if ( SwitchVal >= 3900 and SwtichVal <= 4100 )
  {
    DelayTime = DelayTime[4];
  }
  else if ( SwitchVal >= 4900 and SwtichVal <= 5100 )
  {
    DelayTime = DelayTime[5];
  }
  else if ( SwitchVal >= 5900 and SwtichVal <= 6100 )
  {
    DelayTime = DelayTime[6];
  }
  else if ( SwitchVal >= 6900 and SwtichVal <= 7100 )
  {
    DelayTime = DelayTime[7];
  }
  else if ( SwitchVal >= 7900 and SwtichVal <= 8100 )
  {
    DelayTime = DelayTime[8];
  }
  else if ( SwitchVal >= 8900 and SwtichVal <= 9100 )
  {
    DelayTime = DelayTime[9];
  }
  // read Button Press value
  TriggerState = digitalRead(TriggerPin);
  if (TriggerState == HIGH) {         // check if the input is HIGH (button released)
    // read the value from the sensor
    // sensorValue = analogRead(sensorPin);    
    // turn the RELAY ON
    digitalWrite(RelayPin, LOW); 
    // stop the program for <sensorValue> milliseconds
    delay(DelayTime);          
    // turn the RELAY OFF
    digitalWrite(RelayPin, HIGH);   
    // stop the program for for <sensorValue> milliseconds
    delay(DelayTime);                  
  } else
  {
    digitalWrite(RelayPin, HIGH);  // turn RELAY OFF
  }
}

You’re getting an error, because you seem to be trying to use DelayTime as both an array for values, and a single time variable that you pass to delay(). Those should be separately named variables. You also never assign a value to the SwitchVal, so the comparisons are pointless at the moment.

You can shorten the code a great deal by calculating a minValue and maxValue for the array indexes 1 to 9, and running comparisons in a for loop:

// first check the zero index. If it's not that, move to the next one
for (int i=1; i < 10; i++)
{
  int minValue = i * 1000 - 100;
  int maxValue = minValue + 200;
  // compare the SwitchVal variables to our maxes and mins.
}

Please use code tags.

Read this before posting a programming question

I’m getting a compile error I don’t understand as well.

Please post the error message (copy and paste).

  else if ( SwitchVal >= 900 and SwtichVal <= 1100 )
  {
    DelayTime = DelayTime[1];
  }
  else if ( SwitchVal >= 1900 and SwtichVal <= 2100 )
...

You seem to have odd gaps in your sequences. What if the reading is 1500, for example?

Many apologies for not including the errors. They were corrected with a few changes.

I am trying to use the “for” command and now have more variables defined so it is easier to change and more dynamic.

I’m not sure why, but I can’t get the system to choose anything other than the first array choice in “DelayTime” I am a little confused by they code examples. This is almost there! I can taste it. I can’t wait to post pics of finished products!

Thanks in advance!

The current code is now:

const int sensorPin = A0;    // select the input pin for the potentiometer
const int RelayPin = 13;      // select the pin for the Relay
const int TriggerPin = 7;   // choose the input pin (for a pushbutton)
const int ResistValue = 10; // size of each resistor in ladder
const int SwitchPos = 10; // number of positions on switch
int SwitchVal = 0;  // variable to store the value coming from the sensor
int TriggerState = 0;     // variable for reading the pin status
int DelayTime[] = {500, 125, 250, 375, 500, 750, 1000, 1500, 2000, 2500};  // array for time delay of relay


void setup() {
  // declare the RelayPin as an OUTPUT:
  pinMode(RelayPin, OUTPUT);  
  // declare pushbutton as input
  pinMode(TriggerPin, INPUT);
}

void loop() {
// Thanks Arrch
// first check the zero index. If it's not that, move to the next one
for (int SwitchVal=1; SwitchVal < SwitchPos; SwitchVal++)
{
  int minValue = ( SwitchVal * ResistValue ) - ( ResistValue / 5 );
  int maxValue = minValue + ( ResistValue / 5 );
  // compare the SwitchVal variables to our maxes and mins.
}
  // read Button Press value
  TriggerState = digitalRead(TriggerPin);
  if (TriggerState == HIGH) {         // check if the input is HIGH (button released)
    // read the value from the sensor
    // sensorValue = analogRead(sensorPin);    
    // turn the RELAY ON
    digitalWrite(RelayPin, LOW); 
    // stop the program for <sensorValue> milliseconds
    delay(DelayTime[SwitchVal]);          
    // turn the RELAY OFF
    digitalWrite(RelayPin, HIGH);   
    // stop the program for for <sensorValue> milliseconds
    delay(DelayTime[SwitchVal]);                  
  } else
  {
    digitalWrite(RelayPin, HIGH);  // turn RELAY OFF
  }
}

You didn’t read the link did you? Code tags.

How to use this forum

Read this before posting a programming question

shawnlevin:
I’m not sure why, but I can’t get the system to choose anything other than the first array choice in “DelayTime” I am a little confused by they code examples. This is almost there! I can taste it. I can’t wait to post pics of finished products!

The comments in my code:

// first check the zero index. If it's not that, move to the next one
...
// compare the SwitchVal variables to our maxes and mins.

weren’t just for looks, you actually have to implement the code for those parts.

This SwitchVal:

int SwitchVal = 0;  // variable to store the value coming from the sensor
...
delay(DelayTime[SwitchVal]);

and this SwitchVal:

for (int SwitchVal=1; SwitchVal < SwitchPos; SwitchVal++)
{
  int minValue = ( SwitchVal * ResistValue ) - ( ResistValue / 5 );
  int maxValue = minValue + ( ResistValue / 5 );
  // compare the SwitchVal variables to our maxes and mins.
}

Aren’t the same. The SwitchVal inside the for loop is only valid inside the for loop and goes away when it’s completed, making this for loop useless (although, without more code, it would still be useless).

int minValue = ( SwitchVal * ResistValue ) - ( ResistValue / 5 );
  int maxValue = minValue + ( ResistValue / 5 );

You’re aware that minValue and maxValue will be nowhere near the values in your original code, right?

You also appear to have missed this part of my post:

You also never assign a value to the SwitchVal, so the comparisons are pointless at the moment

Lastly, start following the advice given by Nick and post your code with CODE tags. If you can’t follow simple directions like that, then there is no point in helping you further with your code.

I will continue plugging and get back to you with an updated version soon.

Thank you again for your assistance, it is greatly appreciated.

Nick, my apologies, I missed the code reference and I'll be sure to do this in the future.

Kindest,

Shawn