A quick question about delay... [SOLVED]

So currently I’m writing a c# program to interface with the arduino and make an LED on pin 9 do different stuff. Today I’ve added a “blink” (or as I’ve called it in my code "flicker). I’m not sure why, but unless I put delay(100), the LED would blink forever (or a long time, I never let it run that long to sit around and find out). However, with the delay in place it works as intended (the user sends a byte from the C# program to specify how many times to flicker/blink the LED)

case 'f':

//Needed this delay for some reason or else it flashes forever??
delay (100);

FlickerCount = Serial.read();

for (int i = 0; i < FlickerCount; i++)
    {
      analogWrite(ledPin, PWMValue);
      delay(100);
      analogWrite(ledPin, 0);
      delay(100);
    }
break;

Here is the full code if necessary to see: http://pastebin.com/LH9uTakd

Can someone explain to me or give me some reading material as to why I needed to make it wait 1/10th of a second? I would appreciate it.

Thanks.

Without the delay, your analogWrite stays in play for only a few microseconds at most before your digitalWrite shuts off the LED. Way too fast to have any visible effect.

With the delay, you have the analogWrite engaged for many pwm cycles, which conveys the proper visual effect.

-br

billroy:
Without the delay, your analogWrite stays in play for only a few microseconds at most before your digitalWrite shuts off the LED. Way too fast to have any visible effect.

With the delay, you have the analogWrite engaged for many pwm cycles, which conveys the proper visual effect.

-br

Alright, I think I understand. Thanks.

billroy: Without the delay, your analogWrite stays in play for only a few microseconds at most before your digitalWrite shuts off the LED. Way too fast to have any visible effect.

With the delay, you have the analogWrite engaged for many pwm cycles, which conveys the proper visual effect.

-br

Actually the delay he is talking about is the first one between the case switch and the Serial.read().

@ pantzmaster I'm not sure, but it might be because you are trying to read from the serial port too soon after the previous read so you get the previous (or an undeclared) value? If it's the last value (I haven't looked at the full code), I would suspect that FlickerCount gets the value 'f', which is 0x66, or 102 in decimal. That would make the LED flash for 20.4 seconds. Have you waited a little over 20 seconds to see if it shuts off then?

I'm not sure, but it might be because you are trying to read from the serial port too soon after the previous read so you get the previous (or an undeclared) value? If it's the last value (I haven't looked at the full code), I would suspect that FlickerCount gets the value 'f', which is 0x66, or 102 in decimal. That would make the LED flash for 20.4 seconds. Have you waited a little over 20 seconds to see if it shuts off then?

I just tested it then without the delay, it seems to go on for about 50~ seconds before it stops. Any Idea why it would be 50 seconds for?

pantzmaster:

I'm not sure, but it might be because you are trying to read from the serial port too soon after the previous read so you get the previous (or an undeclared) value? If it's the last value (I haven't looked at the full code), I would suspect that FlickerCount gets the value 'f', which is 0x66, or 102 in decimal. That would make the LED flash for 20.4 seconds. Have you waited a little over 20 seconds to see if it shuts off then?

I just tested it then without the delay, it seems to go on for about 50~ seconds before it stops. Any Idea why it would be 50 seconds for?

It may be getting 0xFF from a Serial.read() before a character is ready. Think about it. Your flicker loop will take 0.2 seconds per iteration, so 255 iterations would take 255 * 0.2s = 51s. You might want to wait until Serial.available()>0 before you Serial.read().

Ah... If you look at the Serial.read() reference page (http://arduino.cc/en/Serial/Read) you will see:

Returns

the first byte of incoming serial data available (or -1 if no data is available) - int

Your loop increments an integer until it reaches the target value. In this case, -1. The binary value of -1 in an int variable is 0b11111111, which is 0xFF like my supposition above. As long as you don't mind the Arduino to do nothing while it waits for your C# program to send the value for FlickerCount, replace that "delay(100);" that you are questioning with "while (Serial.available() == 0);" to sit and spin until the next character comes across the serial port. (You should also realize that what is received may very well be ASCII digits, not a value. Double check what (and how) you are sending the value from C#.)

It would be interesting to see what the actual value of FlickerCount is. Can you do a Serial.Print or something and check it?

TanHadron: It would be interesting to see what the actual value of FlickerCount is. Can you do a Serial.Print or something and check it?

I was going to suggest that, but he has his serial port tied up communicating with his C# program. Maybe if he has an additional serial port on his computer (or additional TTL usb cable) he can move his communication with C# to SoftwareSerial so he can use the Serial Monitor for troubleshooting messages. I don't know his level of knowledge with Arduino for him to understand what I just said tho.

I suspect I'm right, but it would be good to know for sure.

Alright thanks guys you are helping me understand a lot.

I can attempt to do a Serial.print if you guys talk me through and are interested in finding out (since I need to learn that sort of stuff anyway, as is probably little obvious by now my skills concerning Arduino are fairly sub-par. I’ve only been at it a couple of days).

Here is the C# for the button that determines how many times it flickers:

 private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.Write("f");


            //Convert whatever is in the Textbox (how many times it flickers) to a byte, then writes it to serial port
            byte[] flickerData = {Convert.ToByte(FlickerBox.Text) };
           serialPort1.Write(flickerData, 0, 1);



           string ReadValue = serialPort1.ReadChar().ToString();   //Not so sure about this line here
           label4.Text = ReadValue; //Sets a label I have on my form to whatever is read


        }

The part of the Arduino code concerning the flickering part:

case 'f':
//Commenting out delay for now
//delay (100);

FlickerCount = Serial.read();

//Might need help with this part?
Serial.print(FlickerCount);

for (int i = 0; i < FlickerCount; i++)
    {
      analogWrite(ledPin, PWMValue);
      delay(100);
      analogWrite(ledPin, 0);
      delay(100);
    }

    
break;

pantzmaster:
Alright thanks guys you are helping me understand a lot.

I can attempt to do a Serial.print if you guys talk me through and are interested in finding out (since I need to learn that sort of stuff anyway, as is probably little obvious by now my skills concerning Arduino are fairly sub-par. I’ve only been at it a couple of days).

Well, it may be a bit excessive to add an additional serial communication between the Arduino and your computer. Doing that would require some hardware pieces that I don’t know if you have.

Here is the C# for the button that determines how many times it flickers:

 private void button1_Click(object sender, EventArgs e)

{
            serialPort1.Write(“f”);

//Convert whatever is in the Textbox (how many times it flickers) to a byte, then writes it to serial port
            byte flickerData = {Convert.ToByte(FlickerBox.Text) };
           serialPort1.Write(flickerData, 0, 1);

string ReadValue = serialPort1.ReadChar().ToString();   //Not so sure about this line here
           label4.Text = ReadValue; //Sets a label I have on my form to whatever is read

}

I don’t know much about C#, but it does appear that you are getting a numerical value that is represented by some sort of ASCII input. That tells me that the character sent to the Arduino is actually a value. (Unless, of course, the “serialPort1.Write(flickerData, 0, 1);” line converts the value back to ASCII digits.

The part of the Arduino code concerning the flickering part:

case 'f':

//Commenting out delay for now
//delay (100);

FlickerCount = Serial.read();

//Might need help with this part?
Serial.print(FlickerCount);

for (int i = 0; i < FlickerCount; i++)
    {
      analogWrite(ledPin, PWMValue);
      delay(100);
      analogWrite(ledPin, 0);
      delay(100);
    }

break;

Well, do like I said previously and addwhile (Serial.available() == 0); to replace your currently commented out delay. Then see what happens. (If I’m very lucky, and my stars are aligned just right, and I’m holding my tongue just right… It should work. Basically, I haven’t tested it, but it is the first thing I would try.)

You got it, got rid of delay (100) and replaced it with while (Serial.available() == 0); and works just as intended. Is this just basically waiting for nothing to be there (in this case, the 'f') then continuing on with the program, rather than forcing it to wait 100ms?

pantzmaster: You got it, got rid of delay (100) and replaced it with while (Serial.available() == 0); and works just as intended. Is this just basically waiting for nothing to be there (in this case, the 'f') then continuing on with the program, rather than forcing it to wait 100ms?

Actually, more like "wait while nothing is there". You have already read the 'f' so the buffer is empty. Trying to read from the empty buffer is what caused your problem. Note, because of the blocking nature, if your C# crashes between sending the 'f' and the value for your flicker time, the Arduino will be stuck until something, anything is sent over the serial port. Likely not the value you want. Hopefully that will never happen. (Sorry, I just jinxed you...) ;)

Actually, more like "wait while nothing is there". You have already read the 'f' so the buffer is empty. Trying to read from the empty buffer is what caused your problem. Note, because of the blocking nature, if your C# crashes between sending the 'f' and the value for your flicker time, the Arduino will be stuck until something, anything is sent over the serial port. Likely not the value you want. Hopefully that will never happen. (Sorry, I just jinxed you...) ;)

Ahh I see, so it read an empty value 0xFF (255) then ran the loop that many times with a delay of 0.2 seconds (0.1 per delay), making it flicker for 51 seconds rather than flickering for the c# amount. The 'f' gets read then the buffer is empty, so the while (Serial.available() == 0); waits until something else is put into the buffer before reading it (my flicker value sent from the C# program)?

pantzmaster:

Actually, more like “wait while nothing is there”. You have already read the ‘f’ so the buffer is empty. Trying to read from the empty buffer is what caused your problem. Note, because of the blocking nature, if your C# crashes between sending the ‘f’ and the value for your flicker time, the Arduino will be stuck until something, anything is sent over the serial port. Likely not the value you want. Hopefully that will never happen. (Sorry, I just jinxed you…) :wink:

Ahh I see, so it read an empty value 0xFF (255) then ran the loop that many times with a delay of 0.2 seconds (0.1 per delay), making it flicker for 51 seconds rather than flickering for the c# amount. The ‘f’ gets read then the buffer is empty, so the while (Serial.available() == 0); waits until something else is put into the buffer before reading it (my flicker value sent from the C# program)?

Bingo! Someone get that man a cigar! :smiley:

Bingo! Someone get that man a cigar! :D

Well thank you for helping me understand and tackle this problem! You've been a big big help! :D Karma for you (I think I may have already given some, I can't remember)

pantzmaster:

Bingo! Someone get that man a cigar! :D

Well thank you for helping me understand and tackle this problem! You've been a big big help! :D Karma for you (I think I may have already given some, I can't remember)

Thanx. You may want to edit the first post in this thread to add "[Solved]" (with out the quotation marks) to the end of the subject.

Thanks, I have. Just to follow up, should I be adding while (Serial.available() == 0); to most things so It doesn't read 0xFF when I'm sending a couple of values in a row?

pantzmaster: Thanks, I have. Just to follow up, should I be adding while (Serial.available() == 0); to most things so It doesn't read 0xFF when I'm sending a couple of values in a row?

Yep. Before reading the serial port you should always make sure there is data there. Note that this method is a blocking method. That means that the Arduino does nothing but wait for a byte to appear in the serial buffer. If you need to do other things but react when a byte shows on the serial port, you will want to use

// do stuff
if (Serial.available() > 0)
{
  // read a character from the serial port and decide what to do with it
}
// continue doing things

This way if you have something at the serial port you read it and deal with it and then continue doing things. If there isn't anything at the serial port you will just continue doing things.