이종훈's 작업실

Making +63

아두이노에서 10여자리 이상의 큰 수나 소수점 이하의 수를 처리하는 문제는

며칠간의 공부 끝에 내 능력으로는 힘들겠구나 하고 결론을 내렸습니다;


그래서 계속 구글링을 했는데 며칠간의 검색 끝에 결국 괜찮은 라이브러리를 찾았습니다.

https://github.com/nickgammon/BigNumber


BigNumber.zip


원문 도큐먼트가 개발자 개인 블로그 에 있길래 혹시 사라질 지 몰라 카피했습니다. 

일단 예문과 결과값을 보면 제가 원하는 부분을 확실히 해결해 줄 수 있을 듯 합니다. 


우린 답을 찾을 것이다. 늘 그랬듯이. 구글에서.


 

Posted byNick Gammon   Australia  (21,293 posts)  [Biography] bio   Forum Administrator
DateTue 31 Jan 2012 09:00 PM (UTC)

Amended on Sat 23 Aug 2014 03:49 AM (UTC) by Nick Gammon

Message
I love big numbers ... they are so ... big!

So in the spirit of getting your Arduino to handle nice, big, numbers I have ported (with pretty minimal effort on my part) the GNU "bc" library to an Arduino library. This can be downloaded from:

http://www.gammon.com.au/Arduino/BigNumber.zip

Just unzip into your "libraries" folder.

Also now available from GitHub:

https://github.com/nickgammon/BigNumber

Factorials


Example sketch:


// BigNumber test: factorials
#include "BigNumber.h"

// function to display a big number and free it afterwards
void printBignum (BigNumber & n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum

void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print (i);
    Serial.print ("! = ");
    fact *= i;
    printBignum (fact);
  }

}  // end of setup

void loop () { }



Output from above:


2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000
17! = 355687428096000
18! = 6402373705728000
19! = 121645100408832000
20! = 2432902008176640000
21! = 51090942171709440000
22! = 1124000727777607680000
23! = 25852016738884976640000
24! = 620448401733239439360000
25! = 15511210043330985984000000
26! = 403291461126605635584000000
27! = 10888869450418352160768000000
28! = 304888344611713860501504000000
29! = 8841761993739701954543616000000
30! = 265252859812191058636308480000000
31! = 8222838654177922817725562880000000
32! = 263130836933693530167218012160000000
33! = 8683317618811886495518194401280000000
34! = 295232799039604140847618609643520000000
35! = 10333147966386144929666651337523200000000
36! = 371993326789901217467999448150835200000000
37! = 13763753091226345046315979581580902400000000
38! = 523022617466601111760007224100074291200000000
39! = 20397882081197443358640281739902897356800000000
40! = 815915283247897734345611269596115894272000000000
41! = 33452526613163807108170062053440751665152000000000
42! = 1405006117752879898543142606244511569936384000000000
43! = 60415263063373835637355132068513997507264512000000000
44! = 2658271574788448768043625811014615890319638528000000000
45! = 119622220865480194561963161495657715064383733760000000000
46! = 5502622159812088949850305428800254892961651752960000000000
47! = 258623241511168180642964355153611979969197632389120000000000
48! = 12413915592536072670862289047373375038521486354677760000000000
49! = 608281864034267560872252163321295376887552831379210240000000000
50! = 30414093201713378043612608166064768844377641568960512000000000000
51! = 1551118753287382280224243016469303211063259720016986112000000000000
52! = 80658175170943878571660636856403766975289505440883277824000000000000
53! = 4274883284060025564298013753389399649690343788366813724672000000000000
54! = 230843697339241380472092742683027581083278564571807941132288000000000000
55! = 12696403353658275925965100847566516959580321051449436762275840000000000000
56! = 710998587804863451854045647463724949736497978881168458687447040000000000000
57! = 40526919504877216755680601905432322134980384796226602145184481280000000000000
58! = 2350561331282878571829474910515074683828862318181142924420699914240000000000000
59! = 138683118545689835737939019720389406345902876772687432540821294940160000000000000
60! = 8320987112741390144276341183223364380754172606361245952449277696409600000000000000
61! = 507580213877224798800856812176625227226004528988036003099405939480985600000000000000
62! = 31469973260387937525653122354950764088012280797258232192163168247821107200000000000000
63! = 1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000
64! = 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000
65! = 8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000
66! = 544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000
67! = 36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000
68! = 2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000
69! = 171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000
70! = 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000
71! = 850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000
72! = 61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000
73! = 4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000
74! = 330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000
75! = 24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000
76! = 1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000
77! = 145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000
78! = 11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000
79! = 894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000
80! = 71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000
...



Powers



// BigNumber test: powers
#include "BigNumber.h"

// function to display a big number and free it afterwards
void printBignum (BigNumber & n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum


void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  BigNumber::begin ();  // initialize library

  Serial.println ("--- powers of 2 ---");
  
  BigNumber a = 2;

  for (int i = 1; i <= 300; i++)
  {
    Serial.print ("2^");
    Serial.print (i);
    Serial.print (" = ");
    BigNumber p = a.pow (i);
    printBignum (p);
  }  // end of for loop

  Serial.println ("--- powers of 3 ---");
  
  a = 3;

  for (int i = 1; i <= 300; i++)
  {
    Serial.print ("3^");
    Serial.print (i);
    Serial.print (" = ");
    BigNumber p = a.pow (i);
    printBignum (p);
  }  // end of for loop

}  // end of setup

void loop () { }


Output from above:


