Vítejte na Elektro Bastlírn?
Nuke - Elektro Bastlirna
  Vytvořit účet Hlavní · Fórum · DDump · Profil · Zprávy · Hledat na fóru · Příspěvky na provoz EB

Vlákno na téma KORONAVIRUS - nutná registrace


Nuke - Elektro Bastlirna: Diskuzní fórum

 FAQFAQ   HledatHledat   Uživatelské skupinyUživatelské skupiny   ProfilProfil   Soukromé zprávySoukromé zprávy   PřihlášeníPřihlášení 

Arduino Nano: počítadlo otáček s děličkou

 
Přidat nové téma   Zaslat odpověď       Obsah fóra Diskuzní fórum Elektro Bastlírny -> Programování PIC, ATMEL, EEPROM a dalších obvodů
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Roman-W



Založen: May 29, 2013
Příspěvky: 49

PříspěvekZaslal: so červenec 19 2025, 20:23    Předmět: Arduino Nano: počítadlo otáček s děličkou Citovat

Zdravím sehnal jsem si na webu tento kod že ho upravím a nějak si nevím rady jak zakomponovat dělení vstupního signálu optozávory. na vřetenu mam kroužek s 8 výřezy viz příloha. Zapojení je defakto stejné jako na webu jen mam zapojený A0 (výstup z optozávory) a A2 (reset)

https://github.com/embeddedlab786/Counter_8Digit_MAX7219_Eeprom

Do budoucna plánuji dvě opto závory vedle sebe aby to poznalo směr otáčení. Abych mohl při přejetí požadovaného počtu zavitů odmotat na zpětný chod ale to bude další komplikace v programování



kolečka.jpg
 Komentář:
 Velikost:  23.79 kB
 Zobrazeno:  4 krát

kolečka.jpg


Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
bum



Založen: Sep 04, 2011
Příspěvky: 270

PříspěvekZaslal: so červenec 19 2025, 22:30    Předmět: Citovat

Uvedený program co jste uvedl je ukázkový pro zápis hodnot do paměti zadaných tlačítky. Na čítání pulsů použijte vstup kde je možné načítat pulsy při přerušení použijte třeba vstup D2 což je přerušení 0, kde použijete vzorec co máte pro ten kotouč s osmi výřezy. Než takto upravovat tento program je lepší si napsat nový a místo uvedeného displeje použít obyčejný LCD displej ať 16-místný nebo 20-místný buď jednořádkový nebo s více řádky. Také jsem si kdysi stavěl navíječku s programem pro PC, schéma elektroniky, program s popisem je na webu tam se zadal počet závitů a po dosažení zadaného počtu se automaticky vypnul motorek.
To rozlišení směru otáček je možné řešit stejně jako se řeší u rotačního enkodéru. Pokud se mi namotal větší počet závitů tak jsem odmotání řešil přehozením směru otáčení a odpočtem závitů.

_________________
www.mojeelektronika.mzf.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail Zobrazit autorovy WWW stránky
Celeron



Založen: Apr 02, 2011
Příspěvky: 19645
Bydliště: Nový Bydžov

PříspěvekZaslal: so červenec 19 2025, 22:54    Předmět: Citovat

Moc složitý, na co je u počítadla navíječky potřeba EEPROM? Jako že to navíjení zastavíš a druhej den budeš pokračovat? Navíc to vypadá, že s každou změnou nahoru nebo dolů se zapisuje do EEPROM, která má technicky né moc velký počet zápisů a pak odejde.
No a upravit to na dělení osmi bude potřeba další počítadlo, do kterého se bude posílat těch 8 impulzů za otáčku a když přijde devátý, tak se přičte 1 v D1 a D0 vynuluje. On se totiž nezobrazuje obsah počítacího registru ale každý řád displeje má svý počítadlo 0-9 a když se napočítá na jednotkách víc než 9, tak se přičte 1 na desítkách a tak dále. Prostě to tupě kopíruje klasický mechanický počítadlo.

