Timer 2 a přerušení

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

Timer 2 a přerušení

Příspěvek od fulda »

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: 252
Registrován: 24 úno 2013, 14:13
Kontaktovat uživatele:

Re: Timer 2 a přerušení

Příspěvek od MartinL »

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: 1354
Registrován: 04 led 2016, 17:18

Re: Timer 2 a přerušení

Příspěvek od fulda »

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: 1354
Registrován: 04 led 2016, 17:18

Re: Timer 2 a přerušení

Příspěvek od fulda »

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: 1131
Registrován: 01 kvě 2013, 21:27

Re: Timer 2 a přerušení

Příspěvek od DavidO »

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.
Nikoho plánovaně neurážím. Jestli se Vám nelíbí co píšu, tak to nečtěte. A ostatně, třeba za to nemůžu - Researchers believe that dark humor can be a significant symptom of dementia.
Uživatelský avatar
gilhad
Příspěvky: 262
Registrován: 29 kvě 2015, 00:36
Kontaktovat uživatele:

Re: Timer 2 a přerušení

Příspěvek od gilhad »

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: 337
Registrován: 12 kvě 2013, 06:43

Re: Timer 2 a přerušení

Příspěvek od aladin »

dotaz - co znamená hvězdička před proměnnou?
*myvideo[1]
fischertip.cz, Stavebnice.com, MerkurRobot.cz, KlubTechniku.cz
DavidO
Příspěvky: 1131
Registrován: 01 kvě 2013, 21:27

Re: Timer 2 a přerušení

Příspěvek od DavidO »

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ž *.
Nikoho plánovaně neurážím. Jestli se Vám nelíbí co píšu, tak to nečtěte. A ostatně, třeba za to nemůžu - Researchers believe that dark humor can be a significant symptom of dementia.
Uživatelský avatar
gilhad
Příspěvky: 262
Registrován: 29 kvě 2015, 00:36
Kontaktovat uživatele:

Re: Timer 2 a přerušení

Příspěvek od gilhad »

Presne tak, psal jsem to z hlavy a moc to nepouzivam.
Uživatelský avatar
fulda
Příspěvky: 1354
Registrován: 04 led 2016, 17:18

Re: Timer 2 a přerušení

Příspěvek od fulda »

Něco pro Dexe: video
Za pravopisné chyby v této zprávě může moje učitelka češtiny.
Odpovědět