Quick Translation from Javascript to Arduino IDE

Hello - I've been having problems with a little Javascript program that I'm trying to get functioning on an Arduino, but I cannot figure out why the math keeps coming out wrong.

Anyway, here's the JS version of the application on codepen.io - just ignore the jQuery styling stuff at the top.

And here is a thread that has gone deep into the task (and still turns out the wrong answers).

You will see that I have already made a translation that should theoretically be turning out the correct numbers, but unfortunately that isn't the case.

What I would like is for someone to make this application in the Arduino IDE, in such a way that it turns out the same exact numbers. I would like the math do be done in the serial readout, and I would like it to be done using some fixed user input variables rather than bringing all those tables over.

You can see a good example here in my own program - unfortunately, the math is incorrect. If you can take this program and make it work, that's perfectly acceptable too. As long as it's turning out the same exact results for the same settings (42awg heavy insulation):

#include <math.h>

float roundoff(float parnumber, int parplaces)
{
  float number = parnumber - floor(parnumber);
  number = number * pow(10, parplaces);
  number = round(number);
  number = number / pow(10, parplaces);
  number = number + floor(parnumber);
  return number;
}

struct quadraticRoot {
  float discriminant;
  float r1;
  float r2;
};

/* results */
float rWinds[5];
float rLayers[5];
float rMaxLayers[5];
float rWPL[5];
float rMaxWinds[5];
float rWPLInch[5];


float cLength = 1.315;
float cWidth = 0.1875;
float cHeight = 0.34;
float cFlange = 0.975;
float cGauge = 42;
float cOhms = 5250;
const float cFill[5] = {0.62, 0.72, 0.785, 0.907, 1.00};
float cDiameter = 0.0030;
float bDiameter = 0.0025;
float cOhms1000ft = 1659.2617;




float calcWindsPerLayer(float cHeight, float cDiameter, float fill)
{
  return (cHeight / (cDiameter / fill));
}

void setup() {
  Serial.begin(115200);
  circularArea();
  Rin();
  R1000ft();
};


/* Constants */
  const float inchesPerMeter = 1000.0 / 25.4 ; /* 39.37007874015748 */
  const float INCHES_PER_1000FT = 1000 * 12 ; /* 12000 */
  const float COPPER_RESISTIVITY = 1.724e-8 ; /* 0.00000001724 */


float circularAreaA;
float RinA;
float R1000ftA;

void circularArea()
  {
    float rad = bDiameter / 2.0 ;
    circularAreaA = rad * rad * 3.1415926 ;
  };
  void Rin ()
  {
    RinA = COPPER_RESISTIVITY / (12.0 * circularAreaA) ;
  };
  void R1000ft()
  {
    R1000ftA = (COPPER_RESISTIVITY * inchesPerMeter * INCHES_PER_1000FT) / circularAreaA ;
  };




struct quadraticRoot quadratic (float a, float b, float c)
{
  float disc = b * b - 4 * a * c;
  quadraticRoot roots = {disc, 0, 0};

  if (disc > 0)
  {
    if (b == 0)
    {
      float r = abs (0.5 * sqrt(disc) / a);
      roots.r1 = -r;
      roots.r2 = r;
    }
    else
    {
      float sgnb = (b > 0 ? 1 : -1);
      float temp = -0.5 * (b + sgnb * sqrt(disc));
      float r1 = temp / a ;
      float r2 = c / temp ;
      if (r1 < r2)
      {
        roots.r1 = r1 ;
        roots.r2 = r2 ;
      }
      else
      {
        roots.r1 = r2 ;
        roots.r2 = r1 ;
      }
    }
  }
  else if (disc == 0)
  {
    roots.r1 = -0.5 * b / a ;
    roots.r2 = -0.5 * b / a ;
  }

  return roots;
};