Tady to máš upravený, zkus to a dej vědět, jestli to chodí co otáčka, to přičtení 1 na řádu jednotek. Možná bude potřeba softwarový debounce (odrušení zákmitů) nebo detekce hrany místo stavu, kdyby to náhodně přičítalo blbě, dej vědět.
kód:

#include <EEPROM.h>

#define bt_up     A0
#define bt_reset  A2
#define buzzer    13

#define MAX7219_Clock        2
#define MAX7219_Chip_Select  3
#define MAX7219_Data_IN      4

long d1=0, d2=0, d3=0, d4=0, d5=0, d6=0, d7=0, d8=0;

int flag1=0, timer=0;
int pulseCounter = 0;  // Počet pulzů ze snímače (každých 8 = 1 otáčka)

void setup() {
  pinMode(bt_up,    INPUT_PULLUP);
  pinMode(bt_reset, INPUT_PULLUP);
  pinMode(buzzer,   OUTPUT);

  pinMode(MAX7219_Data_IN, OUTPUT);
  pinMode(MAX7219_Chip_Select, OUTPUT);
  pinMode(MAX7219_Clock, OUTPUT);
  digitalWrite(MAX7219_Clock, HIGH);

  delay(200);

  // Nastavení MAX7219
  shift(0x0f, 0x00); // test mode off
  shift(0x0c, 0x01); // normal operation
  shift(0x0b, 0x07); // scan limit 0–7
  shift(0x0a, 0x0f); // brightness max
  shift(0x09, 0xff); // decode B mode for all digits

  if (EEPROM.read(0) != 0) {
    WriteEeprom();
    EEPROM.write(0, 0);
  }

  ReadEeprom();
}

void loop() {
  // Zpracování pulzů z čidla (8 pulzů = 1 otáčka)
  if (digitalRead(bt_up) == LOW) {
    if (flag1 == 0) {
      flag1 = 1;
      pulseCounter++;
      if (pulseCounter >= 8) {
        pulseCounter = 0;

        d1++;
        if (d1 > 9) { d1 = 0; d2++; }
        if (d2 > 9) { d2 = 0; d3++; }
        if (d3 > 9) { d3 = 0; d4++; }
        if (d4 > 9) { d4 = 0; d5++; }
        if (d5 > 9) { d5 = 0; d6++; }
        if (d6 > 9) { d6 = 0; d7++; }
        if (d7 > 9) { d7 = 0; d8++; }
        if (d8 > 9) { d8 = 0; }

        WriteEeprom();
      }
    }
  } else {
    flag1 = 0;
  }

  // RESET
  if (digitalRead(bt_reset) == LOW) {
    digitalWrite(buzzer, HIGH);
    if (timer < 200) timer++;
    if (timer == 200) {
      d1 = d2 = d3 = d4 = d5 = d6 = d7 = d8 = 0;
      pulseCounter = 0;
      WriteEeprom();
    }
  } else {
    digitalWrite(buzzer, LOW);
    timer = 0;
  }

  // Zobrazení na displeji
  shift(0x01, d1);  // nejnižší řád (vpravo)
  shift(0x02, d2);
  shift(0x03, d3);
  shift(0x04, d4);
  shift(0x05, d5);
  shift(0x06, d6);
  shift(0x07, d7);
  shift(0x08, d8);  // nejvyšší řád (vlevo)
  delay(10);
}

void ReadEeprom() {
  d1 = EEPROM.read(1);
  d2 = EEPROM.read(2);
  d3 = EEPROM.read(3);
  d4 = EEPROM.read(4);
  d5 = EEPROM.read(5);
  d6 = EEPROM.read(6);
  d7 = EEPROM.read(7);
  d8 = EEPROM.read(8);
}

