Pages: 1 2 [3] 4   Go Down
Author Topic: cruise control on motorcycle, need to read timing between wheel RPMs on reed swi  (Read 2483 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorr for the multiple posts here. I changed the debounce instructions to the loop() instead of the serloop1() and added the

Code:
  // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastButtonState = reading;
into the code. Just need to figure out how to translate and use

Code:
  // set the LED using the state of the button:
   digitalWrite(ledPin, buttonState);
for my buttons use.

Code:
#include <Servo.h>
Servo throttleServo; // create servo object to control a servo

// set pin numbers:
const int throttleSetPlusThrottleUp = 10; // the number of the pushbutton pin
const int throttleSetPlusThrottleDn = 8;
const int ReturnToPot = 4;
const int ReturnToPot2 = 2;

 // constants won't change. They're used here to
// set pin numbers:
int throttlePositionPot = 0;
int val;

// Variables will change:
int debounceThrottleSetPlusThrottleUp;             // the current reading from the input pin
int debounceThrottleSetPlusThrottleDn;             // the current reading from the input pin
int debounceReturnToPot;             // the current reading from the input pin
int debounceReturnToPot2;             // the current reading from the input pin
int lastdebounceThrottleSetPlusThrottleUp = LOW;   // the previous reading from the input pin
int lastdebounceThrottleSetPlusThrottleDn = LOW;   // the previous reading from the input pin
int lastdebounceReturnToPot = LOW;   // the previous reading from the input pin
int lastdebounceReturnToPot2 = LOW;   // the previous reading from the input pin


// the following variables are long's because the time, measured in miliseconds,
 // will quickly become a bigger number than can be stored in an int.
 long lastDebounceTime = 0;  // the last time the output pin was toggled
  long lastDebounceTime2 = 0;  // the last time the output pin was toggled
   long lastDebounceTime3 = 0;  // the last time the output pin was toggled
    long lastDebounceTime4 = 0;  // the last time the output pin was toggled
 long debounceDelay = 50;    // the debounce time; increase if the output flickers
  long debounceDelay2 = 50;    // the debounce time; increase if the output flickers
   long debounceDelay3 = 50;    // the debounce time; increase if the output flickers
    long debounceDelay4 = 50;    // the debounce time; increase if the output flickers
 
int servoPosition = 0; //Old val1, used to store servo position. Allows use by whole program
 

 
void setup()
{
      throttleServo.attach(12); // attaches the servo on pin 12 to the servo object
 
     // initialize the pushbutton pin as an input:
     pinMode(throttleSetPlusThrottleUp, INPUT);
     pinMode(throttleSetPlusThrottleDn, INPUT);
     pinMode(ReturnToPot, INPUT);
     pinMode(ReturnToPot2, INPUT);
}
 
void loop()
{
 
         // read the state of the switch into a local variable:
     int reading = digitalRead(throttleSetPlusThrottleUp);
     int reading2 = digitalRead(throttleSetPlusThrottleDn);
     int reading3 = digitalRead(ReturnToPot);
     int reading4 = digitalRead(ReturnToPot2);
     
       // If the switch changed, due to noise or pressing:
     if (reading != lastdebounceThrottleSetPlusThrottleUp)
     // reset the debouncing timer
     lastdebounceThrottleSetPlusThrottleUp = millis();
         
       // If the switch changed, due to noise or pressing:
     if (reading2 != lastdebounceThrottleSetPlusThrottleDn)
     // reset the debouncing timer
     lastDebounceTime2 = millis();
         
       // If the switch changed, due to noise or pressing:
     if (reading3 != lastdebounceReturnToPot)
     // reset the debouncing timer
     lastDebounceTime3 = millis();
               
       // If the switch changed, due to noise or pressing:
     if (reading4 != lastdebounceReturnToPot2)
     // reset the debouncing timer
     lastDebounceTime4 = millis();
     
       if ((millis() - lastDebounceTime) > debounceDelay) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceThrottleSetPlusThrottleUp = reading;
   }
     if ((millis() - lastDebounceTime2) > debounceDelay2) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceThrottleSetPlusThrottleDn = reading2;
   }
     if ((millis() - lastDebounceTime3) > debounceDelay3) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceReturnToPot = reading3;
   }
     if ((millis() - lastDebounceTime4) > debounceDelay4) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceReturnToPot2 = reading4;
   }
   
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceThrottleSetPlusThrottleUp = reading;
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceThrottleSetPlusThrottleDn = reading2;
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceReturnToPot = reading3;
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceReturnToPot2 = reading4;
   
   
     val = analogRead(throttlePositionPot); //takes reading from pot current position
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it
 
     if (digitalRead(throttleSetPlusThrottleUp) == HIGH)
     {
          serloop1(); //Enters button control loop
     }
 
     if (digitalRead(throttleSetPlusThrottleDn) == HIGH)
     {
          serloop1(); //Enters button control loop
     }
}
 
 
/**
 * If button control is enabled, loop and handle control buttons
 * If exit buttons (To return to pot control) are pressed, exit loop and return
 * to pot control
 */
