Go Down

Topic: Traction Control for Motorcycle using hall sensors to measure wheel speed. (Read 1 time) previous topic - next topic

akmcgregor

I'm sorry PaulS I am unsure what you are saying. Could you please elaborate a bit more on this.
I had a look at your code PaulMurrayCbr but I don't understand it at all. It looks to be a very long and complicated code.
Is there somewhere or someone I can pay to just write the code for me. I would like to have done it myself but I have realised that I just do not have knowledge to do so?
Thanks.

PaulS

Quote
I'm sorry PaulS I am unsure what you are saying.
Then, forget it. This project is beyond your abilities at this time. If you can't even recognize an attachInterrupt() call, you are not going to get this project working.
The art of getting good answers lies in asking good questions.

akmcgregor

I'm sorry if I've upset you. My knowledge of coding is very basic. I do understand attachInterrupt () by following through examples of 1 interrupt but I am unsure where to put the second one. If I don't put the second one where it is then it would fall into the loop would it not? I thankyou for all the help you have given me so far.

PaulS

Quote
I do understand attachInterrupt ()
Then you should know that you should attach both handlers in setup().

Quote
If I don't put the second one where it is then it would fall into the loop would it not?
I do not know what you mean by "fall into the loop".

Suppose you have to answer the phone when it rings, answer the door when the doorbell rings, and cook dinner.

You would not wait to register that you were responsible for answering the door until the phone rang, would you? Well, that is what you are doing by attaching the second interrupt handler in the first interrupt handler.

You would primarily be responsible for cooking dinner, regardless of how many times the phone or doorbell rang. So, if that is what you mean bt "fall into the loop", well then that IS what is supposed to happen.
The art of getting good answers lies in asking good questions.

akmcgregor

For anyone attempting a project like this I managed to get both sensors to read. All I have to do now is get it to cut the engine when rear wheel is spinning faster. Thanks for all your help PaulS.
Here is the code
Code: [Select]

extern volatile unsigned long timer0_overflow_count;  // Record the most recent timer ticks

volatile boolean ticks_valid0;                         // Indicates a valid reading
volatile boolean ticks_valid1;
volatile unsigned long ticks_per_rev0;                 // Number of ticks counted in the current revolution
volatile unsigned long ticks_per_rev1;
unsigned long msSinceRPMReading0;                      // Number of mSec since the last rpm_sense (used to spot zero RPM)
unsigned long msSinceRPMReading1;
float lastRPM0;                                        // Most recent RPM reading, and highest RPM recorded since last reset
float lastRPM1;
const float __TICKS_TO_RPMS0 = 15e6;                   // Convert clock ticks to RPM by dividng ticks into this number
const float __TICKS_TO_RPMS1 = 15e6;                                                      // The number will change if there are more magnets in an rpm
                                                      //   (e.g. 2 magnets = 29296.875)
const unsigned int __WAIT_BEFORE_ZERO_RPM0 = 2000;     // Number of mS to wait for an rpm_sense before assunming RPM = 0.
const unsigned int __WAIT_BEFORE_ZERO_RPM1 = 2000;
unsigned long msSinceSend0;                            // mSec when the last data was sent to the serial port
unsigned long msSinceSend1;
const unsigned int __WAIT_BETWEEN_SENDS0 = 1000;       // Number of mS to wait before sending a batch of data.
const unsigned int __WAIT_BETWEEN_SENDS1 = 1000;
float kmh0;
float kmh1;
void setup()
{

  Serial.begin(9600);                                 // Initialise serial comms.
  msSinceSend0 = millis();                             // Data sent counter
 
 
  attachInterrupt(0, rpm_sense0, RISING);              // RPM sense will cause an interrupt on pin2
  msSinceRPMReading0 = 0;                              // If more than 2000 (i.e. 2 seconds),
                                                    // then RPMs can be assumed to be zero (< 15rpm
                                                      // at most, with a single magnet, no small IC
                                                      // can run that slowly).
  lastRPM0 = 0;                                        // Current RPM to zero
 
  msSinceSend1 = millis();
  attachInterrupt(1, rpm_sense1, RISING);              // RPM sense will cause an interrupt on pin2
  msSinceRPMReading1 = 0;
 
 
  lastRPM1 = 0; 
 
 }

