How can i find the duration of LOW state and use it in conditions?

I am trying to learn arduino for sometime. I got the basics. Now i need to learn more.

I need to measure the duration of LOW state of hall sensor attached to a pin. (d11)
Then, if this duration is less than a specified time (100ms)

loop must do something under "if" conditions. ( keep sending a voltage to a digital pin (2 volts to d6))

if duration is more than a specified period. (wheel is stopped) hall sensor has no change in that time frame , loop must do something else. such as sending a (specified voltage to a led etc). this is important becasue if sensor stopt right on the magnet, it must not do anyting becasue only the duration of LOW state is important.

if i can manage this, low state for a specified time will stop sending voltage ot same output.

i checked several codes on my books and over internet, measuring rpm is always about counting the ticks ( hall sensor high and mesasure the difference by using millis() ).but i want to measure the pulse length by subtracting High state from duration of period. is that correct? could you please assist?

Look at the millis() and micros() functions. They'll give you the time in milliseconds or microseconds since the board started. If you know the time at the beginning of the pulse and the end of the pulse then you just subtract.

is it why we need to set it to 0 when it interrups? then we can calculate it over and over?

when it senses hall sensor pulse(high), and when it is done with it , and when it again senses, or if it won’t ( in a specified time frame) can i use this duration info to decide on something?

Nope you never need to set it to 0. Just take the time at the beginning and the time at the end and subtract.

See the "Blink Without Delay" example where this sort of thing is used to decide how long an LED has been on or off and whether it is yet time to toggle it.

i saw that example.

here is a code i modified slightly. it is actually a speedometer for bicycles.

i replaced reed switch with a hall sensor on pin 2. i am using NANO and it must give out when hall sensor is pulsing and it should stop when it is low for a duration. hall sensor has a built in led so i can see its activity.

there is serial print out to see hall sensor activity.

problem is, this gives the desired voltage to output pin but does not care if INPUT voltage is really present or not.

i need to supply the arduino input with 2 3 4 volts, these volts will determine the output voltage on PWM pin consequently. ( now it gives 1.76 volts for 2 volt input even there i no input connected) because condition for panel input voltage is <= 90 (8 bit) volts. now it is 0 volts because of test bench has no input from panel.

if no hall sensor movement, it gives 0 volts as expected.

int valu = 0;
int panel = 11; //panel voltage input pin 2 3 4 volts preset.
int thr = 6; //voltage output 
int THR1 = 90;  // output preset voltage. approx 1.7 volts 8 bit
int THR2 = 130; // 2.7 volts
int THR3 = 185; // 4.3 volts
int PNLLO = 420; // constant signal from control panel 2 volt. 10 bit
int PNLMD = 630; // 3 volt. 10 bit
int PNLHI = 800; // 4 volt. 10 bit

float rotationTime;
float distanceTravelledPerSecond;
float wheelCircumference = 2;  // Circumference of the wheel
float RPM;
float speeds;
float maximumSpeed;
unsigned int distanceTravelled;
//unsigned int averageSpeed;  // not needed for now
unsigned long revoloutions = 0;
unsigned long startRotation = 0;
unsigned long endRotation = 0;
unsigned long timeInSeconds;
unsigned long timeInMilliseconds;
unsigned long lastMillis;
boolean reedSwitchState;
boolean lastReedSwitchState;
const int reedSwitchPin = 2;

int buttonState;
int val;
int val2;

void DoTimeAndDistanceCalcs()
{
  revoloutions ++;
  endRotation = millis();
  rotationTime = endRotation - startRotation;
  startRotation = endRotation;
  RPM = (600 / rotationTime);
  distanceTravelled = revoloutions * wheelCircumference / 100;
  distanceTravelledPerSecond = RPM * wheelCircumference;
  distanceTravelledPerSecond = distanceTravelledPerSecond / 1000 * 60;
  speeds = distanceTravelledPerSecond;
  if (speeds > maximumSpeed)
    maximumSpeed = speeds;
  timeInSeconds = millis();
  timeInSeconds = timeInMilliseconds / 1000;
  //averageSpeed = (distanceTravelled / timeInSeconds);  //not needed for now
}

