Changing a variable without reloading the sketch

Hey all,
I've written a sketch that triggers a camera flash when I receive a certain voltage into one of my analog input pins on an Arduino Uno. Everything works as expected, but in order to change "delayLength" I have to edit the sketch and reload it. What's the easiest way to edit "delayLength" without reloading the sketch? I prefer a software solution, as the Arduino is always plugged into my computer (mac) when running this sketch anyway.

Thanks for the help.

int sensorPin = A0;    // select the input pin that the 555 timer out plugs in to
int flashPin = 13;      // select the pin that will be used to trigger the flash
int delayLength = 0;  // variable to store the length of the delay between sensing voltage and triggering the flash

void setup() {
  // declare the flashPin as an OUTPUT:
  pinMode(flashPin, OUTPUT);  
}

void loop() {
  // read value from sensorPin and begin loop if the vaule is greater than 100 
  while (analogRead(sensorPin)<100) {}
  // stop the program for <delayLength> seconds
  delay(delayLength);
  // turn the flashPin on
  digitalWrite(flashPin, HIGH);  
  // stop the program for 10 milliseconds:
  delay(10);          
  // turn the flashPin off:        
  digitalWrite(flashPin, LOW);
  // read value from sensorPin and stop loop until the value is less than 100.
  while(analogRead(sensorPin)>100){}        
}

It really depends on the range you need to change.
You could simply wire a pot to another analogue pin, and use that value, or you could use the serial monitor or other terminal emulator to enter strings representing the required number.

The range will generally be between 0 and 500 or so. I tried messing around with the serial monitor a little, but couldn't figure it out. What command would I use to change the value of delayLength?

0 to 500 is probably easier with a pot.
Otherwise, there is no single command to do what you want, but numeric entry comes up every other day here.
Do a few searches.

You can enter a number into the Serial Monitor. My example sketch changes delayTime to a number up to 3 digits long. At 9600 baud, it takes just under 1 ms to recieve a character. Change the timeout, and buffer size to suit the maximum number to be entered.

size_t len;
char buf[4];
int delayTime = 0;
void setup(){
  Serial.begin(9600);
  Serial.setTimeout(3);
}
void loop()
{
  if(Serial.available() > 0){
    len = Serial.readBytes(buf, 3);
    buf [len] = '\0';
  }
  if(strlen(buf) > 0){
    Serial.println(atoi(buf));
    delayTime = atoi(buf);
    *buf = '\0';
  }
}

I'm sure that's there are more [efficient] ways to do this!

At 9600 baud, it takes just under 1 ms to recieve a character.

sp. "At 9600 baud, it takes just over 1 ms to receive a character."

9600 baud = 9600 bits per second = 1200 bytes per second.
1 second / 1200 bps = about 0.83 ms per byte.
What other procedures, etc. add up to more than 1 ms?

dkl65:
What other procedures, etc. add up to more than 1 ms?

Start and stop...

Since your program spends so much time in delays it may be a while between commanding a change and the change happening.

You might have a look here: http://arduino.cc/en/Tutorial/BlinkWithoutDelay

That lets your program have plenty of time to get input.

I wrote this a while ago. It's not perfect but it runs and has serial i/o.

unsigned long waitUntil = 0UL; // because millis() returns UL 
enum whatFlag { 
  led13state, endOfLine, dataBegun, badEntry }; 
byte  Flags = 0;

void printUsage()
{
  Serial.println( "Blink w/user input. Enter 0 to 1000 for led-on interval" );
  Serial.println();
}

void setup()
{
  pinMode( 13, OUTPUT );
  digitalWrite( 13, bitRead( Flags, led13state ));  
  Serial.begin( 9600 );
  printUsage();
}