// ------------------------------------------------------------------------------------------------
// FUNCTION: RPM-SENSE
//
// Called whenever the RPM sense signal rises. In my setup, the hall effect switch is normally
// high, goes low when a south pole is introduced to the sensor, and rises back to high as the
// magnet goes away. Thus, the RPM sense is called on the trailing edge of the magnet.
// ------------------------------------------------------------------------------------------------
void rpm_sense0()
{
  static unsigned long pre_count0;               // Last timer0_overflow_count value
  unsigned long ticks_now0;                      //

  ticks_now0 = timer0_overflow_count;            // Read the timer

  byte t0 = TCNT0;
  if ((TIFR0 & _BV(TOV0)) && (t0<255))
    ticks_now0++;
  ticks_now0 = (ticks_now0 << 8) + t0;

  if (pre_count0 == 0) {                         // First time around the loop?
    pre_count0 = ticks_now0;                      // Yes - set the precount, don't use this number.
  } else {
    ticks_per_rev0 = ticks_now0 - pre_count0;      // No - calculate the number of ticks...
    pre_count0 = ticks_now0;                      // ...reset the counter...
    ticks_valid0 = true;                         // ...and flag the change up.
  }
 }

void rpm_sense1()
{
  static unsigned long pre_count1;               // Last timer0_overflow_count value
  unsigned long ticks_now1;                      //

  ticks_now1 = timer0_overflow_count;            // Read the timer

  byte t1 = TCNT0;
  if ((TIFR0 & _BV(TOV0)) && (t1<255))
    ticks_now1++;
  ticks_now1 = (ticks_now1 << 8) + t1;

  if (pre_count1 == 0) {                         // First time around the loop?
    pre_count1 = ticks_now1;                      // Yes - set the precount, don't use this number.
  } else {
    ticks_per_rev1 = ticks_now1 - pre_count1;      // No - calculate the number of ticks...
    pre_count1 = ticks_now1;                      // ...reset the counter...
    ticks_valid1 = true;                         // ...and flag the change up.
  }
}