void calculateResults(){
  
    for (int i = 0; i < 5; i++) {
              float a;
              float b;
              float c;
              float lenInches ;
              float fill = cFill[i];
              float wireDia = cDiameter / fill;
              lenInches = cOhms / (R1000ftA / INCHES_PER_1000FT) ;
          
                a = PI * wireDia ;
                b = (2.0 * cLength) + ((PI - 2.0) * cWidth) + (PI * wireDia) ;
                c = -((lenInches * wireDia) / cHeight) ;
                quadraticRoot q = {a,b,c};
                
              if (q.discriminant < 0)
              {
                //do nothing
              } else {
                rLayers[i] = ((q.r1 < 0) ? q.r2 : q.r1);
                rMaxLayers[i] = ((cFlange - cWidth) / 2.0) / (cDiameter / (cFill[i]/100));
                rWPL[i] = cHeight / (wireDia / cFill[i]);
                rWPLInch[i] = rWPL[i] * (1.0 / cHeight);
                rWinds[i] = rWPL[i] * rLayers[i];
                rMaxWinds[i] = rMaxLayers[i] * rWPL[i];

                };
};
};

  


void loop() {
      delay(100);
        calculateResults();
      Serial.print("--------------");
      Serial.print("Loose | Scatter - 62%");
      Serial.print("--------------");
      Serial.print("rWinds[0] = ");
      Serial.println(rWinds[0]);
      Serial.print("rLayers[0] = ");
      Serial.println(rWinds[0]);
      Serial.print("rMaxLayers[0] = ");
      Serial.println(rMaxLayers[0]);
      Serial.print("rWPL[0] = ");
      Serial.println(rWPL[0]);
      Serial.print("rWPLInch[0] = ");
      Serial.println(rWPLInch[0]);
      Serial.print("rMaxWinds[0] = ");
      Serial.println(rMaxWinds[0]);
      Serial.print("--------------");
      Serial.print("Tight | Scatter - 72%");
      Serial.print("--------------");
      Serial.print("rWinds[1] = ");
      Serial.println(rWinds[1]);
      Serial.print("rLayers[1] = ");
      Serial.println(rWinds[1]);
      Serial.print("rMaxLayers[1] = ");
      Serial.println(rMaxLayers[1]);
      Serial.print("rWPL[1] = ");
      Serial.println(rWPL[1]);
      Serial.print("rWPLInch[1] = ");
      Serial.println(rWPLInch[1]);
      Serial.print("rMaxWinds[1] = ");
      Serial.println(rMaxWinds[1]);
      Serial.print("--------------");
      Serial.print("Loose | Oscillate - 78%");
      Serial.print("--------------");
      Serial.print("rWinds[2] = ");
      Serial.println(rWinds[2]);
      Serial.print("rLayers[2] = ");
      Serial.println(rWinds[2]);
      Serial.print("rMaxLayers[2] = ");
      Serial.println(rMaxLayers[2]);
      Serial.print("rWPL[2] = ");
      Serial.println(rWPL[2]);
      Serial.print("rWPLInch[2] = ");
      Serial.println(rWPLInch[2]);
      Serial.print("rMaxWinds[2] = ");
      Serial.println(rMaxWinds[2]);
      Serial.print("--------------");
      Serial.print("Tight | Oscillate - 90%");
      Serial.print("--------------");
      Serial.print("rWinds[3] = ");
      Serial.println(rWinds[3]);
      Serial.print("rLayers[3] = ");
      Serial.println(rWinds[3]);
      Serial.print("rMaxLayers[3] = ");
      Serial.println(rMaxLayers[3]);
      Serial.print("rWPL[3] = ");
      Serial.println(rWPL[3]);
      Serial.print("rWPLInch[3] = ");
      Serial.println(rWPLInch[3]);
      Serial.print("rMaxWinds[3] = ");
      Serial.println(rMaxWinds[3]);
      Serial.print("--------------");
      Serial.print("Perfect | Oscillate - 100%");
      Serial.print("--------------");
      Serial.print("rWinds[4] = ");
      Serial.println(rWinds[4]);
      Serial.print("rLayers[4] = ");
      Serial.println(rWinds[4]);
      Serial.print("rMaxLayers[4] = ");
      Serial.println(rMaxLayers[4]);
      Serial.print("rWPL[4] = ");
      Serial.println(rWPL[4]);
      Serial.print("rWPLInch[4] = ");
      Serial.println(rWPLInch[4]);
      Serial.print("rMaxWinds[4] = ");
      Serial.println(rMaxWinds[4]);
      delay(25000);
};

Try it on some Arduino that has an ARM processor core. Your problem is probably because the float type is implemented with 64 bits in JS, but it's only 32 bits in the AVR implementation.

Is there any way I can dumb the math down? I got straight Cs in high school :poop:

Failing that, I have an ESP32 that I've been putting the program on for testing, I dunno where that falls but it hasn't been able to turn out the right answers yet.

