Browse Source
ADDED: E-Series Resistor Calculator
ADDED: E-Series Resistor Calculator
Fixes https://gitlab.com/kicad/code/kicad/issues/2155pull/16/head
committed by
Seth Hillbrand
10 changed files with 9677 additions and 6761 deletions
-
5pcb_calculator/CMakeLists.txt
-
1777pcb_calculator/dialogs/pcb_calculator_frame_base.cpp
-
13511pcb_calculator/dialogs/pcb_calculator_frame_base.fbp
-
405pcb_calculator/dialogs/pcb_calculator_frame_base.h
-
409pcb_calculator/eserie.cpp
-
241pcb_calculator/eserie.h
-
33pcb_calculator/eserie_help.h
-
31pcb_calculator/eserie_help.md
-
21pcb_calculator/pcb_calculator.h
-
5pcb_calculator/pcb_calculator_frame.cpp
1777
pcb_calculator/dialogs/pcb_calculator_frame_base.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
13511
pcb_calculator/dialogs/pcb_calculator_frame_base.fbp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,409 @@ |
|||
/*
|
|||
* This program source code file |
|||
* is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 <janvi@veith.net> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <dialog_helpers.h>
|
|||
#include <pcb_calculator.h>
|
|||
#include <wx/wx.h>
|
|||
|
|||
#include <array>
|
|||
#include <iostream>
|
|||
#include <string>
|
|||
#include <sys/time.h>
|
|||
#include <vector>
|
|||
|
|||
#include "eserie.h"
|
|||
#include "profile.h"
|
|||
|
|||
wxString eseries_help = |
|||
#include "eserie_help.h"
|
|||
|
|||
eserie r; |
|||
|
|||
void eserie::set_reqR( double aR ) |
|||
{ |
|||
reqR = aR; |
|||
} |
|||
|
|||
void eserie::set_rb( uint32_t a_rb ) |
|||
{ |
|||
rb_state = a_rb; |
|||
} |
|||
|
|||
uint32_t eserie::get_rb( void ) |
|||
{ |
|||
return rb_state; |
|||
} |
|||
|
|||
std::array<r_data, S4R + 1> eserie::get_rslt( void ) |
|||
{ |
|||
return results; |
|||
} |
|||
|
|||
void eserie::exclude( double aValue ) |
|||
{ |
|||
if( aValue ) // if there is a value to exclude other than a wire jumper
|
|||
{ |
|||
for( r_data& i : luts[rb_state] ) // then search it in the selected E-Serie lookup table
|
|||
{ |
|||
if( i.e_value == aValue ) // if value to exclude found
|
|||
{ |
|||
i.e_use = false; // disable its use
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void eserie::simple_solution( uint32_t aSize ) |
|||
{ |
|||
uint32_t i; |
|||
|
|||
results[S2R].e_value = std::numeric_limits<double>::max(); // assume no 2R solution or max deviation
|
|||
|
|||
for( i = 0; i < aSize; i++ ) |
|||
{ |
|||
if( abs( cmb_lut[i].e_value - reqR ) < abs( results[S2R].e_value ) ) |
|||
{ |
|||
results[S2R].e_value = cmb_lut[i].e_value - reqR; // save signed deviation in Ohms
|
|||
results[S2R].e_name = cmb_lut[i].e_name; // save combination text
|
|||
results[S2R].e_use = true; // this is a possible solution
|
|||
} |
|||
} |
|||
} |
|||
|
|||
void eserie::combine4( uint32_t aSize ) |
|||
{ |
|||
uint32_t i,j; |
|||
double tmp; |
|||
std::string s; |
|||
|
|||
results[S4R].e_use = false; // disable 4R solution, until
|
|||
results[S4R].e_value = results[S3R].e_value; // 4R becomes better than 3R solution
|
|||
|
|||
#ifdef BENCHMARK
|
|||
PROF_COUNTER combine4_timer; // start timer to count execution time
|
|||
#endif
|
|||
|
|||
for( i = 0; i < aSize; i++ ) // 4R search outer loop
|
|||
{ // scan valid intermediate 2R solutions
|
|||
for( j = 0; j < aSize; j++ ) // inner loop combines all with itself
|
|||
{ |
|||
tmp = cmb_lut[i].e_value + cmb_lut[j].e_value; // calculate 2R+2R serial
|
|||
tmp -= reqR; // calculate 4R deviation
|
|||
|
|||
if( abs( tmp ) < abs( results[S4R].e_value ) ) // if new 4R is better
|
|||
{ |
|||
results[S4R].e_value = tmp; // save amount of benefit
|
|||
std::string s = "( "; |
|||
s.append( cmb_lut[i].e_name ); // mention 1st 2 component
|
|||
s.append( " ) + ( " ); // in series
|
|||
s.append( cmb_lut[j].e_name ); // with 2nd 2 components
|
|||
s.append( " )" ); |
|||
results[S4R].e_name = s; // save the result and
|
|||
results[S4R].e_use = true; // enable for later use
|
|||
} |
|||
|
|||
tmp = ( cmb_lut[i].e_value * cmb_lut[j].e_value ) / |
|||
( cmb_lut[i].e_value + cmb_lut[j].e_value ); // calculate 2R|2R parallel
|
|||
tmp -= reqR; // calculate 4R deviation
|
|||
|
|||
if( abs( tmp ) < abs( results[S4R].e_value ) ) // if new 4R is better
|
|||
{ |
|||
results[S4R].e_value = tmp; // save amount of benefit
|
|||
std::string s = "( "; |
|||
s.append( cmb_lut[i].e_name ); // mention 1st 2 component
|
|||
s.append( " ) | ( " ); // in parallel
|
|||
s.append( cmb_lut[j].e_name ); // with 2nd 2 components
|
|||
s.append( " )" ); |
|||
results[S4R].e_name = s; // save the result
|
|||
results[S4R].e_use = true; // enable later use
|
|||
} |
|||
} |
|||
} |
|||
|
|||
#ifdef BENCHMARK
|
|||
if( rb_state == E12 ) |
|||
{ |
|||
std::cout<<"4R Time = "<<combine4_timer.msecs()<<" mSec"<<std::endl; |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void eserie::new_calc( void ) |
|||
{ |
|||
for( r_data& i : cmb_lut ) |
|||
{ |
|||
i.e_use = false; // before any calculation is done, assume that
|
|||
} |
|||
|
|||
for( r_data& i : results ) |
|||
{ |
|||
i.e_use = false; // no combinations and no results are available
|
|||
} |
|||
|
|||
for( r_data& i : luts[rb_state]) |
|||
{ |
|||
i.e_use = true; // all selecte E-values available
|
|||
} |
|||
} |
|||
|
|||
uint32_t eserie::combine2( void ) |
|||
{ |
|||
uint32_t combi2R = 0; // target index counts calculated 2R combinations
|
|||
std::string s; |
|||
|
|||
for( const r_data& i : luts[rb_state] ) // outer loop to sweep selected source lookup table
|
|||
{ |
|||
if( i.e_use ) |
|||
{ |
|||
for( const r_data& j : luts[rb_state] ) // inner loop to combine values with itself
|
|||
{ |
|||
if( j.e_use ) |
|||
{ |
|||
cmb_lut[combi2R].e_use = true; |
|||
cmb_lut[combi2R].e_value = i.e_value + j.e_value; // calculate 2R serial
|
|||
s = i.e_name; |
|||
s.append( " + " ); |
|||
cmb_lut[combi2R].e_name = s.append(j.e_name); |
|||
combi2R++; // next destination
|
|||
cmb_lut[combi2R].e_use = true; // calculate 2R parallel
|
|||
cmb_lut[combi2R].e_value = i.e_value * j.e_value / |
|||
( i.e_value + j.e_value ); |
|||
s = i.e_name; |
|||
s.append( " | " ); |
|||
cmb_lut[combi2R].e_name = s.append( j.e_name ); |
|||
combi2R++; // next destination
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
return ( combi2R ); |
|||
} |
|||
|
|||
void eserie::combine3( uint32_t aSize ) |
|||
{ |
|||
uint32_t j = 0; |
|||
double tmp = 0; // avoid warning for being uninitialized
|
|||
std::string s; |
|||
|
|||
results[S3R].e_use = false; // disable 3R solution, until
|
|||
results[S3R].e_value = results[S2R].e_value; // 3R becomes better than 2R solution
|
|||
|
|||
for( const r_data& i : luts[rb_state] ) // 3R Outer loop to selected primary E serie LUT
|
|||
{ |
|||
if( i.e_use ) // skip all excluded values
|
|||
{ |
|||
for( j = 0; j < aSize; j++ ) // inner loop combines with all 2R intermediate results
|
|||
{ // R+2R serial combi
|
|||
tmp = cmb_lut[j].e_value + i.e_value; |
|||
tmp -= reqR; // calculate deviation
|
|||
|
|||
if( abs( tmp ) < abs( results[S3R].e_value ) ) // compare if better
|
|||
{ // then take it
|
|||
s = i.e_name; // mention 3rd component
|
|||
s.append( " + ( " ); // in series
|
|||
s.append( cmb_lut[j].e_name ); // with 2R combination
|
|||
s.append( " )" ); |
|||
results[S3R].e_name = s; // save S3R result
|
|||
results[S3R].e_value = tmp; // save amount of benefit
|
|||
results[S3R].e_use = true; // enable later use
|
|||
} |
|||
|
|||
tmp = i.e_value * cmb_lut[j].e_value / |
|||
( i.e_value + cmb_lut[j].e_value ); // calculate R + 2R parallel
|
|||
tmp -= reqR; // calculate deviation
|
|||
|
|||
if( abs( tmp ) < abs( results[S3R].e_value ) ) // compare if better
|
|||
{ // then take it
|
|||
s = i.e_name; // mention 3rd component
|
|||
s.append( " | ( " ); // in parallel
|
|||
s.append( cmb_lut[j].e_name ); // with 2R combination
|
|||
s.append( " )" ); |
|||
results[S3R].e_name = s; |
|||
results[S3R].e_value = tmp; // save amount of benefit
|
|||
results[S3R].e_use = true; // enable later use
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
// if there is a 3R result with remaining deviation
|
|||
if( ( results[S3R].e_use == true ) && tmp ) |
|||
{ // consider to search a possibly better 4R solution
|
|||
combine4( aSize ); // calculate 4R for small series always
|
|||
} |
|||
} |
|||
|
|||
void eserie::calculate( void ) |
|||
{ |
|||
uint32_t no_of_2Rcombi = 0; |
|||
|
|||
no_of_2Rcombi = combine2(); // combine all 2R combinations for selected E serie
|
|||
simple_solution( no_of_2Rcombi ); // search for simple 2 component solution
|
|||
|
|||
if( results[S2R].e_value ) // if simple 2R result is not exact
|
|||
{ |
|||
combine3( no_of_2Rcombi ); // continiue searching for a possibly better solution
|
|||
} |
|||
strip3(); |
|||
strip4(); |
|||
} |
|||
|
|||
void eserie::strip3( void ) |
|||
{ |
|||
std::string s; |
|||
|
|||
if( results[S3R].e_use ) // if there is a 3 term result available
|
|||
{ // what is connected either by two "|" or by 3 plus
|
|||
s = results[S3R].e_name; |
|||
|
|||
if( ( std::count( s.begin(), s.end(), '+' ) == 2 ) || \ |
|||
( std::count( s.begin(), s.end(), '|' ) == 2 ) ) |
|||
{ // then strip one pair of braces
|
|||
s.erase( s.find( "(" ), 1 ); // it is known sure, this is available
|
|||
s.erase( s.find( ")" ), 1 ); // in any unstripped 3R result term
|
|||
results[S3R].e_name = s; // use stripped result
|
|||
} |
|||
} |
|||
} |
|||
|
|||
void eserie::strip4( void ) |
|||
{ |
|||
std::string s; |
|||
|
|||
if( results[S4R].e_use ) // if there is a 4 term result available
|
|||
{ // what are connected either by 3 "+" or by 3 "|"
|
|||
s = results[S4R].e_name; |
|||
|
|||
if( ( std::count( s.begin(), s.end(), '+' ) == 3 ) || |
|||
( std::count( s.begin(), s.end(), '|' ) == 3 ) ) |
|||
{ // then strip two pair of braces
|
|||
s.erase( s.find( "(" ), 1 ); // it is known sure, they are available
|
|||
s.erase( s.find( ")" ), 1 ); // in any unstripped 4R result term
|
|||
s.erase( s.find( "(" ), 1 ); |
|||
s.erase( s.find( ")" ), 1 ); |
|||
results[S4R].e_name = s; // use stripped result
|
|||
} |
|||
} |
|||
} |
|||
|
|||
void PCB_CALCULATOR_FRAME::OnCalculateESeries( wxCommandEvent& event ) |
|||
{ |
|||
double reqr; // required resistor stored in local copy
|
|||
double error, err3 = 0; |
|||
wxString es, fs; // error and formula strings
|
|||
|
|||
reqr = ( 1000 * DoubleFromString( m_ResRequired->GetValue() ) ); |
|||
r.set_reqR(reqr); // keep a local copy of requred resistor value
|
|||
r.new_calc(); // assume all values available
|
|||
/*
|
|||
* Exclude itself. For the case, a value from the available series is found as required value, |
|||
* the calculator assumes this value needs a replacement for the reason of being not available. |
|||
* Two further exclude values can be entered to exclude and are skipped as not being availabe. |
|||
* All values entered in KiloOhms are converted to Ohm for internal calculation |
|||
*/ |
|||
r.exclude( 1000 * DoubleFromString( m_ResRequired->GetValue() ) ); |
|||
r.exclude( 1000 * DoubleFromString( m_ResExclude1->GetValue() ) ); |
|||
r.exclude( 1000 * DoubleFromString( m_ResExclude2->GetValue() ) ); |
|||
r.calculate(); |
|||
|
|||
fs = r.get_rslt()[S2R].e_name; // show 2R solution formula string
|
|||
m_ESeries_Sol2R->SetValue( fs ); |
|||
error = reqr + r.get_rslt()[S2R].e_value; // absolute value of solution
|
|||
error = ( reqr / error - 1 ) * 100; // error in percent
|
|||
|
|||
if( error ) |
|||
{ |
|||
es.Printf( "%+.2f",error); // if 2R solution with error
|
|||
} |
|||
else |
|||
{ |
|||
es = "Exact"; // 2R solution is already exact
|
|||
} |
|||
|
|||
m_ESeriesError2R->SetValue( es ); // anyway show 2R error string
|
|||
|
|||
if( r.get_rslt()[S3R].e_use ) // if 3R solution available
|
|||
{ |
|||
err3 = reqr + r.get_rslt()[S3R].e_value; // calculate the 3R
|
|||
err3 = ( reqr / err3 - 1 ) * 100; // error in percent
|
|||
|
|||
if( err3 ) // build 3R error string
|
|||
{ |
|||
es.Printf( "%+.2f",err3); |
|||
} |
|||
else |
|||
{ |
|||
es = "Exact"; |
|||
} |
|||
|
|||
m_ESeriesError3R->SetValue( es ); // show 3R error string
|
|||
fs = r.get_rslt()[S3R].e_name; |
|||
m_ESeries_Sol3R->SetValue( fs ); // show 3R formula string
|
|||
} |
|||
else // nothing better than 2R found
|
|||
{ |
|||
fs = "Not worth using"; |
|||
m_ESeries_Sol3R->SetValue( fs ); |
|||
m_ESeriesError3R->SetValue( wxEmptyString ); |
|||
} |
|||
|
|||
fs = wxEmptyString; |
|||
|
|||
if( r.get_rslt()[S4R].e_use ) // show 4R solution if available
|
|||
{ |
|||
fs = r.get_rslt()[S4R].e_name; |
|||
|
|||
error = reqr + r.get_rslt()[S4R].e_value; // absolute value of solution
|
|||
error = ( reqr / error - 1 ) * 100; // error in percent
|
|||
|
|||
if( error ) |
|||
{ |
|||
es.Printf( "%+.2f",error ); |
|||
} |
|||
else |
|||
{ |
|||
es = "Exact"; |
|||
} |
|||
|
|||
m_ESeriesError4R->SetValue( es ); |
|||
} |
|||
else // no 4R solution
|
|||
{ |
|||
fs = "Not worth using"; |
|||
es = wxEmptyString; |
|||
m_ESeriesError4R->SetValue( es ); |
|||
} |
|||
|
|||
m_ESeries_Sol4R->SetValue( fs ); |
|||
} |
|||
|
|||
void PCB_CALCULATOR_FRAME::OnESerieSelection( wxCommandEvent& event ) |
|||
{ |
|||
r.set_rb ( event.GetSelection() ); |
|||
} |
|||
|
|||
void PCB_CALCULATOR_FRAME::ES_Init() // initialize ESeries tab at each pcb-calculator start
|
|||
{ |
|||
wxString msg; |
|||
|
|||
// show markdown formula explanation in lower help panel
|
|||
ConvertMarkdown2Html( wxGetTranslation( eseries_help ), msg ); |
|||
m_panelESeriesHelp->SetPage( msg ); |
|||
} |
@ -0,0 +1,241 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 <janvi@veith.net> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
/** |
|||
* @file eserie.h |
|||
*/ |
|||
|
|||
extern double DoubleFromString( const wxString& TextValue ); |
|||
|
|||
/** |
|||
* If BENCHMARK is defined, any 4R E12 calculations will print its execution time to console |
|||
* My Hasswell Enthusiast reports 225 mSec what are reproducable within plusminus 2 percent |
|||
*/ |
|||
|
|||
#define BENCHMARK |
|||
|
|||
/** |
|||
* E-Values derived from a geometric sequence formula by Charles Renard were already |
|||
* accepted and widely used before the ISO recommendation no. 3 has been published. |
|||
* For this historical reason, rounding rules of some values are sometimes irregular. |
|||
* Although all E-Values could be calculated at runtime, we initialize them in a lookup table |
|||
* what seems the most easy way to consider any inconvenient irregular rules. Same table is |
|||
* also used to lookup non calculatable but readable BOM value strings. Supported E-series are: |
|||
*/ |
|||
|
|||
enum { E1, E3, E6, E12 }; |
|||
|
|||
/** |
|||
* This calculator suggests solutions for 2R, 3R and 4R replacement combinations |
|||
*/ |
|||
|
|||
enum { S2R, S3R, S4R }; |
|||
|
|||
/** |
|||
* 6 decade E-series values from 10 Ohms to 1M and its associated BOM strings. |
|||
* Series E3,E6,E12 are defined by additional values for cumulative use with previous series |
|||
*/ |
|||
|
|||
#define E1_VAL { true, "1K", 1000 },\ |
|||
{ true, "10K", 10000 },\ |
|||
{ true, "100K", 100000 },\ |
|||
{ true, "10R", 10 },\ |
|||
{ true, "100R", 100 },\ |
|||
{ true, "1M", 1000000 } |
|||
|
|||
#define E3_ADD { true, "22R", 22 },\ |
|||
{ true, "47R", 47 },\ |
|||
{ true, "220R", 220 },\ |
|||
{ true, "470R", 470 },\ |
|||
{ true, "2K2", 2200 },\ |
|||
{ true, "4K7", 4700 },\ |
|||
{ true, "22K", 22000 },\ |
|||
{ true, "47K", 47000 },\ |
|||
{ true, "220K", 220000 },\ |
|||
{ true, "470K", 470000 } |
|||
|
|||
#define E6_ADD { true, "15R", 15 },\ |
|||
{ true, "33R", 33 },\ |
|||
{ true, "68R", 68 },\ |
|||
{ true, "150R", 150 },\ |
|||
{ true, "330R", 330 },\ |
|||
{ true, "680R", 680 },\ |
|||
{ true, "1K5", 1500 },\ |
|||
{ true, "3K3", 3300 },\ |
|||
{ true, "6K8", 6800 },\ |
|||
{ true, "15K", 15000 },\ |
|||
{ true, "33K", 33000 },\ |
|||
{ true, "68K", 68000 },\ |
|||
{ true, "150K", 150000 },\ |
|||
{ true, "330K", 330000 },\ |
|||
{ true, "680K", 680000 } |
|||
|
|||
#define E12_ADD { true, "12R", 12 },\ |
|||
{ true, "18R", 18 },\ |
|||
{ true, "27R", 27 },\ |
|||
{ true, "39R", 39 },\ |
|||
{ true, "56R", 56 },\ |
|||
{ true, "82R", 82 },\ |
|||
{ true, "120R", 120 },\ |
|||
{ true, "180R", 180 },\ |
|||
{ true, "270R", 270 },\ |
|||
{ true, "390R", 390 },\ |
|||
{ true, "560R", 560 },\ |
|||
{ true, "820R", 820 },\ |
|||
{ true, "1K2", 1200 },\ |
|||
{ true, "1K8", 1800 },\ |
|||
{ true, "2K7", 2700 },\ |
|||
{ true, "3K9", 3900 },\ |
|||
{ true, "5K6", 5600 },\ |
|||
{ true, "8K2", 8200 },\ |
|||
{ true, "12K", 12000 },\ |
|||
{ true, "18K", 18000 },\ |
|||
{ true, "27K", 27000 },\ |
|||
{ true, "39K", 39000 },\ |
|||
{ true, "56K", 56000 },\ |
|||
{ true, "82K", 82000 },\ |
|||
{ true, "120K", 120000 },\ |
|||
{ true, "180K", 180000 },\ |
|||
{ true, "270K", 270000 },\ |
|||
{ true, "390K", 390000 },\ |
|||
{ true, "560K", 560000 },\ |
|||
{ true, "820K", 820000 } |
|||
|
|||
struct r_data { |
|||
bool e_use; |
|||
std::string e_name; |
|||
double e_value; |
|||
}; |
|||
|
|||
class eserie |
|||
{ |
|||
private: |
|||
std::vector<std::vector<r_data>> luts { |
|||
{ E1_VAL }, |
|||
{ E1_VAL, E3_ADD }, |
|||
{ E1_VAL, E3_ADD, E6_ADD }, |
|||
{ E1_VAL, E3_ADD, E6_ADD, E12_ADD } |
|||
}; |
|||
/* |
|||
* TODO: Manual array size calculation is dangerous. Unlike legacy ANSI-C Arrays |
|||
* std::array can not drop length param by providing aggregate init list up |
|||
* to C++17. Reserved array size should be 2*E12² of std::vector primary list. |
|||
* Exceeding memory limit 7442 will crash the calculator without any warnings ! |
|||
* Compare to previous MAX_COMB macro for legacy ANSI-C array automatic solution |
|||
* #define E12_SIZE sizeof ( e12_lut ) / sizeof ( r_data ) |
|||
* #define MAX_COMB (2 * E12_SIZE * E12_SIZE) |
|||
* 2 component combinations including redundant swappable terms are for the moment |
|||
* 72 combinations for E1 |
|||
* 512 combinations for E3 |
|||
* 1922 combinations for E6 |
|||
* 7442 combinations for E12 |
|||
*/ |
|||
|
|||
#define MAX_CMB 7442 // maximum combinations for E12 |
|||
|
|||
std::array<r_data,MAX_CMB> cmb_lut; // intermediate 2R combinations |
|||
std::array<r_data,S4R+1> results; // 2R, 3R and 4R results |
|||
uint32_t rb_state = E6; // Radio Button State |
|||
uint32_t cb_state = false; // Check Box 4R enable |
|||
double reqR; // required Resistor |
|||
|
|||
/** |
|||
* Build all 2R combinations from the selected E-serie values |
|||
* |
|||
* Pre-calculated value combinations are saved in intermediate look up table cmb_lut |
|||
* @return is the number of found combinations what also depends from exclude values |
|||
*/ |
|||
uint32_t combine2( void ); |
|||
|
|||
/** |
|||
* Search for closest two component solution |
|||
* |
|||
* @param aSize is the number of valid 2R combinations in cmb_lut on where to search |
|||
* The 2R result with smallest deviation will be saved in results |
|||
*/ |
|||
void simple_solution( uint32_t aSize ); |
|||
|
|||
/** |
|||
* Check if there is a better 3 R solution than previous one using only two components. |
|||
* |
|||
* @param aSize gives the number of available combinations to be checked inside cmb_lut |
|||
* Therefore cmb_lut is combinated with the primary E-serie look up table |
|||
* The 3R result with smallest deviation will be saved in results if better than 2R |
|||
*/ |
|||
void combine3( uint32_t aSize ); |
|||
|
|||
/** |
|||
* Check if there is a better four component solution. |
|||
* |
|||
* @param aSsize gives the number of 2R combinations to be checked inside cmb_lut |
|||
* Occupied calculation time depends from number of available E-serie values |
|||
* with the power of 4 why execution for E12 is conditional with 4R check box |
|||
* for the case the previously found 3R solution is already exact |
|||
*/ |
|||
void combine4( uint32_t aSize ); |
|||
|
|||
/* |
|||
* Strip redundant braces from three component result |
|||
* |
|||
* Example: R1+(R2+R3) become R1+R2+R3 |
|||
* and R1|(R2|R3) become R1|R2|R3 |
|||
* while R1+(R2|R3) or (R1+R2)|R3) remains untouched |
|||
*/ |
|||
void strip3( void ); |
|||
|
|||
/* |
|||
* Strip redundant braces from four component result |
|||
* |
|||
* Example: (R1+R2)+(R3+R4) become R1+R2+R3+R4 |
|||
* and (R1|R2)|(R2|R3) become R1|R2|R3|R4 |
|||
* while (R1+R2)|(R3+R4) remains untouched |
|||
*/ |
|||
void strip4( void ); |
|||
|
|||
public: |
|||
|
|||
/** |
|||
* If any value of the selected E-serie not available, it can be entered as an exclude value. |
|||
* |
|||
* @param aValue is the value to exclude from calculation |
|||
* Values to exclude are set to false in the selected E-serie source lookup table |
|||
*/ |
|||
void exclude( double aValue ); |
|||
|
|||
/** |
|||
* initialize next calculation and erase results from previous calculation |
|||
*/ |
|||
void new_calc( void ); |
|||
|
|||
/** |
|||
* called on calculate button to execute all the 2R, 3R and 4R calculations |
|||
*/ |
|||
void calculate( void ); |
|||
|
|||
/** |
|||
* Interface for CheckBox, RadioButton, RequriedResistor and calculated Results |
|||
*/ |
|||
void set_4R_cb ( bool a_tb ); |
|||
bool get_4R_cb ( void ); |
|||
void set_rb ( uint32_t a_rb ); |
|||
uint32_t get_rb ( void ); |
|||
void set_reqR ( double aR ); |
|||
std::array<r_data,S4R+1> get_rslt ( void ); |
|||
}; |
@ -0,0 +1,33 @@ |
|||
// Do not edit this file, it is autogenerated by CMake from the .md file |
|||
_HKI( "E-series defined in IEC 60063 are a widely accepted system of preferred\n" |
|||
"numbers for electronic components. Available values are approximately\n" |
|||
"equally spaced in a logarithmic scale. Although E-series are used for\n" |
|||
"Zener diodes, inductors and other components, this calculator is mainly\n" |
|||
"intended for resistors.\n" |
|||
"\n" |
|||
" E12: 1,0 1,2 1,5 1,8 2,2 2,7 3,3 3,9 4,7 5,6 6,8 8,2\n" |
|||
" E6: 1,0 - 1,5 - 2,2 - 3,3 - 4,7 - 6,8 -\n" |
|||
" E3: 1,0 - - - 2,2 - - - 4,7 - - -\n" |
|||
" E1: 1,0 - - - - - - - - - - -\n" |
|||
"If your design requires any resistor value which is not readily available,\n" |
|||
"this calculator will find a combination of standard E-series components to\n" |
|||
"create it. You can enter the required resistance from 0,0025 to 4000 KOhm. \n" |
|||
"Solutions using 3 or 4 resistors are given if a better match can be found. \n" |
|||
"The 4R checkbox option will take longer to process is considered for the E12\n" |
|||
"series only. Optionally it is possible to exclude up to two additional\n" |
|||
"values from the solution for the reason of being not available. If a\n" |
|||
"E-series value is entered to the required input field, it is always excluded\n" |
|||
"from any solution as it is assumed that this value is unavailable.\n" |
|||
"\n" |
|||
"Solutions are given in the following formats:\n" |
|||
"\n" |
|||
" R1 + R2 +...+ Rn resistors in series\n" |
|||
" R1 | R2 |...| Rn resistors in parallel\n" |
|||
" R1 + (R2|R3)... any combination of the above\n" |
|||
"__Example:__ Voltage dividers, commonly used for 1:10 range selection\n" |
|||
"require resistor ratio values 1:9. Unfortunately the \"9\" is a value, what\n" |
|||
"is not even in the E192 series available. Deviation of 1% and more is yet\n" |
|||
"unacceptable for 8 bit accuracy. For a required resistor value of 9 KOhm,\n" |
|||
"the calculator suggests the E6 values 2k2 + 6k8 in series as a possible\n" |
|||
"exact solution.\n" |
|||
"" ); |
@ -0,0 +1,31 @@ |
|||
E-series defined in IEC 60063 are a widely accepted system of preferred |
|||
numbers for electronic components. Available values are approximately |
|||
equally spaced in a logarithmic scale. Although E-series are used for |
|||
Zener diodes, inductors and other components, this calculator is mainly |
|||
intended for resistors. |
|||
|
|||
E12: 1,0 1,2 1,5 1,8 2,2 2,7 3,3 3,9 4,7 5,6 6,8 8,2 |
|||
E6: 1,0 - 1,5 - 2,2 - 3,3 - 4,7 - 6,8 - |
|||
E3: 1,0 - - - 2,2 - - - 4,7 - - - |
|||
E1: 1,0 - - - - - - - - - - - |
|||
If your design requires any resistor value which is not readily available, |
|||
this calculator will find a combination of standard E-series components to |
|||
create it. You can enter the required resistance from 0,0025 to 4000 KOhm. |
|||
Solutions using 3 or 4 resistors are given if a better match can be found. |
|||
The 4R checkbox option will take longer to process is considered for the E12 |
|||
series only. Optionally it is possible to exclude up to two additional |
|||
values from the solution for the reason of being not available. If a |
|||
E-series value is entered to the required input field, it is always excluded |
|||
from any solution as it is assumed that this value is unavailable. |
|||
|
|||
Solutions are given in the following formats: |
|||
|
|||
R1 + R2 +...+ Rn resistors in series |
|||
R1 | R2 |...| Rn resistors in parallel |
|||
R1 + (R2|R3)... any combination of the above |
|||
__Example:__ Voltage dividers, commonly used for 1:10 range selection |
|||
require resistor ratio values 1:9. Unfortunately the "9" is a value, what |
|||
is not even in the E192 series available. Deviation of 1% and more is yet |
|||
unacceptable for 8 bit accuracy. For a required resistor value of 9 KOhm, |
|||
the calculator suggests the E6 values 2k2 + 6k8 in series as a possible |
|||
exact solution. |
Write
Preview
Loading…
Cancel
Save
Reference in new issue