Calculating the difference in a set of variables in percent

ok guys i'm stuck, lol...

I've made really good progress on my project but i'm stuck. I really have to give it up for how easy this audrino is to program on, i went from knowing almost nothing about code to within 2 days coming up with this.

I'm using an audrino leonardo and i'm sampling 4 ABS wheel speed sensors on an automobile, averaging the front and the rear separately and trying to calculate slip % based on the difference. Right now i'm just using an agilent function generator and an audrino uno as a 2nd function generator to simulate 2 different +5vpp square wave inputs (split to the 4 inputs). I'll be using 2 max9926 chips to condition the vr sensors (or hall effect) to give me +5vpp signals, once they're actually in a car. i've already got that setup working so the hardware i done with i'm just stuck on the software.

I have the 4 inputs working using interrupts, i have a cycle that repeats every 250ms or so (i need fairly fast response) so it counts the pulses, averages them and displays it all on an lcd (lcd is just for debugging right now) then clears the pulse count.

I can get the pulses for each input, i can average and i can subtract the difference and get that to display. the problem is is when i try to get a slip %. I need it to take the speed of the non drive wheels, subtract that from the drive wheels, get the difference then divide the non drive speed by the difference. For example drive wheels are spinning at 90mph, non drive wheels are at 60mph, difference is 30mph; 30/60= .5 or 50%.

All I can get to display is 0, or 0.00 when i set that variable as float or try to use floating point math coming up with the "slip" variable. Eventually I need to get the slip amount to output a "voltage" using the pwm trick mapped out by the threshold set by a potentiometer.

Anyway here is my code, hopefully someone can point out what i'm doing wrong:

volatile int pulse0 = 0;
volatile int pulse1 = 0;
volatile int pulse2 = 0;
volatile int pulse3 = 0;

int pot = A0;
int threshold = 0;

const int TxPin = 6;
#include <SoftwareSerial.h>
SoftwareSerial mySerial = SoftwareSerial(255, TxPin);


void setup() {
  mySerial.begin(9600);
  pinMode(TxPin, OUTPUT);
  digitalWrite(TxPin, HIGH);
  mySerial.write(22);
  mySerial.write(17);
  attachInterrupt(0, count0, RISING);
  attachInterrupt(1, count1, RISING);
  attachInterrupt(2, count2, RISING);
  attachInterrupt(3, count3, RISING);
  }

void loop() {
  mySerial.write(12);
  delay(5);
  noInterrupts();
  mySerial.print(pulse0);
  mySerial.print("/");
  mySerial.print(pulse1);
  mySerial.print(" ");
  mySerial.print(pulse2);
  mySerial.print("/");
  mySerial.print(pulse3);
  mySerial.write(13);
  int drive = (pulse0 + pulse1) / 2;
  mySerial.print(drive);
  mySerial.print("/");
  int nondrive = (pulse3 + pulse3) / 2;
  mySerial.print(nondrive);
  mySerial.print(" SLP:");
  int diff = (drive - nondrive);
  int slip = diff / nondrive;
  mySerial.print(slip);
  
  
 // threshold = analogRead(pot);
 // threshold = map(threshold, 0, 1023, 0, 100);
 // mySerial.print("THR:");
 // mySerial.print(threshold);
   
  pulse0 = 0;
  pulse1 = 0;
  pulse2 = 0;
  pulse3 = 0;
  interrupts();
  delay(243);
  }
void count0()
{
  pulse0++;
}
void count1()
{
  pulse1++;
}
void count2()
{
  pulse2++;
}
void count3()
{
  pulse3++;
}

If you use integer Mathis you end up with zero.int is ok for the counters, but you need to have floats for the calculated vars.

marco_c:
If you use integer Mathis you end up with zero.int is ok for the counters, but you need to have floats for the calculated vars.

so i need to change the variables for drive and nondrive to float vs. int?

I think so. Try it.