void serloop1()
{
     servoPosition = throttleServo.read(); //reads current servo location   
 
     int btnControlEnabled = 1; //If button control is enabled this equals 1, else it equals 0
 
     while(btnControlEnabled == 1)
     {
       if (digitalRead(throttleSetPlusThrottleUp) == HIGH)
       {
          throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
       }
       //If first button not pressed, check the next...
       else if (digitalRead(throttleSetPlusThrottleDn) == HIGH)
       {
          throttleServo.write(servoPosition - 2); //ADDS 2 degrees to servo position for decreased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
       }
       else if (digitalRead(ReturnToPot) == HIGH)
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       else if (digitalRead(ReturnToPot2) == HIGH)
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       //If nothing pressed...
       else
       {
         //...do nothing at all, go back to start of loop
       }
     }
     
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46090
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
        // read the state of the switch into a local variable:
     int reading = digitalRead(throttleSetPlusThrottleUp);
     int reading2 = digitalRead(throttleSetPlusThrottleDn);
     int reading3 = digitalRead(ReturnToPot);
     int reading4 = digitalRead(ReturnToPot2);
You now have some good names for some of the pins. It's a shame that the same can not be said for the states of those pins.

What do ReturnToPot and ReturnToPot2 mean?

Personally, I think that if find yourself in a position where some of the variables need numbers, all the related ones need numbers (ReturnToPot1 and reading1).

Code:
    if (reading != lastdebounceThrottleSetPlusThrottleUp)
I also think that variables being compared like this should have names that indicate that they go together. I can see that currDebounceThrottleSetPlusThrottleUp and lastDebounceThrottleSetPlusThrottleUp go together. I can't see that reading and lastdebounceThrottleSetPlusThrottleUp go together.

Using camel case notation requires capital letters on ALL words, except the first one, not capital letters on some of the words.

Debounce and state change detection are two separate things. It looks, from the names, that you are trying to mix them.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4019
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Time works seamlessly with unsigned longs, no problem with roll over.
Time is a fudge-up with longs but you got almost 25 days find that bug, and if you kludge your way around it then it will never get you except that you won't get why unsigned's are right for handling time.

Logged

Examples can be found in your IDE.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46090
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Time is a fudge-up with longs but you got almost 25 days find that bug, and if you kludge your way around it then it will never get you except that you won't get why unsigned's are right for handling time.
Not too many people can ride for 24 plus days at a time, without gas or other stops, so this isn't likely to be a real problem.

Edit: fixed typo.
« Last Edit: February 16, 2013, 11:12:13 am by PaulS » Logged

Pakistan
Offline Offline
Sr. Member
****
Karma: 6
Posts: 356
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Time is a fudge-up with longs but you got almost 25 days find that bug, and if you kludge your way around it then it will never get you except that you won't get why unsigned's are right for handling time.
No too many people can ride for 24 plus days at a time, without gas or other stops, so this isn't likely to be a real problem.
May be someone very excited about the cruise controller may ride and sleep both..just like a crazy little boy with his new toy smiley-mr-green smiley-mr-green
Logged


Carlisle PA USA
Offline Offline
Newbie
*
Karma: 0
Posts: 23
I'm so old I'm getting paid for it!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

msumrell ...

Since timing your wheel rotation seems to be a major problem, why not start with that problem and make a simple fully-operational speedometer program with your reed switch and your board.  That way you can SAFELY create a sketch that will help with the overall program (the wisdom of which is not mine to judge).  Once you get that working and comprehensively tested with ZERO glitches or anomalies, you can think about integrating it into other functions.  This effort will help you to understand the complexities of interrupt driven timing and debouncing contact closures/opens.  For example, you may not have thought about it, but a bumpy road can do VERY weird things to contact state detection.  Hey, then there's mechanical resonance if you're using a reed switch!

Opinions are like noses ... everybody's got one.  Break the task into primitive pieces.  Fully understand the mechanics and process for each piece that you work on.

Blessings in abundance, all the best, & ENJOY!  ... and STAY SAFE
Art in Carlisle, PA USA
« Last Edit: February 16, 2013, 12:22:29 pm by webtest » Logged

Blessings in abundance, all the best, & ENJOY!
Art in Carlisle, PA USA

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have completed an initial program that works well as far as throttle control from the pot and setting speed with two buttons that bump up or down the servo by 2* and two others that release the first two buttons back to the throttle pot, clutch and front break levers.

I have now also written code in to read the speed hall sensor and bump the servo by 2 degrees based on the loop comparison. I got the code from youTube for an LCD RPM read out of a hall sensor reading rpm of a drill motor. I removed all the LCD refference and incorporated. I have not made any attempt to tie it into the bikes hall sensor as of yet.

I would like to know if the code looks like it makes any sense as I really do not fully understand the hall read/calculation part of the program.

Code:
#include <Bounce.h>
#include <Servo.h>

   Servo throttleServo; // create servo object to control a servo
 
   int throttleServoPotpin = 0;
   int servoPosition = 0; //Old val1, used to store servo position. Allows use by whole program
   int val;
 

 
   // set pin numbers:
   const int throttlePosSet_Up = 10; // the number of the pushbutton pin
   const int throttlePosSet_Dn = 8;
   const int returnThrottleToPot1 = 4;
   const int returnThrottleToPot2 = 2;
   // read the hall effect sensor on pin 6
   const int rpmHallSensor=6;
 
 
   long debounceDelay = 50;    // the debounce time; increase if the output flickers
 
   //Debounce objects
   // Instantiate a Bounce object with a 5 millisecond debounce time
   Bounce bouncer1 = Bounce(throttlePosSet_Up, debounceDelay);
   Bounce bouncer2 = Bounce(throttlePosSet_Dn, debounceDelay);
   Bounce bouncer3 = Bounce(returnThrottleToPot1, debounceDelay);
   Bounce bouncer4 = Bounce(returnThrottleToPot2, debounceDelay);

   const unsigned long sampleTime=100;
   const int maxRPM = 10200;
   int currentRPM = 0;
   int kount2rpm = 0;
     

void setup()
{
     throttleServo.attach(12); // attaches the servo on pin 12 to the servo object
     // initialize the pushbutton pin as an input:
     pinMode(throttlePosSet_Up, INPUT);
     pinMode(throttlePosSet_Dn, INPUT);
     pinMode(returnThrottleToPot1, INPUT);
     pinMode(returnThrottleToPot2, INPUT);
     // initialize input for pick up of motorcycle speed hall sensor
     pinMode(rpmHallSensor,INPUT);
 }
 
void loop()
{
     val = analogRead(throttleServoPotpin); //takes reading from pot current position
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it
 
     //Update debounce tool
     bouncer1.update();
     bouncer2.update();
 
     //Do not need to update these here are they are not used
     //bouncer3.update();
     //bouncer4.update();
 
 
     if (bouncer1.read() == HIGH)
     {
          serloop1(); //Enters button control loop
     }
 
     if (bouncer2.read() == HIGH)
     {
          serloop1(); //Enters button control loop
     }
}
/**
 * If button control is enabled, loop and handle control buttons
 * If exit buttons (To return to pot control) are pressed, exit loop and return
 * to pot control
 */
void serloop1()
{
     servoPosition = throttleServo.read(); //reads current servo location
     int btnControlEnabled = 1; //If button control is enabled this equals 1, else it equals 0
     while(btnControlEnabled == 1)
     {
       //Update all debounce tools
       bouncer1.update();
       bouncer2.update();
       bouncer3.update();
       bouncer4.update();
 
       if (bouncer1.read() == HIGH)
       {
          throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
         
          digitalRead(rpmHallSensor);         
               
          currentRPM = digitalRead(rpmHallSensor);
          if (kount2rpm != currentRPM);
         
           serloop2();
         

             
       }
             

       //If first button not pressed, check the next...
       else if (bouncer2.read() == HIGH)
       {
          throttleServo.write(servoPosition - 2); //ADDS 2 degrees to servo position for decreased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
         
          digitalRead(rpmHallSensor);         
               
          currentRPM = digitalRead(rpmHallSensor);
          if (kount2rpm != currentRPM);
         
           serloop3();
         
          }         

       
       
       else if (bouncer3.read() == HIGH)
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       else if (bouncer4.read() == HIGH)
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       //If nothing pressed...
       else
       {
         //...do nothing at all, go back to start of loop
       }
     }

      int rpm=getRPM();
      }     
      int getRPM()
      {
      // sample for sampleTime in millisecs
      int kount=0;
 
      boolean kflag=LOW;
 
      unsigned long currentTime=0;
 
      unsigned long startTime=millis();
 
      while (currentTime<=sampleTime)
      {
      if (digitalRead(rpmHallSensor)==HIGH)
      {
       kflag=HIGH;
      }
      if (digitalRead(rpmHallSensor)==LOW && kflag==HIGH)
      {
      kount++;
      kflag=LOW;
      }
      currentTime=millis()-startTime;
      }
      int kount2rpm = int(60000./float(sampleTime))*kount;
      return kount2rpm;
      serloop1();
}     
void serloop2()
{
      if (kount2rpm < currentRPM);     
      serloop4();
}   
void serloop3()
{     
      if (kount2rpm > currentRPM);
      serloop5();
}
void serloop4()
{
      servoPosition = throttleServo.read(); //reads current servo location
      throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm       
}
void serloop5()
{
      servoPosition = throttleServo.read(); //reads current servo location
      throttleServo.write(servoPosition - 2); //SUBTRACT 2 degrees to servo position for increased motor rpm       
}

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46090
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
     val = analogRead(throttleServoPotpin); //takes reading from pot current position
Why is Servo in this name? It's not the Servo pot that you are reading. Pin should be capitalized.

Code:
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it
The analogRead() range is 0 to 1023, not 0 to 1083.

There does not to be any test for whether the servo should be controlling the speed.

Function names should reflect what they do. serloop1(), serloop2(), serloop3(), etc. do not even come close.

Code:
      return kount2rpm;
      serloop1();
}
If it weren't for the return statement stopping serloop1() from calling serloop1() again, this would be another instance of recursion. You REALLY need to get out of the habit of doing that.

