Pages: [1]   Go Down
Author Topic: Attempting to control the flow of a program with a while() function  (Read 637 times)
0 Members and 1 Guest are viewing this topic.
Chicago
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm currently trying to make a speedometer using a hall effect sensor(senses the presence of a magnetic field). In my sketch I have 2 functions set up, one that checks the value returned by the hall effect sensor and then sets a variable to HIGH or LOW, the other sets a variable (time) to the current millis() value, then returns that value. What I'm trying to do, and failing at is getting the millis() value when it is high, then letting the program continue to run until the state changes to HIGH again. Hopefully that makes sense, the basic sketch is below, I'm not trying to calculate the speed yet, I'm just trying to first get the time elapsed between HIGH -> LOW -> HIGH.

Code:
int startTime;
int stopTime;
int elapsedTime;
int val;
int state;
int time;
int threshold=520; //sets threshold to 520, this must be calibarated for each sensor


void setup(){
  Serial.begin(9600);
}

void check() {
    if(val < threshold) //checks to see if the value is less than the set threshold
      state=LOW;      //this then sets the state to either low or high
    else
      state=HIGH;
}

int getTimeValue() { //if state is HIGH(magnet present) then assign current millis value to time variable and return that value
    if(state == HIGH) {
      time = millis();
      return time;
    }
}
 
 
void loop() {
  Serial.print("Raw Value: ");
 
  val = analogRead(0); //get raw reading from hall effect sensor, assign to val variable
 
  Serial.print(val); //print raw value, for calbrating the threshold variable
 
  Serial.println("  Elapsed Time: ");
 
  check();
 
  startTime = getTimeValue(); //if the state is HIGH (magnet is present) assign current millis value to startTime

  check(); //checking to see what the state is, HIGH or LOW
 
  //********  somewhere in here I need to control the program so it just loops, without doing anything if the state
  //********  is equal to LOW, then exit this loop when it changes to HIGH then continue running and execute the lines below
  //********  I tried using while(state == LOW); but that stops the program entirely and it never exits, any help is appreciated
 
  stopTime = getTimeValue(); //if it is HIGH again, assign new millis value to stopTime
 
  elapsedTime = (stopTime - startTime); // calculate the difference, should give elapsed time
 
  Serial.print(elapsedTime); //print elapsedTime to serial monitor
}
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 27
Posts: 1184
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You need to do one thing in the while loop - refresh the value of state with the current value of the variable so that when it changes you will exit the loop.

As it is it will never exit because the value of state never changes.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Finland
Offline Offline
Sr. Member
****
Karma: 0
Posts: 270
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A switch-type Hall sensor (a.k.a unipolar hall sensor) is more suitable for a speedometer. Instead of analog readings, it returns logical HIGHs or LOWs depending on the presence of a magnetic field. You could then use interrupts to detect the state changes (FALLING or RISING edges). It would make your sketch a lot simpler.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3969
Where is your SSCCE?!?!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a good tutorial here on how to use the while loop:

http://hacking.majenko.co.uk/the-while-loop
Logged

Why not visit my eBay shop? http://stores.ebay.co.uk/Majenko-Technologies
Replacement for the Arduino IDE: UECIDE - Proper serial terminal, graphing facilities, plugins, overhauled internals.
Java isn't bad in itself, but it has enabled morons to write programs.

Chicago
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys,

Thanks for the info. I had a suspicion that I needed a latching sensor. Anyways, I learned something along the way, and now I understand a little better how the while() loop works. I'm placing an order for latching hall effect sensors now  smiley

I got the previous bit of code to work, it just is not accurate enough because the signal is really "bouncy" when going from LOW to HIGH, and there is actually a very short duration where the signal is HIGH for a few millis while the magnet is passing by the sensor, which is giving it a false reading of 0 or 1 for the elapsed time, but it does return the correct value for elapsed time when it first changes to HIGH. I'm sure there is a way around this problem, and while I'm waiting for the latching type sensor I would love to try and figure it out.