void WriteEeprom() {
  EEPROM.write(1, d1);
  EEPROM.write(2, d2);
  EEPROM.write(3, d3);
  EEPROM.write(4, d4);
  EEPROM.write(5, d5);
  EEPROM.write(6, d6);
  EEPROM.write(7, d7);
  EEPROM.write(8, d8);
}

void shift(byte send_to_address, byte send_this_data) {
  digitalWrite(MAX7219_Chip_Select, LOW);
  shiftOut(MAX7219_Data_IN, MAX7219_Clock, MSBFIRST, send_to_address);
  shiftOut(MAX7219_Data_IN, MAX7219_Clock, MSBFIRST, send_this_data);
  digitalWrite(MAX7219_Chip_Select, HIGH);
}


Na ten směr se dvěma snímačema můžeš použít již hotový knihovny pro n-codéry.

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
samec



Založen: Dec 19, 2017
Příspěvky: 5466

PříspěvekZaslal: ne červenec 20 2025, 9:50    Předmět: Citovat

Čo za obludnosť? Autor toho kódu by mal radše sadiť zemiaky, lebo programovaniu nerozumie. Niečo tak primitívne sa dá inteligentne napísať na desať riadkov.

Zahoď ten kód a napíš si vlastný.
Alebo ak nevieš napísať vlastný program, tak zahoď aj arduino a kúp si hotový čítač.
https://vi.aliexpress.com/item/1005005883201203.html
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Michal22



Založen: Mar 28, 2012
Příspěvky: 8119
Bydliště: Brno

PříspěvekZaslal: ne červenec 20 2025, 13:17    Předmět: Citovat

Samče, nějak jsem si vzpomněl, že už po několikáté uvádíš, že někdo dělá něco špatně, a že ty to umíš podstatně líp.
Tak byl bys tě dobroty a předvedl nám někdy svoje dovednosti v reálu?
Diky

_________________
Civilizace založená na oboustranné lepící pásce nemůže dobře skončit...
I kdyby se z tebe jednou stal král, neodsuzuj lidi, kteří ti nebudou provolávat slávu- raději se zeptej sám sebe, proč tomu tak není...
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
samec



Založen: Dec 19, 2017
Příspěvky: 5466

PříspěvekZaslal: ne červenec 20 2025, 14:52    Předmět: Citovat

Ak nevidíš, koľko chýb je v použití toho kódu a v tom kóde samotnom, tak si najprv naštuduj základy programovania a potom sa vyjadruj.

Až bude zadanie dodefinované, že na čom sa má počítadlo zobrazovať, či sa má ukladať do EPROM, prípadne ako sú optočleny rozmiestnené, tak možno program rozvinúť...
kód:

#define vstup1 A0 //vstup z 1. optozavory

static char pocet_pulsu = 0;
int pocet_otacek = 0;

void setup() {
 pinMode(vtup1, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(vstup1), nahoru, RISING);
}

void loop() {
 if(pocet_pulsu >= 8) {
  pocet_pulsu -= 8;
  pocet_otacek++;
 }

 //todo: zobraz pocet otacek ...
}

void nahoru() {  //interrupt
 pocet_pulsu++;
}

Mimochodom, na obojsmerné počítanie by boli vhodnejšie kotúčiky s medzerami rovnako širokými, ako má plná časť medzi nimi.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
lesana87



Založen: Sep 20, 2014
Příspěvky: 3724

PříspěvekZaslal: ne červenec 20 2025, 16:20    Předmět: Citovat

Snímat stav pomalého vstupu přes přerušení je cesta k chytání kdejakého rušení a zákmitů, zvláště po doplnění snímače na kvadraturní kodér. Myslím si, že čistější je vstup(y) samplovat vhodnou frekvencí od časovače.
Jinak samče, když jseš u toho správnýho programování, určitě jsi slyšel o race condition, jseš si jistej, že pocet_pulsu -= 8; je atomická operace?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
samec



Založen: Dec 19, 2017
Příspěvky: 5466

PříspěvekZaslal: po červenec 21 2025, 9:35    Předmět: Citovat