--- powers of 2 ---
2^1 = 2
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
2^8 = 256
2^9 = 512
2^10 = 1024
2^11 = 2048
2^12 = 4096
2^13 = 8192
2^14 = 16384
2^15 = 32768
2^16 = 65536
2^17 = 131072
2^18 = 262144
2^19 = 524288
2^20 = 1048576
2^21 = 2097152
2^22 = 4194304
2^23 = 8388608
2^24 = 16777216
2^25 = 33554432
2^26 = 67108864
2^27 = 134217728
2^28 = 268435456
2^29 = 536870912
2^30 = 1073741824
2^31 = 2147483648
2^32 = 4294967296
2^33 = 8589934592
2^34 = 17179869184
2^35 = 34359738368
2^36 = 68719476736
2^37 = 137438953472
2^38 = 274877906944
2^39 = 549755813888
2^40 = 1099511627776
2^41 = 2199023255552
2^42 = 4398046511104
2^43 = 8796093022208
2^44 = 17592186044416
2^45 = 35184372088832
2^46 = 70368744177664
2^47 = 140737488355328
2^48 = 281474976710656
2^49 = 562949953421312
2^50 = 1125899906842624
2^51 = 2251799813685248
2^52 = 4503599627370496
2^53 = 9007199254740992
2^54 = 18014398509481984
2^55 = 36028797018963968
2^56 = 72057594037927936
2^57 = 144115188075855872
2^58 = 288230376151711744
2^59 = 576460752303423488
2^60 = 1152921504606846976
2^61 = 2305843009213693952
2^62 = 4611686018427387904
2^63 = 9223372036854775808
2^64 = 18446744073709551616
2^65 = 36893488147419103232
2^66 = 73786976294838206464
2^67 = 147573952589676412928
2^68 = 295147905179352825856
2^69 = 590295810358705651712
2^70 = 1180591620717411303424
2^71 = 2361183241434822606848
2^72 = 4722366482869645213696
2^73 = 9444732965739290427392
2^74 = 18889465931478580854784
2^75 = 37778931862957161709568
2^76 = 75557863725914323419136
2^77 = 151115727451828646838272
2^78 = 302231454903657293676544
2^79 = 604462909807314587353088
2^80 = 1208925819614629174706176
2^81 = 2417851639229258349412352
2^82 = 4835703278458516698824704
2^83 = 9671406556917033397649408
2^84 = 19342813113834066795298816
2^85 = 38685626227668133590597632
2^86 = 77371252455336267181195264
2^87 = 154742504910672534362390528
2^88 = 309485009821345068724781056
2^89 = 618970019642690137449562112
2^90 = 1237940039285380274899124224
2^91 = 2475880078570760549798248448
2^92 = 4951760157141521099596496896
2^93 = 9903520314283042199192993792
2^94 = 19807040628566084398385987584
2^95 = 39614081257132168796771975168
2^96 = 79228162514264337593543950336
2^97 = 158456325028528675187087900672
2^98 = 316912650057057350374175801344
2^99 = 633825300114114700748351602688
2^100 = 1267650600228229401496703205376
2^101 = 2535301200456458802993406410752
2^102 = 5070602400912917605986812821504
2^103 = 10141204801825835211973625643008
2^104 = 20282409603651670423947251286016
2^105 = 40564819207303340847894502572032
2^106 = 81129638414606681695789005144064
2^107 = 162259276829213363391578010288128
2^108 = 324518553658426726783156020576256
2^109 = 649037107316853453566312041152512
2^110 = 1298074214633706907132624082305024
2^111 = 2596148429267413814265248164610048
2^112 = 5192296858534827628530496329220096
2^113 = 10384593717069655257060992658440192
2^114 = 20769187434139310514121985316880384
2^115 = 41538374868278621028243970633760768
2^116 = 83076749736557242056487941267521536
2^117 = 166153499473114484112975882535043072
2^118 = 332306998946228968225951765070086144
2^119 = 664613997892457936451903530140172288
2^120 = 1329227995784915872903807060280344576
2^121 = 2658455991569831745807614120560689152
2^122 = 5316911983139663491615228241121378304
2^123 = 10633823966279326983230456482242756608
2^124 = 21267647932558653966460912964485513216
2^125 = 42535295865117307932921825928971026432
2^126 = 85070591730234615865843651857942052864
2^127 = 170141183460469231731687303715884105728
2^128 = 340282366920938463463374607431768211456
2^129 = 680564733841876926926749214863536422912
2^130 = 1361129467683753853853498429727072845824
2^131 = 2722258935367507707706996859454145691648
2^132 = 5444517870735015415413993718908291383296
2^133 = 10889035741470030830827987437816582766592
2^134 = 21778071482940061661655974875633165533184
2^135 = 43556142965880123323311949751266331066368
2^136 = 87112285931760246646623899502532662132736
2^137 = 174224571863520493293247799005065324265472
2^138 = 348449143727040986586495598010130648530944
2^139 = 696898287454081973172991196020261297061888
2^140 = 1393796574908163946345982392040522594123776
2^141 = 2787593149816327892691964784081045188247552
2^142 = 5575186299632655785383929568162090376495104
2^143 = 11150372599265311570767859136324180752990208
2^144 = 22300745198530623141535718272648361505980416
2^145 = 44601490397061246283071436545296723011960832
2^146 = 89202980794122492566142873090593446023921664
2^147 = 178405961588244985132285746181186892047843328
2^148 = 356811923176489970264571492362373784095686656
2^149 = 713623846352979940529142984724747568191373312
2^150 = 1427247692705959881058285969449495136382746624
2^151 = 2854495385411919762116571938898990272765493248
2^152 = 5708990770823839524233143877797980545530986496
2^153 = 11417981541647679048466287755595961091061972992
2^154 = 22835963083295358096932575511191922182123945984
2^155 = 45671926166590716193865151022383844364247891968
2^156 = 91343852333181432387730302044767688728495783936
2^157 = 182687704666362864775460604089535377456991567872
2^158 = 365375409332725729550921208179070754913983135744
2^159 = 730750818665451459101842416358141509827966271488
2^160 = 1461501637330902918203684832716283019655932542976
2^161 = 2923003274661805836407369665432566039311865085952
2^162 = 5846006549323611672814739330865132078623730171904
2^163 = 11692013098647223345629478661730264157247460343808
2^164 = 23384026197294446691258957323460528314494920687616
2^165 = 46768052394588893382517914646921056628989841375232
2^166 = 93536104789177786765035829293842113257979682750464
2^167 = 187072209578355573530071658587684226515959365500928
2^168 = 374144419156711147060143317175368453031918731001856
2^169 = 748288838313422294120286634350736906063837462003712
2^170 = 1496577676626844588240573268701473812127674924007424
2^171 = 2993155353253689176481146537402947624255349848014848
2^172 = 5986310706507378352962293074805895248510699696029696
2^173 = 11972621413014756705924586149611790497021399392059392
2^174 = 23945242826029513411849172299223580994042798784118784
2^175 = 47890485652059026823698344598447161988085597568237568
2^176 = 95780971304118053647396689196894323976171195136475136
2^177 = 191561942608236107294793378393788647952342390272950272
2^178 = 383123885216472214589586756787577295904684780545900544
2^179 = 766247770432944429179173513575154591809369561091801088
2^180 = 1532495540865888858358347027150309183618739122183602176
2^181 = 3064991081731777716716694054300618367237478244367204352
2^182 = 6129982163463555433433388108601236734474956488734408704
2^183 = 12259964326927110866866776217202473468949912977468817408
2^184 = 24519928653854221733733552434404946937899825954937634816
2^185 = 49039857307708443467467104868809893875799651909875269632
2^186 = 98079714615416886934934209737619787751599303819750539264
2^187 = 196159429230833773869868419475239575503198607639501078528
2^188 = 392318858461667547739736838950479151006397215279002157056
2^189 = 784637716923335095479473677900958302012794430558004314112
2^190 = 1569275433846670190958947355801916604025588861116008628224
2^191 = 3138550867693340381917894711603833208051177722232017256448
2^192 = 6277101735386680763835789423207666416102355444464034512896
2^193 = 12554203470773361527671578846415332832204710888928069025792
2^194 = 25108406941546723055343157692830665664409421777856138051584
2^195 = 50216813883093446110686315385661331328818843555712276103168
2^196 = 100433627766186892221372630771322662657637687111424552206336
2^197 = 200867255532373784442745261542645325315275374222849104412672
2^198 = 401734511064747568885490523085290650630550748445698208825344
2^199 = 803469022129495137770981046170581301261101496891396417650688
2^200 = 1606938044258990275541962092341162602522202993782792835301376
...
--- powers of 3 ---
3^1 = 3
3^2 = 9
3^3 = 27
3^4 = 81
3^5 = 243
3^6 = 729
3^7 = 2187
3^8 = 6561
3^9 = 19683
3^10 = 59049
3^11 = 177147
3^12 = 531441
3^13 = 1594323
3^14 = 4782969
3^15 = 14348907
3^16 = 43046721
3^17 = 129140163
3^18 = 387420489
3^19 = 1162261467
3^20 = 3486784401
3^21 = 10460353203
3^22 = 31381059609
3^23 = 94143178827
3^24 = 282429536481
3^25 = 847288609443
3^26 = 2541865828329
3^27 = 7625597484987
3^28 = 22876792454961
3^29 = 68630377364883
3^30 = 205891132094649
3^31 = 617673396283947
3^32 = 1853020188851841
3^33 = 5559060566555523
3^34 = 16677181699666569
3^35 = 50031545098999707
3^36 = 150094635296999121
3^37 = 450283905890997363
3^38 = 1350851717672992089
3^39 = 4052555153018976267
3^40 = 12157665459056928801
3^41 = 36472996377170786403
3^42 = 109418989131512359209
3^43 = 328256967394537077627
3^44 = 984770902183611232881
3^45 = 2954312706550833698643
3^46 = 8862938119652501095929
3^47 = 26588814358957503287787
3^48 = 79766443076872509863361
3^49 = 239299329230617529590083
3^50 = 717897987691852588770249
3^51 = 2153693963075557766310747
3^52 = 6461081889226673298932241
3^53 = 19383245667680019896796723
3^54 = 58149737003040059690390169
3^55 = 174449211009120179071170507
3^56 = 523347633027360537213511521
3^57 = 1570042899082081611640534563
3^58 = 4710128697246244834921603689
3^59 = 14130386091738734504764811067
3^60 = 42391158275216203514294433201
3^61 = 127173474825648610542883299603
3^62 = 381520424476945831628649898809
3^63 = 1144561273430837494885949696427
3^64 = 3433683820292512484657849089281
3^65 = 10301051460877537453973547267843
3^66 = 30903154382632612361920641803529
3^67 = 92709463147897837085761925410587
3^68 = 278128389443693511257285776231761
3^69 = 834385168331080533771857328695283
3^70 = 2503155504993241601315571986085849
3^71 = 7509466514979724803946715958257547
3^72 = 22528399544939174411840147874772641
3^73 = 67585198634817523235520443624317923
3^74 = 202755595904452569706561330872953769
3^75 = 608266787713357709119683992618861307
3^76 = 1824800363140073127359051977856583921
3^77 = 5474401089420219382077155933569751763
3^78 = 16423203268260658146231467800709255289
3^79 = 49269609804781974438694403402127765867
3^80 = 147808829414345923316083210206383297601
3^81 = 443426488243037769948249630619149892803
3^82 = 1330279464729113309844748891857449678409
3^83 = 3990838394187339929534246675572349035227
3^84 = 11972515182562019788602740026717047105681
3^85 = 35917545547686059365808220080151141317043
3^86 = 107752636643058178097424660240453423951129
3^87 = 323257909929174534292273980721360271853387
3^88 = 969773729787523602876821942164080815560161
3^89 = 2909321189362570808630465826492242446680483
3^90 = 8727963568087712425891397479476727340041449
3^91 = 26183890704263137277674192438430182020124347
3^92 = 78551672112789411833022577315290546060373041
3^93 = 235655016338368235499067731945871638181119123
3^94 = 706965049015104706497203195837614914543357369
3^95 = 2120895147045314119491609587512844743630072107
3^96 = 6362685441135942358474828762538534230890216321
3^97 = 19088056323407827075424486287615602692670648963
3^98 = 57264168970223481226273458862846808078011946889
3^99 = 171792506910670443678820376588540424234035840667
3^100 = 515377520732011331036461129765621272702107522001
3^101 = 1546132562196033993109383389296863818106322566003
3^102 = 4638397686588101979328150167890591454318967698009
3^103 = 13915193059764305937984450503671774362956903094027
3^104 = 41745579179292917813953351511015323088870709282081
3^105 = 125236737537878753441860054533045969266612127846243
3^106 = 375710212613636260325580163599137907799836383538729
3^107 = 1127130637840908780976740490797413723399509150616187
3^108 = 3381391913522726342930221472392241170198527451848561
3^109 = 10144175740568179028790664417176723510595582355545683
3^110 = 30432527221704537086371993251530170531786747066637049
3^111 = 91297581665113611259115979754590511595360241199911147
3^112 = 273892744995340833777347939263771534786080723599733441
3^113 = 821678234986022501332043817791314604358242170799200323
3^114 = 2465034704958067503996131453373943813074726512397600969
3^115 = 7395104114874202511988394360121831439224179537192802907
3^116 = 22185312344622607535965183080365494317672538611578408721
3^117 = 66555937033867822607895549241096482953017615834735226163
3^118 = 199667811101603467823686647723289448859052847504205678489
3^119 = 599003433304810403471059943169868346577158542512617035467
3^120 = 1797010299914431210413179829509605039731475627537851106401
3^121 = 5391030899743293631239539488528815119194426882613553319203
3^122 = 16173092699229880893718618465586445357583280647840659957609
3^123 = 48519278097689642681155855396759336072749841943521979872827
3^124 = 145557834293068928043467566190278008218249525830565939618481
3^125 = 436673502879206784130402698570834024654748577491697818855443
3^126 = 1310020508637620352391208095712502073964245732475093456566329
3^127 = 3930061525912861057173624287137506221892737197425280369698987
3^128 = 11790184577738583171520872861412518665678211592275841109096961
3^129 = 35370553733215749514562618584237555997034634776827523327290883
3^130 = 106111661199647248543687855752712667991103904330482569981872649
3^131 = 318334983598941745631063567258138003973311712991447709945617947
3^132 = 955004950796825236893190701774414011919935138974343129836853841
3^133 = 2865014852390475710679572105323242035759805416923029389510561523
3^134 = 8595044557171427132038716315969726107279416250769088168531684569
3^135 = 25785133671514281396116148947909178321838248752307264505595053707
3^136 = 77355401014542844188348446843727534965514746256921793516785161121
3^137 = 232066203043628532565045340531182604896544238770765380550355483363
3^138 = 696198609130885597695136021593547814689632716312296141651066450089
3^139 = 2088595827392656793085408064780643444068898148936888424953199350267
3^140 = 6265787482177970379256224194341930332206694446810665274859598050801
3^141 = 18797362446533911137768672583025790996620083340431995824578794152403
3^142 = 56392087339601733413306017749077372989860250021295987473736382457209
3^143 = 169176262018805200239918053247232118969580750063887962421209147371627
3^144 = 507528786056415600719754159741696356908742250191663887263627442114881
3^145 = 1522586358169246802159262479225089070726226750574991661790882326344643
3^146 = 4567759074507740406477787437675267212178680251724974985372646979033929
3^147 = 13703277223523221219433362313025801636536040755174924956117940937101787
3^148 = 41109831670569663658300086939077404909608122265524774868353822811305361
3^149 = 123329495011708990974900260817232214728824366796574324605061468433916083
3^150 = 369988485035126972924700782451696644186473100389722973815184405301748249
3^151 = 1109965455105380918774102347355089932559419301169168921445553215905244747
3^152 = 3329896365316142756322307042065269797678257903507506764336659647715734241
3^153 = 9989689095948428268966921126195809393034773710522520293009978943147202723
3^154 = 29969067287845284806900763378587428179104321131567560879029936829441608169
3^155 = 89907201863535854420702290135762284537312963394702682637089810488324824507
3^156 = 269721605590607563262106870407286853611938890184108047911269431464974473521
3^157 = 809164816771822689786320611221860560835816670552324143733808294394923420563
3^158 = 2427494450315468069358961833665581682507450011656972431201424883184770261689
3^159 = 7282483350946404208076885500996745047522350034970917293604274649554310785067
3^160 = 21847450052839212624230656502990235142567050104912751880812823948662932355201
...