void setup() {
  pinMode(reedSwitchPin, INPUT);
  Serial.begin(9600);
  buttonState = digitalRead(reedSwitchPin);
  // lcd.begin(16,4);

}
void loop() {

  valu = analogRead(panel);
  val = digitalRead(reedSwitchPin);
  delay(10);
  val2 = digitalRead(reedSwitchPin);

  if (val == val2) {
    if (val != buttonState) {
      lastReedSwitchState = reedSwitchState;
      reedSwitchState = val;


      if ((lastReedSwitchState == HIGH) && (reedSwitchState == LOW) && (valu <= PNLLO)) {
        DoTimeAndDistanceCalcs();

        analogWrite(thr, THR1); // this supplies THR1 preset voltage to output pin

        //  lcd.setCursor(8,3); from original code

      }





      else  {
        DoTimeAndDistanceCalcs();
        delay(1500);
        analogWrite(thr, 0); // if no activity on hall sensor gives 0 volts to output.
      }
    }


  }
  buttonState = val ;
  Serial.println(digitalRead(reedSwitchPin)); //halls sensor activity

}

i need to add two other conditions for my panel voltages. 2 is already written in sketch.

but i cant add 3 volts and 4 volts. which are THR2 and THR3.

i need to tell it to

A)output THR2 if there is hall sensor activity and if panel supplies 3 volts
B)output THR3 if there is hall sensor activity and if panel supplies 4 volts to arduino input pin.

what ever i do, it acts weird.it tries to give 1.76 volts and other preset voltages in a loop. or i am missing somehting? could you please help to add these to my sketch?

if we can manage to do this, whenever i supply appropriate voltage to arduino, arduino will give correct preset output votlages as long as hall sensor is pulsing.

analogWrite(thr, THR1); // this supplies THR1 preset voltage to output pin

Despite the comment that is not what it does. It supplies 5V to the pin using a PWM signal that turns on and off rapidly. The on/off cycle is controlled by the second parameter of analogWrite().

there is a simple filter to convert PWM to DC. this works on my application.

could you please help to solve longer HALL state "HIGH" situation which makes arduino keeps output voltage on?

i need to add a statement which makes it to stop if hall sensor stuck at a positon for a period of time which magnet levels with sensor but no voltage needed on output pin.

(if hall sensor reads high more than 1 second stop sending it)

could you please help to solve longer HALL state "HIGH" situation which makes arduino keeps output voltage on?

How is your hall effect sensor wired? You MUST pull the pin HIGH or LOW. You can pull it HIGH using the internal pullup resistor, or you can pull it HIGH or LOW using an external resistor.

i need to add a statement which makes it to stop if hall sensor stuck at a positon for a period of time which magnet levels with sensor but no voltage needed on output pin.

This is a requirement that has long since been solved. Mr. Google will surely help you find a solution. That solution will involve know what time it is now (using millis() or micros()) and knowing what time the last state change happened (again using millis() or micros()).

there is a simple filter to convert PWM to DC. this works on my application.

I must have missed your earlier mention of the filter.

on my hall sensor shield, there is a resistor between ground and signal.

If you want to use pulses from a Hall sensor to measure RPM you should record the value of micros() for every pulse and by subtracting the previous value from the recent value you will know the time between pulses and can calculate the speed from that.

It is pointless to have any delay() in code that should run as fast as possible.

I suggested this in another recent Thread. It compiles but I have not tested it and I have not heard whether it worked.

byte pulsePin = 2;
unsigned long prevPrintMillis;
unsigned long printIntervalMillis = 1000;

unsigned long prevPulseMicros;
unsigned long newPulseMicros;
volatile unsigned long latestPulseMicros;
volatile boolean newPulse = false;
unsigned long microsBetweenPulses;