lesana87 napsal(a):
Snímat stav pomalého vstupu přes přerušení je cesta k chytání kdejakého rušení a zákmitů, zvláště po doplnění snímače na kvadraturní kodér. Myslím si, že čistější je vstup(y) samplovat vhodnou frekvencí od časovače.
Jak pomalý je podĺa teba pomalý vstup? Koľko sekúnd bude trvať jeden ten výsek na kotúčiku pri rýchlosti otáčania napríklad 1200 rpm?

lesana87 napsal(a):
Jinak samče, když jseš u toho správnýho programování, určitě jsi slyšel o race condition, jseš si jistej, že pocet_pulsu -= 8; je atomická operace?
Máš pravdu.
kód:

#define vstup1 A0 //vstup z 1. optozavory

static long pocet_pulsu = 0;
long pocet_otacek = 0;

void setup() {
 pinMode(vtup1, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(vstup1), nahoru, RISING);
}

void loop() {
 pocet_otacek = pocet_pulsu / 8;

 //todo: zobraz pocet otacek ...
}

void nahoru() {  //interrupt
 pocet_pulsu++;
}
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
nostalcomp



Založen: Nov 09, 2022
Příspěvky: 120

PříspěvekZaslal: po červenec 21 2025, 10:00    Předmět: Citovat

No, to už je lepší. Ta konstrukce s tím IFem se ti opravdu hodně nepovedla. Já bych obě verze napsal asi takto:

kód:

// pulsy = BYTE
// otacky = WORD

void nahoru1 ()
{
pulsy++;
otacky += (pulsy == 8);
pulsy *=  (pulsy < 8);
}

//nebo:

// pulsy = UNSIGNED LONG
// otacky = WORD

void nahoru2 ()
{
pulsy++;
otacky = pulsy >> 3;
}

Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
lesana87



Založen: Sep 20, 2014
Příspěvky: 3724

PříspěvekZaslal: po červenec 21 2025, 11:33    Předmět: Citovat

samec napsal(a):
Jak pomalý je podĺa teba pomalý vstup? Koľko sekúnd bude trvať jeden ten výsek na kotúčiku pri rýchlosti otáčania napríklad 1200 rpm?

To je 160 Hz, to je pomalý vstup.
Přijde mi zbytečné, dělat na navíječce 8 zubů na otáčku, k čemu je dobrá osmina závitu? Já mám na soustruhu 2 zuby na otáčku snímané kvadraturně dvojicí optočlenů a je to dostatečné i pro měření ot/min. Do 3000 ot/min stačí samplovat 1kHz, to jsou také pomalé vstupy. Zároveň tím časovačem multiplexuju LED displej.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
samec



Založen: Dec 19, 2017
Příspěvky: 5466

PříspěvekZaslal: po červenec 21 2025, 13:38    Předmět: Citovat

1/160 sú vzdialenosti medzi pulzami. Samotné pulzy (medzery v disku) sú 6x kratšie. Takže pulz má dlžku cca 1ms. Pri dvojnásobnej rýchlosti 500µs. Ak to navzorkuješ cez časovač, aj tak potrebuješ prerušenie. Problém s atomárnymi inštrukciami zostáva, rušenie tiež. A čo ak sa kotúčik zastaví presne hranou v optozávore? To ti ani neuronka nepomôže, pokiaľ to nebude odolné už na úrovni senzora.

Mal som radšej ostať pri konštatovaní, že ten pôvodný nalinkovaný softvér je blbosť a viac sa k tomu nevyjadrovať.

Jeden pulz na otočku je málo, lebo to by znamenalo chybu jedného závitu v závislosti od počiatočnej polohy kotúčika voči polohe začiatku vinutia a zrejme približnej polohe začiatku a konca navíjania.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
HF_Tech



Založen: Apr 25, 2022
Příspěvky: 1440

PříspěvekZaslal: po červenec 21 2025, 13:53    Předmět: Citovat

