1

If the vibration sensor with Arduino detects two high inputs within 1 minute, I want the led to flash in one second.

My ability to write Arduino code is very low; I tried with millis() but I couldn't.

I want it to ignore the first high entrance.

Thank you for all the information you will give.

const byte sensor = 7;
const byte LED = 13;
unsigned long sensorMillis;
unsigned long ledTurnedOnAt;
unsigned long high_1 = 60000UL;
bool ledState = false;

void setup() {
  pinMode(sensor, INPUT);
  pinMode(13, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  if (digitalRead(sensor) == HIGH) {
    sensorMillis = currentMillis;
    ledstate = true;
  }

  if (ledstate == HIGH) && ((unsigned long)(currentMillis - ledTurnedOnAt) <= high_1) {
    digitalWrite(8, HIGH);
    delay (1000);
    digitalWrite(8, LOW);
  }

  ledstate = false;
}
7
  • It works better if you ask a question about a specific thing you are getting stuck on. – timemage Dec 14 '20 at 14:45
  • Edit your question to show the code for your attempt, along with a description of how it fails to meet your goal. You'll also need to map out your desired logic in detail. First high reading is ignored. 2nd high reading lights LED. Then what? Do you want the LED to turn off once the vibration sensor shuts off, or after some period of time? Or do you want it to stay on forever once it turns on the first time? – Duncan C Dec 14 '20 at 14:49
  • I want it to ignore the first high input, I want the led to flash immediately with the second high input. – Sabri73 Dec 14 '20 at 14:52
  • 1
    You may want to read about The Finite State Machine. – Edgar Bonet Dec 14 '20 at 17:07
  • 1
    thank you edgar Bonet – Sabri73 Dec 14 '20 at 21:05
2

One simple solution could be:

Start by noticing the first time you get the HIGH input whit a simple if statement:

if (digitalRead(sensor) == HIGH) {
}

where sensor is the pin of the sensor according to your code.

When this statement is True, you are interested in remain here until one of two things happens:

  • either you interrupt some kind of loop with another HIGH input,
  • or the time you have set is passed.

One way of knowing elapsed times will be with the millis() function, that returns the milliseconds since the board began running. We should get the elapsed time the first time we enter the loop:

if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
}

Then, as I have said, we need to remain here for a specific amount of time. We could use the while loop, but, which condition needs to be true?

So we have a start time, lets said x and you need to stay in the loop for, let's say, y milliseconds. This is the same as saying that you want to stay in the loop until the time we enter the loop and a specific amount of milliseconds, x+y. When the millis() function gives us a greater number, we should exit the loop:

if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
  while (millis() <= (startTime+1000))
//                              ^ The second you are interested, 1000 milliseconds.
}

Now, we have to check if there is another interrupt during this time, by using the same statement of the beginning:

if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
  while (millis() <= (startTime+1000)) {
    if (digitalRead(sensor) == HIGH) {
      // 2 interrupts in less than 1000 millis!
    }
  }
}

Summarizing is nicer to declare a global with the specific time we want, instead of the 1000 value we are using now:

const long maxTimeInterval = 1000;

And changing it in our code (that is inside the loop())

if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
  while (millis() <= (startTime+maxTimeInterval)) {
    if (digitalRead(sensor) == HIGH) {
      // 2 interrupts in less than 1000 millis!
      digitalWrite(LED, HIGH);
    }
  }
}

Hope this helps!

5
  • > Start by noticing the first time you get the HIGH input whit a simple if statement Cannot see you your code doing so. – DataFiddler Dec 20 '20 at 11:23
  • @DataFiddler I have all wrapped inside if (digitalRead(sensor) == HIGH) { ... } – Juan CA Dec 20 '20 at 12:52
  • Thank you very much. @Juan CA you are great. code works well. – Sabri73 Dec 20 '20 at 13:38
  • @juan CA .I asked a lot of people, nobody succeeded. You succeeded easily. You are wonderful. If you were close, I would like to give you a gift. – Sabri73 Dec 20 '20 at 13:43
  • Thank you very much to all site administrators – Sabri73 Dec 20 '20 at 13:44
1
const int sensor = 7;
const int LED = 13;
unsigned long sensorMillis;
unsigned long ledTurnedOnAt;
unsigned long high_1 = 60000UL;
bool ledState = false;
void setup() {
  pinMode(sensor, INPUT);
  pinMode(LED, OUTPUT);
  delay(1000); //Warm up Time
}

void loop() {
  unsigned long currentMillis = millis();

  if (digitalRead(sensor) == HIGH) {
    sensorMillis = currentMillis;
    ledstate = true;
  }

  if (ledstate == HIGH) && ((unsigned long)(currentMillis - ledTurnedOnAt) <= high_1) {
    digitalWrite(8, HIGH);
    delay (1000);
    digitalWrite(8, HIGH);
  }

  ledstate = false;
}

I haven't checked this because I don't have my hardware. However, I added a delay of 1 second in the setup as a warm up time. This in theory should ignore the first high. Hope it helped.

1
  • 1
    "N0m4d "Thank you very much for your attention and help – Sabri73 Dec 15 '20 at 9:46
0

Or what about adding another global boolean;

bool firstTime = true;

and then amend you loop() code as follows;

if (digitalRead(sensor) == HIGH) {
    if (firstTime) firstTime = false;
    else {
        sensorMillis = currentMillis;
        ledstate = true;
    }
  }
1
  • thank you Rob W. i will try – Sabri73 Dec 19 '20 at 14:44

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.