marco_c:
I think so. Try it.

holy sheet that worked lol!

i'm so happy :smiley:

thank you so much!!

i can go to bed now at 5am lol

Using floats is one way to deal with small values, but it has its drawbacks and is not an approach I'd recommend.

I'd suggest that instead of calculating your slip ratio as an integer, you calculate the percentage slip:

int percentageSlip = (100 * diff) / nondrive;

Also suggest you need to consider what happens when any of your calculated values are zero - for example, when the vehicle is stationary. Dividing by zero is rarely useful.

Thanks peter,

for the sake of having more numbers to play with i stopped dividing the 2 sets of pulses for drive and non drive and just add them. This is working better but I want to speed it up and implement some kind of smoothing. i also thought about instead of counting pulses i should somehow time the pulses for better resolution; the shorter the time between pulses the faster the wheel turns. so i could have the program react even faster than ever 100ms. i could take 5-10 samples and use that for smoothing and still have it react faster than this at 200ms.
or am i going about this all wrong and should i just calculate the slip on the fly and get rid of the delay function? if i do that though then i'll really have a problem with resolution; right now i have to wait 200ms to get enough pulses to do decent math with any shorter and the error goes through the roof

here is the code as it sits:

  const int TxPin = 6;
  const int output = 11;
#include <SoftwareSerial.h>
SoftwareSerial mySerial = SoftwareSerial(255, TxPin);
  int pot = A0;
  volatile int pulse0 = 0;
  volatile int pulse1 = 0;
  volatile int pulse2 = 0;
  volatile int pulse3 = 0;
  volatile int drive = 0;
  volatile int nondrive = 0;
  volatile int diff = 0;
  volatile int slip = 0;
  volatile int threshold = 0;
  volatile int overslip = 0;
  
void setup() {
  mySerial.begin(9600);
  pinMode(TxPin, OUTPUT);
  digitalWrite(TxPin, HIGH);
  mySerial.write(22);
  mySerial.write(17);
  mySerial.write(212);                  // set Quarter note tone
  mySerial.write(220);                  // A note tone
  mySerial.write(12);                   // blank disp
  mySerial.print("CompJLT INC");        // First line
  mySerial.write(13);                   // Form feed
  mySerial.print("Traction Control");   // Second line
  delay(4000);
  mySerial.write(12); 
  attachInterrupt(0, count0, RISING);
  attachInterrupt(1, count1, RISING);
  attachInterrupt(2, count2, RISING);
  attachInterrupt(3, count3, RISING);
 
}
void loop() {
  mySerial.write(12);
  delay(5);
  noInterrupts();
  drive = pulse0 + pulse1;
  nondrive = pulse3 + pulse3;
  diff = (drive - nondrive);
  slip = (100 * diff) / nondrive;
  interrupts();  
  mySerial.print(drive);
  mySerial.print("/");
  mySerial.print(nondrive);
  mySerial.print(" ");
  mySerial.write(13);  
  mySerial.print("S:");
  mySerial.print(slip);
  threshold = analogRead(pot);
  threshold = map(threshold, 0, 1023, 0, 100);
  mySerial.print(" T:");
  mySerial.print(threshold);
  
  overslip = slip - threshold;
  if (overslip > 0)
  {
  if (overslip > 100)
  {
  analogWrite(output, 255);
  }
  else
  {    
  overslip = map(overslip, 0, 100, 0, 255);
  analogWrite(output, overslip);
  }
  }
  else
  {
  analogWrite(output, 0);
  }
  
  mySerial.print(" O:");
  mySerial.print(overslip);
    
  pulse0 = 0;
  pulse1 = 0;
  pulse2 = 0;
  pulse3 = 0;
  overslip = 0;
  delay(200);
}
void count0()
{
  pulse0++;
}
void count1()
{
  pulse1++;
}
void count2()
{
  pulse2++;
}
void count3()
{
  pulse3++;
}