Stránka 1 z 2
Arduino Nano: počítadlo otáček s děličkou
Napsal: 19 črc 2025, 21:23
od Roman-W
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/Count ... 219_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í
Napsal: 19 črc 2025, 23:30
od bum
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ů.
Napsal: 19 črc 2025, 23:54
od Celeron
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: Vybrat vše
#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.
Napsal: 20 črc 2025, 10:50
od samec
Č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
Napsal: 20 črc 2025, 14:17
od Michal22
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
Napsal: 20 črc 2025, 15:52
od samec
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: Vybrat vše
#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.
Napsal: 20 črc 2025, 17:20
od lesana87
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?
Napsal: 21 črc 2025, 10:35
od samec
lesana87 píše: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 píš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?
Máš pravdu.
Kód: Vybrat vše
#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++;
}
Napsal: 21 črc 2025, 11:00
od nostalcomp
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: Vybrat vše
// 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;
}
Napsal: 21 črc 2025, 12:33
od lesana87
samec píš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?
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.
Napsal: 21 črc 2025, 14:38
od samec
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.
Napsal: 21 črc 2025, 14:53
od HF_Tech
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

Napsal: 21 črc 2025, 17:11
od Celeron
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: Vybrat vše
#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;
}
}
Napsal: 21 črc 2025, 17:23
od lesana87
samec píše: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.
Napsal: 21 črc 2025, 20:32
od samec
Celeron píše:Rozklad registru counter na řády jsem nikdy nezkoušel ale našel jsem to na netu.
Kód: Vybrat vše
...
// 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: Vybrat vše
char dekadicky[8];
sprintf(dekadicky,"%d",value");
for(char i=0; i <=8; i++) sendToMAX7219(i, dekadicky[i] - '0'); // ;-)