Who would have thought your humble Arduino could calculate 100 factorial! Or 2 to the power 300! It runs pretty fast too. 

Calculate e



// BigNumber test: calculate e
#include "BigNumber.h"

// function to display a big number and free it afterwards
void printBignum (BigNumber & n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum

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

  BigNumber::begin (50);  // max around 160 on the Uno

  // some big numbers
  BigNumber n = 1, e = 1, one = 1;

  int i = 1;
  BigNumber E;  // previous result

  unsigned long start = millis ();
  do
  { 
    E = e;
    n *= i++;  // n is i factorial
    e += one / n;
  }  while (e != E);
  unsigned long time = millis () - start;

  printBignum (e);
  Serial.print (time);
  Serial.println (" mS");
} // end of setup

void loop () { }


Output:


2.71828182845904523536028747135266249775724709369978
629 mS


Theory:

http://en.wikipedia.org/wiki/E_%28mathematical_constant%29

E can be calculated as:


1 + (1/1!) + (1/2!) + (1/3!) ...


That's why the code above is calculating running factorials, and adding the inverse of the factorial to the running total. The code breaks out of the loop when, for the desired number of decimal places, the calculated value doesn't change. That is, at this level of precision, the new amount added does not change the result.

BigNumber class


The C++ BigNumber class handles allocation and deallocation in the constructor and destructor.

For example, factorials can be produced like this:

Code:


  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print (i);
    Serial.print ("! = ");
    fact *= i;
    printBignum (fact);
  }


The normal arithmetic operations are supported (eg. assignment, add, subtract, divide, multiply, modulus). Also things like a++ or a--.

Also comparisons can be done in the natural way.

The only memory allocation you have to worry about is when you get a number to print. Since the library may have to return any size number, it does a malloc to store the number (plus a sign, and decimal point if required). It is up to you to free that string. eg.


// function to display a big number and free it afterwards
void printBignum (BigNumber n)
{
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum


An important parameter is the "scale" of the number, which you can set with setScale (n). The scale is effectively the number of decimal places.

For example:


  BigNumber::begin ();  // initialize library

  BigNumber a, b = 2, c;
 
  BigNumber::setScale (0);
  a = BigNumber (1) / BigNumber (3);
  c = b.sqrt ();
  Serial.print ("1/3 = ");
  printBignum (a);
  Serial.print ("sqrt(2) = ");
  printBignum (c);


Output:


1/3 = 0
sqrt(2) = 1


Change the scale to setScale (20) and we get:


1/3 = 0.33333333333333333333
sqrt(2) = 1.41421356237309504880


Change the scale to setScale (100) and we get:


1/3 = 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
sqrt(2) = 1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727



So clearly the scale is affecting the results. Note that, of course, the larger the scale the slower the calculation and the more memory it will require.

Some caveats



  • Working with large numbers is necessarily slow - the larger the number, or the more decimal places, the slower.

  • Each digit requires a byte of memory, plus some overhead (eg. where the decimal point is) - large numbers will soon gobble up the available memory.

  • Doing a toString also requires memory - a byte per digit, plus the sign, decimal point, and trailing 0x00 byte.

  • An "error" condition inside the library (eg. running out of memory) calls exit(), effectively sending the library into a tight loop.

  • You may need to cast some numbers to avoid "ambiguous" warnings from the compiler.

  • If you only have 2048 bytes of RAM, you clearly need to use a library like this with caution. Running out of memory will be quite likely unless you closely manage the size of your numbers, and how many you have.

  • Memory fragmentation will quite possibly be a problem, particularly if you calculate numbers of different sizes (eg. factorials).


The supplied library has some example code (eg. powers, factorials, sine calculations, e^x, and ln(x) ).

Note that cosine and tangent can effectively be calculated from the sine.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted byNick Gammon   Australia  (21,293 posts)  [Biography] bio   Forum Administrator
DateReply #1 on Tue 22 Jan 2013 05:28 AM (UTC)

Amended on Tue 22 Jan 2013 06:16 AM (UTC) by Nick Gammon

Message
Improvements to printing


Thanks to suggestions from Paul Stoffregen, the library has now been modified to allow you to directly print big numbers.

For example, the Factorials example now looks like this:


// BigNumber test: factorials
#include "BigNumber.h"

void setup ()
{
  Serial.begin (115200);
  while (!Serial) ;
  delay(500);
  Serial.println ();
  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print(i);
    Serial.print("! = ");
    fact *= i;
    Serial.println (fact);
  }

}  // end of setup

void loop () { }


Modified line in bold. This was done by deriving the BigNumber class from the Printable class. This means that you can now print big numbers from any class derived from Stream (eg. Serial, Serial1, etc.).

Also changed slightly to support chips which did not have an exit() function defined in their library.

- Nick Gammon

www.gammon.com.au, www.mushclient.com






신고

Comment +0

정수만 갖고 코딩하는것도 초보 수준인데 개념만 살짝 갖고 있는 float 변수형의 16자리수 계산에 대해 개념을 잡으려니 안개처럼 몽실몽실하게 흩어지는군요.





출처: http://elenoa.tistory.com/241

일단 부동소수점이 정확하기 힘들다는 것은 알았습니다.

이진수로 십진수를 계산하기 때문에 어쩔 수 없는 문제지요. 

예전에 인텔도 CPU에서 부동소수점 처리에 결함이 생긴 펜티업 칩 때문에 큰 손실을 본 적이 있습니다(링크)

그리고 저는 고작 10여자리의 부동소수점 때문에 골머리를 썩고 있네요.





아두이노의 레퍼런스를 읽어봅니다





6-7자리의 정확도를 갖고 있다는군요. 

거기다 저는 연산을 해야 하기 때문에 곱셈/덧셈을 할때마다 정확한 자리수가 줄어들겠죠?

생각해보니 이것도 큰 문제네요. 소숫점 이하 50자리까지 정확하다고 해도 그 숫자끼리 몇번 곱하면 곱할때마다 자릿수의 절반씩은 믿을 수 없게 될텐데요





double 을 사용한다고 해도 모자랍니다. 




비슷한 문제를 저만 겪는 건 아닐 것 같아 검색을 해보니 포럼에 비슷한 토론이 많이 있는데 딱히 이거다 하는 해결책은 안보이는군요.





하드웨어의 한계도 있어서 이런 물건도 나오는 듯 합니다. 




그 와중에 GitHub에서 SoftFloat 이라는 아두이노 라이브러리를 찾았는데

description이 하나도 없어서 이해를 못하겠네요;; 헤더파일 보고 해석할 역량은 안되는데 말이죠

https://github.com/mmoller2k/Float64



신고

Comment +0


키보드 매트릭스를 테스트하는 중인데 이상하게 2열의 1,2,3 등의 숫자만 입력이 안되더군요






핀에 문제가 있나 하고 핀아웃도 다시 확인하고






배선설정과 실제 스케치간에 연결이 다른부분이 있나 다시 확인해봤습니다. 

문제는 그냥 제가 시리얼로 결과를 확인하고 있다는 것이었지요

Tx 핀으로 입력을 하는데 그걸 시리얼 출력으로 쓰고있으니 당연히 안되는 것이었습니다. 




수정해서 키패드 입력을 LED 디스플레이로 하는건 금방 되었는데

본격적으로 계획을 짜보니 이게 생각보다 난이도가 상당히 높네요.

스케치를 짜려고 보니 생각해야 할 부분이 많습니다.


1. 키패드 매트릭스는 사칙연산 부호 등 때문에 char 형태로 데이터를 주고받음 -> '0' 문자를 숫자로 변경하는건 쉬움. 

2. 25개의 매트릭스 입력에 따라 숫자, 문자 등으로 분류하여 각각 다른 계산을 해야함 -> 역시 어렵진 않을듯. 

3. 계산기의 자리수는 16자리이므로 최대 9999999999999999 까지 표시할 수 있다. 

소수점을 사용해야 하므로 float 변수를 사용하는데 소수점 이하를 표시하려면

앞에 표시될 '0.' 글자를 빼면 소수점 14자리까지 쓸 수 있어야 한다. 

기본적으로 디스플레이에서 float 함수를 쓰면 소수점 2번째 자리까지만 표시되며

"%f" 형을 사용해 float 형을 출력하면 이하 숫자의 오류가 생긴다. 

dtostrf() 함수를 사용하면 3번째이하 자리수를 처리할 수 있지만 

소수점 이하 자리수를 정확히 알고 있는 경우가 아니면 역시 오류가 생긴다 ->갑자기 최종보스 출현한 난이도..;


검색해보니 부동소수점 문제는 원래 어렵더군요.. 

아두이노 계산기 예제라고 나와있는것도 죄다 정수처리만 가능한 간단형 버전이고요.



913425.45 를 출력하면 저렇게 나옵니다.

일단 정확하게 출력하는것도 문제지만 그걸 또 연산처리해야한다는 점이 엄청 골치아프네요

신고

Comment +2

  • 하얀마음얀1004 2017.10.31 08:48 신고

    몇년전에 구매한 버튼이 여러개 달린 LCD에는 아나로그 입력핀 1개에 여러개의 저항에 버튼을 달아 저항값을 읽어 눌린 버튼을 처리하는것을 보았습니다.
    핀이 부족할 때는 그방법도 좋을것 같습니다.

    • 그 문제는 해결되었습니다. 지금은 float 형의 소수점 이하 10자리까지 제대로 표시하는 문제가 남아있는데 이건 검색을 해봐도 어렵네요..

아예 AVR 정품 AVR ISP 를 사고싶은 마음도 있지만 

이건 그냥 장비병인 것 같습니다.  쇼핑몰만 둘러보다 포기.




Aliexpress에서 호환 AVRISP MKii 를 샀는데 도착하고 보니 Vcc 에 전원이 안 들어오는 불량품이네요..

일단 Dispute 넣고 그냥 아두이노에 ArduinoISP 넣고 Atmega128에 부트로더를 구웠습니다. 



사실 지난번 ISP 드라이버 안 잡혔을때 이렇게 할까 했지만 미루다 보니 이렇게 됐네요

그냥 아두이노 보드 하나 잡아서 ISP를 따로 만들어 두어야 하나 생각중입니다. 






마찬가지로 지난번에 케이스에 넣었던 FTDI 보드로 업로드했더니 잘 됩니다. 

Blink로 빨간색 LED를 껐다 켰다 해 보았습니다. 






처음에 Atmega128을 쓰려고 했던 이유가 아두이노 핀이 모자랄 것 같아서였습니다

마침 Atmega128 칩도 많이 있는 이유도 있었죠.

그런데 아두이노 보드를 하나하나 체크해 보니 핀이 모자르진 않다는 걸 알게 되었습니다. 

오히려 딱 맞게 쓰고 한두개는 여유있을 정도네요


덕분에 좀 쉽게 갈 수 있을 것 같습니다. 





항상 CNC로 보드를 깎아 버리는걸 선호하지만

이번에는 추가로 주변회로가 어떻게 변할 지 몰라서 

전용 테스트 보드를 만들기에는 문제가 있습니다. 

일반 단면 만능기판에 테스트 보드를 구성하기로 했습니다. 




LED 디스플레이 선을 연결하고 테스트해봤습니다. 

이번 작업은 여기까지입니다.




신고

Comment +0


변환보드를 하나 살까 했는데 변환보드 하나에 6000원이라 


에라 하고 이글캐드를 실행해서 보드를 만들고 CNC로 깎았습니다. 


역시나 패턴이 좁아서 실패를 두어번 했네요










USBASP로 부트로더를 심으려고 하는데 안됩니다. 


에러 메세지를 보니 USBASP가 안 잡힌답니다.  


분명 드라이버를 설치했는데 말이죠.


부트로더를 쓸 때마다 최신 운영체제에 대응이 늦어 골때리는 경우가 자주 생기는군요


단순히 시키는 대로 해볼 뿐이라 이런 경우 어떻게 대응해야 하는지 잘 모르고 그대로 스톱됩니다. 






원래 계획대로 쉬프트 레지스터를 쓸지 말지 생각중입니다. 

신고

Comment +0

기계식 키보드의 키를 심어서 계산기를 만들면

타격감과 오타율이 적은 계산기를 만들 수 있지 않을까 하던 중에

단순히 기존 계산기를 모딩하지 않고 아예 아두이노로 제작할까 하는 생각이 들었습니다. 






그리고 디스플레이를 전에 구해놓은 HCMS-2912 디스플레이를 이용해서 만들면 

참 이쁜 물건이 될 것 같더군요.







계산기의 키패드는 보통 5열 5행이기 때문에

5*5 키패드 매트릭스가 필요합니다. 








5*5 매트릭스는 10개의 입력핀이 필요하기 때문에

아두이노에서 직접 입력을 받는건 힘들고

74HC165 같은 쉬프트 레지스터를 이용하게 됩니다. 









그래서 74HC165 를 일단 몇개 구매했습니다. 

그리고 아두이노 보드를 계산기 기판에 그대로 심으면 높이 차이가 많이 생겨 케이스를 씌우는 데 무리가 따를 것 같아

아예 계산기 보드에 아두이노를 포함시키려 했습니다. 







그런데 부품박스를 열어보니 ATMEGA168 옆에 ATMEGA128 칩이 보입니다. 






검색해보니(링크) 아두이노로 사용 가능합니다. 







핀 수가 훨씬 많기 때문에 쉬프트 레지스터 없이 바로 사용이 가능하겠네요


결국 ATMEGA168(아두이노)+쉬프트 레지스터 로 가느냐

아니면 ATMEGA128 을 아두이노로 만들어서 쓰느냐 하는 문제인데

ATMEGA128이 쓸데없이 재고가 많은 관계로 이걸 쓰기로 했습니다. 






신고

Comment +0



회로는 이제 거의 손댈 부분이 없습니다. 


나중에 케이스 만들때 완성형 보드는 새로 만들어야 겠지만 스키메틱은 바뀌지 않을 듯 합니다.


중간에 DC 모터펌프를 사용한 버전을 만들어 보았다가 


취소하고 다시 스텝모터로 돌아오는 바람에 시간이 많이 걸렸네요



수정사항은 몇개 없지만 전원을 넣을 때마다 일정 확률로(?) 스텝 드라이버가 터지는 바람에


한 4개쯤 날려먹고.. 컨덴서를 몇개 추가하고 전원 스위치를 더했습니다. 








정량펌프는 전에 못보던 깔끔한 물건이 나왔길래 구매해봤는데


꽤 괜찮습니다. 크기도 적당하고 그냥 이걸로 가야겠네요








드라이빙 전류는 0.2A 정도가 적당하더군요










이제 최종적으로 코드를 마무리해야 합니다.


그러려면 펌프가 회전하는 수에 비해 펌프질되는 유량이 얼마나 되는지 측정해야 하므로


간단한 코드로 800ml 정도 물을 펌프질해봤습니다. 


OLED에 나오는 숫자는 모터의 회전 수입니다. 


3079회전 = 물 605g

4000회전 = 물 778g

(물 1g = 1ml)

7079회전 - 1383ml 이므로

1ml 당 5.12회전
1회전당 0.195ml


모터 70회전에 물방울은 355방울이 떨어졌고


마이크로스텝 1/16 이므로


3200스텝 = 1회전= 5.07방울 = 0.195ml 입니다


-> 고속과 저속에서 유량이 달라지더군요; 주로 쓰는 속도 기준으로 재측정할 예정입니다. 



스텝 딜레이는 40us 정도가 최하이며 그 이하로 내리면 가감속 코드 없이는 탈조가 납니다. 



코드를 최종적으로 수정한 다음 케이스를 씌워야 하는데


이럴땐 같이 작업하는 디자이너 한명 있으면 좋겠다 싶네요. 


매번 어떻게든 더 이쁜모양 만들어 보려고 발버둥 칩니다.

저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0




인코더 스위치를 넣어서 회로를 짜놓고


코딩을 하려니 어렵더군요.. 


일단 간단한 입력은 되는데 


인코더의 입력을 놓치지 않고 받아들이기 위해선 인터럽트가 필요하고


이제 간신히 u8glib 조금씩 이해가 가는 와중에 


인터럽트 집어넣으려니 머리가 뱅글뱅글 도네요.




스킬업한 다음에나 생각해볼 일인 것 같아 제거하고


토글 스위치 3개(up,down,select) 넣고 약간 생각해 보니


이것도 디바운스나 동시입력에 대한 부분을 처리해야 해서 뭔가 골치아파지는것을 느꼈습니다.









인스트럭터블스에서 본 기억을 찾아내서 다시 자료를 검색해보고


단순히 아날로그 입력 1핀만으로 여러개의 스위치 사용이 가능한 방법을 썼습니다. 


위와 같이 직렬 저항 사이에 스위치 입력을 넣으면 


5V 입력이 분배가 되어 스위치를 누를때마다 0-1023 에서 특정한 범위의 값으로 들어오게 되고


그걸 확인해서 스위치 입력을 확인하는 방법입니다. 




써보니 많은 장점이 있더군요.


1.여러개의 스위치를 1핀으로 간편하게 확인 가능하다.

2.디바운스 처리가 쉽다

3.여러개의 스위치를 동시입력하는 경우도 처리 가능하다

4.입력값 처리에 따라 스위치를 둔감하게 혹은 민감하게 조정 가능하다







처음 만들었던 회로 뒷면에 다시 납땜해서 수정했습니다. 







원하는 값을 스위치로 변경해서 입력하고 메뉴를 전환하면 단계별로 메뉴가 바뀌는 부분까지 마쳤습니다. 


화면 바뀔때마다 구성이 다른데 기본동작이 완료되면 수정할 계획이고요


이제 입력된 값을 바탕으로 스텝모터를 돌리는 부분을 진행할 차례군요







저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +2

  • 하얀마음 2016.09.19 08:36 신고

    좋은 글 잘 보고 있습니다.
    바운스현상은 1uF이하의 콘덴서 추가하시면 해결하실 수 있습니다.

    좋은 하루 되세요.

    아래글 참고...
    http://m.blog.naver.com/cubloc/220597232293

화면에서 일단 간단한 로고나 메세지를 보여준 후


메뉴로 넘어가고 그 다음 메뉴로 넘어가는 등의 구성을 생각했습니다.


그래서 일단 텍스트로 꾸며봤는데



void loop() {


  u8g.firstPage();  //OLED 루프

  do {

    switch(draw_state){

      case 0:StartPage();delay(500)break;

      case 1:SecondPage();delay(500);break;    

    }

    }

  while( u8g.nextPage() ); 


이렇게 u8glib 함수 사이에 딜레이를 넣어봤습니다. 








첫번째 화면을 뿌리고 잠시 후에 두번째 화면으로 바뀌어야 하는데


두 화면을 동시에 뿌리려는 듯 겹친 화면이 나옵니다. 




void StartPage(){

   u8g.drawStr(0,10,"ColdBrewSystem 0.9");

   u8g.drawStr(0,25,"pashiran's");

   u8g.drawStr(0,40,"workspace");

   delay(500);


그래서 위와 같이 호출하는 화면함수에 딜레이를 넣었습니다. 





그랬더니 화면 자체에 딜레이가 걸려버립니다. 



여기저기 딜레이 위치를 바꿔봤지만 해결이 안되었는데







void loop() {


  u8g.firstPage();  //OLED 루프

  do {

    switch(draw_state){

      case 0:StartPage();break;

      case 1:SecondPage();break;    

    }

    }

  while( u8g.nextPage() );



if(draw_state==0){

  draw_state++;

}

else{

  draw_state=0;

}

delay(500);


} //loop의 끝 


이렇게 해야 하니 정상적으로 나옵니다. 


기본적으로는 u8glib이 함수 호출하면 메모리에 디스플레이 할 정보를 불러들이고서 


메모리를 읽어서 화면에 뿌려주는 방식이라  


그 과정 사이에 명령어를 사용할 때는 주의해야 하더군요.






저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0

다들 더위때문에 고생하시겠네요.


더위에 약한 체질이라 정말 올 여름은 지옥같았습니다. 


시원한 곳에서도 머리가 멍해 뭘 하기가 힘들더군요. 


전기자전거고 뭐고 할 여력이 없었습니다.


더위가 조금 가시는 듯 해 작업을 해 봤는데, 여전히 덥군요.


기상청은 양치기소년도 저리가라 할 정도로 


번복에 번복을 반복해 8월 말까지 더운게 아닐까 걱정이 될 정도네요.





 




OLED 버전은 천천히 진행할 생각이라 일단 구동계가 완성된 


아두이노 나노에 간단히 프로그래밍하고 커넥터들을 달았습니다. 


기본 서보모터 커넥터는 연결이 간편하지만 


기분상 불안한 면이 있어 커넥터를 교체했습니다. 


ESC에서 5V 출력이 나오기 때문에 배선이 편했습니다




스케치는 다음과 같습니다. 


// 스로틀과 서보를 연계시키고 

// 스로틀의 이동폭을 제한하는 스케치


#include <Servo.h>


Servo servocontrol;  // 서보를 제어할 서보 오브젝트

Servo bldcmotorcontrol;     // 모터를 제어할 서보 오브젝트       

int servopos;    // 서보 위치를 저장할 변수

int motorspeed;  // 모터 속도를 저장할 변수

int throttlePin = A0; // 쓰로틀핀을 A0 로 선언

int throttleValue;  // 쓰로틀의 수치



void setup() 

  servocontrol.attach(9);  // 핀 9의 서보신호를 컨트롤서보에 연결

  bldcmotorcontrol.attach(8);     // 핀 8의 서보신호를 모터에 연결

 

 

void loop() 

  throttleValue=analogRead(throttlePin);  // 쓰로틀의 입력값을 아날로그로 읽음

  throttleValue=map(throttleValue,0,1023,0,179); //서보모터의 각도에 맞게 매핑함

  bldcmotorcontrol.write(throttleValue);

  if(throttleValue>50){

  throttleValue = 90;

  }

  servocontrol.write(throttleValue);

  delay(15);

  } 


throttleValue=map(throttleValue,0,1023,0,179); 명령어로 


스로틀에 따라 서보의 PWM 신호를 매핑했기 때문에 


ESC의 모터 출력은 스로틀을 따라갑니다만 서보모터는 일정 각도 이상 올라가면 안됩니다. 


50보다 큰 값이 들어오면 90으로 고정하도록 했습니다. 


마지막에 딜레이는 지우는걸 잊었군요







일단 원하던 대로 작동하는군요.


본체는 수치를 약간 수정했기 때문에 출력을 다시 해야 합니다.


좀 시원해지면 한번에 몰아쳐 끝내려고 했는데 여전히 더워서 맥을 못추겠네요




저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +7


저희 집 식구들은 커피를 많이 마시는 편인데


빨대로 간이 더치커피 기계를 만들어 사용해왔습니다만


물조절도 불편하고 공간도 차지하고 여러모로 불편한 부분이 있습니다. 



전에 정량펌프를 알리 익스프레스에서 구매하여 사용해봤지만 


DC 모터를 이용한 싸구려 펌프라서 토츌량도 적당하지 않고 금방 고장나버리더군요.



최근에 더워서 커피 소비량이 늘다보니 다시 한번 마무리해봤는데


저기다가 아두이노+스텝드라이버+파워+LCD를 추가할 생각하니


덩치가 좀 큰듯 하네요.  




시제품 만들어보고 수정할지 말지 생각해봐야겠습니다. 



저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0

기구부 출력은 부품 하나에도 몇 시간이 걸리므로, 


틈날때마다 계속 아두이노 스케치를 수정하는 중입니다.



제대로 끝까지 스케치를 완성해본 건 처음이라 삽질을 하고 있지만


그래도 기본적인 부분은 어느정도 알고 있으니


레퍼런스나 인터넷을 참조해서 조금씩 진도가 나가고 있습니다.





이 책 강추. 








현재 OLED에 보여주는 정보는


1. 배터리전압

2. 크루즈 모드 or PAS level - pas는 추후 추가 예정

3. 스로틀 레벨 

4. 속도

5. 최고속도

6. 평균속도

7. 이동거리

8. 누적 이동거리



1. 전압 디스플레이 - 이건 쉬웠음. 전압분배로 해결하면 되고 찾아보면 인터넷에 예제도 많음. 


2. 크루즈 or PAS - 아직 계획 없음 


3. 스로틀 레벨 - 아날로그 입력을 그냥 변환해서 보여주면 됨


4. 속도 - 속도센서 필요. 기성제품 분해하자니 돈이 아깝고 리드스위치로 자작하자니 성가시고 


(5,6,7,8번은 속도만 제대로 체크되면 거기서 계산하면 되는거라 따로 뭘 할 필요는 없음)





@OLED 화면 디스플레이되는 한 사이클의 시간이 은근 길어서


스피드 센서 입력은 인터럽트를 필요로 하겠더군요.




인터럽트 발생시마다 1바퀴 만큼 이동한 것으로 확인하고 


millis() 를 이용해 시간을 체크하면 1바퀴 회전시간을 알 수 있습니다. 


이걸로 속도를 계산하고 최고속도나 이동거리 계산 등을 하면 되죠. 



위 OLED 사진에서 맨 아랫줄이 millis 로 계산된 인터럽트 간 타임입니다. 


수동으로 on/off 해보니 인터럽트 타임이 제대로 계산되는데 


그 값을 loop로 넘기는 부분이 잘 안되고 있네요. 





@이동거리는 EEPROM에 저장하지 않으면 리셋됩니다.


EEPROM의 저장한도가 10000번 정도라 하는데 


주행중에 이동거리가 1킬로 증가할 때마다 기록한다고 치면 


1만 킬로 정도가 한계고


적어도 0.1킬로마다 저장하고 싶은데 그러면 1000킬로에 수명이 다 되겠네요


수명을 생각하면서 기록하는 방법을 고민해 봐야할듯







 

기구부 설계와 출력 및 후가공이 끝났습니다. 


볼트로 조이는 부분은 인서트 너트를 사용했는데


꽉 조였을때는 통째로 빠지는 경우가 있어 적당히 조이는게 중요.



설계중 좋은 자전거가 공짜로 생길 뻔한 일이 있어 


부랴부랴 마운트를 착탈식으로 바꿔 새 자전거에 대비하려 했으나 


무산되어버렸습니다..



그래도 마운트 착탈식 구조는 마음에 들어 그대로 사용 예정. 









옆으로 끼운 후 손나사를 돌리면 고정됩니다.  작동도 잘 되는군요.






스로틀은 그냥 오른손 핸들에 끼울 생각이었으나 


변속기와 겹치는 위치를 어떻게 조정할지 생각


스로틀 스위치는 윗부분을 들어내고 


OLED 까지 내장하는 구조로 해야 편할 것 같습니다(후가공 엄청 해야할듯)




스로틀에 OLED와 스위치를 일체형으로 만들고


뒷부분 안장 밑에 나머지 전장부가 들어가면 될 듯 합니다.



저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +1

처음 OLED 에 표시될 부분은 배터리의 전압입니다. 


아두이노는 5V 까지의 입력을 아날로그로 읽을 수 있지만


그 이상의 전압은 전압분배회로를 이용해 분압된 전압을 읽은 후 


분압된 만큼 다시 역으로 계산해서 원래 전압을 표시하면 됩니다. 



RC용 LiPo 배터리를 사용할 생각이고


3셀~6셀 정도의 배터리를 사용한다고 할 때


1셀의 전압은 3.6V 부터 4.3V 까지이므로 


4.3*6셀 = 25.8V 까지를 측정범위로 잡으면 되겠군요 




Vin = Vout / ( R2 / ( R1 + R2)) 를 계산하면 되는데



귀찮으니 그냥 앱을 사용합니다. 





18K 와 4.3K 저항을 사용하면 됩니다. 





그런데 저항박스를 뒤져보니 해당 저항이 없군요...







저항을 쓰기 편하게 Vin 30v, Vout 5V 입력하니 R1 10K, R2 2K 가 나왔습니다. 


입력전압은 1/6 되어 계산이 됩니다. 



  voltValue = analogRead(vinPin);

  batVoltage = voltValue*30/1024;   // Vout 5V * 전압분배비 6 = 30 을 곱한 후 1024로 나눔.



여기서 1024로 나누니 약간 오차가 있어 1080으로 조정해서 맞췄습니다. 



이렇게 한 후 





전압(왼쪽 위)이 제대로 표시가 됩니다. 




저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +6

별 생각없이 화면구성을 짜며 스케치 업로드를 하다가 보니



메모리 용량이 88%? 아직 제대로 스케치 시작도 못했는데 


화면구성만으로 이정도 차지하면 메인 스케치는 어떻게 할것인가 놀랐습니다만



생각해보니 폰트 데이터 용량을 생각해보지 않아 u8glib wiki에 들어가 봤습니다. 








처음 사용했던 속도표시용 폰트의 용량









같은 폰트인데 특수문자들이 제거된 다이어트(?) 폰트









그냥 작은 폰트의 용량






이렇게 심한 차이가 나는군요. 


생각해보면 당연한 것이 폰트 데이터를 전부 메모리에 집어넣지 않으면 출력도 할 수 없으니


쓰건 안쓰건 폰트를 포함시키는 순간 그만큼 스케치 용량이 늘어날 수 밖에 없습니다.





같은 크기인데 다른 폰트(u8g_font_fur30r)를 넣어봤더니 용량 차이가 저렇게 납니다. 


87% -> 58%











크기가 절반인 u8g_font_fur14r 폰트를 사용하고 u8g.setScale2x2(); 명령어로 2배 뻥튀기해봤습니다. 


87% -> 45%









다만 이 경우는 폰트 크기가 두배가 된 만큼 계단현상이 일어납니다. 




큰 폰트는 속도 디스플레이용이라 


아예 0-9까지 비트맵을 넣어 사용하면 더 용량을 줄일 수 있을 것 같습니다만


그건 나중에 정말 용량이 모자랄때나 해보면 될 것 같네요.




저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +1

  • 저는 무슨 이유인지 oled를 사용하면 다른 부품과 i2c통신에 에러가 나서 oled전용으로 아두이노 1개를 사용했습니다.

기구적으로는 이제 95% 정도 된듯. 






사실상 마운트 부분만 맞추면 됩니다만 이것도 기초적인 치수는 다 나왔는데


아예 고정시켜버리느냐 분리가 쉽게 하느냐 고민하다가


계속 달고다니긴 좀 불편할 듯 해서 분리형을 고민하는 중인데


어떤 형태로 해야 편할지 



뭐 이런 자잘한 고민들을 하고 있습니다. 


볼트류 고정 때문에 인서트 너트를 주문해 놨는데 그것들만 도착하면 최종 수정하고 조립하면 될듯. 






일단 서보 테스터로 구동할 수는 있지만


볼륨조정으로 속도를 조정하는건 너무 불편할 것 같아


전에 올렸듯 


전기자전거용 스로틀 - 아두이노 - 서보 로 연결해서 서보/스로틀 컨트롤을 최적화할 생각이고요.




그러다 보니 왠지 아두이노를 기왕 집어넣는 김에 서보 컨트롤러만 쓰기엔 아까울 듯 하여


전에 사서 처박아 두었던 OLED를 꺼내들었습니다. 



ADAFRUIT의 라이브러리를 좀 뒤적여 봤지만 메모리를 너무 많이 차지하고 깜박임도 심해서


U8GLIB으로 변경. 구동방식을 이해하는 데 좀 더 어렵긴 했는데


반응이 빠르고 메모리도 좀 더 적게 차지하네요






0.9인치 OLED는 너무 작아서 가시성이 안좋더군요. 


1.3인치 화이트로 바꾸니 심플하고 가시성도 괜찮습니다. 



아직 아두이노 프로그래밍엔 왕초보지만 U8GLIB WIKI와 


일부 인터넷의 소스코드들을 뚫어져라 봤더니 어느정도 이해는 가능했습니다. 



직접적으로 입출력를 디스플레이하기 전에 화면 구성만 짜보는 중입니다. 


배터리 전압과 속도, 스로틀 출력 등을 화면에 보여주기 위해 조금씩 옮겨보는 중입니다. 


화면에는 그냥 랜덤으로 디스플레이됩니다. 


스로틀 바는 특수문자 폰트를 사용해 디스플레이하려 했더니 


폰트 추가할때마다 메모리를 상당히 소모하더군요.


현재는 기본폰트와 대형폰트 2종류를 사용하고 있습니다. 



좌표가 왼쪽 위부터 0.0으로 시작하기에 숫자가 한자리수일때는 왼쪽으로 붙었다가


두자리수일때 오른쪽으로 왔다갔다 하는 문제가 있어 


숫자를 표시할때마다 두자리수 이상의 숫자는 


글자의 가로픽셀만큼 이동해서 디스플레이하는 식입니다. 



OLED를 붙이려 생각했더니 당연히 속도계를 생각하게 되고 


추가로 몇몇 센서도 붙여보고 싶고


그러다보니 프로그래밍 내용도 점점 복잡해질게 뻔해서


일단 인서트너트와 같이 주문한 아두이노 미니 도착하면 


스로틀제어만 하는 기본형으로 제작을 하고,


추가로 업그레이드를 하는 방식으로 갈 생각입니다. 




저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +2

  • 거의 완성이 되어 가는군요.
    기대가 되네요.
    날씨가 덥습니다.
    건강 유의 하세요.

    • 아두이노 프로그래밍 부분은 완성이 되려면 한참 멀은 것 같습니다.
      벌려놓고 보니 인터럽트며 셋업이며 처음 제대로 프로그래밍을 하는데 큰 산이 많네요
      일단 움직이게만 만들어 놓고 OLED 디스플레이 부분은 추가로 할 생각입니다.


처음 소개할 때 올렸던 사진입니다. 


http://pashiran.tistory.com/661 에서 말했듯 


마찰 구동식 자전거의 마찰접촉은 작용 반작용의 원리로 작동되는 것이라


위와 같이 스프링으로 모터의 무게를 상쇄해 주어야 하죠.



그리고 위에서 파생된 문제로 모터의 위치와 브라켓의 위치가 자유롭지 않은 부분이 있습니다.


브라켓에 장착된 스프링이 모터를 밀어서 타이어에 접촉시키기 때문에 


브라켓의 각도, 자전거의 각도, 모터의 위치


심지어 주행중 가속도의 변화까지 모두 터와 타이어의 접촉상태에 영향을 주고



모터가 클 경우 브라켓의 이동범위가 확보되기 힘들기 때문에


저처럼 65mm 이상의 지름을 갖는 모터를 사용하려면 설계 면에서도 상당히 애로사항이 있습니다. 










애로사항의 결과.. 


초기부터 시작해서 큰 수정만 여섯번 이상, 자잘한 수정은 훨씬 더 많이 들어갔습니다. 






결정적으로 90% 이상 만들어놓고 방향을 전환하게 된 건 스프링 때문인데


일단 딱 맞는 스프링 찾기가 굉장히 힘들더군요.


스프링은 보통 강선의 굵기와 꼬인 길이, 꼬인 지름에 따라 다른 탄성을 보이는데


이게 베어링이나 볼트 너트처럼 딱 정해진 표준 스프링이 없다는 문제가 있습니다. 



그래서 저는 스프링을 사서 안맞으면 다른거 써보고 다른거 써보고


중국에서 주문해보고 한국에서 주문해보고 10여종을 써봤습니다만


미묘하게 전부 맞지는 않더군요.



스프링 탄성을 조절하는 조정부를 만들면 되긴 하는데 


선반가공 없이 3d 프린터와 소형 cnc로 만드는 부품의 한계가 있어


만족할만한 설계가 나오지 않았습니다. 




중간에 몇번 언급했지만 모터를 한단계 줄여야겠다 싶어서 


하비킹에 재주문한 순간 BACKORDER에 걸려 몇달이 지나는 바람에 생각할 시간이 많아졌는데요





어차피 쓰로틀을 사용하려면 analog 를 PWM으로 변환할 아두이노가 들어가야 하고 


그러니 귀찮게 스프링 가지고 시간을 끄느니 서보모터를 넣어서 마찰접촉을 컨트롤하게 하는 게 낫지 않나?


하는 생각이 들었습니다.








도면 뽑아보니 서보모터를 눕히는게 공간도 적어지고 좋겠어서 변경했습니다. 











RC용 샥을 넣긴 했는데 아날로그 신호를 PWM으로 매핑하는 부분을 잘 조정하면


딱히 샥이 없어도 괜찮을 것 같긴 합니다. 그래도 일단 샀으니 넣어봄





저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0


#include <Servo.h>


Servo controllservo;  // 서보를 제어할 서보 오브젝트

Servo motorservo;     // 모터를 제어할 서보 오브젝트       

int servopos = 0;     // 서보 위치를 저장할 변수 선언

int motorspeed = 0;   // 모터 속도를 저장할 변수 선언

int throttlePin = A0; // 쓰로틀의 입력을 A0 로 선언

int throttleValue = 0;   // 쓰로틀의 수치를 0으로 선언



void setup() 

  controllservo.attach(9);  // 핀 9의 서보신호를 컨트롤서보에 연결

  motorservo.attach(8);     // 핀 10의 서보신호를 모터에 연결

 

 

void loop() 

  throttleValue=analogRead(throttlePin);  // 쓰로틀의 입력값을 아날로그로 읽음

  throttleValue=map(throttleValue,0,1023,0,179); //서보모터의 각도에 맞게 매핑함

  controllservo.write(throttleValue);

  delay(15);

  }



컨트롤러의 홀센서out 신호를 A0 에 연결, 전원선을 아두이노의 5V, GND에 연결,

아두이노의 9번핀을 서보모터의 컨트롤 핀에 연결하고

서보모터의 전원을 연결합니다. 

서보모터의 전원 GND와 아두이노의 GND를 연결합니다. 




대충 짠 코드입니다. motorservo나 servopos  등 쓰이지 않는 것들이 있습니다. 

나중에 쓰게 되겠지요




http://pashiran.tistory.com/669 이 링크에서 분석한 바 있지만


쓰로틀에 따라 홀 센서의 전압 출력은 쓰로틀을 올릴수록 올라갑니다. 


5V 안쪽의 값이기 때문에 그대로 analogRead() 명령어를 사용한 후


서보 범위에 맞도록 map 명령어를 사용해 수치를 바꿔줍니다. 


throttleValue=map(throttleValue,0,1023,0,179) 라는 부분이 있는데


아날로그 입력값인 0~1023 을 0~179 범위로 매핑하게 됩니다. 



이 출력을 이용해 RC용 서보모터를 조정하거나 ESC에 연결해서 모터를 가감속할 수 있습니다. 







새로 산 부품이 도착하는 대로 추가설계 진행 예정입니다. 

저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0



요즘 프린트 결과물이 영 좋지 못합니다. 결도 다 흐트러지고 원도 찌그러지고..






구매후 여태까지 계속 유지/보수/개조를 하면서 원본에 있던 부품중 남아있는게 거의 없는데


이제 저 레일바퀴도 거의 맛이 갔네요. 






언젠간 해야 하겠다고 생각했던 LM가이드로의 교체 


더 미룰 수 없겠습니다. 



LM 교체는 프린터를 거의 전부 분해해야하는지라 시간이 좀 많이 걸릴듯합니다. 


저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0



미끄럼방지 테잎을 붙여봤습니다. 


적갈색인 것과 투명한 것이 있는데 투명이 좋을 것 같아 이걸로 골랐지만...


적갈색과 비교해 좀 심하게 거칠더군요.










심하게 거칠다보니 이런 사고를 냈습니다. 


그냥 수축튜브 씌우는 정도로 마무리를 했어야 하는데... 












이렇게 된거 실리콘 케이블로 바꾸자 하고는 뚜껑을 들어내고 전선을 잘랐습니다. 


그런데... 납땜이 안되더군요.


알고보니 저 부분이 전부 에나멜선이었습니다. 대형 사고를 쳤습니다. 


에나멜 코팅 때문에 납땜이 안됩니다. 










에나멜 코팅을 전부 벗기지 않으면 안되는 상황이라서

한가닥 한가닥 라이터로 지져 코팅을 태우고 사포질로 마무리합니다






그리고 실리콘 케이블과 납땜하고 수축튜브로 마무리했습니다. 



그리고 모터 커버가 안 닫혀서 다시 들어내고 더 잘라내고 같은짓을 한번 더 하고;;;; 다시 납땜했습니다. 



그 과정에 뭘 잘못건드렸는지 베어링에 문제가 생긴듯... 돌긴 하는데 저항이 좀 있습니다..



모터 마운트 설계도 최적화되지 않은 것 같아 다시 잡아야 하나 하고 고민하던 참에 


비싼모터 얼마 쓰지도 못하고 중고품을 만들어버렸습니다... 



저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +4

  • 임철호 2016.01.25 17:47 신고

    언능 만들어서 타시는 모습 모고 싶네요... 저도 로드에 전기 모터 키트 사서 달려고 생각중인데 뭐 사서 달지 검색하다가 보게 됐느데 멎있네요... 이것 저것 하시는거 신기하네요 화이팅

  • 황인철 2016.01.25 22:59 신고

    델타프린터 자작을 참고할려고 왔다가 한줄 남깁니다. 잘은 모르지만, 에나멜선 하나하나가 전부 모터내부의 코일을 따로따로 구성하기 때문에 에나멜선 하나하나 마다 전원이 연결되어야 할 듯합니다. 번거롭더라도 확실히 하나하나 전부 에나멜을 벗기고 납땜해야 할듯합니다.



날이 추워서 테스트가 늦었습니다. 


일부 설계를 수정하고 스프링을 달아 구동해 보았습니다. 


일단 튀어올라서 바퀴에 닿긴 하는데 닿은 상황이 유지되지 않는군요.


손으로 밀어보니 생각보다 바퀴를 타고 올라가는 힘이 강하지 않아 접촉을 유지하지 못합니다. 


이제 되지 않을까 기대했던 상황이라 약간 아쉽긴 한데 그래도 이제 어느정도 되는구나 싶기도 하네요.





#튜닝 리스트

1.새로 출력한 부품으로 교체해서 위치를 잘 잡아보기

2.모터에 사포스티커를 붙여 마찰을 강화해보기

3.모터 브라켓 재가공해서 접촉위치 조정하기

4.스프링 바꿔보기


저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +1

  • 안녕하세요 저두지금 같은원리의 전기 자전거를 만들고 있어 정보수집하다가 들렸습니다 열정이 정말 대단 하십니다 전 그냥타이어에 접지상태로 운행태스트를해봤구요 지금은 보완할점을 구상중입니다 그런데 테스트중에 가장 불편한점은 서보테스터로 속도를 조절하기는 너무 불편하더군요 저두 솔센더 악셀를 사용해볼려구 테스트 하고있는데 잘 안되네요 성공 하셧다는 분들도 있으시던데 전기 자잔거 꼭 성공하시구요 담에 들리겠습니다 수고하세요



온라인으로 소매에서 사는건 힘들고 


알리에서 사는건 손에 들어보기 전에는 강도를 짐작하기 어려워서 그냥 청계천에 오랫만에 나와봤습니다. 









날은 춥지만 여기만 오면 그냥 눈이 휙휙 돌아갑니다. 신기한 것도 많고..















단순 공구상 뿐 아니라 특수자재나 공업용품 등을 구하기 쉽습니다. 


세운상가 쪽으로 들어가면 전자부품도 취급하는 업체들이 많은데


청계천 변으로는 기계, 공업부품 업체들이 대부분입니다. 







마끼다에서 전기자전거도 만들었던가요??










오늘 찾아온 업체입니다. 







소형 스프링은 딱히 정해진 규격대로 생산되지가 않습니다. 


그래서 주문한 대로만 생산되지만 여기서는 남는 물건들을 소량으로 따로 판매도 합니다.


저렇게 따로 나와있는것들은 무조건 개당 500원입니다. 



손으로 뒤져보면서 적당히 얼추 맞겠다 싶은 것들을 10여개 골라왔습니다. 








길바닥에서 작업하시는 분들이 있습니다. 


청계천 거리에서는 가끔은 절단기도 돌아가고 용접기도 돌아가고 합니다. 






예전에 왔을때는 없던 계양 대리점이 있네요. 창밖에서 침흘리며 봤습니다. 










영화같은 곳에서 보던 양철 공구상자도 있군요. 요즘도 생산이 되나봅니다. 


이곳에는 공구상도 이삼십미터마나 하나씩 있을정도로 많은데 잘 보면 구색이 약간씩 다릅니다. 


목수들 쓰는 공구가 많은 집이 있고, 인테리어 업자들이 찾겠다 싶은 공구점이 있고


전기업자들이 쓸 공구가 많은 집도 있고 그렇습니다. 









M5, M6 이상 약간 긴 볼트들의 보유량이 좀 늘어났는데 


정리가 마땅치 않던 김에 마침 적당한 정리함을 만나서 사왔습니다.


저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +2





핸들쥐고 가변저항을 돌리는건 매우 불편할 것 같아


중국산 컨트롤러를 하나 사서 분해해 봤습니다. 



컨트롤러 내부에는 전압표시 LED와 전원스위치와 홀센서가 들어있습니다. 










48V 용 컨트롤러라 사용 예정인 rc배터리와는 전압이 맞지 않습니다. 


다만 LED만 표시되지 않을 뿐 별 다른 문제는 없습니다. 









홀센서의 모델명(S49EH)을 보고 데이터쉬트를 찾아봅니다. 




















핀아웃을 확인합니다.














홀센서의 Vout을 확인해봅니다. 레버를 올렸을때와 내렸을 때의 전압차이입니다.


이걸 그대로 서보 테스터에 연결할 수 있으면 좋겠지만 어렵겠더군요. 


PWM 신호를 만들어 줘야 하기 때문에 아두이노 등을 이용해 아날로그 전압 -> PWM 변환을 하거나 


서보 테스터를 트로틀 레버에 심어야 하는데 후자는 기구적으로 어려울 것 같군요.


일단 컨트롤 부분은 불편해서 서보테스터 달아서 수동으로 조작하게 될 것 같습니다. 




저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +6

  • 혹시 성공하시면 꼭좀 자료올려주세요 저두 서보테스터에 홀센서 연결해볼려구 아무리 해봐두 안되더라구요 그게 신호방식이 다른건지도 몰랐습니다 성공 하셨다는 분들도 있으신던데 어렵네요

  • 김종만 2017.02.16 13:33 신고

    혹시 홀센서 s49 eh 구입 가능할까요?

    • 센서 단독으로는 구하기 힘드실거에요. 중국에서 생산된 3D 프린터용 센서 모듈중 홀센서 사용하는건 대부분 저 모델 쓰니 하나 구매하신다음 홀센서만 떼어내는 방법도 있습니다.
      http://eleparts.co.kr/EPXDPVRD
      http://nasspop.com/product/detail.html?product_no=55&cate_no=98&display_group=1



      꼭 같은 모델이 아닌 그냥 홀센서 아무거나 필요하신거면 대부분 전자부품 쇼핑몰에서 팝니다.
      http://www.devicemart.co.kr/29552

    • 나타샤 2017.03.06 11:28 신고

      인터넷링크가깨져 폰으론검색이안됩니다 검색링크 다시좀 좀부탁합니다ㆍ그리고 스프링식악셀내부저항값은 얼마로 계산해야하나요?vr로대체는될까요?된다면 몇와트몇옴짜리가가능할까요

  • 확인해보니 엘레파츠는 제품이 사라졌네요.
    악셀 내부저항은 상관없고 홀센서 출력 전압을 pwm서보신호로 바꿔주는 프로그램을 이용해서 제작했습니다.
    위 글 이후로도 쭉 작업한 게 있으니 전기자전거 카테고리로 모아놓은 글 쭉 읽어보세요
    vr 이 가변저항을 말씀하시는 것인지? 모르겠지만 서보테스터를 이용하는 방법은 있습니다.
    그냥 ESC를 연결해서 서보테스터의 가변저항을 돌려주면 모터 속도가 변합니다.



정말 거의 다 됐다고 생각했으나 생각 외의 복병이 있었습니다. 


한쪽에서만 고정하는 모터를 위와 같이 양쪽으로 고정함으로서 전체적인 제작 난이도를 낮추면서도


구조적으로 더 안정하게 만들 수 있었는데요.








그런데 전에는 모터 고정 플레이트가 없었기 때문에 저정도 위치에 모터가 있게 됩니다만











이제는 모터 고정 플레이트 때문에 모터가 저기까지 내려와야 하는 상황이 되어버렸습니다. 


위쪽에 배치하면 체인에 걸리더군요.


저기서도 작동이 되긴 하지만 보도블럭이라도 지나가면 걸릴 것 같고


전에는 살짝 보였는데 저렇게 하면 그냥 훤히 보여서 디자인적으로도 문제가 있고


또한 체인 아래쪽에 모터가 걸치게 되어서 체인의 이물질이 모터에 다 튈 수 밖에 없다는 문제까지 드러났습니다.











아 막판에 의외의 복병이네 하고 생각하다가 다시 저기다가 모터를 대놓고 문득 생각해보니










전에는 저렇게 한쪽 고정이었기 때문에 축 평형을 위해서 반대쪽까지 고정축이 관통을 해야만 하는 상황이었습니다. 










그래서 어쩔 수 없이 자전거 기둥을 피해서 저렇게 장착을 하다 보니 


모터의 가동성이 안나와 어쩔 수 없이 하부로 옮긴 거였습니다.









그런데 이제 고정측이 양쪽이라.. 그냥 축을 나눠도 되는 상황이더군요.








중간지지대에는 전산볼트를 2개 넣고 출력물로 고정해 비틀림을 잡아주도록 했습니다. 


일단은 프로토타잎을 출력해서 맞춰보는 중입니다. 




저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +6




자전거에 고정되는 부분은 기둥 한개 뿐이라 저렇게 무게로 내려가게 됩니다. 







예전에 다른 일로 사뒀던 실리콘 판을 잘라서 끼워넣고 조입니다. 


그래도 모터 무게로 조금씩 내려가는게 보여서 윗부분 형태를 수정할 계획입니다. 








가조립을 해놓고 보니 기어가 낮을때는 체인이 걸리는 문제가 발생하네요.








반대쪽은 10mm 정도 여유가 있습니다만 모터의 축 때문에 


좀 더 유효하게 쓸 수 있는 공간이 낭비되는 느낌이 심합니다. 









그래서 잘라냅니다. 











쇠톱으로는 자르기 힘든 강철이라 고생좀 했습니다. 








원래 쓰던 쇠톱날은 오래 써서 날도 거의 없길래 새 날을 사서 2개정도 사용하니 잘리더군요.








공간의 여유가 생긴 만큼 모터의 반대쪽도 마운트를 만들어 끼울 생각으로 축을 조립했습니다. 


구매시 같이 포함되어 있는 프로펠러 축입니다. 


위에서 잘라낸 모터 축이나 이런 악세사리는 모두 별도 구매 가능한 부품이라


잘라내도 부담이 적습니다. 











이건 알루미늄이라 금방 잘리는군요.














임시로 아크릴 3T를 사용해 브라켓을 만들었습니다. 







이렇게 해서 양쪽으로 결합하면 얇은 판재로도 충분히 튼튼하게 고정이 가능합니다. 


원래 알루미늄을 깎으려고 했는데 그냥 PCB 판 하나 깎아서 대체하려고 합니다. 











모터를 밀어주는 스프링을 이런 구조로 만들어 테스트해 봤습니다. 








못 버티더군요..









돈 안들이고 있는 재료로 어떻게든 해결을 보려고 3D 프린터용으로 구매했던 스프링을 꺼내들어봅니다. 









이런 구조로 가운데서 밀어주면 될 것 같습니다. 






저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +2

  • 김정식 2015.12.22 21:23 신고

    안녕하세요. 날씨가 추운데 감기 조심하세요.

    잘보구 있습니다. 완성품이 기대가 되네요. ^^ 좋은밤되세요.


마찰식 전기자전거에서는 모터의 작용 반작용으로 

모터가 자동으로 상승하는 메커니즘을 사용한다는 것은 지난번에 설명했습니다. 

옆으로 뉘어서 모터의 무게부하를 거의 없게 만든 후 속력을 올렸다 내렸다 할 때의 움직임을 찍어봤습니다. 



이번에 새로 안 사실인데 모터의 전력선이 강선이라 움직이는데 저항을 많이 주네요. 

단순히 케이블타이로 고정하려 했는데 

전선 고정부도 따로 잘 만들어야 움직임에 방해가 없을 것 같습니다. 


스프링강선을 찾아보니 인터넷으로 소량 구입이 가능한 곳을 찾기 힘들었습니다. 








용산알씨에서는 소량으로 매우 싸게 팔긴 하는데 스테인레스가 아니고








오픈마켓에서 소분해서 파는 건 양이 너무 많아서 가격이 좀 하네요.








일단 어느 정도의 굵기가 맞는지 확인을 해야 해서 


굵기별로 한두개씩 사봤습니다. 







측면의 모터 고정 플레이트는 알루미늄 가공 계획입니다만 일단 시제품은 출력물로도 충분하더군요









굵기별로 여러개 샀는데 구매한 것 중 제일 굵은 2mm 를 써야 어느정도 힘이 되더군요.









스프링강을 휘고 잘라줍니다.


스테인레스 스틸이 아니라서 어느정도 사용한 후 


비슷한 굵기의 스테인레스 강선으로 교체할 생각을 갖고 있습니다. 










이런 식으로 고정해 봤습니다. 


모터를 장착해 보니 스프링 구조상 처음에는 힘을 많이 받고 올라갈수록 장력이 약해지므로


중간까지만 힘을 발휘하는 상황이 되더군요.


일단 자전거에 조립후 테스트를 해 봐야 겠지만 스프링의 장착 방법과 조정 방법을 더 고민해 봐야 겠습니다. 






저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0



모터를 설치할 부분은 저곳입니다. 체인스테이와 사이를 가로지르는 보강 기둥 사이로 넣을 생각입니다. 









ADD-E 의 설치 동영상이 많은 도움이 되네요. 










이런 부분이 꽤나 도움이 됩니다. 








ADD-E 는 자전거의 형태에 따라 설치 방법이 약간씩 다른데


크랭크를 분리해서 설치하는 방법과







킥스탠드 마운트에 설치하는 방법이 있습니다. 



크랭크 분리 공구도 있지만 BB너트의 형태가 한쪽은 그냥 BB쉘 내부로 들어가는 형태라서


해당 부품을 교체하기 전에는 크랭크 마운트 설치는 불가능한 상황... 


저렴한 BB 부품은 1만원대이긴 합니다만 너트 하나 바꾸자고 필요없는 BB 사기도 좀 애매하고


좀 생각해 보니 브라켓 설계와 제작도 애매할 것 같아서 그냥 체인스테이에 고정하기로 했습니다





















목업을 프린터로 쭉쭉 뽑아봤습니다. 3D 프린터는 이럴때 정말 편해요.


왼쪽부터 시작한 것입니다. 


1번은 체인 스테이 사이가 너무 좁아서 아예 들어가질 않았고


2번은 들어가긴 했는데 충분히 깊이 둘어가질 않았고


3번은 딱 맞았습니다. 








상부 브라켓도 왼쪽부터 시작해서 수정한 버전입니다. 









현재는 대략 이런 모습입니다. 아직 조정할 부분이 많습니다. 





저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +4

  • 김정식 2015.12.03 22:54 신고

    안녕하세요. 오랜만에 들립니다.

    눈비가 많이 온다는데 몸 조심하세요.

    담에 또 들리겠습니다. 완성된 전기자전거가 아주 기대됩니다. ^^ 좋은밤 되세요.

    • 안녕하세요! 프린팅은 잘 되시죠?

    • 김정식 2015.12.08 20:02 신고

      안녕하세요.^^

      식사는 하셨는지 모르겠네요.

      덕분에 프린터는 아주 잘되구 있습니다.ㅎㅎㅎ

      오늘도 좋은밤 되세요!! 또 들리겠습니다.

  • 기대가 많이 됩니다.
    좋은 글 감사합니다.

3d 프린터로 뽑은 목업을 설치해 보았습니다

상단부에선 공간이 영 안나오네요





이것때문에 마운트 형태도 바꿔보고 이리저리 변경해봤지만 안되는군요

그래도 프린터 덕에 테스트는 쉬웠습니다





ADD-E처럼 하단부에 장착해야 할 것 같습니다.

2D 스케치로 일단 맞춰보는 중입니다






저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +1



처음에는 모터를 타이어에 접촉시키기 위한 구동기구가 따로 있는줄 알았으나, 


알고보니 원리는 간단했습니다. 









모터가 돌면










작용 반작용의 원리에 의해 모터를 고정하고 있는 브라켓에 반대 방향의 힘이 가해집니다. 









그런데 브라켓은 한쪽이 고정되어 있으므로








지렛대의 원리로 고정부에서 먼 쪽의 반작용이 더 강하게 작용합니다. 










그래서 모터는 일순간 위로 상승합니다. 







에시로 찍은 동영상입니다.


전선은 살짝 손가락으로 고정한 상태에서 모터 속도를 올리면 모터가 앞으로 튀어나오는 것이 보입니다. 







-모터가 살짝 올라가고 나서 타이어에 접촉하게 되면

 

 돌면서 타이어를 밀어내는 힘으로 그 자리를 유지합니다.



-모터가 멈추면 타이어는 계속 돌기 때문에 밀려서 제자리로 돌아오게 됩니다










-모터의 위치가 살짝 움직여서 타이어와 접촉되고 또 바로 떨어져야 하기 때문에


모터 브라켓은 회전 각도를 조정 가능하도록 만들어야 하고


-모터의 무게로 접촉이 잘 되지 않을 수 있어 스프링을 넣고 장력 조절을 통해 


접촉/비접촉 전환이 확실하도록 해야 합니다. 





저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +1



킥스타터(링크) 에 올라온 에디(ADD-E) 라는 전기 자전거 킷을 보았습니다. 


제가 딱 이상적으로 생각하던 형태더군요. 


작고, 


부품 조달이 쉽고, 


가볍고 분리가 쉽고,


안쓸때는 전혀 마찰이 없고,


자작이 가능할 것(중요)









내용물이야 뭐 이것저것 있지만 핵심 부분은 RC용 BLDC 모터와 컨트롤러, 배터리만 있으면 될 듯 합니다.











키트를 사면 좋겠지만 손대기 힘든 가격이어서 일단 자료조사만 하고 있었습니다. 








43초쯤에 모터가 자동으로 타이어에 접촉되는 장면이 있습니다. 


전 이때까지만 해도 이게 내부에 다른 구동기구가 있는 것으로 생각하고 있었습니다. 






그런데 어느정도 지난 뒤 instructables 뉴스레터에 


이 마찰 구동식 전기 자전거에 대한 자세한 설명이 올라왔더군요.





http://www.instructables.com/id/Friction-drive-build-for-bikes/






마운트를 만드는데 금속가공을 마구 해대서 따라하기 힘들어 보입니다. 


그래서 그런지 제작자가 아예 마운트 부분은 키트를 만들어 팔더군요.



http://www.machinecrafted.co.uk/





관련 자료를 계속 찾다가 다른 키트도 발견했습니다. 




https://sites.google.com/site/commuterbooster/


이쪽은 컨트롤러까지 포함해서 판매하고 있습니다. 













그리고 이 사이트에는 키트 외에 필요한 것들에 대한 쇼핑 리스트가 올라와 있습니다. 


저같은 RC 초보에게 엄청 도움되네요!








판매자의 키트와 핵심 부품들을 전부 구매하면 680$ 가 넘게 소요됩니다













하지만 전 판매자의 키트를 사용할 계획이 없고, 


가방은 작은게 있고 충전기도 있고 파워 서플라이도 있습니다. 


그리고 일단 배터리는 하나만 구입한다고 하면 대략 150$ 정도에 핵심 부품 구입이 가능하군요.











정리를 해 보니 170$ 정도 됩니다. 


송료포함 150$ 아래가 되어야 세금이 안붙는데.. 이리저리 바꿔봐도 안되겠더군요.


하여간 최초 재료비는 20만원 가까이 들었습니다. 











통돌이 모터라 테스트하는도중 어디 잡을데가 없어서 저런 식의 브라켓을 씌워줘 봤습니다만








불편해서 다시 이런 식으로 만들었습니다. 










연결은 이렇게 하면 됩니다. 


ESC 에는 모터에 연결하는 바나나잭(4mm) 이 납땜되어 있지 않아서 따로 납땜해야 합니다.



모터-ESC-배터리를 연결한 후


ESC의 서보 연결선을 서보 테스터에 연결하고


서보 테스터를 돌리면 모터가 회전합니다. 







서보 테스터의 신호는 간단합니다. 아두이노에서 PWM으로 간단하게 구현할 수도 있기 때문에


기본적인 제작이 끝나게 되면 아두이노를 제어기로 업그레이드해볼 생각도 있습니다. 








4Cell(14.8V) 구동시 3300RPM







5Cell(18.5V) 구동시 4300RPM이 나옵니다. 



모터의 지름은 59mm 이므로, 원주는 59 * 3.14 = 185.26mm


185.26mm * 4300 RPM = 796618 mm / Minute 가 됩니다.


* 60 하여


47797080 mm / Hour 


= 47.8 Km/H 가 되므로 

(4Cell 구동시에는 36.7Km/H)



무부하 무저항으로 가정시에는 대략 48 Km 의 속도로 굴러간다는 계산이 나옵니다.


실제 자전거 마찰시에는 60% 정도의 속도만 나온다고 해도 거의 30Km/H 가까이 될 것 같습니다. 






저작자 표시 비영리 동일 조건 변경 허락
신고

Comment +0



일단 배치는 끝났습니다. 


위치가 맞게 배치된건지 100% 확신할 수가 없어서 


원래 주옥션 보드에 맞춰보기로 합니다. 







그냥 출력하면 A4용지에 맞게 자동으로 축소되기 때문에 그대로는 쓸 수가 없습니다. 


이글캐드의 print 메뉴에서 Print to File (PDF) 를 선택하면 PDF 파일로 변환이 이뤄집니다. 








이 파일을 포토샵에서 불러들여 잘 보이도록 Brightness/Contrast 조정을 하고









출력시에 크기를 100% 로 한 후 드래그해서 출력될 부분을 조정할 수 있습니다. 












OHP에 출력해서 보드 위에 얹으면 육안으로 쉽게 확인할 수 있습니다. 



CapsLock, Tab,LShift 가 모두 잘 배치된게 확인되고요.








Space 키와 스태빌라이저 구멍도 제자리에 맞습니다. 







우측 엔터키는 라이브러리 따로 작성하는게 귀찮아서 1*2 키를 그대로 쓴거라


키는 90도 회전되어 있습니다. 센터는 모두 잘 맞는군요.



추가작업

1. NumLock LED 

2. USB 충전회로와 커넥터 위치 잡기

3. 매트릭스 재점검





저작자 표시 비영리 동일 조건 변경 허락
신고

'Making > Wireless Mechanical Keyboard' 카테고리의 다른 글

키보드 그리는 중.. 3  (0) 2015.09.27
키보드 그리는 중.. 2  (6) 2015.09.24
키보드 그리는 중.  (0) 2015.08.29

Comment +0

', 'auto'); ga('send', 'pageview');