Help: Javascript to Arduino IDE

Hi! I'm currently attempting to take a JS program (visible on codepen.io) and bring it into the Arduino C/C++ environment, whatever it's called officially.

I'm pasting the Arduino program I managed to come up with, you can see it's just meant to take some dummy numbers (already defined variables that'd normally be user-entered) and perform the calculations, then print them into the serial monitor for me to double check.

Right now I'm getting a lot of zeros and I'm certain that most of the problem arises from the quadratic equation where the bobbin's core size and the winding area are calculated. And also stuff that references back to that quadratic pile, like this:

COIL.layers = ((q.r1 < 0) ? q.r2 : q.r1) ;

I just don't know how that's supposed to look in C, I have it written out as a bool statement...regardless, it's no help if I'm not getting any meaningful answers out of the quadratic equation.

Anyway, I'm just hoping someone here who did better in math class can help me work this one out...it's been bothering me for a while now :cry:

#include <math.h>

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

/* variables - bobbin & wire
normally, these would be user-entered in a form - for this example, we just have some default numbers to compare against the codepen.io example
*/
float cLength = 1.315;
float cWidth = 0.1875;
float cHeight = 0.34;
float cFlange = 0.975;
float cGauge = 42;
int cOhms = 5250;
int cFill[5] = {62,72,78,90,100};
float cDiameter = 0.0030;
float bDiameter = 0.0025;
float cOhms1000ft = 1659.261741783075;

int roots[2];




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


void setup() {
  Serial.begin(115200);
};


/* Constants */
  float inchesPerMeter = 1000.0 / 25.4 ; /* 39.37007874015748 */
  int INCHES_PER_1000FT = 1000 * 12 ; /* 12000 */
  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 ;
  };


  
void quadratic(int a,int b,int c){
  int disc = b*b-4*a*c;
  roots[0] = disc;
  if (disc > 0){
    if (b == 0){
      int r = fabs(0.5 * sqrt(disc) / a);
        roots[1] = -r;
        roots[2] = r;
      } else {
        int sgnb;
        if (b > 0){sgnb = 1;} else {sgnb = -1;}
        int temp = -0.5 * (b + sgnb * sqrt(disc));
        int r1 = temp / a ;
        int r2 = c / temp ;
        if (r1 < r2)
        {
          roots[1] = r1 ;
          roots[2] = r2 ;
        } else
        {
          roots[1] = r2 ;
          roots[2] = r1 ;
        }
      }
      Serial.print("roots[0] (disc) = ");
      Serial.println(roots[0]);
      Serial.print("roots[1] (r1) = ");
      Serial.println(roots[1]);
      Serial.print("roots[2] (r2) = ");
      Serial.println(roots[2]);
  }
  if (disc == 0){
      roots[1] = -0.5 * b / a ;
      roots[2] = -0.5 * b / a ;
      } else {
    //do nothing
    };
};


void calculateResults(){
        for (int i = 0; i < 5; i++) {

              float a2,b2,c2;
              float lenInches ;
              float wireDia = cDiameter;
              float fill = cFill[i]/100;
              lenInches = cOhms / (R1000ftA / INCHES_PER_1000FT) ;
              wireDia = wireDia / fill ;
          
                a2 = PI * wireDia ;
                b2 = (2.0 * cLength) + ((PI - 2.0) * cWidth) + (PI * wireDia) ;
                c2 = -((lenInches * wireDia) / cHeight) ;
                quadratic(a2,b2,c2) ;
          
              if (roots[0] < 0)
              {
                //trace("error: roots are unreal\n") ;
              } else {
                if (roots[1] < 0) {rLayers[i] = roots[2];
                } else {rLayers[i] = roots[1];
                };
              };
      
                /*MaxLayers*/
                rMaxLayers[i] = ((cFlange - cWidth) / 2.0) / (cDiameter / (cFill[i]/100));
                /*WindsPerLayer - rWPL*/
                rWPL[i] = round(cHeight / (cDiameter / cFill[i]));
                rWPLInch[i] = round(rWPL[i] * (1.0 / cHeight));
                rWinds[i] = round(rWPL[i] * rLayers[i]);
                rLayers[i] = round(rLayers[i]);
                rMaxWinds[i] = round(rMaxLayers[i] * rWPL[i]);

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


  


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("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("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("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("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("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];
       */
};

It looks like some of the 'functions' should be structures and some should be functions. Any place where 'this.' is used seems to indicate the 'function' is being used as a structure:

function quadraticRoot(discriminant, r1, r2)
{
  this.discriminant = discriminant ;
  this.r1 = r1 ;
  this.r2 = r2 ;
}

This should probably translate to C++ as:

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

And used like this:

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

I think most cases of 'var' should be 'float'.

1 Like

I had actually just gotten rid of that quadraticRoot portion because I thought it was self-referencing for....other reasons :nerd_face:

Thank you though, I'm gonna try to work that whole quadratic block out using your guidance here...I may be back to annoy you some more very shortly though.

While I'm annoying you here and now though, can I just ask you about this thing here:

COIL.layers = ((q.r1 < 0) ? q.r2 : q.r1) ;

Does that translate over to C++ directly?

I was told it means if q.r1 is less than 0, COIL.layers is equal to q.r2 -- otherwise, COIL.layers is equal to q.r1

if that's correct, could it theoretically be written out as a bool statement too:

if (q.r1 < 0) {COIL.layers = q.r2;} else {COIL.layers = q.r1;}

OK well I'm wading through this stuff now and filling in blanks wherever possible, but I just ran into something I'm uncertain of:

Screen Shot 2021-07-22 at 6.33.27 PM

that line var q = quadratic(a,b,c);
What would that become? Sorry for being annoying :poop:

:cry: come back :tired_face:

Sorry. I got interrupted by dinner and TV and sleep. Here is my cut at translating the Javascript to C++. I can't do anything with the "document" which describes the layout of the HTML page so I commented those lines out. I turned the arrays of 'var' into arrays of 'struct' and initialized them at compile time.

#define ArrayLength(a) (sizeof (a) / sizeof ((a)[0]))

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;
}

// quadratic root type constructor
struct quadraticRoot
{
  float discriminant;
  float r1;
  float r2;
};

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;
}

/*
  resistivity is in units ohm-meter
  and needs conversion to ohms-1000Ft.
*/
const float inchesPerMeter = 1000.0 / 25.4 ;
const float INCHES_PER_1000FT = 1000 * 12 ;
const float COPPER_RESISTIVITY = 1.724e-8 ; /* ohm-meter */
//
float circularArea(float dia)
{
  float rad = dia / 2.0 ;
  return rad * rad * PI;
}

float Rin (float dia)
{
  return COPPER_RESISTIVITY / (12.0 * circularArea(dia));
}

float R1000ft(float dia)
{
  return (COPPER_RESISTIVITY * inchesPerMeter * INCHES_PER_1000FT) / circularArea(dia);
}

void dumpWinds()
{
  //trace("winds:"+COIL.winds + " layers:" + COIL.layers + " maxlayers:" + COIL.maxlayers + " wpl:" + COIL.wpl },
}
// coil type constructor
struct coil_t
{
  const char *name;
  float L;
  float W;
  float H;
  float flange;
  int awg;
  float dia;
  float Rdc1k;
  float winds;
  float ohms;
  float fill;
  float maxlayers;
  float layers;
  float wpl;
  float wplinch;
} COIL = {"strat", 2.5, 0.1875, 0.625, 0.75, 42, 0.0028, 1659, 0, 0, 0, 72, 0, 0, 0};


void showWinds1()
{
  //  float frm = document.displayFrm ;
  //  float e = document.getElementById("l1");
  dumpWinds();
  //  frm.winds1.value = COIL.winds ;
  //  frm.maxlayers1.value = COIL.maxlayers ;
  //  frm.wpl1.value = COIL.wpl ;
  //  frm.maxwinds1.value = COIL.maxlayers * COIL.wpl ;
  //
  //  frm.layers1.value = COIL.layers ;

  if (COIL.layers > COIL.maxlayers)
  {
    // e.style.color = "red" ;
  }
  else
  {
    // e.style.color = "black" ;
  }
}



/*
** COIL handling routines
*/


void adjustBobbin(float L, float  W, float  H, float flange)
{
  COIL.L = L;
  COIL.W = W;
  COIL.H = H;
  COIL.flange = flange;
}

/*
** Wire handling routines
*/
// constructor for magnet wire descriptor
struct wire_t
{
  int awg;
  float bare;
  float single;
  float heavy;
  // float rdc;
} wireTable[] =
{
  {24, 0.0201, 0.0213, 0.0233},
  {25, 0.0179, 0.0190, 0.0199},
  {26, 0.0159, 0.0170, 0.0178},
  {27, 0.0142, 0.0153, 0.0161},
  {28, 0.0126, 0.0137, 0.0144},
  {29, 0.0113, 0.0123, 0.0130},
  {30, 0.0100, 0.0109, 0.0116},
  {31, 0.0089, 0.0097, 0.0105},
  {32, 0.0080, 0.0088, 0.0095},
  {33, 0.0071, 0.0078, 0.0084},
  {34, 0.0063, 0.0069, 0.0075},
  {35, 0.0056, 0.0062, 0.0067},
  {36, 0.0050, 0.0056, 0.0060},
  {37, 0.0045, 0.0050, 0.0055},
  {38, 0.0040, 0.0045, 0.0049},
  {39, 0.0035, 0.0039, 0.0043},
  {40, 0.0031, 0.0035, 0.0038},
  {41, 0.0028, 0.0031, 0.0034},
  {42, 0.0025, 0.0028, 0.0030},
  {43, 0.0022, 0.0025, 0.0027},
  {44, 0.0020, 0.0022, 0.0025},
  {45, 0.00176, 0.00192, 0.00215},
  {46, 0.00157, 0.00173, 0.00196},
  {47, 0.00140, 0.00158, 0.00178},
  {48, 0.00124, 0.00140, 0.00155},
  {49, 0.00111, 0.00124, 0.00139},
  {50, 0.00099, 0.00113, 0.00128},
  {51, 0.00088, 0.00103, 0.00117},
  {52, 0.00078, 0.00093, 0.00107},
  {53, 0.00070, 0.00079, 0.00090},
  {54, 0.00062, 0.00070, 0.00082},
  {55, 0.00055, 0.00064, 0.00075},
};

//
void initWireOptionList()
{
  //  float wireOptions = document.parametersFrm.wireAWG.options ;
  //  float isSelected = false;
  //  for (float i = 0 ; i < ArrayLength(wireTable) ; i++)
  //  {
  //    // set the default wire gauge to awg 42
  //    isSelected = ((wireTable[i].awg == 42) ? true : false);
  //
  //    wireOptions[i] = new Option(wireTable[i].awg, i, isSelected, isSelected);
  //  }
}

void setWireOptionIndex(int widx)
{
  // document.parametersFrm.wireAWG.selectedIndex = widx ;
}

void showWireInfo()
{
  //  float frm = document.displayFrm ;
  //  frm.gauge.value = COIL.gauge ;
  //  frm.dia.value = COIL.dia ;
  //  frm.Rdc1k.value = COIL.Rdc1k ;
}

void showBuildInfo()
{
  //document.displayFrm.dia.value = COIL.dia ;
}

void updateWireBuild(int idx)
{
  //  int widx = parametersFrm.wireAWG.selectedIndex ;
  //
  //  if (idx != 0)
  //    COIL.dia = wireTable[widx].heavy ;
  //  else
  //    COIL.dia = wireTable[widx].single ;
}

void updateWireSelection(int idx)
{
  COIL.awg = wireTable[idx].awg ;
  COIL.Rdc1k = R1000ft(wireTable[idx].bare);
  // updateWireBuild(parametersFrm.build.selectedIndex);
}

/*
** Fill factor routines
*/
void updateResistance(float rdc)
{
  //trace("updateResistance(rdc) rdc=" + rdc},
  // float ohms = rdc;
  if (rdc <= 0 || rdc > 128000)
  {
    // rdc = bobbinTable[parametersFrm.bobbin.selectedIndex].ohms;
  }
  COIL.ohms = rdc ;
  //document.parametersFrm.ohms.value = COIL.ohms;
  //document.displayFrm.wirelength.value = roundoff(((COIL.ohms / COIL.Rdc1k) * 1000), 0},
}

// bobbin constructor
struct bobbin
{
  const char *name;
  float L;
  float W;
  float H;
  float flange;
  int awg;
  float ohms;
  float winds;
} bobbinTable[] =
{
  /* NOTE: "flange is the bobbin width, not the core width */
  //********************....description........length..width.height.flange..wire.ohms..winds
  {"Gittler", 0.125, .125, 4.0, .245, 42, 1000, 12000},
  {"Round Spool", 0.1875, .1875, .50, .5000, 43, 1000, 7800},
  {"Jazz Bass Bridge", 2.777, .1875, .5000, .6290, 42, 7250, 8750},
  {"Jazz Bass Neck", 2.6580, .1875, .5000, .6300, 42, 7500, 8700},
  {"Precision Bass", 1.315, .1875, .340, .975, 42, 5250, 10000 },
  {"P90 Lollar", 2.2500, .2500, .2500, 1.1250, 42, 8000, 10000},
  {"P90 WD", 2.1850, .2500, .2500, 1.1850, 42, 8000, 10000},
  {"PAF 50mm", 2.2250, .2600, .2500, .7000, 42, 3715, 4200},
  {"Mini Humbucker", 2.173, .189, .285, .514, 42, 3910, 5350},
  {"Rickenbacker toaster", 2.165, .26, .185, .93, 44, 6060, 5000},
  {"Strat 1967", 2.2500, .1875, .4360, .6250, 42, 5880, 7656},
  {"Strat VN Bridge short", 2.250, .1875, .1712, .6250, 44, 4750, 4000},
  {"Strat VN Bridge tall", 2.2500, .1875, .1825, .6250, 44, 4750, 4000},
  {"Tele Bridge 51+", 2.3785, .1875, .5000, .7620, 42, 7500, 9200},
  {"Tele Bridge 60-70's", 2.3785, .1875, .5000, .7620, 42, 6400, 7800},
  {"Tele Bridge, Barden", 2.3750, .0625, .3650, .2925, 43, 2225, 2200},
  {"Tele Bridge, Duncan", 2.3785, .1875, .5310, .7620, 43, 7200, 8000},
  {"Tele Neck 50's", 2.1555, .1875, .4700, .5000, 43, 7700, 8000},
  {"Tele Neck 60's", 2.1555, .1875, .4700, .5000, 43, 6900, 7800},
  {"Tele Neck, Barden", 2.1250, .0625, .3650, .2070, 43, 2070, 2200},
  {"Tele Neck, Duncan", 2.1555, .1875, .4700, .5000, 42, 7700, 8000},
  {"Tele Neck, Lollar", 2.1555, .1875, .4700, .5000, 43, 6800, 7800}
};

// build pickup option list for select box menu
void initBobbinOptionList()
{
  //  float optionList = document.parametersFrm.bobbin.options ;
  //  float i = 0 ;
  //  optionList[0] = new Option(bobbinTable[0].name, i, true, true);
  //  for (i = 0 ; i < ArrayLength(bobbinTable) ; i++)
  //  {
  //    // select newest addition to table as low-rent unit test
  //    isSelected = ((bobbinTable[i].name == "Precision Bass") ? true : false
  //  },
  //  optionList[i] = new Option(bobbinTable[i].name, i, isSelected, isSelected);
}

// show bobbin dimensions in form
void showBobbinSpecs()
{
  //  float frm = document.displayFrm ;
  //  frm.L.value = COIL.L ;
  //  frm.W.value = COIL.W ;
  //  frm.H.value = COIL.H ;
  //  frm.flange.value = COIL.flange ;
}

// put bobbin dimensions into COIL structure
void updateBobbinType(int idx)
{
  if (idx < 0 || idx >= ArrayLength(bobbinTable))
  {
    //trace("updateBobbinType(idx) idx out of range:" + idx},
    return ;
  }
  COIL.L = bobbinTable[idx].L ;
  COIL.W = bobbinTable[idx].W ;
  COIL.H = bobbinTable[idx].H ;
  COIL.flange = bobbinTable[idx].flange ;
  COIL.winds = bobbinTable[idx].winds ;
  COIL.awg = bobbinTable[idx].awg ;
  updateResistance(bobbinTable[idx].ohms);

  //    showWinds(},
}

/*
** The money shot
*/
float calcMaxLayers()
{
  float MaxLayers = ((COIL.flange - COIL.W) / 2.0) / (COIL.dia / (COIL.fill / 100));

  return roundoff(MaxLayers + 0.5, 0);
}

float calcWindsPerLayer(float bobbinHeight, float wireDia, float fillFactor)
{
  return (bobbinHeight / (wireDia / fillFactor));
}

void windsFromRdc()
{
  //trace("windsFromRdc()"},
  float a, b, c ;
  float lenInches ;
  float wireDia = COIL.dia ;
  //float fill = Math.sqrt(COIL.fill/100},
  float fill = COIL.fill / 100 ;
  lenInches = COIL.ohms / (COIL.Rdc1k / INCHES_PER_1000FT);
  wireDia = wireDia / fill ;

  a = PI * wireDia;
  b = (2.0 * COIL.L) + ((PI - 2.0) * COIL.W) + (PI * wireDia);
  c = -((lenInches * wireDia) / COIL.H);

  quadraticRoot q = {a, b, c};

  if (q.discriminant < 0)
  {
    //trace("error: roots are unreal\n"},
  }
  else
  {
    COIL.layers = ((q.r1 < 0) ? q.r2 : q.r1);
    COIL.wpl = roundoff(calcWindsPerLayer(COIL.H, COIL.dia, fill), 0);
    COIL.wplinch = roundoff((COIL.wpl * (1.0 / COIL.H)), 0);
    COIL.winds = roundoff((COIL.wpl * COIL.layers), 0);
    COIL.layers = roundoff(COIL.layers, 1);
    COIL.maxlayers = calcMaxLayers();
  }
}

void doWindsTable()
{
  //windsFromRdc(},
  //return ;

  COIL.fill = 62 ;    // loose scatter wind
  windsFromRdc();
  showWinds1();
}

/*
** Display routines
*/
void showCoilSpecs()
{
  showWireInfo();
  showBobbinSpecs();
  //showWindsData();
}

void startup()
{
//  updateBobbinType(parametersFrm.bobbin.selectedIndex);
//  updateWireSelection(parametersFrm.wireAWG.selectedIndex);
//  parametersFrm.build.selectedIndex = 0 ;
//  updateWireBuild(parametersFrm.build.selectedIndex);
  updateResistance(0);

  windsFromRdc();
  //    showWinds(},
  showCoilSpecs();
  //    showWindsData()  ;
}

void setup() {}
void loop() {}
1 Like

Thank you for doing that, I really appreciate it - I'll try to do some testing tomorrow and see what kind of answers it spits out this time. If I can't make sense out of it still, I may have to just ask your hourly rate :nerd_face:

So I seem to have some improper math going on in my version of this thing - I've defined all the variables manually, then the math gets printed out in the serial monitor. MaxLayers is working fine, but stuff like WPL and MaxWinds is coming out with extra decimal places (though the numbers are suspiciously close to the correct sequence).

Is there any chance I can hassle you again for another look, or I could pay your hourly rate to go through what's here and make it work:

#include <math.h>

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];

/* variables - user-defined
float cLength;
float cWidth;
float cHeight;
float cFlange;
float cGauge;
int cOhms;
int cFill;
float cDiameter;
float cOhms1000ft;
*/
float cLength = 1.315;
float cWidth = 0.1875;
float cHeight = 0.34;
float cFlange = 0.975;
float cGauge = 42;
float cOhms = 5250;
float cFill[5] = {62,72,78.5,90.7,100};
float cDiameter = 0.0030;
float bDiameter = 0.0025;
float cOhms1000ft = 1659.261741783075;





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


void setup() {
  Serial.begin(115200);
};


/* Constants */
  float inchesPerMeter = 1000.0 / 25.4 ; /* 39.37007874015748 */
  int INCHES_PER_1000FT = 1000 * 12 ; /* 12000 */
  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 = fabs(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 ;
        }
      }
      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++) {
              float a;
              float b;
              float c;
              float lenInches ;
              float wireDia = cDiameter;
              float fill = cFill[i]/100;
              lenInches = cOhms / (R1000ftA / INCHES_PER_1000FT) ;
              wireDia = wireDia / fill ;
          
                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] = round(cHeight / (cDiameter / cFill[i]));
                rWPLInch[i] = round(rWPL[i] * (1.0 / cHeight));
                rWinds[i] = round(rWPL[i] * rLayers[i]);
                rLayers[i] = round(rLayers[i]);
                rMaxWinds[i] = round(rMaxLayers[i] * rWPL[i]);

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

  


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("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("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("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("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("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];
       */
};


Using these settings

I'd just like to get through this part now, I can't track down where the math is going wrong exactly -_-

I've been messing around with this all day and I'm nowhere closer...I just can't figure out what the mathematical issue is. My answers come out like this:
Screen Shot 2021-07-24 at 6.35.44 PM

and the answers on the codepen app look like this:

Clearly something is being multiplied a few too many times in the layers/winds department..

It looks like the Javascript can do all sorts of calculations. What values do you want to get out of it? What values do you have to put into it?

I notice that the table of bobbins, only AWG 42, 43, and 44 is ever used.

I'm just using 42awg for example's sake (w/ heavy insulation), I want my arduino version to be producing the same calculations as this JS device. It's a tool that makes estimates as to how much pickup wire you should/can put onto a bobbin (for guitar usage).

Somewhere I've messed up though, I can't get the same answers out except for the MaxLayers calculation.

In my version, I've manually defined all of the variables that are defined by the dropdowns and text fields in the JS version, it's set to 42awg with heavy gauge insulation (.0030).

I'm just hoping maybe you'll be able to look over this mess and see where I went wrong :flushed:

Here you can see the results variables:

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

and here are the user-defined variables that are used to make calculations (they've been manually defined in the arduino one):

float cLength = 1.315;
float cWidth = 0.1875;
float cHeight = 0.34;
float cFlange = 0.975;
float cGauge = 42;
float cOhms = 5250; //user's desired overall resistance
float cFill[5] = {62,72,78.5,90.7,100};
float cDiameter = 0.0030; //diameter with insulation
float bDiameter = 0.0025; //bare wire diameter
float cOhms1000ft = 1659.261741783075;

I can't find the issue, I've been diddling around with this thing for hours. I don't have any good theories or anything...something I've noticed is that a lot of the answers are just two decimal places off from being correct. For instance, the rWPL value may be 93252.00 in my program, but on the original JS one it's 932.52 - if you compare the sets of answers, you'll see the same for a bunch of them. Maybe it's something to do with the floating point math...? I'm really far out of my element here....I'm relying on you 100% John, just let me know if there's a fee.

Here is my guess at how the various tables and functions would work on the Ardiuno. I don't know if it is producing usable answers or not.

#define ArrayLength(a) (sizeof (a) / sizeof ((a)[0]))

const float Fills[] = {0.62, 0.72, 0.785, 0.907, 1.00};
const int FillCount = ArrayLength(Fills);

// quadratic root type constructor
struct quadraticRoot
{
  float discriminant;
  float r1;
  float r2;
};


/*
  resistivity is in units ohm-meter
  and needs conversion to ohms-1000Ft.
*/
const float inchesPerMeter = 1000.0 / 25.4 ;
const float INCHES_PER_1000FT = 1000 * 12 ;
const float COPPER_RESISTIVITY = 1.724e-8 ; /* ohm-meter */

struct Coil
{
  float Windings;
  float Layers;
  float MaxLayers;
  float WindingsPerLayer;
  float MaxWindings;
  float WindingsPerLayerInch;
};

/*
** Wire handling routines
*/
// Wire gages
struct Wire
{
  int awg;
  float bare;
  float singleInsulated;
  float dooubleInsulated;
} const WireTable[] =
{
  {24, 0.0201, 0.0213, 0.0233},
  {25, 0.0179, 0.0190, 0.0199},
  {26, 0.0159, 0.0170, 0.0178},
  {27, 0.0142, 0.0153, 0.0161},
  {28, 0.0126, 0.0137, 0.0144},
  {29, 0.0113, 0.0123, 0.0130},
  {30, 0.0100, 0.0109, 0.0116},
  {31, 0.0089, 0.0097, 0.0105},
  {32, 0.0080, 0.0088, 0.0095},
  {33, 0.0071, 0.0078, 0.0084},
  {34, 0.0063, 0.0069, 0.0075},
  {35, 0.0056, 0.0062, 0.0067},
  {36, 0.0050, 0.0056, 0.0060},
  {37, 0.0045, 0.0050, 0.0055},
  {38, 0.0040, 0.0045, 0.0049},
  {39, 0.0035, 0.0039, 0.0043},
  {40, 0.0031, 0.0035, 0.0038},
  {41, 0.0028, 0.0031, 0.0034},
  {42, 0.0025, 0.0028, 0.0030},
  {43, 0.0022, 0.0025, 0.0027},
  {44, 0.0020, 0.0022, 0.0025},
  {45, 0.00176, 0.00192, 0.00215},
  {46, 0.00157, 0.00173, 0.00196},
  {47, 0.00140, 0.00158, 0.00178},
  {48, 0.00124, 0.00140, 0.00155},
  {49, 0.00111, 0.00124, 0.00139},
  {50, 0.00099, 0.00113, 0.00128},
  {51, 0.00088, 0.00103, 0.00117},
  {52, 0.00078, 0.00093, 0.00107},
  {53, 0.00070, 0.00079, 0.00090},
  {54, 0.00062, 0.00070, 0.00082},
  {55, 0.00055, 0.00064, 0.00075},
};


// Bobbins
struct Bobbin
{
  const char *name;
  float L;
  float W;
  float H;
  float flange;
  int AWG;
  float Ohms;
  float windings;
} const BobbinTable[] =
{
  /* NOTE: "flange is the bobbin width, not the core width */
  //********************....description........length..width.height.flange..wire.ohms..winds
  {"Gittler", 0.125, .125, 4.0, .245, 42, 1000, 12000},
  {"Round Spool", 0.1875, .1875, .50, .5000, 43, 1000, 7800},
  {"Jazz Bass Bridge", 2.777, .1875, .5000, .6290, 42, 7250, 8750},
  {"Jazz Bass Neck", 2.6580, .1875, .5000, .6300, 42, 7500, 8700},
  {"Precision Bass", 1.315, .1875, .340, .975, 42, 5250, 10000 },
  {"P90 Lollar", 2.2500, .2500, .2500, 1.1250, 42, 8000, 10000},
  {"P90 WD", 2.1850, .2500, .2500, 1.1850, 42, 8000, 10000},
  {"PAF 50mm", 2.2250, .2600, .2500, .7000, 42, 3715, 4200},
  {"Mini Humbucker", 2.173, .189, .285, .514, 42, 3910, 5350},
  {"Rickenbacker toaster", 2.165, .26, .185, .93, 44, 6060, 5000},
  {"Strat 1967", 2.2500, .1875, .4360, .6250, 42, 5880, 7656},
  {"Strat VN Bridge short", 2.250, .1875, .1712, .6250, 44, 4750, 4000},
  {"Strat VN Bridge tall", 2.2500, .1875, .1825, .6250, 44, 4750, 4000},
  {"Tele Bridge 51+", 2.3785, .1875, .5000, .7620, 42, 7500, 9200},
  {"Tele Bridge 60-70's", 2.3785, .1875, .5000, .7620, 42, 6400, 7800},
  {"Tele Bridge, Barden", 2.3750, .0625, .3650, .2925, 43, 2225, 2200},
  {"Tele Bridge, Duncan", 2.3785, .1875, .5310, .7620, 43, 7200, 8000},
  {"Tele Neck 50's", 2.1555, .1875, .4700, .5000, 43, 7700, 8000},
  {"Tele Neck 60's", 2.1555, .1875, .4700, .5000, 43, 6900, 7800},
  {"Tele Neck, Barden", 2.1250, .0625, .3650, .2070, 43, 2070, 2200},
  {"Tele Neck, Duncan", 2.1555, .1875, .4700, .5000, 42, 7700, 8000},
  {"Tele Neck, Lollar", 2.1555, .1875, .4700, .5000, 43, 6800, 7800}
};
const int BobbinCount = ArrayLength(BobbinTable);


/*
** The money shot
*/
float calcMaxLayers(Bobbin b, float wireDia, float fillFactor)
{
  return ((b.flange - b.W) / 2.0) / (wireDia / fillFactor);
}

float calcWindsPerLayer(float bobbinHeight, float wireDia, float fillFactor)
{
  return (bobbinHeight / (wireDia / fillFactor));
}

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 windsFromRdc(Coil &c, Bobbin b, float fillFactor)
{
  float wireDiameter = WireTable[b.AWG - 24].bare;

  float resistance1kft = R1000ft(wireDiameter);

  float lenInches = b.Ohms / (resistance1kft / INCHES_PER_1000FT);
  wireDiameter = wireDiameter / fillFactor ;

  float A = PI * wireDiameter;
  float B = (2.0 * b.L) + ((PI - 2.0) * b.W) + (PI * wireDiameter);
  float C = -((lenInches * wireDiameter) / b.H);

  quadraticRoot q = {A, B, C};

  if (q.discriminant < 0)
  {
    //trace("error: roots are unreal\n"},
  }
  else
  {
    c.Layers = (q.r1 < 0) ? q.r2 : q.r1;
    c.WindingsPerLayer = calcWindsPerLayer(b.H, wireDiameter, fillFactor);
    c.WindingsPerLayerInch = c.WindingsPerLayer * (1.0 / b.H);
    c.Windings = c.WindingsPerLayer * c.Layers;
    c.MaxLayers = calcMaxLayers(b, wireDiameter, fillFactor);

    Serial.print("Layers: ");
    Serial.println(c.Layers);
    Serial.print("WindingsPerLayer: ");
    Serial.println(c.WindingsPerLayer);
    Serial.print("WindingsPerLayerInch: ");
    Serial.println(c.WindingsPerLayerInch);
    Serial.print("Windings: ");
    Serial.println(c.Windings);
    Serial.print("MaxLayers: ");
    Serial.println(c.MaxLayers);
  }
}


//
float circularArea(float diameter)
{
  float radius = diameter / 2.0 ;
  return radius * radius * PI;
}

float Rin (float dia)
{
  return COPPER_RESISTIVITY / (12.0 * circularArea(dia));
}

float R1000ft(float dia)
{
  return (COPPER_RESISTIVITY * inchesPerMeter * INCHES_PER_1000FT) / circularArea(dia);
}

int getWireLengthInFeet(Wire w, float totalResistance)
{
  float resistancePerThousandFeet = R1000ft(w.bare);
  return (totalResistance / resistancePerThousandFeet) * 1000;
}

void setup()
{
  Serial.begin(115200);

  Bobbin b = BobbinTable[4];  // "Precision Bass"

  int gage = b.AWG;
  Wire w = WireTable[gage - 24];

  int wireLengthFeet = getWireLengthInFeet(w, b.Ohms);

  Serial.print(b.name);
  Serial.print(": Feet of wire:");
  Serial.println(wireLengthFeet);

  for (int fill = 0; fill < FillCount; fill++)
  {
    Serial.print("Fill ");
    Serial.print(Fills[fill] * 100);
    Serial.println('%');
    Coil c;
    windsFromRdc(c, b, Fills[fill]);
  }

}

void loop() {}
1 Like

OK well I suppose I better just plug this thing in and try to get it working then - my own version wouldn't be using all the tables and whatnot, so it's much simpler....this is my own version as of right now:

#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;
float cFill[5] = {62,72,78.5,90.7,100};
float cDiameter = 0.0030;
float bDiameter = 0.0025;
float cOhms1000ft = 1659.261741783075;







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 ;
        }
      }
      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++) {
              float a;
              float b;
              float c;
              float lenInches ;
              float fill = cFill[i]/100;
              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]); //cDiameter
                rWPLInch[i] = rWPL[i] * (1.0 / cHeight);
                rWinds[i] = rWPL[i] * rLayers[i];
                rLayers[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("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("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("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("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("rMaxWinds[4] = ");
      Serial.println(rMaxWinds[4]);
      delay(25000);

};

I was making use of the looping function to perform calculations across the different fill factors. It just comes out with some majorly inflated answers :sleepy:

I have returned to annoy you again...this thing is so close, I'm just having trouble getting the correct calculations for the Layers and the Winds. If you look at the numbers it's putting out, you can see they're a couple decimal points off (except for Layers and Winds), so there's some encouragement there:

Screen Shot 2021-07-25 at 3.59.24 PM

I'm doing my best to figure out what's going wrong, but I feel like you might be able to spot the issue quicker, mainly because you don't suck at this sort of thing, and I do.

Could you please take a look at my version of the code and see if there's anything silly I'm doing? I have just had my head in this for so long, I'm embarrassed to even say, that's why I was offering to just pay you to do it before :poop: . Anyway, here's my most recent code:

#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.261741783075;





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 ;
        }
      }
      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++) {
              float a;
              float b;
              float c;
              float lenInches ;
              float fill = cFill[i]/100;
              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("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("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("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("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("rMaxWinds[4] = ");
      Serial.println(rMaxWinds[4]);
      delay(25000);
};

You can compare the results to the codepen version using the settings 42awg and Heavy insulation.

Don't abandon me :cry: :cry:

Your version compiled and functioned, it read out some numbers in the serial monitor but I couldn't confirm they were the same as the other program because I wasn't sure exactly which specs it was using (I compared all the specs for the Precision Bass, they didn't match up).

I'm really out of ideas, I think there must be some difference in the way the math is being performed in C/C++, maybe a different order of operation or something, I just know that I absolutely cannot figure it out.

Screen Shot 2021-07-25 at 6.01.40 PM
[your version on the serial monitor]

Anyway, I fully expect you to come save me now :grinning:

John, don't make me cry myself to sleep again tonight - I've gone back to the drawing board with this thing, just re-translating it from JS again to see if perhaps I missed something the first time..

I think you'd have a much better chance of doing it correctly than I do - maybe I could send you some money to get things moving? I dunno what the rules are for freelancing around these parts...I just know that I desperately want this thing finished.

There is a whole forum section for finding people to do programming projects (often paid projects):

You will need to describe, in fine detail, what you want the sketch to do.

Well I tried bringing it to them as you suggested, and they ended up having some trouble with it too. But I think I've got it extremely close to being done now, maybe you can help with this final thing. The rLayers calculation (rLayers[i] = (q.r1 < 0) ? q.r2 : q.r1;) is coming up with the wrong answer still, and it's affecting the rWinds calculation directly.

Everything else is calculating properly enough now.

I switched all of the floats over to doubles (I'm using an ESP32) at someone else's suggestion too.

#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;





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];

                };
};
};

  


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);
  
};