void loop()
{
  static byte  c; // c for character buffer
  //  static byte  endOfLineState = 0;
  static unsigned long timeSinceLastSerialRead = 0UL;
  static int enter = 0; // to get serial-entered number value.
  static int ledMillisOn = 100;  // must be 0-999

  // flash led and state changer
  if ( waitUntil - millis() >= 1000000UL )  // when millis() passes waitUntil the _unsigned_ subtract 
  {                                       // leaves very large positive result
    if ( bitRead( Flags, led13state ) && ( ledMillisOn < 1 ))
    {
      Flags &= !( 1 << led13state );  // led is OFF since ON time is 0
      waitUntil = millis() + 100000UL;
    }
    else if ( bitRead( Flags, led13state ) && ( ledMillisOn > 999 ))
    {
      Flags |= ( 1 << led13state );  // led if ON since OFF time is 0
      waitUntil = millis() + 100000UL;
    }
    else
    {
      Flags ^= ( 1 << led13state ); // led13state T/F bit toggle 

        if (bitRead( Flags, led13state ))
      {  
        waitUntil = millis() + (unsigned long)( ledMillisOn );
      } 
      else 
      {
        waitUntil = millis() + (unsigned long)( 1000 - ledMillisOn ); 
      }
    }
    digitalWrite( 13, bitRead( Flags, led13state ));  
  }

  // serial input
  if ( Serial.available() ) 
  {
    c = Serial.read();
    //    Serial.print(".");
    //    Serial.print( c );
    timeSinceLastSerialRead = millis();
    if (( c >= '0' && c <= '9' ) and !( Flags & ( 1 << badEntry )))
    {
      enter *= 10;  // decimal shifting whatever is in enter 1 place up
      enter += ( c - '0' ); // ascii 48 is '0' 
      bitSet( Flags, dataBegun );  // entry is treated as started/ongoing

      if ( enter > 1000 )
      {
        Flags |= ( 1 << badEntry );  // causes numeric conversion to stop
      }
    }
    else if (( c == 13 || c == 10 ) && bitRead( Flags, dataBegun )) 
    {
      bitSet( Flags, endOfLine );  // entry is treated as finished
    }
    else
    {
      bitSet( Flags, badEntry );
      bitSet( Flags, dataBegun );
    }
  }
  else if (( millis() - timeSinceLastSerialRead >= 100 ) && !( bitRead( Flags, endOfLine )))
  {
    if ( bitRead( Flags, dataBegun ))
    {
      bitSet( Flags, endOfLine );  // entry is treated as finished
    }
  } 

  // serial output
  if ( bitRead( Flags, endOfLine ) && bitRead( Flags, dataBegun )) // should be done and have data
  {
    if ( bitRead( Flags, badEntry ))
    {
      Serial.println();
      Serial.println( "Bad Entry" );
      bitClear( Flags, badEntry );
      printUsage();
    }
    else
    {
      Serial.print( "New ON interval >> " );
      Serial.print( enter );
      Serial.println( " <<" );

      ledMillisOn = enter;
    }
    enter = 0;
    bitClear( Flags, endOfLine );
    bitClear( Flags, dataBegun ); // clears bits, endOfLine and dataBegun
  }
}

AWOL:
0 to 500 is probably easier with a pot.
Otherwise, there is no single command to do what you want, but numeric entry comes up every other day here.
Do a few searches.

If I do go the pot route, I would need to know what value it's sending into the arduino. How can I display the value of an analog pin in a window on my computer while the sketch is running? Would this have to be done through the serial monitor as well?

According to the picture...
1 second / 9600 baud = about 0.10417 ms per bit = about 0.83 ms per byte (1200 bps)
0.10417 ms start + 0.83 ms per byte + 0.10417 ms end = 1.0417 ms.

How can I display the value of an analog pin in a window on my computer while the sketch is running?

Print the analogRead() on the pot pin to the Serial Monitor!

juggleitup:
If I do go the pot route, I would need to know what value it's sending into the arduino. How can I display the value of an analog pin in a window on my computer while the sketch is running? Would this have to be done through the serial monitor as well?

Serial monitor or any serial terminal program.

How exactly would I do that? Sorry for all the newb questions. I did a couple searches and couldn't find anything relevant.

Serial.begin (9600);
...
Serial.println (analogRead(potPin));


Rob

dkl65:
9600 baud = 9600 bits per second = 1200 bytes per second.

Have to count the start and stop bits. So divide by 10:

9600 baud = 960 bytes per second, or 1.0416 mS each.

Graynomad:
Serial.begin (9600);
...
Serial.println (analogRead(potPin));


Rob

Thanks. Would this continually update as I turn the pot or would I have to reenter that command every time?

You read the analog and save it, then apply that to your delay and print it out. You could set up a timer and code to make automatic reads then update and print only when the value changes but are you ready for that? Either way, the read is made when analogRead() is run.

But since loop() repeats, if you keep loop time short (no long delays or processes) then your code will be able to catch input and respond quickly.

At 16MHz and with short routines, loop() can go around about 100x to 1000x a millisecond. Every big process is just a sequence of little ones, they don't all have to run in the same pass through loop(), there's no good reason why a program can't have quick i/o response.

juggleitup:
How exactly would I do that? Sorry for all the newb questions. I did a couple searches and couldn't find anything relevant.

Have you used Serial Monitor before? You can set up the speed and send line-ending down at the bottom-right of the Monitor. I think the default is 9600, no line ending.