Go Down

Topic: Using Hall Sensor(TLE-4905) with Arduino Mega (Read 854 times) previous topic - next topic

cyber_warrior

Hi,

I am using hall sensor with Arduino Mega to measure RPM of my car. I have seen many posts about how to use it but I have an issue. The pin connection in my setup is as shown in the image i.e the hall sensor is  connected to external clock input (T5) of Timer/Counter5. Pin T5 is digital pin 47 in arduino mega and this pin doesn't have an external interrupt associated with it. So how can I measure RPM without using interrupt in this case?

PS: The circuit is much more complex and therefore I cannot change the pin connections.

Thank in advance. :)

cattledog

Quote
So how can I measure RPM without using interrupt in this case?
The input of the hall sensor to the external clock source T5 will count pulses in TCNT5. The hall sensor is open collector so be sure to have an external pullup or use  INPUT_PULLUP.  Set up the timer to trigger on one pulse edge. You will need to refer to the Atmel processor data sheet for the Mega.

You can determine RPM from the number of pulses occurring in a fixed period of time. Use another hardware timer, or a milis()  software timer as a counting period.

cyber_warrior

If possible, can you share a code which does this? Because I am not that well acquainted with Arduino yet...

Thanks :)

MasterT

How you powered up your sensor? Be advised, that arduino doesn't tolerate voltage above Vcc on its inputs.
Here is the code, reply #4.

cyber_warrior

The sensor is powered correctly I think. No issues with that. And thanks for sharing the code. It looks very complex but can you just drop me some hints how can I use it in my case? (I mean I have no idea what this means "to get maximum precision out of arduino's ICP feature")

MasterT

The sensor is powered correctly I think. No issues with that. And thanks for sharing the code. It looks very complex but can you just drop me some hints how can I use it in my case? (I mean I have no idea what this means "to get maximum precision out of arduino's ICP feature")
It's mean best accuracy. There are many ways to measure frequency (or RPM) by arduino.

cattledog

Quote
Here is the code, reply #4.
That code is using the ICP(input capture) pin. ICP5 is on D48.

The OP claims that he only has the external clock source pin(T5) on D47 available.

If that's the case, you can not determine the pulse characteristics, but only the count the number of pulses in a period of time.

You will be using the timer/counter as a counter. Here is some sample code written for Timer1 on a UNO.

Code: [Select]

unsigned long count_period = 2000;
unsigned int count_to_rpm = 60000UL / count_period; //convert counts to RPM
byte number_of_sensors = 1;
unsigned long final_counts;
unsigned long start_time = millis();
unsigned long measured_time;
unsigned long current_time = millis();

void setup()
{
  Serial.begin(115200);
  TCCR1A = 0; //initialize Timer1
  TCCR1B = 0;
  TCNT1 = 0;
  pinMode( 5, INPUT_PULLUP); //external source pin for timer1
  //set external clock source pin D5 rising edge
  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);

  //Test pulses to confirm circuit 50 pps =  3000
  //pinMode(11, OUTPUT);
  //tone(11, 50);//test pulse jumper pin 11 to pin 5
}

void loop()
{
  current_time = millis();
  if (current_time - start_time >= count_period)
  {
    TCCR1B = 0; //stop counter
    final_counts = TCNT1; //frequency limited by unsigned int TCNT1 without rollover counts
    TCNT1 = 0;
    measured_time = current_time - start_time;
    start_time = current_time;;
    unsigned int rpm = (final_counts * count_to_rpm) / number_of_sensors;
    TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12); //restart external clock source

    Serial.print(measured_time);
    Serial.print("\t\t");
    Serial.print(final_counts);
    Serial.print("\t\t");
    Serial.println(rpm);
  }
}

MasterT

That code is using the ICP(input capture) pin. ICP5 is on D48.

The OP claims that he only has the external clock source pin(T5) on D47 available.
Right, only ICP4 on pin D49.  But since OP didn't noticed, it means he did not read anything in the code, except first comments line.
For average person it would not take much time to change registers names Timer4 to Timer5. Think of it like stupidity test, and sadly, OP failed. No offence meant.

cattledog

Quote
The circuit is much more complex and therefore I cannot change the pin connections.
Quote
I am not that well acquainted with Arduino yet...
I too, have my doubts that the OP will have success wandering off the standard path and into Timer/Counter country with register settings. The code I suggested can be pretty much directly converted from Timer1 to Timer5.




cyber_warrior

That code is using the ICP(input capture) pin. ICP5 is on D48.

The OP claims that he only has the external clock source pin(T5) on D47 available.

If that's the case, you can not determine the pulse characteristics, but only the count the number of pulses in a period of time.

You will be using the timer/counter as a counter. Here is some sample code written for Timer1 on a UNO.

Okay so I understand this code pretty well. I tried running it with the following changes and it prints only zeroes in the output. Where am I going wrong? (I think the pin number in pinMode is not right...)

Code: [Select]

unsigned long count_period = 2000;
unsigned int count_to_rpm = 60000UL / count_period; //convert counts to RPM
byte number_of_sensors = 1;
unsigned long final_counts;
unsigned long start_time = millis();
unsigned long measured_time;
unsigned long current_time = millis();

void setup()
{
  Serial.begin(115200);
  TCCR5A = 0; //initialize Timer5
  TCCR5B = 0;
  TCNT5 = 0;
  pinMode( 47, INPUT_PULLUP); //external source pin for timer1
  //set external clock source pin D5 rising edge
  TCCR5B =  bit (CS50) | bit (CS51) | bit (CS52);

  //Test pulses to confirm circuit 50 pps =  3000
  //pinMode(11, OUTPUT);
  //tone(11, 50);//test pulse jumper pin 11 to pin 5
}

