Timer 2 a přerušení

Odpovědět
Uživatelský avatar
fulda
Příspěvky: 521
Registrován: 04 led 2016, 17:18

Timer 2 a přerušení

Příspěvek od fulda » 29 led 2018, 17:13

Ahoj,

rozhodl jsem se, že se na arduinu naučím používat přerušení od časovače. (a pak to celé budu chtít zabalit do knihovny, to bude mazec)

Pro začátek jsem se podíval na TENTO příklad (odkazuje na něj arduino.cc.

Protože se mi stránka zobrazuje zmršená, tak dole přidávám vykopírovaný program ze stránky.

A teď, co mne zaujalo je, že autor potřebuje, aby mu TIMER2 probíhal 250x a nikoli 256x. Tak to řeší tak, že po každém přetečení přiřadí do TCNT2 hodnotu 6. To je podle mne dost prasárna. já bych si myslel, že by bylo správnější uložit do registru OCR2A hodnotu 250, nastavit si režim TCCR2A.WGM2 = Mode2 (CTC, clear timer when reach) a pak reagovat na přerušení "TIMER2_COMPA_vect" (TIMSK2.OIE2A =1, TIMSK2.OIE2B=0, TIMSK2.TOIE2=0)

Je moje úvaha správná? Nebo je nějaký důvod, proč tuhle metodu nepoužívat?

--- kód ze stránky ---

Kód: Vybrat vše

#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT

int ledPin = 13;
int int_counter = 0;
volatile int second = 0;
int oldSecond = 0;
long starttime = 0;

// Aruino runs at 16 Mhz, so we have 1000 Overflows per second...
// 1/ ((16000000 / 64) / 256) = 1 / 1000
ISR(TIMER2_OVF_vect) {
  RESET_TIMER2;
  int_counter += 1;
  if (int_counter == 1000) {
    second+=1;
    int_counter = 0;
  } 
};

void setup() {
  Serial.begin(9600);
  Serial.println("Initializing timerinterrupt");
  //Timer2 Settings: Timer Prescaler /64, 
  TCCR2 |= (1< <CS22);    
  TCCR2 &= ~((1<<CS21) | (1<<CS20));     
  // Use normal mode
  TCCR2 &= ~((1<<WGM21) | (1<<WGM20));  
  // Use internal clock - external clock not used in Arduino
  ASSR |= (0<<AS2);
  //Timer2 Overflow Interrupt Enable
  TIMSK |= (1<<TOIE2) | (0<<OCIE2);  
  RESET_TIMER2;               
  sei();
  starttime = millis();
}

void loop() {
  if (oldSecond != second) {
    Serial.print(second);
    Serial.print(". ->");
    Serial.print(millis() - starttime);
    Serial.println(".");
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    oldSecond = second;
  }
}
Za pravopisné chyby v této zprávě může moje učitelka češtiny.

MartinL
Příspěvky: 114
Registrován: 24 úno 2013, 14:13

Re: Timer 2 a přerušení

Příspěvek od MartinL » 29 led 2018, 18:18

Já osobně to používám, tak jak navrhuješ ty. Funguje to bez problémů. Důvod, proč to autor dělá tak, jak to dělá může být různý. Třeba to jinak neumí, nechce se mu studovat datasheet (a tedy využít možností toho čítače), atd ...

Uživatelský avatar
fulda
Příspěvky: 521
Registrován: 04 led 2016, 17:18

Re: Timer 2 a přerušení

Příspěvek od fulda » 04 úno 2018, 21:11

Ahoj,

Mám tady jedno ochutnávkové VIDEO mého tajného projektu Klíčenka-uíno.

Není to nic světového, jen Arduino Nano, které má na sobě 56 LEDek zapojených do charlieplexingu.
Vlastně je to taková hračka na cesty, kdy si nemůžete vzít celého robota, ale můžete si vzít počítač a něco malého.

Chtěl bych k tomu udělat nějakou knihovnu a pár příkladů.

Zatím je to tak, že mám "video ram" = 7 bajtů globální proměnná. Co se do ní zapíše, to se zobrazuje. Asi bych k tomu mohl přibalit pár málo užitečných funkcí, jako smazat obrazovku, nakreslit bod a smazat bod.

A nakonec ještě dvě až tři hry jako arkanoid, had a autíčko.

Otázka je, kolik toho balit do knihovny a kolik toho nechat venku? Jak vlastně pojmout ty ukázkové programy?

Jindra
Za pravopisné chyby v této zprávě může moje učitelka češtiny.

Uživatelský avatar
fulda
Příspěvky: 521
Registrován: 04 led 2016, 17:18

Re: Timer 2 a přerušení

Příspěvek od fulda » 08 úno 2018, 14:42

Trochu si ujasňuji, jak má vypadat knihovna pro mou hračku. Úplně přesně si nejsem jistý, jak v Arduinu přistupovat ke statické knihovně. Všichni mluví o objektové, ale ta se mi úplně moc nehodí.

Abych popsal situaci - používám přerušení od Timer 2, v rámci ISR pracuji s kusem paměti, kterému říkám video ram (ano, je to 7 bajtů). Celkem logicky ISR nelze zabalit do objektu. Tím pádem bych tu video ram také chtěl definovat globálně a do objektu si dám jen pointer na ní.

Zatím mám takovou představu, že bych si definoval pseudo objekt a ISR nechal mimo. Zhruba takhle:

Kód: Vybrat vše

#ifndef Zobrazovac_h
#define Zobrazovac_h

class Zobrazovac
{
   public:
     Zobrazovac(int cas);
     void dot(int x,y);
     void cleardot(int x,y);
     byte myvideo[7];
};

#endif

Kód: Vybrat vše

byte video[7] = {0,1,2,3,4,5,6}

ISR(TIMER2_COMPA_vect) {
  int_counter += 1;
  }
  
Zobrazovac::Zobrazovac(int cas);
{
  myvideo=video;
}
Pro pobavení přikládám obrázky.
Přílohy
klicenka_uino_A.jpg
klicenka_uino_B.jpg
Za pravopisné chyby v této zprávě může moje učitelka češtiny.

DavidO
Příspěvky: 428
Registrován: 01 kvě 2013, 21:27

Re: Timer 2 a přerušení

Příspěvek od DavidO » 08 úno 2018, 18:46

To je teda tekovej Singleton, jestli tomu dobře rozumím. Ale na těch malých kontrolerech (notabene na Arduinu) obvykle nic není úplně metodicky, takže bych to zas tak moc asi neřešil, ostatně kdyby uživatel tu knihovnu použil (kolik jich bude ;-)) a navíc vytvořil víc instancí, tak by to byla spíš jeho blbost.