Proto je lepší použít ten kvadraturní enkodér. U něj si naprogramuješ zámek, že se vyhodnotí pouze první hrana a pak se čeká až na změnu na druhém vstupu. Když se ještě dodělá obsluha od všech vstupů a hran, tak stačí na snímání úplně primitivní půlkolečko Cool
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Celeron



Založen: Apr 02, 2011
Příspěvky: 19645
Bydliště: Nový Bydžov

PříspěvekZaslal: po červenec 21 2025, 16:11    Předmět: Citovat

Hodně tady mudrujte, tazatel chtěl upravit původní program aby jen dělil osmi.
Samo že se to dá napsat elegantněji, jeden kotouček 8 výřezů, dva fototrandy.
To načítání pulzů mám v počítadle odzkoušený s magnetickým n-codérem 100 pulzů na otáčku. U magneťáku se nemusí vůbec řešit zákmity co mají fototranzistory.
U tohodle je jen 8 zářezů co generují kvadraturní signál (A, B, 90° fázový posun). Rozklad registru counter na řády jsem nikdy nezkoušel ale našel jsem to na netu. Zapojení stejný jako původní. Bez záruky, nemám moc času se v tom rejpat. Asi by bylo lepší přepojit to na využití přerušení a došlechtit tam ochranu proti zákmitům.
kód:

#include <Arduino.h>

#define SIG_A A0
#define SIG_B A1
#define RESET_BTN A2
#define BUZZER 13

#define MAX7219_DIN   4
#define MAX7219_CLK   2
#define MAX7219_CS    3

long counter = 0;
bool lastA = 1;
bool lastB = 1;
int resetTimer = 0;

void setup() {
  pinMode(SIG_A, INPUT_PULLUP);
  pinMode(SIG_B, INPUT_PULLUP);
  pinMode(RESET_BTN, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);

  pinMode(MAX7219_DIN, OUTPUT);
  pinMode(MAX7219_CLK, OUTPUT);
  pinMode(MAX7219_CS, OUTPUT);

  digitalWrite(MAX7219_CLK, HIGH);
  delay(100);

  initMAX7219();
}

void loop() {
  // Čtení signálu A a B
  bool A = digitalRead(SIG_A);
  bool B = digitalRead(SIG_B);

  if (A != lastA) {
    if (A == LOW) {
      if (B == HIGH) counter++;  // směr 1
      else counter--;            // směr 2
    }
    lastA = A;
  }

  // RESET držení
  if (digitalRead(RESET_BTN) == LOW) {
    digitalWrite(BUZZER, HIGH);
    if (++resetTimer > 200) {
      counter = 0;
    }
  } else {
    digitalWrite(BUZZER, LOW);
    resetTimer = 0;
  }

  displayNumber(counter/8);
  delay(5); // stabilizace
}
// inic Maxe
void initMAX7219() {
  sendToMAX7219(0x0F, 0x00); // Test off
  sendToMAX7219(0x0C, 0x01); // Shutdown = normal
  sendToMAX7219(0x0B, 0x07); // Scan limit = 8 digits
  sendToMAX7219(0x0A, 0x0F); // Brightness max
  sendToMAX7219(0x09, 0xFF); // Decode all digits
}
// plnění Maxe
void sendToMAX7219(byte address, byte data) {
  digitalWrite(MAX7219_CS, LOW);
  shiftOut(MAX7219_DIN, MAX7219_CLK, MSBFIRST, address);
  shiftOut(MAX7219_DIN, MAX7219_CLK, MSBFIRST, data);
  digitalWrite(MAX7219_CS, HIGH);
}
// rozklad pro Maxe
void displayNumber(long value) {
  unsigned long absVal = abs(value);
  for (int i = 1; i <= 8; i++) {
    byte digit = absVal % 10;
    sendToMAX7219(i, digit);
    absVal /= 10;
  }
}

_________________
Jirka

Proč mi nemůže všechno chodit hned ?!!
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
lesana87



