1

Hello guys (and gals)!

I'm trying to figure out how to program thresholds using my arduino board.

Essentially, to make this as simple as possible, this is what I have going on.

I am sampling a value every one second, I am taking the value and trying to make certain actions occur based on when this value crosses certain thresholds.

The value read every second will be a value between 0-150.

The thresholds will work something like this:

If value crosses over 20 and becomes 20 or higher, do an action.

If value crosses over 20 and becomes 19.9 or less, do a different action.

And then do the same for a threshold at 30, 40, 50, and 65.

I would need to have it so that if it reads a value of 15, and then a second later, reads a value of 23, it does an action. But if it reads 23, and then reads 24 a next, it needs to not do anything because it hasn't crossed over from one threshold to another. I only want an action to perform if a threshold is crossed either by increasing or decreasing past it.

So again, to reiterate;

If first value read is 34, and second is 42, do an action.

If first value is read at 57, and second at 44, do an action.

If first value is 24, and second value is 26, do nothing. (no threshold was crossed)

The next part would be figured out if a threshold was crossed twice, or more, to do that action twice or more times.

Any advice on how to code this?

Thanks in advance.

1

Thanks again for your contributions.

I've gone ahead and decided to go with the following code. Its purpose is to turn vol up or down based on current car MPH. I choose to define brackets that cover a range of values. When one bracket ends, another begins. I've also set the previous bracket to current bracket at the end of each loop so that the application knows where it was previously, so that if it hops above or goes under a defined bracket, it does the desired action.

I've used a random generator to supply the MPH for testing purposes for now and commented out a few things that disturbed the testing process. If you'd like to critique this code to make is better, please let me know.

Note: I've also borrowed some of this code from another individual (Matthew McMillan, http://matthewcmcmillan.blogspot.com) who wanted to figure out how to convert a vehicle speed sensor wire info into MPH. I needed this code in order to make use of the vehicle's speed.

#include <SPI.h>
#include <Wire.h>

const int lightPin = 0;
const int hardwareCounterPin = 5;
const int samplePeriod = 1000; //in milliseconds
const float pulsesPerMile = 4000; // this is pulses per mile for Toyota. Other cars are different.
const float convertMph = pulsesPerMile/3600;
unsigned int count;
float mph;
unsigned int imph;
int roundedMph;
int previousMph;
int prevCount;

// Declare brackets
const int BracketA = 1;
const int BracketB = 2;
const int BracketC = 3;
const int BracketD = 4;
const int BracketE = 5;
const int BracketF = 6;

// Initialize Previous and Current Brackets
int PreviousBracket = 1;
int CurrentBracket = 1;


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

  TCCR1A = 0; //Configure hardware counter 
  TCNT1 = 0;  // Reset hardware counter to zero
}

void loop() {


  /////////////////////////////////////////////////////////////
  // This uses the hardware pulse counter on the Arduino.
  // Currently it collects samples for one second.
  //
  bitSet(TCCR1B, CS12); // start counting pulses
  bitSet(TCCR1B, CS11); // Clock on rising edge
  delay(samplePeriod); // Allow pulse counter to collect for samplePeriod
  TCCR1B = 0; // stop counting
  count = TCNT1; // Store the hardware counter in a variable
  TCNT1 = 0;     // Reset hardware counter to zero
  mph = (count/convertMph)*10; // Convert pulse count into mph.
  imph = (unsigned int) mph; // Cast to integer. 10x allows retaining 10th of mph resolution.

  int x = imph / 10;
  int y = imph % 10;

  // Round to whole mile per hour
  //if(y >= 5){
  //  roundedMph = x + 1;
  //}else{
  //  roundedMph = x;
 // }


  //Code to write your own MPH for testing purposes.
  //if (Serial.available() > 0) {
                // read the incoming byte:
               // roundedMph = Serial.read();
               //}

  //If mph is less than 1mph just show 0mph.
  //Readings of 0.9mph or lower are some what erratic and can
  //occasionally be triggered by electrical noise.
  //if(x == 0){
  //  roundedMph = 0;
 // }

  roundedMph = random(1,80);


  // Don't display mph readings that are more than 50 mph higher than the 
  // previous reading because it is probably a spurious reading.
  // Accelerating 50mph in one second is rocketship fast so it is probably
  // not real.
  if((roundedMph - previousMph) > 50){
    roundedMph = previousMph;
  }


  //Place the gatherered MPH value into a bracket
  //---------------------------------------------
  if(roundedMph >= 0 && roundedMph < 20) {
   CurrentBracket = BracketA;  //Value1
   Serial.println("I Choose Bracket A");
    }

  if(roundedMph >= 20 && roundedMph < 30) {
   CurrentBracket = BracketB;  //Value2
   Serial.println("I Choose Bracket B");
    }

  if(roundedMph >= 30 && roundedMph < 40) {
   CurrentBracket = BracketC;  //Value3
   Serial.println("I Choose Bracket C");
    }

  if(roundedMph >= 40 && roundedMph < 50) {
   CurrentBracket = BracketD;  //Value4
   Serial.println("I Choose Bracket D");
    }

  if(roundedMph >= 50 && roundedMph < 65) {
   CurrentBracket = BracketE;  //Value5
   Serial.println("I Choose Bracket E");
    }

  if(roundedMph >= 65) {
   CurrentBracket = BracketF;  //Value6
   Serial.println("I Choose Bracket F");
    }


 //Decide if bracket stayed the same, went up, or down. 
 //--------------------------------------------------- 
 if(CurrentBracket == PreviousBracket) {
 //Do Nothing
 Serial.println("Nothing Changed");
 }  

if(CurrentBracket > PreviousBracket) {
 //Command for Vol Up
 int VolUp;
 VolUp = CurrentBracket - PreviousBracket;
Serial.println("Volume Went Up One by "); 
Serial.println(VolUp);
delay(2000); // Delay to not change Vol to fast if near threshold 
}

if(CurrentBracket < PreviousBracket) {
  //Command for Vol Down
  int VolDown;
  VolDown = PreviousBracket - CurrentBracket;
 Serial.println("Volume Went Down One by ");  
 Serial.println(VolDown);
 delay(2000); // Delay to not change Vol to fast if near threshold
 }
  previousMph = roundedMph; // Set previousMph for use in next loop.
  PreviousBracket = CurrentBracket; //Set PreviousBracket for use in next loop.
}
0

The way you described it, the first and good solution I can approach it is state machine.

You have a lot of thresholds to check and very specific details such as going up at some level and doing something or nothing depending on the level.

What I advise you is creating the state machine for you code setting up all the thresholds and saving the actual state of your system into a variable. After you have this set up, coding is just a matter of switch/cases or if statements.

For example. The first part is to check if it goes until 20 and then keep with at least 20.

switch (state) {
    case 1:
        if (value >= 20 && value < 30)
             state = 2;
        break;
     case 2:
        if (value < 20)
             state = 1;  // initial state
        else if (value >= 20 && value < 30)
             state = 3; // or call a function
        break;
     case 3:
          doSomething();
          break;
}

And you could have some delay or timer interrupt to check the value each 1s and repeat the state machine again and again. If you change or read the value inside an interrupt function call, make sure you declare the variable as volatile otherwise the compiler will optimize it and your machine won't work properly.

This way you can expand the idea and have all the thresholds set up.

  • That code is faulty – as it stands, once the state changes to 3, it stays at 3 no matter what value occurs. Also, when state is 1, a value of 30 or more doesn't get processed. So for example the sequence 15, 35, 15 results in no actions occurring. – James Waldby - jwpat7 May 14 '15 at 4:45
  • Good point, @jwpat. Well, inside the function doSomething, there could be a verification and then decide which state to go in sequence. This code is just a start point where someone could develop their own code. The user has to make sure it checks every single situation to make sure it'll work properly. – bpinhosilva May 14 '15 at 4:51
  • It's always a good idea to add a Serial.print() and else/default to be notified via serial if any values go over/under your radar, especially as a beginner. – Avamander Feb 21 '16 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.