Noob millis() question

Hi everyone,

I'm brand new to this whole game, but loving it so far the first day. I've got a question though and need a little bit of help here. Im running an arduino uno, and trying to get a simple pushbutton switch to control an LED in a toggleswitch method. Since the switch is Normally Open, I have a simple sketch that keeps the LED on and off after the button is hit. I've done this two ways, one by remembering the preceding digitalRead and only toggling the LED if there was a change, and the other way was by toggling the LED if it had been more than a second since the last hit. Both methods work, however, as time continues, the time method becomes less and less reliable. After about 2 minutes of the program running, you have to push the button several times before the light will actually turn on and off. I assumed it was because the millis() number was getting so big that the simple subtraction was taking too long.

I'm just trying to learn the system better so any info would be helpful. Here are the sketches:

TIME:

int buttonPin = 13;
int ledPin = 7;
int val = 0;
int toggleTime = 0;
int ledState = 0;


void setup() {                

  Serial.begin(9600);
  pinMode(buttonPin, INPUT);     
  pinMode(ledPin,OUTPUT);
}

void loop(){
  val = digitalRead(buttonPin);
  if(val && (millis() - toggleTime) > 1000){
    toggleTime = millis();
    
    if(ledState == 0){
      ledState = 1; 
    }else{
      ledState = 0;
    }
    digitalWrite(ledPin,ledState);
    
  }
}

SIMPLER BETTER METHOD:

int buttonPin = 13;
int ledPin = 7;
int val = 0;
int toggleState = 0;
int ledState = 0;


void setup() {                

  Serial.begin(9600);
  pinMode(buttonPin, INPUT);     
  pinMode(ledPin,OUTPUT);
}

void loop(){
  val = digitalRead(buttonPin);
  if(val && !toggleState){
    
    if(ledState == 0){
      ledState = 1; 
    }else{
      ledState = 0;
    }
    digitalWrite(ledPin,ledState);
  }
  toggleState = val;
}

I suspect the problem you are having with the first method is forgetting that millis() returns a unsigned long value and you are manipulating it with an int value. Read up on types and their various lengths and what you have to do to make them play well with one another. ;)

Lefty

That happened to me too. Unsigned long fixed it. http://www.arduino.cc/en/Reference/UnsignedLong unsigned long toggleTime;

Thanks guys, that makes sense and works much better. A quick question though. I read the docs on signed and unsigned variables, and confess that I really don't understand the difference. Can someone put it in slightly more human terms for me and maybe give a simple example of the difference so I can get it through my thick skull. Thanks!

it comes down to how bits are interpreted. With a signed data type one bit represents whether or not the value is negative. So if you have 8 bits they can represent the following.

unsigned: 0 to 255 (2^8-1) signed: -128 to 127 ( (-1)*2^7 to (1)*2^7-1)

Both have 256 possible values, but on different ranges.

Well I will try to get you started. Both signed and unsigned longs are 32 bits long in Arduino C/C++ (really AVR gcc). A unsigned long is really simple it ranges from 0 to the max that 32 bits can represent and if you increment the max value then it rolls over to become 0. A signed long variable uses 31 bits for the value and the 32nd bit is the sign bit to tell if the value is a positive or negative value. You can research twos complement arithmetic to see how signed variable work in calculations. Anyway because millis() is just a increment count of time elapsed from the last power up or reset condition, it works best as a unsigned variable, otherwise if it used a signed resulted it would be a time machine that could go into the past. ;D

Lefty

Mathematically this (-1)*(0)*2^7-1 is -1... ::)

Mathematically this (-1)*(0)*2^7-1 is -1

You sure about that?

Corrected! Trying to make it more obvious that the -1 is related to the 8th bit... whoops.

briliant everyone. Thanks so much, I had gathered that one bit was for a negative number but couldn't really understand how that played out. Excellent explanation. I'm sure I'll have more questions as time moves on. trying to tackle ppm/pwm today.