void loop()
{
  unsigned long thisMillis0 = millis();          // Read the time once

  // Calculate RPM
  if (ticks_valid0) {                            // Only come here if we have a valid RPM reading
    unsigned long thisTicks0;
   
    noInterrupts();
    thisTicks0 = ticks_per_rev0;
    ticks_valid0 = false;
    interrupts();
   
    lastRPM0 = __TICKS_TO_RPMS0 / thisTicks0;      // Convert ticks to RPMs
    ticks_valid0 = false;                        // Reset the flag.
    msSinceRPMReading0 = thisMillis0;             // Set the time we read the RPM.
   
  } else {
    // No tick this loop - is it more than X seconds since the last one?
    if (thisMillis0 - msSinceRPMReading0 > __WAIT_BEFORE_ZERO_RPM0) {
      lastRPM0 = 0;                              // At least 2s since last RPM-sense, so assume zero RPMs
      msSinceRPMReading0 = thisMillis0;           // Reset counter
    }
  }
 
  kmh0 = (lastRPM0 * 1.8 * 60 / 1000);
 
  // Is it time to send the data?
  if (thisMillis0 < msSinceSend0)                  // If thisMillis has recycled, reset it
    msSinceSend0 = millis();
   
  if (thisMillis0 - msSinceSend0 > __WAIT_BETWEEN_SENDS0) {
    // Yes: Build the serial output...

{
  unsigned long thisMillis1 = millis();          // Read the time once

  // Calculate RPM
  if (ticks_valid1) {                            // Only come here if we have a valid RPM reading
    unsigned long thisTicks1;
   
    noInterrupts();
    thisTicks1 = ticks_per_rev1;
    ticks_valid1 = false;
    interrupts();
   
    lastRPM1 = __TICKS_TO_RPMS1 / thisTicks1;      // Convert ticks to RPMs
    ticks_valid1 = false;                        // Reset the flag.
    msSinceRPMReading1 = thisMillis1;             // Set the time we read the RPM.
   
  } else {
    // No tick this loop - is it more than X seconds since the last one?
    if (thisMillis1 - msSinceRPMReading1 > __WAIT_BEFORE_ZERO_RPM1) {
      lastRPM1 = 0;                              // At least 2s since last RPM-sense, so assume zero RPMs
      msSinceRPMReading1 = thisMillis1;           // Reset counter
    }
  }
 
  kmh1 = (lastRPM1 * 1.8 * 60 / 1000);
 
  // Is it time to send the data?
  if (thisMillis1 < msSinceSend1)                  // If thisMillis has recycled, reset it
    msSinceSend1 = millis();
   
  if (thisMillis1 - msSinceSend1 > __WAIT_BETWEEN_SENDS1) {
    // Yes: Build the serial output...
   
    Serial.print("RPMs = \t");
    Serial.print(lastRPM0);                       // Current RPMs
    Serial.print("\t KM/H \t");
    Serial.print(kmh0);
    Serial.print("\t RPMs = \t");
    Serial.print(lastRPM1);                       // Current RPMs
    Serial.print("\t KM/H \t");
    Serial.print(kmh1);
    Serial.println();                            // EOL.

    msSinceSend0 = millis();                      // Reset the timer
    msSinceSend1 = millis();
  }  }
  }
}

nixtas

Hello can someone please explain me this part of code;why we use 15e6 and how it changes when we have more magnet's.i want to use 5 reads per revolution.thank's

const float __TICKS_TO_RPMS1 = 15e6;                   

//Convert clock ticks to RPM by dividng ticks into this number

// The number will change if there are more magnets in an rpm
                                                          //   (e.g. 2 magnets = 29296.875)

cattledog

The posted code is using Timer0 counts to measure time. The default prescaler on that timer is 64, so at 16MHz, each "tick" is 4 microseconds. There are 250000 "ticks" per second, so *60 for one minute is 15000000 (15e6). That's where his basic time period numerator comes from.

I do not understand the comment
Code: [Select]
//Convert clock ticks to RPM by dividing ticks into this number
// The number will change if there are more magnets in an rpm
//   (e.g. 2 magnets = 29296.875)


I think that you simply multiply the counted number of ticks per revolution (interrupt) by the number of magnets before dividing into the 15e6.

Code: [Select]
lastRPM0 = __TICKS_TO_RPMS0 / nMagnets*thisTicks0;      // Convert ticks to RPMs

or alternatively

Code: [Select]
const float __TICKS_TO_RPMS0 = 15e6/nMagnets;   


nixtas

The posted code is using Timer0 counts to measure time. The default prescaler on that timer is 64, so at 16MHz, each "tick" is 4 microseconds. There are 250000 "ticks" per second, so *60 for one minute is 15000000 (15e6). That's where his basic time period numerator comes from.

I do not understand the comment
Code: [Select]
//Convert clock ticks to RPM by dividing ticks into this number
// The number will change if there are more magnets in an rpm
//   (e.g. 2 magnets = 29296.875)


I think that you simply multiply the counted number of ticks per revolution (interrupt) by the number of magnets before dividing into the 15e6.

Code: [Select]
lastRPM0 = __TICKS_TO_RPMS0 / nMagnets*thisTicks0;      // Convert ticks to RPMs

or alternatively

Code: [Select]
const float __TICKS_TO_RPMS0 = 15e6/nMagnets;  


Thank's a lot.It make sense as you explain it.I must say that the comment with the two magnets and  29296.875 value drived me crazy.i was trying to find a connection between them all day.thanks again

Go Up