void loop()
{
  current_time = millis();
  if (current_time - start_time >= count_period)
  {
    TCCR5B = 0; //stop counter
    final_counts = TCNT5; //frequency limited by unsigned int TCNT5 without rollover counts
    TCNT5 = 0;
    measured_time = current_time - start_time;
    start_time = current_time;;
    unsigned int rpm = (final_counts * count_to_rpm) / number_of_sensors;
    TCCR5B =  bit (CS50) | bit (CS51) | bit (CS52); //restart external clock source

    Serial.print(measured_time);
    Serial.print("\t\t");
    Serial.print(final_counts);
    Serial.print("\t\t");
    Serial.println(rpm);
  }
}


Thanks for the help. :)

cattledog

Quote
it prints only zeroes in the output.
What is your input?

Before trying with the hall sensor, use the test I suggested with a pulse from tone() jumpered from an output pin to your input pin 47.

Quote
I think the pin number in pinMode is not right..
Pin 47 should be correct.


cyber_warrior

Okay it works now. The hall sensor wasn't receiving power from the arduino (I had to power it with battery). Thanks alot for the help :))))

Southpark

I too, have my doubts that the OP will have success wandering off the standard path and into Timer/Counter country with register settings. The code I suggested can be pretty much directly converted from Timer1 to Timer5.
Approx 1 year late getting here hehehe. But --- cattledog, first --- thanks very much for posting your code, as I am just about to try your code and then study and understand it real carefully.

Last year, I was trying to use the arduino mega to read rpm of small dc motors up to around 4000 rpm (max) --- using interrupt counting of pulses. Wvmarle (member) correctly pointed out that there can be (or will be) over-head associated with interrupt counting. I'm using a 1024 p/r rotary encoder at the moment, so that could be an issue with the number of interrupts coming at the angular speeds being used here. I can later try lower pulse per rev rotary encoders too. I've been getting maybe +/- 5 percent variation (from averaged rpm value) with my interrupt counting code, while the hand-held laser tachometer gives quite nice and stable readings at the 'correct' (averaged) RPM value.

So I'm going to turn toward the method used in your code!

One small question is --- what did you mean by "have my doubts that the OP will have success wandering off the standard path and into Timer/Counter country with register settings" ?

What did you mean by wandering off the standard path, and into timer/counter country with register settings? Your method for RPM measurement is based on timer/counter country, right? Just trying to understand this - as I don't want to head down the wrong path myself. Thanks again!


cattledog

#13
Jul 08, 2019, 01:16 am Last Edit: Jul 08, 2019, 01:17 am by cattledog
Quote
One small question is --- what did you mean by "have my doubts that the OP will have success wandering off the standard path and into Timer/Counter country with register settings" ?
No worries for you.

The OP was a self proclaimed newbie who was "not well acquainted with Arduino yet". He even appeared to be short of pins on a Mega somehow and couldn't figure out how to change anything around to free different pins.

Using the external clock source as a high speed rpm counter is very much recommended when interrupts techniques start to fail.


Southpark

#14
Jul 08, 2019, 01:19 am Last Edit: Jul 09, 2019, 09:04 am by Southpark
Cattledog ..... your code works very nicely on my mega 2560 (as was expected!)

I'll paste your code (with the timer numbers and pin numbers in some comments for aligning with the mega 2560).

I'll also paste some results from the serial monitor.

Using the external clock source as a high speed rpm counter is very much recommended when interrupts techniques start to fail.
A very significant and great recommendation cattledog!


Code: [Select]

unsigned long count_period = 2000;  // units of millisec
unsigned int count_to_rpm = 60000UL / count_period; //convert counts to RPM
byte number_of_sensors = 1;
unsigned long final_counts;
unsigned long start_time = millis();
unsigned long measured_time;
unsigned long current_time = millis();

void setup()
{
  Serial.begin(115200);
  TCCR5A = 0; //initialize Timer5
  TCCR5B = 0;
  TCNT5 = 0;
  pinMode( 47, INPUT_PULLUP); //external source pin for timer 5 of MEGA 2560
  //set external clock source pin T5 (digital pin 47) to clock on a rising edge
  TCCR5B =  bit (CS50) | bit (CS51) | bit (CS52);

  //Test pulses to confirm circuit 50 pps =  3000
  pinMode(11, OUTPUT);
  tone(11, 50);//test pulse jumper pin 11 to pin 47 of MEGA 2560
}

void loop()
{
  current_time = millis();
  if (current_time - start_time >= count_period)
  {
    TCCR5B = 0; //stop counter
    final_counts = TCNT5; //frequency limited by unsigned int TCNT5 without rollover counts
    TCNT5 = 0;
    measured_time = current_time - start_time;
    start_time = current_time;;
    unsigned int rpm = (final_counts * count_to_rpm) / number_of_sensors;
    TCCR5B =  bit (CS50) | bit (CS51) | bit (CS52); //restart external clock source

    Serial.print(measured_time);
    Serial.print("\t\t");
    Serial.print(final_counts);
    Serial.print("\t\t");
    Serial.println(rpm);
  }
}


Code: [Select]

2000 101 3030
2000 100 3000
2000 100 3000
2000 100 3000
2000 100 3000
2000 100 3000
2000 101 3030
2000 100 3000
2000 100 3000


Go Up