AFAIK, the ESP32 has double precision floating point. Change all the "float" declarations to "double".

1 Like

Well I thought you might be on to something there but I'm still not getting the right answers out of this thing....that would have been very convenient though, it's a shame. Gotta think of the next idea now..

OK well I have most of it working now, except for one variable isn't calculating properly still - rLayers. The rWinds calculation relies on that layers one too. I tried entering a correct layers value manually and found that the Winds were able to calculate just fine, so it's definitely just an issue with the rLayers calculation....

Now if only I knew what the hell I was doing...

#include <math.h>

double roundoff(double parnumber, int parplaces)
{
  double number = parnumber - floor(parnumber);
  number = number * pow(10, parplaces);
  number = round(number);
  number = number / pow(10, parplaces);
  number = number + floor(parnumber);
  return number;
}

struct quadraticRoot {
  double discriminant;
  double r1;
  double r2;
};

/* results */
double rWinds[5];
double rLayers[5];
double rMaxLayers[5];
double rWPL[5];
double rMaxWinds[5];
double rWPLInch[5];

/* variables - user-defined
double cLength;
double cWidth;
double cHeight;
double cFlange;
double cGauge;
int cOhms;
int cFill;
double cDiameter;
double cOhms1000ft;
*/
double cLength = 1.315;
double cWidth = 0.1875;
double cHeight = 0.34;
double cFlange = 0.975;
double cGauge = 42;
double cOhms = 5250;
const double cFill[5] = {0.62, 0.72, 0.785, 0.907, 1.00};
double cDiameter = 0.0030;
double bDiameter = 0.0025;
double cOhms1000ft = 1659.261741783075;





/* Currently Un-used wire specs */
double ga24[4] = {24, 0.0201, 0.0213, 0.0233};
double ga25[4] = {25, 0.0179, 0.0190, 0.0199};
double ga26[4] = {26, 0.0159, 0.0170, 0.0178};
double ga27[4] = {27, 0.0142, 0.0153, 0.0161};
double ga28[4] = {28, 0.0126, 0.0137, 0.0144};
double ga29[4] = {29, 0.0113, 0.0123, 0.0130};
double ga30[4] = {30, 0.0100, 0.0109, 0.0116};
double ga31[4] = {31, 0.0089, 0.0097, 0.0105};
double ga32[4] = {32, 0.0080, 0.0088, 0.0095};
double ga33[4] = {33, 0.0071, 0.0078, 0.0084};
double ga34[4] = {34, 0.0063, 0.0069, 0.0075};
double ga35[4] = {35, 0.0056, 0.0062, 0.0067};
double ga36[4] = {36, 0.0050, 0.0056, 0.0060};
double ga37[4] = {37, 0.0045, 0.0050, 0.0055};
double ga38[4] = {38, 0.0040, 0.0045, 0.0049};
double ga39[4] = {39, 0.0035, 0.0039, 0.0043};
double ga40[4] = {40, 0.0031, 0.0035, 0.0038};
double ga41[4] = {41, 0.0028, 0.0031, 0.0034};
double ga42[4] = {42, 0.0025, 0.0028, 0.0030};
double ga43[4] = {43, 0.0022, 0.0025, 0.0027};
double ga44[4] = {44, 0.0020, 0.0022, 0.0025};
double ga45[4] = {45, 0.00176, 0.00192, 0.00215};
double ga46[4] = {46, 0.00157, 0.00173, 0.00196};
double ga47[4] = {47, 0.00140, 0.00158, 0.00178};
double ga48[4] = {48, 0.00124, 0.00140, 0.00155};
double ga49[4] = {49, 0.00111, 0.00124, 0.00139};
double ga50[4] = {50, 0.00099, 0.00113, 0.00128};
double ga51[4] = {51, 0.00088, 0.00103, 0.00117};
double ga52[4] = {52, 0.00078, 0.00093, 0.00107};
double ga53[4] = {53, 0.00070, 0.00079, 0.00090};
double ga54[4] = {54, 0.00062, 0.00070, 0.00082};
double ga55[4] = {55, 0.00055, 0.00064, 0.00075};


void setup() {
  Serial.begin(115200);
  circularArea();
  Rin();
  R1000ft();
};


/* Constants */
  const double inchesPerMeter = 1000.0 / 25.4 ; /* 39.37007874015748 */
  const double INCHES_PER_1000FT = 1000 * 12 ; /* 12000 */
  const double COPPER_RESISTIVITY = 1.724e-8 ; /* 0.00000001724 */


double circularAreaA;
double RinA;
double R1000ftA;

void circularArea()
  {
    double rad = bDiameter / 2.0 ;
    circularAreaA = rad * rad * 3.1415926 ;
  };
  void Rin ()
  {
    RinA = COPPER_RESISTIVITY / (12.0 * circularAreaA) ;
  };
  void R1000ft()
  {
    R1000ftA = (COPPER_RESISTIVITY * inchesPerMeter * INCHES_PER_1000FT) / circularAreaA ;
  };




struct quadraticRoot quadratic(double a, double b, double c) {
  double disc = b * b - 4 * a * c;
  quadraticRoot roots = {disc, 0, 0};
  if (disc > 0) {


    if (b == 0) {
        double r = abs(0.5 * sqrt(disc) / a);
        roots.r1 = -r;
        roots.r2 = r;
      } else {
        double sgnb = (b > 0 ? 1 : -1);
        double temp = -0.5 * (b + sgnb * sqrt(disc));
        double r1 = temp / a ;
        double r2 = c / temp ;
        if (r1 < r2)
        {
          roots.r1 = r1 ;
          roots.r2 = r2 ;
        } else
        {
          roots.r1 = r2 ;
          roots.r2 = r1 ;
        }
      }
      return(roots);


    } else if (disc == 0) {
      roots.r1 = -0.5 * b / a ;
      roots.r2 = -0.5 * b / a ;
      return(roots);
    } else {
      return(roots);
    }

};





void calculateResults(){
  
    for (int i = 0; i < 5; i++) {
              double a;
              double b;
              double c;
              double lenInches ;
              double fill = cFill[i]; //%100
              double wireDia = cDiameter / fill;
              lenInches = cOhms / (R1000ftA / INCHES_PER_1000FT) ;
          
                a = PI * wireDia ;
                b = (2.0 * cLength) + ((PI - 2.0) * cWidth) + (PI * wireDia) ;
                c = -((lenInches * wireDia) / cHeight) ;
                quadraticRoot q = {a,b,c};
                
              if (q.discriminant < 0)
              {
                //do nothing
              } else {
                rLayers[i] = (q.r1 < 0) ? q.r2 : q.r1;
                rMaxLayers[i] = ((cFlange - cWidth) / 2.0) / (cDiameter / (cFill[i]));
                rWPL[i] = cHeight / (wireDia); //cDiameter
                rWPLInch[i] = rWPL[i] * (1.0 / cHeight);
                rWinds[i] = rWPL[i] * rLayers[i];
                rMaxWinds[i] = rMaxLayers[i] * rWPL[i];
/*
                 rLayers[i] = ((q.r1 < 0) ? q.r2 : q.r1);
                rMaxLayers[i] = ((cFlange - cWidth) / 2.0) / (cDiameter / (cFill[i]/100));
                rWPL[i] = roundoff((cHeight / (wireDia / cFill[i])),0); //cDiameter
                rWPLInch[i] = roundoff((rWPL[i] * (1.0 / cHeight)),0);
                rWinds[i] = roundoff((rWPL[i] * rLayers[i]),0);
                rLayers[i] = roundoff(rLayers[i],1);
                rMaxWinds[i] = rMaxLayers[i] * rWPL[i];

 */
                /* if (COIL.layers > COIL.maxlayers)  RED */
                };
};
};

  