void setup() {
    Serial.begin(9600);
    Serial.println("Starting my program");

    pinMode(pulsePin, INPUT_PULLUP);
    attachInterrupt(0, pulseDetect, RISING);
}

void loop() {
    if (newPulse == true) {
        prevPulseMicros = newPulseMicros;
        noInterrupts();
            newPulseMicros = latestPulseMicros;
            newPulse = false;
        interrupts();
        microsBetweenPulses = newPulseMicros - prevPulseMicros;
    }
    if (millis() - prevPrintMillis >= printIntervalMillis) {
        prevPrintMillis += printIntervalMillis;
        Serial.print("Micros Between Pulses ");
        Serial.println(microsBetweenPulses);
    }
}

void pulseDetect() {
    latestPulseMicros = micros();
    newPulse = true;
}

...R

my intention is not measuring the rpm. that was best i could find at that moment.

i think i did it finally. and learned a lot in past weeks.

here is what i did.

int val = 0;
int panel = 11; //panel voltage input pin 2 3 4 volts preset.
int thr = 6; //voltage output
int THR1 = 90;  // output preset voltage. approx 1.7 volts 8 bit. RC filter for PWM to DC.
int THR2 = 130; // 2.7 volts
int THR3 = 185; // 4.3 volts
int PNLLO = 420; // constant signal from control panel 2 volt. 10 bit
int PNLMD = 630; // 3 volt. 10 bit
int PNLHI = 800; // 4 volt. 10 bit
int ledPin = 13;  //integrated led
int hallsensor = 2; // hall sensor pin.
 
 
 
int firsttime = 1;
unsigned long startTime;
unsigned long hallTime;
 
void setup()
{
 
 
 
  pinMode(ledPin, OUTPUT);
  pinMode(hallsensor, INPUT);
  pinMode(hallsensor, INPUT_PULLUP);
  digitalWrite(hallsensor, HIGH);
 
  Serial.begin(9600);
}
 
void loop()
{
  if ((digitalRead(hallsensor) == LOW) && (panel <= PNLLO)) {  //if panel gives 2 volts.
    if (firsttime == 1) {
      startTime = millis();
      firsttime = 0;
      analogWrite(thr, THR1); // arduino has 1.7 volts output
     
      delay (400);
    
 
    } else
    { if ((digitalRead(hallsensor) == LOW) && (panel > PNLLO) && (panel < PNLHI)) { //if panel gives 3 volts.
        if (firsttime == 1) {
          startTime = millis();
          firsttime = 0;
          analogWrite(thr, THR2); // arduino has 1.7 volts output
        
          delay (400);
 
        } else
        { if ((digitalRead(hallsensor) == LOW) && (panel >= PNLHI)) { //if panel gives 4 volts.
            if (firsttime == 1) {
              startTime = millis();
              firsttime = 0;
              analogWrite(thr, THR3); // arduino has 1.7 volts output
             
              delay (400);
            }
 
          }
        }
      }
    }
 
 
 
 
    hallTime = millis() - startTime;
    if (hallTime >= 1) {
      Serial.print("Time: ");
      Serial.print(hallTime);
      Serial.print(" milliseconds ");
      Serial.print(int(hallTime / 1000));
      Serial.println(" seconds");
    }
    if (hallTime > 500) {  // if hall sensor matches to the magnet for more dan 0.5 sec
      digitalWrite(ledPin, HIGH);
      analogWrite(thr, 0); // cut power
    }
 
  } //***
  else if (firsttime == 0) { // if no pulse on hall sensor
    firsttime = 1;
    Serial.println("Time: 0 milleseconds; 0 seconds");
    digitalWrite(ledPin, LOW);
    delay (400);
    analogWrite(thr, 0); // more than delay, cut power.
  }
}

i need to try it on actual setup.

You may find the pulseIn() function useful

Allan

wow, interesting :slight_smile: this can work easily. may be on next version. thank you.