Arduino Nano: počítadlo otáček s děličkou
Moderátor: Moderátoři
Arduino Nano: počítadlo otáček s děličkou
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í
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ů.
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);
}
Proč mi nemůže všechno chodit hned ?!!
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
Tak byl bys tě dobroty a předvedl nám někdy svoje dovednosti v reálu?
Diky
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í...
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++;
}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?
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: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.
Máš pravdu.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?
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++;
}- nostalcomp
- Příspěvky: 169
- Registrován: 09 lis 2022, 00:00
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;
}
To je 160 Hz, to je pomalý vstup.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?
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.
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.
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;
}
}
Proč mi nemůže všechno chodit hned ?!!
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.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.
Ja by som to nehľadal. Rovno by som napísalCeleron 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; } }
Kód: Vybrat vše
char dekadicky[8];
sprintf(dekadicky,"%d",value");
for(char i=0; i <=8; i++) sendToMAX7219(i, dekadicky[i] - '0'); // ;-)