Jump to content
InSides

Turntable Tachometer / Controller

Recommended Posts

Nejasna je bila paralelna veza tastera i 4066..posto rade isti posao na eksternom kontroleru, sada je jasno.

S obzirom da su tasteri jednim krajem na fiksnom potencijalu, mozes koristiti, ili fetice, kao sto rece  @guja011

ili ULN2003, ili neki iz te serije, zavisno kakav je upravljacki napon. Bez da ti smetaju izlazne zastite ili ponasanje 4066 bez napona. 4066 je prakticno pouzdaniji kao brzi prosledjivac signala, nego proizvodjac stanja.

Ti u stvari zelis da izmerenu brzinu jednostavno implementiras u korekciju eksternog kontrolera...sto ubija smisao tastera za up-down, zadas arduinu zeljenu brzinu(sa jednim dva ili vise tastera), a on sam neka je odrzava. MAda je to verovatno sledeca faza. :) 

Tasteri i mikrokontroleri se slabo slazu zbog ponasanja mehanickih tastera i nestabilnog kontakta pri ukljucenju, sto se izbegava nacinom citanja statusa, ili pravljenjem "bounce free" tastera.

 

Share this post


Link to post
Share on other sites
27 minutes ago, vladd said:

Ti u stvari zelis da izmerenu brzinu jednostavno implementiras u korekciju eksternog kontrolera...sto ubija smisao tastera za up-down, zadas arduinu zeljenu brzinu(sa jednim dva ili vise tastera), a on sam neka je odrzava. MAda je to verovatno sledeca faza. :) 

Крајна фаза је потпуна елиминација екстерног контролера - разгледам разне DDS чипове које могу директно контролирати преко I2C протокола - тако да ми симулација тастера ни не треба.

Циљ је имати само два физичка тастера - први за укључивање/искључивање, и други за пребацивање брзине 33/45. Ардуино би радио све.

У основи, Ардуино и сада ради скоро све - само мора симулирати те тастере зато што екстерни контролер не дозвољава упад у микроконтролер.

Share this post


Link to post
Share on other sites

Унапређење #3

Аутоматско штимање PI/PID параметара.

Позадина

Примарна функција тахометра је увек била да буде основа за констуирање бољег погона за грамофон. Закључио сам да се то (боље, стабилније) може постићи једино имплементацијом затворене петље - зато што погон каишом је подложан drift-у, т.ј. флуктуацији (*) без оглед на степен стабилности који пружа идеални мотор, идеални лежај, идеални каиш (а ништа од ових није идеално).

(*) Бар три параметара коју имају утицај овде су (1) вањска температура собе, (2) комплијанса и затезање каиша, (3) унутрашња температура мотора и лежаја.

Екстерни контролер који користим је синусни генератор који генерира три фазе и има распон од 1Hz до 80Hz, са најмањим кораком од 0.01Hz. Имајући то у виду, ограничење са којим радим је (1) прецизност контролера и (2) немогућност да Ардуино прочита тренутну вредност фрекфенције.

Компромис

Ардуино "клика" тастере на екстерном контролеру и тако мења фрекфенцију синусоиде. Једина непозната вредност је "величина промене" коју један "клик" Ардуина ефектуира.

Та вредност се води у променљивој derivedQ:

float derivedQ = 0.01; // Indicates the correction in RPM derived from a single 0.01Hz step (single "click").

Што би значило да један "клик" Ардуина, који означује промену од 0.01Hz у фрекфенцији, једнако је промени од 0.01 ротацију у минути на стране грамофонског тањира. Ова вредност је била, благо речено одокативна (**) да би код прорадио.

(**) Одокативно је можда строго. Вредност је резултат мерења, споредби и прерачуна - па узета средња вредност.

Како се подвижни систем мења у зависности екстерних параметара, логично је да којефицијент промене (derivedQ) би требало да флуктуира да би увећао прецизност целог склопа.

Решење

Код већ укључује доста услова за имплементацију аутоматске калкулације овог параметра. Калкулација се почиње радити тек након регулација прође пар циклуса.

Приступ се онда своди на прерачун разлике броја ротације пре и након корекције, као и броја корака који су довели до те корекције.

derivedQ = abs(currentRPM - fixRPM) / fixSteps;

Код

Сва логика око калкулација просека се налази унутар процедури showRPM():

if (fixSteps > 1)
{
  derivedQ = abs(currentRPM - fixRPM) / fixSteps;
  if (derivedQ > setQ) { derivedQ = setQ; }
  fixSteps = 0;
  fixRPM = 0;
}

А регулира се уз помоћ пар променљива:

float fixRPM = 0, fixSteps = 0; // Variables for programmatic calculation of derivedQ.
const float setQ = 0.01;

Прве две променљиве садрже (1) стару вредност ротација и (2) број корака у том циклусу корекције. Константа setQ служи за имплементацију максималне вредности којефицијента. (***)

(***) Грешка у калкулацији, или вањски узроци могу да доведе до енормно (за овај систем) велике вредности којефицијента. Имплементација ове константе се осигурава да прерачунати којефицијент никад не пређе задану вредност.

Процедура је релативно једноставна:

  1. Активира се само ако се уради корекција, и ако та корекција укључује бар 2 корака;
  2. При активацији, fixRPM добија тренутну вредност ротација, а fixSteps тренутну вредност калкулираних корака (stepsX);
  3. Након истека времена хлађења (correctionSpinCount) калкулира се нови којефицијент (разлика између старе и нове вредност ротација се дели бројем корака);
  4. fixRPM и fixSteps се ресетирају како би били спремни за нову корекцију (ако до те корекције дође);
  5. У случају промене брзине (33.3 према 45 и обратно) све вредности се ресетирају, и почињу се калкулирати тек након истека времена хлађења.

Такође сам допунио рутину за дебагирање да сада штампа (1) тренутну вредност ротације, (2) просечну вредност ротације, (3) тренутну вредност којефицијента корекције и (4) број слота у пољу за просеке (од 1 до averageTotal):

if (debugSerial)
{
  Serial.print(currentX, 4);
  Serial.print(" ");
  Serial.print(currentRPM, 4);
  Serial.print(" ");
  Serial.print(derivedQ, 4);
  Serial.print(" ");
  Serial.print(averageCount);
  Serial.println();
}

 

Резултати

Циљ је био увећавање прецизности регулације, т.ј. финија регулација:

RPM (true)   RPM (average)   derivedQ       averageSlot

33.1941      33.1722         0.0100	    9
33.1943      33.1746         0.0100	    10
33.1984      33.1774         0.0100	    11
33.1962      33.1799         0.0077	    12
33.2046      33.1829         0.0077	    13
33.2162      33.1864         0.0077	    14
33.2255      33.1905         0.0077	    15
33.2304      33.1952         0.0077	    0
33.2343      33.1999         0.0077	    1
33.2340      33.2041         0.0077	    2
33.2361      33.2079         0.0077	    3
33.2322      33.2110	     0.0077	    4
33.2328      33.2136	     0.0077	    5
33.2364      33.2160	     0.0077	    6
33.2395      33.2186	     0.0087	    7
33.2428      33.2217	     0.0087	    8
33.2520      33.2254	     0.0087	    9

Кључна је вредност derivedQ, као и брзина промене.

У овом примерку, derivedQ је добила прецизнију вредност од константе, а тиме и прецизнију регулацију. Број окидања игра велику улогу и брзини промене - тачно 12 окидања, односно укупно 3 пуне ротације тањира, било је довољно за две пуне калкулације derivedQ параметра.

Закључак

Циљ постигнут, сада се погон може користити са било којој комбинацији каиша и каишница без претходних мерења за фиксне параметре.  

Код је, као и увек (108755f), овде:

https://github.com/stojnev/dwr-controller

 

Share this post


Link to post
Share on other sites
On 3/23/2018 at 5:18 PM, guja011 said:

imaš malecki previd , cenim da je desni deo slike u pitanju , curenje kroz zaštitnu diodu.

kada je čip na napajanju dioda je u kontri pa ne curi.

 

mali previd.jpg

@guja011 имајући ово у виду, као и шему из прве поруке, дали мислиш да бих могао да решим "проблем" са неком мањом корекцијом на шеми? 

Share this post


Link to post
Share on other sites

Мали рефактор кода, одвојена рутина за стопирање ротације - лакше за оддржавање, бржа реакција на дисплеју.

Код је, као и увек (b3ed158), овде:

https://github.com/stojnev/dwr-controller

 

Share this post


Link to post
Share on other sites

У GitHub repo-у, додао Gerber датотеке за две плочице:

30125469_10155291805245796_1191042497_o.jpg.c9a0baeecb76bdc0b6b32bea4f3ee49d.thumb.jpg.0d046d155ec6be87edc09d4886885b3f.jpg

Плочице стигли из Кине (EasyEDA), проверено раде како су и замишљене.

Код је, као и увек (f0e7ce1), овде:

https://github.com/stojnev/dwr-controller

Share this post


Link to post
Share on other sites

Унапређење #4

Рутине за чување укупног времена свирања.

Позадина

Како већ погон користи флексибилну (читај програмабилну) контролу, једна од задњих опција које сам хтео имплементирати је снимање укупног времена свирања. Ово је, бар за мене, прилично корисна функција за праћење старости звучнице.

Ова могућност би морала укључити бар следећe:

  1. Снимање укупног времена ротације;
  2. Приказ тог времена у формат који се лако чита (нарочито на минијатурном дисплеју); и,
  3. Брисање (ресетирање) укупног времена.

Приступ

Типично, Ардуино ресетира све параметре (променљиве) при сваком искључивању. На срећу, Nano има ЕЕПРОМ (non-volatile) величине једног (1) килобајта, што би требало бити довољно за ову фукнционалност.

Имплементација је прилично једноставна:

  1. При сваког извршења главне петље, упоређује се број тикова (ticks) са ранијом вредности;
  2. Кад разлика тикова надмаши 1 секунду, у ЕЕПРОМ се упише нова вредност;
  3. Кад се напуни слот ЕЕПРОМ-а, показивач се повећа.

Код

Сва логика око снимања се налази унутар процедури checkTimer():

void checkTimer()
{
  if (timerCurrentMicros == 0 && timerPreviousMicros == 0)
  {
    timerCurrentMicros = micros();
    timerPreviousMicros = timerCurrentMicros;
  }
  else { timerCurrentMicros = micros(); }
  int timerSeconds = (int) ((timerCurrentMicros - timerPreviousMicros) / 1000000);
  if (timerSeconds > 0)
  {
    for (int e = 0; e < timerSlots; e++)
    {
      byte valueX = EEPROM.read(e);
      timerX[e] = (int) valueX;   
    }
    timerPreviousMicros = timerCurrentMicros;
    int changeX = timerSeconds;
    for (int e = 0; e < 4; e++)
    {
      timerX[e] += changeX;
      if (timerX[e] > 255)
      {
        changeX = timerX[e] - 255;
        timerX[e] = changeX;
        changeX = 1;
      }
      else
      {
        changeX = 0;
      }
      EEPROM.write(e, timerX[e]);
    }
  }
}

А регулира се уз помоћ пар променљива:

unsigned long timerCurrentMicros = 0, timerPreviousMicros = 0;
const int timerSlots = 4; int timerX[timerSlots]; const int timerMessageWait = 5000; long timerMessage = 0; boolean timerShown = false;

Калкулација укупног времена је у процедури calculateRunTime():

void calculateRuntime(int & calcX1, int & calcX2)
{
  long runtimeX = 0;
  for (int e = 0; e < timerSlots; e++)
  {
    int tempX = (int) EEPROM.read(e);
    if (tempX > 0) { runtimeX += tempX * pow(255, e); }
  }
  calcX2 = (runtimeX / 60) % 60;
  calcX1 = (int) (runtimeX / 3600);
}

Ресетирање тајмера (ЕЕПРОМ-а) је у процедури clearTimer():

void clearTimer()
{
  if (activeSpin || !timerShown)
  {
    return;
  }
  writeToDisplay(5);
  for (int e = 0; e <= timerSlots; e++) {
    EEPROM.write(e, 0);
  }
}

Рад

За приступ тајмеру, тахометар мора да буде у stand-by стању:

  1. Дужи притисак на дугме за промену брзине показује укупно време;
  2. Након 5 секунди дисплеј се враћа на stand-by мод;
  3. Дужи притисак на дугме за укључивања ротације док је дисплеј у моду првог корака (показано укупно време) ресетира тајмер.

Приказ показује укупан број сати и минута, због ограничења простора на дисплеју:

tachometer_timer.thumb.jpg.f1402f98b6ad8d86c5d93bc027eab567.jpg

Закључак

Ово је задње планирано унапређење. Будуће промене су планиране једино у склопу оддржавања.

Код је, као и увек (4f0184d), овде:

https://github.com/stojnev/dwr-controller

Share this post


Link to post
Share on other sites

Проблем #2

Раније сам писао да сам имао проблеме са имплементацијом CD4066B:

On 3/23/2018 at 2:16 PM, InSides said:

Па онда би да ревидирам употребу CD4066B зато што не понаша се баш како пише у datasheet-у. :)

Моја имплементација је радила, али мање него идеално. Нипошто за решење на дуже стазе.

Решење

Након дискусије, и предлогa који је @guja011 дао:

On 3/23/2018 at 6:08 PM, guja011 said:

mada opet nije jasno kad već tastuješ samo ka masi, što nisi turio obične diskretne fetiće?

Заменио сам CD4066B за четири BC337 транзистора, у комплету са 1кО отпорницима на сваку од транзисторских база:

bc337_switch.jpg.bca2cace864a4d26e207f0fdcdf89d35.jpg

Нема цурења, нема проблематичних понашања, ради како је оригинално замишљено.

Редизајнирао плочицу, нови сет Гербера и breadboard слике на GitHub-у.

Код је, као и увек (3d63b2a), овде:

https://github.com/stojnev/dwr-controller

Share this post


Link to post
Share on other sites

Проблем #3

Мало сам читао спецификацију Ардуина, и схватио да ЕЕПРОМ има лимит снимања (writing cycles). Загарантован број циклуса је око 100,000 - што изгледа пуно - али имајући у виду како Ардуино снима податке у ЕЕПРОМ, и није баш.

Када се на то дода податак да је код снимао у ЕЕПРОМ сваке секунде, добијемо ситуацију у коју ЕЕПРОМ је практично неупотребљив за мање од 30 сати писања.

Решење

Сва логика писања у ЕЕПРОМ се налази у процедури:

void checkTimer()

Пар корекција ради оптимизације, и сада имамо чак и прецизнији тајмер, који штеди ЕЕПРОМ.

Код је, као и увек (73432a0), овде:

https://github.com/stojnev/dwr-controller

Share this post


Link to post
Share on other sites
On 4/18/2018 at 4:39 PM, InSides said:

tachometer_timer.thumb.jpg.f1402f98b6ad8d86c5d93bc027eab567.jpg

Да заокружимо пројект овде - хвала @Leonardo за веома прецизну обраду горње плоче - даљинац је сада спакован:

image_1.jpg

Share this post


Link to post
Share on other sites
1 minute ago, Woland said:

abre, NATO je srećan što se ne usmerite na krstareće rakete, znanja bi se pronašlo, a i sklepali bi smo je nekako, pa bi ih izbacili iz biznisa :)

Није важно дали ракете раде, добре би биле за параде.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×