void loop() {
      delay(100);
        calculateResults();
      Serial.print("--------------");
      Serial.print("Loose | Scatter - 62%");
      Serial.println("--------------");
      Serial.print("rWinds[0] = ");
      Serial.println(rWinds[0]);
      Serial.print("rLayers[0] = ");
      Serial.println(rLayers[0]);
      Serial.print("rMaxLayers[0] = ");
      Serial.println(rMaxLayers[0]);
      Serial.print("rWPL[0] = ");
      Serial.println(rWPL[0]);
      Serial.print("rWPLInch[0] = ");
      Serial.println(rWPLInch[0]);
      Serial.print("rMaxWinds[0] = ");
      Serial.println(rMaxWinds[0]);
      Serial.print("--------------");
      Serial.print("Tight | Scatter - 72%");
      Serial.println("--------------");
      Serial.print("rWinds[1] = ");
      Serial.println(rWinds[1]);
      Serial.print("rLayers[1] = ");
      Serial.println(rLayers[1]);
      Serial.print("rMaxLayers[1] = ");
      Serial.println(rMaxLayers[1]);
      Serial.print("rWPL[1] = ");
      Serial.println(rWPL[1]);
      Serial.print("rWPLInch[1] = ");
      Serial.println(rWPLInch[1]);
      Serial.print("rMaxWinds[1] = ");
      Serial.println(rMaxWinds[1]);
      Serial.print("--------------");
      Serial.print("Loose | Oscillate - 78%");
      Serial.println("--------------");
      Serial.print("rWinds[2] = ");
      Serial.println(rWinds[2]);
      Serial.print("rLayers[2] = ");
      Serial.println(rLayers[2]);
      Serial.print("rMaxLayers[2] = ");
      Serial.println(rMaxLayers[2]);
      Serial.print("rWPL[2] = ");
      Serial.println(rWPL[2]);
      Serial.print("rWPLInch[2] = ");
      Serial.println(rWPLInch[2]);
      Serial.print("rMaxWinds[2] = ");
      Serial.println(rMaxWinds[2]);
      Serial.print("--------------");
      Serial.print("Tight | Oscillate - 90%");
      Serial.println("--------------");
      Serial.print("rWinds[3] = ");
      Serial.println(rWinds[3]);
      Serial.print("rLayers[3] = ");
      Serial.println(rLayers[3]);
      Serial.print("rMaxLayers[3] = ");
      Serial.println(rMaxLayers[3]);
      Serial.print("rWPL[3] = ");
      Serial.println(rWPL[3]);
      Serial.print("rWPLInch[3] = ");
      Serial.println(rWPLInch[3]);
      Serial.print("rMaxWinds[3] = ");
      Serial.println(rMaxWinds[3]);
      Serial.print("--------------");
      Serial.print("Perfect | Oscillate - 100%");
      Serial.println("--------------");
      Serial.print("rWinds[4] = ");
      Serial.println(rWinds[4]);
      Serial.print("rLayers[4] = ");
      Serial.println(rLayers[4]);
      Serial.print("rMaxLayers[4] = ");
      Serial.println(rMaxLayers[4]);
      Serial.print("rWPL[4] = ");
      Serial.println(rWPL[4]);
      Serial.print("rWPLInch[4] = ");
      Serial.println(rWPLInch[4]);
      Serial.print("rMaxWinds[4] = ");
      Serial.println(rMaxWinds[4]);
      delay(25000);
      /*
int rWinds[4];
int rLayers[4];
int rMaxLayers[4];
int rWPL[4];
int rMaxWinds[4];
int rWPLInch[4];
       */
};

look up the exact implementation details in both JS and C++ for functions like abs(), floor(), round() etc. The transcendental functions are likely to be the same in both languages, but truncation might be defined differently.

Also, in quadratic() you assign a value to struct 'roots' and return it. But, it's dynamically declared. All variables declared inside a function are temporary unless specified otherwise with the 'static' keyword. You should make it static so the memory it occupies is not de-allocated before returning its value.

I didn't look but perhaps you also commit this error elsewhere as well.

1 Like

If I'm being honest, I'm not certain of how to approach that...I taught myself coding, so I rely on the help of others frequently :). I'm just glad I was able to narrow the issue down to a single calculation: rLayers[i] = (q.r1 < 0) ? q.r2 : q.r1;

That rLayers variable references some arguments from the pile of quadratic crap, but I simply cannot find where I've gone wrong. The number it's spitting out is 2.85, when the answer it should be getting is over 10,000.

I suppose I'll have to go back to the JS version and re-try bringing it into C/C++, especially since I've yet to get a correct rLayers answer out of this thing in the Arduino IDE. I must be missing something...

I really hope you're not saying that you're unwilling to consult the documentation. That is crucial for a task like this.

i think what i meant was that i wouldn't have known to consult some documentation here

What do you mean, "wouldn't have known..."? Why does the past matter? You need to consult the JS and C++ documentation of the functions I mentioned. I'll show you how to apply the static keyword as I described above...

If you're generally not in the habit of reading the documentation, you need to change because experienced people always do, so they won't have much sympathy for your help requests.