Asi bych se nebál udělat to tak, že v .h knihovny budou protoypy funkcí dot, cleardot volně loženbé (bez třídy) a v .cpp bude kromě jejich těl i nadeklarované to pole jako globální proměnná, ale nebude v .h a tedy nebude vidět zvenku. Jestli pak potřebuješ z ISR sahat na něco "privátního" (třeba to pole), tak buď napsat ISR do .cpp, nebo ISR nechat jinde a tam si buď přihodit odkaz na extern pole, anebo si na to napiš funkci, kterou buď zveřejníš stejně jako jiné v .h, anebo tam, kde bude ISR, si explicitně "ručně" napsat její prototyp. Anebo udělat druhé .h pro privátní použití.

Jestli to chceš mít jako standardní třídu, tak zřejmě řešíš problém přístupu z ISR do member dat třídy? Když by se video ram udělala jako static member, tak ho budou sdílet všechny instance, čili můžeš si instancí udělat kolik chceš a furt to tam bude 1x, ale asi to nebude úplně hezký pro přístup z ISR kde to chceš mít co nejrychlejc hotový (např. že by sis udělal jednu globální instanci pro účely ISR a z ISR na to sahal normálně přes member funkce - i když možná že by to kompilátor správně odhalil a přístup by nakonec byl efektivní)
Jo a myvideo by spíš měl být pointr, aby se zbytečně nealokovalo to pole v objektu.

Uživatelský avatar
gilhad
Příspěvky: 139
Registrován: 29 kvě 2015, 00:36

Re: Timer 2 a přerušení

Příspěvek od gilhad » 09 úno 2018, 03:37

Rekl bych, ze ty LEDky na "klicence" jsou taky singletony, takze reprezentovat je jako singleton dava docela rozumny smysl.

Z te tridy bych bud uplne vyhodil ten clen "myvideo", nebo ho udelal jako pointer a v konstruktoru nastavil na tu globalni promennou "byte video[7]" (pak by se dala odvodit debugovaci trida, co by psala jinam, nebo extenderova trida, co by psala jinam prez nejaky rozsirovaci port a tak podobne a vsechny by mohly pouzivat uz napsane funkce (nebo si je upravit).

Ale pokud na to "byte video[7]" chces sahat jak z prerucseni, tak z programu, tak by rozhodne melo byt "volatile byte video[7]", jinak ti to muze kompilator nevhodne zoptimalizovat do nepouzitelna. "volatile" tomu rika, ze se to muze menit "samo" i mimo poradi, takze pred kazdym pouzitim hodnoty je potreba tu hodnotu znova precist (protoze ji mezitim mohl ten interrupt zmenit)

Kód: Vybrat vše

*myvideo[1]=0;
delay(1000);
if (*myvideo[1]!=0) { 
   // tohle by kompilator vyhodil, protoze prece "vi", ze to je nula, protoze je to posledni hodnota, kterou tam nacpal
   // takze se to musi dat "volatile" coz ho prinuti to pred testem znovu nacist a test skutecne provest (a tudiz se zmeny z interruptu skutecne projevi)
}

aladin
Příspěvky: 136
Registrován: 12 kvě 2013, 06:43

Re: Timer 2 a přerušení

Příspěvek od aladin » 19 úno 2018, 10:44

dotaz - co znamená hvězdička před proměnnou?
*myvideo[1]
MerkurRobot.cz
KlubTechniku.cz
Stavebnice.com

DavidO
Příspěvky: 428
Registrován: 01 kvě 2013, 21:27

Re: Timer 2 a přerušení

Příspěvek od DavidO » 19 úno 2018, 12:23

Hvězdička před proměnnou znamená dereferenci pointru, neboli když je proměnná ukazatel, tak *proměnná je to, na co ten ukazatel ukazuje.
Ale v tomhle případě to zřejmě bude chyba, protože takhle jak to je použité by to pole muselo být deklarované jako pole pointrů na byte, aby to typově bylo v pořádku. Pokud to měl být pointr na pole bytů, tak by se to v deklaraci muselo napsat byte (*myvideo)[7]; a pak použilo např. if( (*myvideo)[1] == 15), tj. správně uzávorkované kvůli vyšší prioritě [] než *.

Uživatelský avatar
gilhad
Příspěvky: 139
Registrován: 29 kvě 2015, 00:36

Re: Timer 2 a přerušení

Příspěvek od gilhad » 19 úno 2018, 17:50

Presne tak, psal jsem to z hlavy a moc to nepouzivam.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host