I gave up reading at that point. The horrid indenting makes it too hard to see the structure of the code. Before posting code here, please use Tools + Auto Format to correct the indenting. You'll find that it makes your coding easier, too.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This code is not doing anything useful:
Code:
if (kount2rpm != currentRPM);

As a general comment, your function names 'serloop1' etc are utterly useless and the structure of the code does not seem remotely sensible.

I would expect to find a state machine at the high level dealing with the logic to engage and disengage cruise control. In the 'engaged' mode I'd expect to find code managing the target speed in response to user commands to increment/decrement it, code to determine the actual speed and take action to make the actual speed move towards the target speed. The function name 'getRPM' at least indicates what it does, although it's a blocking function working on a very short timescale and that doesn't seem like a very good approach - I think it would work better to use an asynchronous approach to count revolutions in a period and then calculate the 'current speed' at the end of each period. Blink without delay shows you how to carry out processing at regular intervals, and I'd use that to trigger the calculation at the end of each period. This has the disadvantage that the RPM Hall sensor would only be polled once per loop() rather than being polled intenseively in getROM(). Can you actually afford to poll the RPM Hall sensor in the background? If not, I'd consider counting pulses using an interrupt. Given that the result will be used to drive a mechanical actuator I assume you want to avoid jitter, so I'd suggest applying some smoothing to the calculated speed - an exponential average would probably work well (e.g. smoothed speed equals 90% of previous smoothed speed plus 10% of measured speed).
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would like to reference the following in my attempt to get this code figured out.
"http://www.freetronics.com/pages/jaycar-water-flow-gauge"