Založen: Sep 20, 2014
Příspěvky: 3724

PříspěvekZaslal: po červenec 21 2025, 16:23    Předmět: Citovat

samec napsal(a):
Ak to navzorkuješ cez časovač, aj tak potrebuješ prerušenie. Problém s atomárnymi inštrukciami zostáva, rušenie tiež. A čo ak sa kotúčik zastaví presne hranou v optozávore? To ti ani neuronka nepomôže, pokiaľ to nebude odolné už na úrovni senzora.

S tím si právě ten samplovaný kvadraturní kodér poradí s prstem v nose, klidně se to může třepat na hraně, jak chce a generovat to třeba 100ns pulsy, to přes přerušení od hrany nepochytáš ani náhodou. A dva zuby na otáčku jsou 8 impulsů na otáčku, stejně jako tady.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
samec



Založen: Dec 19, 2017
Příspěvky: 5466

PříspěvekZaslal: po červenec 21 2025, 19:32    Předmět: Citovat

Celeron napsal(a):
Rozklad registru counter na řády jsem nikdy nezkoušel ale našel jsem to na netu.
kód:
...
// rozklad pro Maxe
void displayNumber(long value) {
  unsigned long absVal = abs(value);
  for (int i = 1; i <= 8; i++) {
    byte digit = absVal % 10;
    sendToMAX7219(i, digit);
    absVal /= 10;
  }
}
Ja by som to nehľadal. Rovno by som napísal
kód:
char dekadicky[8];

sprintf(dekadicky,"%d",value");
for(char i=0; i <=8; i++) sendToMAX7219(i, dekadicky[i] - '0');  // ;-)
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
Přidat nové téma   Zaslat odpověď       Obsah fóra Diskuzní fórum Elektro Bastlírny -> Programování PIC, ATMEL, EEPROM a dalších obvodů Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra.
Nemůžete odpovídat na témata v tomto fóru.
Nemůžete upravovat své příspěvky v tomto fóru.
Nemůžete mazat své příspěvky v tomto fóru.
Nemůžete hlasovat v tomto fóru.
Nemůžete připojovat soubory k příspěvkům
Můžete stahovat a prohlížet přiložené soubory

Powered by phpBB © 2001, 2005 phpBB Group
Forums ©
Nuke - Elektro Bastlirna

Informace na portálu Elektro bastlírny jsou prezentovány za účelem vzdělání čtenářů a rozšíření zájmu o elektroniku. Autoři článků na serveru neberou žádnou zodpovědnost za škody vzniklé těmito zapojeními. Rovněž neberou žádnou odpovědnost za případnou újmu na zdraví vzniklou úrazem elektrickým proudem. Autoři a správci těchto stránek nepřejímají záruku za správnost zveřejněných materiálů. Předkládané informace a zapojení jsou zveřejněny bez ohledu na případné patenty třetích osob. Nároky na odškodnění na základě změn, chyb nebo vynechání jsou zásadně vyloučeny. Všechny registrované nebo jiné obchodní známky zde použité jsou majetkem jejich vlastníků. Uvedením nejsou zpochybněna z toho vyplývající vlastnická práva. Použití konstrukcí v rozporu se zákonem je přísně zakázáno. Vzhledem k tomu, že původ předkládaných materiálů nelze žádným způsobem dohledat, nelze je použít pro komerční účely! Tento nekomerční server nemá z uvedených zapojení či konstrukcí žádný zisk. Nezodpovídáme za pravost předkládaných materiálů třetími osobami a jejich původ. V případě, že zjistíte porušení autorského práva či jiné nesrovnalosti, kontaktujte administrátory na diskuzním fóru EB.


PHP-Nuke Copyright © 2005 by Francisco Burzi. This is free software, and you may redistribute it under the GPL. PHP-Nuke comes with absolutely no warranty, for details, see the license.
Čas potřebný ke zpracování stránky 0.21 sekund