Any ideas or hints? my modified sketch is below:

Code:

int startTime;
int stopTime;
int elapsedTime;
int val;
int state;
int time;
int threshold=520; //sets threshold to 520, this must be calibarated for each sensor


void setup(){
  Serial.begin(9600);
}

void check() {
    val = analogRead(0);
    if(val < threshold) //checks to see if the value is less than the set threshold
      state=LOW;      //this then sets the state to either low or high
    else
      state=HIGH;
}

int getTimeValue() { //if state is HIGH(magnet present) then assign current millis value to time variable and return that value
    check();
    if(state == HIGH) {
      time = millis();
      delay(100);
    }
    return time;
}
 
 
void loop() {
 
  check();
 
  startTime = getTimeValue(); //if the state is HIGH (magnet is present) assign current millis value to startTime
 

  check(); //checking to see what the state is, HIGH or LOW
 
  while(state == LOW) { //this is the new while() statement that constantly checks for the signal to go HIGH
    check();
  }
 
  check();
 
  stopTime = getTimeValue(); //if it is HIGH again, assign new millis value to stopTime
 
  Serial.println("Elapsed Time: ");
 
  elapsedTime = (stopTime - startTime); // calculate the difference, should give elapsed time
 
  Serial.print(elapsedTime); 
}
Logged

Chicago
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thought I would post again since I have gotten somewhere with this. It now "accurately" reads the elapsed time since the last HIGH value was read, and with this I can now calculate speed, rpm, distance. It still randomly gives a weird negative number for elapsed time, not too often though. Next, I want to be able to store data and be-able to upload it to a database later... but that is a whole other can of worms.

Here's the sketch if you are interested:

Code:
float startTime;
float stopTime;
float elapsedTime;
float val;
float state;
float time;
float thresholdHigh=540; //sets threshold to 520, this must be calibarated for each sensor
float thresholdLow=520;


void setup(){
  Serial.begin(9600);
}

void check() {
    val = analogRead(0);
    if(val < thresholdLow) { //checks to see if the value is less than the set threshold
      state=LOW;      //this then sets the state to either low or high
    } else if(val > thresholdHigh) {
      state=HIGH;
    }
}

 
int getTimeValue() { //if state is HIGH(magnet present) then assign current millis value to time variable and return that value
    check();
    while(state == HIGH) { //used a while() loop here to try and stabilize the switch bewteen LOW & HIGH
      time = millis();     //this will only return the value of time when the magnet is no longer present,
      check();             //even with this it still gives a weir negative elapsed time reading every once and a while.
    }
    return time;
}
 
void loop() {
 
  check();
 
  startTime = getTimeValue(); //if the state is HIGH (magnet is present) assign current millis value to startTime
 

  check(); //checking to see what the state is, HIGH or LOW
 
  while(state == LOW) { //this is the new while() statement that constantly checks for the signal to go HIGH
    check();
  }
 
  check();
 
  stopTime = getTimeValue(); //if it is HIGH again, assign new millis value to stopTime
 
  Serial.print(" Elapsed Time: ");
 
  elapsedTime = (stopTime - startTime); // calculate the difference, should give elapsed time
 
  Serial.println(elapsedTime);
  Serial.print("Speed FPS: ");
  float speed = (15.70/(elapsedTime/1000))/12;
  if(speed < 0){
   speed = 0;
  }
  Serial.print(speed);
}
Logged

UK
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3969
Where is your SSCCE?!?!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Store your times (that you get from millis()) in unsigned long, not float.
Logged

Why not visit my eBay shop? http://stores.ebay.co.uk/Majenko-Technologies
Replacement for the Arduino IDE: UECIDE - Proper serial terminal, graphing facilities, plugins, overhauled internals.
Java isn't bad in itself, but it has enabled morons to write programs.

Pages: [1]   Go Up
Jump to: