0

just a question that requires a simple answer. How do I process a large number of arithmetic steps in arduino efficiently and precisely?

For example I have this code function setup:

void calc() {
  batterymoment = input*batterymass;
  totalmoment = 149650+batterymoment;
  buoyancymoment = buoyancymass*centrebuoyancy;
  wheelmoment = totalmoment - buoyancymoment;
  wheelweight = totalmass - buoyancymass;
  cgwheels = wheelmoment/wheelweight;
  maindistance = mainarm - wheelweight;
  nosedistance = wheelweight - nosearm;
  mainmass = (((wheelweight)*(1-((maindistance)/(maindistance+nosedistance))))/2);
  nosemass = (((wheelweight)*(1-((nosedistance)/(nosedistance+maindistance))))/2);
  mainmoment = mainmass*mainarm;
  nosemoment = nosemass*nosearm;
  netmoment = buoyancymoment+mainmoment+nosemoment;
  netcg = netmoment/totalmass;
  staticmargin = adc - netcg;
  answer = staticmargin/meanadc;

}

Now I've properly setup up data types for all of these variables and they are a combination of float, int and long. I don't think it's a problem with the data type. What I'm getting when I print final answer in the serial is the same number regardless the input the user enters.

I'm guessing I need to format the code in such a way that it performs each line step by step and verifies the answer before proceeding to the next arithmetic line. If so would I need a function for each arithmetic step? Or is there a simpler way to process this that I'm missing.

Any guidance is appreciated. Thanks.

Here is the code in its entirety:

unsigned long batterymoment,num1,num2,input,totalmoment;
double buoyancymoment,wheelmoment,cgwheels,mainmass,nosemass,maindistance,nosedistance;
double mainmoment,nosemoment,netmoment,netcg,staticmargin,answer;
double centrebuoyancy = 14.164;
double mainarm = 14.3;
double adc = 11.4;
double meanadc = 22.65;
double nosearm = 1.8;
int totalmass = 12404;
int batterymass = 720;
int buoyancymass = 4401;
int batteryposition,wheelweight;
boolean mySwitch = false;

void calc() {
  batterymoment = input*batterymass;
  totalmoment = 149650+batterymoment;
  buoyancymoment = buoyancymass*centrebuoyancy;
  wheelmoment = totalmoment - buoyancymoment;
  wheelweight = totalmass - buoyancymass;
  cgwheels = wheelmoment/wheelweight;
  maindistance = mainarm - wheelweight;
  nosedistance = wheelweight - nosearm;
  mainmass = (((wheelweight)*(1-((maindistance)/(maindistance+nosedistance))))/2);
  nosemass = (((wheelweight)*(1-((nosedistance)/(nosedistance+maindistance))))/2);
  mainmoment = mainmass*mainarm;
  nosemoment = nosemass*nosearm;
  netmoment = buoyancymoment+mainmoment+nosemoment;
  netcg = netmoment/totalmass;
  staticmargin = adc - netcg;
  answer = staticmargin/meanadc;  
 }

void setup() {
  Serial.begin(9600);
  num1=0;
  num2=0;
  Serial.println("Enter battery position");
 }

void loop() {
  while (Serial.available()){
    batteryposition = Serial.read();
    if(batteryposition>47 && batteryposition<58){  
      if(!mySwitch){
         num1=(num1*10)+(batteryposition-48);
      }else{
         num2=(num2*10)+(batteryposition-48);
        }
       }

if(batteryposition==61){
  input=num1+num2;
  calc();
  Serial.print("Static margin is: ");
  Serial.println(answer);
  num1=0;
  num1=0;
  mySwitch=false;
  }
 }
}

So depending on the user input, the calculations will change the final output answer. For example if a 5 should be entered the output should be -4.22 based on my calculations in excel.

  • Please do show the declarations, the actual result, and the expected result. And put some extra Serial.print("answer:");Serial.println(answer); debugging code in to help you isolate the problem. – Dave X Mar 10 '16 at 18:15
  • And what does it print? I'd put a "input=5;" in the code before calc(), and then try difft debug printing in calc() until you get something unexpected. – Dave X Mar 10 '16 at 18:41
  • it prints -113.70 regardless of the input @DaveX – Jertise Mar 10 '16 at 18:42
  • 2
    What I have found useful, is testing complex algorithms in a spreadsheet or small console application (even not so complex ones). Once I get them working, I convert to Arduino code, which is pretty straightforward. This is not a warranty of bug-free code but it's pretty close. – fabrosell Mar 10 '16 at 18:54
  • Again, do you want to clear num1 twice or did you intend to clear num2 after the processing. – Dave X Mar 10 '16 at 20:19
3

You're getting the same value every time because that is the value that is being calculated.

I think you have something wrong with how you have implemented your formula. If you start from "answer = " and repeatedly substitute the variables with the formulae or values that make up those variables you end up with this:

answer = (11.4 - (((4401 * 14.164) + ((((12404 - 4401)*(1-((14.3 - (12404 - 4401))/((14.3 - (12404 - 4401))+(12404 - 4401 - 1.8)))))/2) * 14.3) + ((((12404 - 4401)*(1-((12404 - 4401 - 1.8)/((12404 - 4401 - 1.8)+(14.3 - (12404 - 4401))))))/2) * 1.8)) / 12404)) / 22.65

There's nothing variable about that at all.

Your input value is being used to calculate batterymoment. batterymoment us being used to calculate totalmoment. totalmoment is being used to calculate wheelmoment. wheelmoment is being used to calculate cgwheels. cgwheels is never used for anything.

0

Per your comments, the calc() function is not acting as expected.

Change calc() to be:

void calc() {
  Serial.print("input:");Serial.println(input);
  batterymoment = input*batterymass;
  totalmoment = 149650+batterymoment;
  buoyancymoment = buoyancymass*centrebuoyancy;
  wheelmoment = totalmoment - buoyancymoment;
  wheelweight = totalmass - buoyancymass;
  cgwheels = wheelmoment/wheelweight;
  maindistance = mainarm - wheelweight;
  nosedistance = wheelweight - nosearm;
  mainmass = (((wheelweight)*(1-((maindistance)/(maindistance+nosedistance))))/2);
  nosemass = (((wheelweight)*(1-((nosedistance)/(nosedistance+maindistance))))/2);
  mainmoment = mainmass*mainarm;
  nosemoment = nosemass*nosearm;
  netmoment = buoyancymoment+mainmoment+nosemoment;
  netcg = netmoment/totalmass;
  staticmargin = adc - netcg;
  answer = staticmargin/meanadc;
  Serial.print("answer:");Serial.println(answer);  
 }

and see if it gets the expected inputs and works as expected. Then add debugging statements in-process until you discover the mismatch.

I'd turn in into more of a function, or a series of better defined functions, and then test them individually.

As your code is there is interaction between global variables, serial parsing, and calculations. If you break it into distinct pieces, you can isolate where the problem is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.