I do not know how to determine calibration number for my application and if this looks feasible for calculating rpm from the bike hall sensor (not motor rpm but just rather a constant), I still have to figure out how to incorporate it back into my main program.

I took their code,
Code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Specify the pins for the two counter reset buttons and indicator LED
byte resetButtonA = 11;
byte resetButtonB = 12;
byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = pin 2; 1 = pin 3
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitresA;
unsigned long totalMilliLitresB;

unsigned long oldTime;

void setup()
{
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print("                ");
  
  // Initialize a serial connection for reporting values to the host
  Serial.begin(38400);
  
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  // Set up the pair of counter reset buttons and activate internal pull-up resistors
  pinMode(resetButtonA, INPUT);
  digitalWrite(resetButtonA, HIGH);
  pinMode(resetButtonB, INPUT);
  digitalWrite(resetButtonB, HIGH);
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitresA = 0;
  totalMilliLitresB = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{
  if(digitalRead(resetButtonA) == LOW)
  {
    totalMilliLitresA = 0;
    lcd.setCursor(0, 1);
    lcd.print("0L      ");
  }
  if(digitalRead(resetButtonB) == LOW)
  {
    totalMilliLitresB = 0;
    lcd.setCursor(8, 1);
    lcd.print("0L      ");
  }
  
  if( (digitalRead(resetButtonA) == LOW) || (digitalRead(resetButtonB) == LOW) )
  {
    digitalWrite(statusLed, LOW);
  } else {
    digitalWrite(statusLed, HIGH);
  }
  
  if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
    //lcd.setCursor(15, 0);
    //lcd.print("*");
    
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitresA += flowMilliLitres;
    totalMilliLitresB += flowMilliLitres;
  
    // During testing it can be useful to output the literal pulse count value so you
    // can compare that and the calculated flow rate against the data sheets for the
    // flow sensor. Uncomment the following two lines to display the count value.
    //Serial.print(pulseCount, DEC);
    //Serial.print("  ");
    
    // Write the calculated value to the serial port. Because we want to output a
    // floating point value and print() can't handle floats we have to do some trickery
    // to output the whole number part, then a decimal point, then the fractional part.
    unsigned int frac;
    
    // Print the flow rate for this second in litres / minute
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print(".");             // Print the decimal point
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate)) * 10;
    Serial.print(frac, DEC) ;      // Print the fractional part of the variable

    // Print the number of litres flowed in this second
    Serial.print(" ");             // Output separator
    Serial.print(flowMilliLitres);

    // Print the cumulative total of litres flowed since starting
    Serial.print(" ");             // Output separator
    Serial.print(totalMilliLitresA);
    Serial.print(" ");             // Output separator
    Serial.println(totalMilliLitresB);
    
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("Flow: ");
    if(int(flowRate) < 10)
    {
      lcd.print(" ");
    }
    lcd.print((int)flowRate);   // Print the integer part of the variable
    lcd.print('.');             // Print the decimal point
    lcd.print(frac, DEC) ;      // Print the fractional part of the variable
    lcd.print(" L");
    lcd.print("/min");
    
    lcd.setCursor(0, 1);
    lcd.print(int(totalMilliLitresA / 1000));
    lcd.print("L");
    lcd.setCursor(8, 1);
    lcd.print(int(totalMilliLitresB / 1000));
    lcd.print("L");

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/**
 * Invoked by interrupt0 once per rotation of the hall-effect sensor. Interrupt
 * handlers should be kept as small as possible so they return quickly.
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

and turned it into this.

Code:
// HOW WOULD I DETERMINE MY CALIBRATION FACTOR?
float calibrationFactor = 4.5;

volatile byte pulseCount;
float rpmRate;

unsigned int rpm;

byte sensorInterrupt = 0;  // 0 = pin 2; 1 = pin 3
byte sensorPin       = 2;

unsigned long oldTime;


void setup()
{
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  rpmRate          = 0.0;
  rpm   = 0;
  oldTime           = 0;


  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

}


void loop()
{
 

  if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);


    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    rpmRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    rpm = (rpmRate / 60);

    // to output the whole number part, then a decimal point, then the fractional part.
    unsigned int frac;


    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (rpmRate - int(rpmRate)) * 10;


    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}


/**
 * Invoked by interrupt0 once per rotation of the hall-effect sensor. Interrupt
 * handlers should be kept as small as possible so they return quickly.
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}


Logged

Saskatchewan
Offline Offline
Sr. Member
****
Karma: 15
Posts: 348
When the going gets weird, the weird turn pro. - Hunter S. Thompson
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Giving that a quick once over it appears that they count pulses for a period of time then do the calculations. I don't see that approach working for cruise control. I think you want to generate a signal with the hall sensor and track it's frequency. Basically the times between pulses. It's this frequency that you'll ultimately have to control via the servo and throttle setup. It will have to try to match the frequency it was reading when you set it.

How will you read the brake to disconnect things? You mention the front lever. I'd use the brake light circuit and a relay. Tap the wire and put it through the coil to ground. When you hit the brakes, front or rear, the light goes on, the relay closes, a pin goes low and an interrupt can disconnect the servo. This has to be almost instant. Your code above disables interrupts. I don't see that as feasible.

Just some ideas. Please just do this as an intellectual exercise. I don't agree with cruise on bikes period.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't see that approach working for cruise control.

I don't see why not. If anything, a controller that took a second or so to respond would be less likely to keep twitching the throttle around in response to timing jitter, and would probably give you a smoother and more consistent control.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4019
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

With the time/distance (appx 7 ft) between data points, he's going to need code just to keep it from constantly over-adjusting throttle. His response will always lag worse at lower speed.

Logged

Examples can be found in your IDE.

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah, but are you really expecting to use cruise control at the slow speeds where that would be an issue? Cruise control doesn't (shouldn't) need to be fast reacting.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: 1 2 [3] 4   Go Up
Jump to: