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í 

Atmega8 - nezávislá sekvence pípání

 
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
Nikeed12



Založen: Sep 11, 2014
Příspěvky: 45

PříspěvekZaslal: ne únor 07 2016, 20:57    Předmět: Atmega8 - nezávislá sekvence pípání Citovat

Dobrý den, neví někdo jak docílit při stisku tlačítka k nule (při log. 0) sekvenci pípání, která by běžela paralelně s hlavní smyčkou programu a neovlivňovala jeho chod?
Zkoušel jsem vytvořit funkci a tu poté volat v přetečení časovače s podmínkou stisknuteho tlačítka, bohužel během doby kdy bylo tlačítko zmacknuto tak hlavní smyčka byla ve stopu, dále jsem zkusil vytvořit sekvenci pipani přímo v přerušení od časovače a pomocí externího přerušení zapnout časovač a tím i pipani, ale nepodařilo se mi časovač ukončit a když jo tak v nejistém stavu (log výstup 1 nebo 0).

Jinak sekvenci pipani mám na mysli cyklus:
Zapni
Počkej 100ms
Vypni
Počkej 100ms

Výstup je přes tranzistor na 12v sirénku.

A musí být vyvolaná okamžitě a zároveň okamžitě ukončena (nejpozději do cca 50ms od stisknutí nebo puštění tlačítka).
Nemohl by mě někdo nakopnout jak to zrealizovat?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zaky



Založen: Oct 30, 2010
Příspěvky: 6609
Bydliště: Praha

PříspěvekZaslal: ne únor 07 2016, 22:11    Předmět: Citovat

50 ms je z hlediska běhu programu spousta času. ještě nám řekni, co ještě a jak časově kriticky musí procesor ještě kromě zvukové sekvence stíhat?
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Nikeed12



Založen: Sep 11, 2014
Příspěvky: 45

PříspěvekZaslal: ne únor 07 2016, 23:19    Předmět: Citovat

V závislosti na čase už teoreticky nic, jen reakce na tlačítka, spínání výstupů relatek a nějaké úkony ihned po zapnutí (zpožděne sepnutí navolenych výstupu, které se uložily do eeprom před vypnutím zařízení)
Ale jak jsem psal, tlačítka a výstupy musí být v provozu, pokud bude v činosti zvuková sekvence a ta bude v provozu jen tehdy, pokud bude zmáčknuto tlačítko.
Jinak těch 50ms je maximum, které se dá tolerovat, samozřejmě čím rychleji to bude tím lépe.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mtajovsky



Založen: Sep 19, 2007
Příspěvky: 3697
Bydliště: Praha

PříspěvekZaslal: po únor 08 2016, 0:06    Předmět: Citovat

Musíte udělat událostí řízený automat. Zapomeňte na věci jako "počkej 100 ms", nebo "dokud je tlačítko stisknuté".

Je třeba určit, které události a stavy jsou důležité. Ve vašem případě na první pohled vidím události:
- stisk tlačítka
- uvolnění tlačítka
- vypršení časovače 100 ms

a stavy:
- pípnutí zapnuto
- pípnutí vypnuto

V hlavní smyčce je nutno detekovat uvedené události a správně reagovat. Například:
- stisk tlačítka -> pípání se zapne, stav se nastaví do "pípání zapnuto", odstartuje se časovač 100 ms a poznačí se stav tlačítka

- časovač 100 ms vypršel -> je-li stav "pípání zapnuto", pak jej vypni, jinak jej zapni. Poznač nový stav a restartuj časovač.

- tlačítko uvolněno -> vypnout pípání, zastavit časovač, poznačit stav tlačítka

V ideálním případě je třeba vyřešit všechny kombinace možných událostí a možných stavů. Některé kombinace nebudou mít smysl - pak se nic nedělá, některé kombinace jsou chybové a značí chybu v naprogramování, například kdyby se zjistila událost vypršení časovače při uvolněném tlačítku, protože při jeho uvolnění časovač zastavujeme.

Základní zásadou je odstranit veškeré čekací smyčky vyjma těch mikrosekundových, které se používají třeba při řízení LCD. Čekací smyčky jsou povolené jen v inicializační fázi programu, ale po odstartování hlavní smyčky, která detekuje události, už se nesmí používat.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
Nikeed12



Založen: Sep 11, 2014
Příspěvky: 45

PříspěvekZaslal: po únor 08 2016, 0:32    Předmět: Citovat

Čekací smyčku jsem měl vytvořenou jako funkci, ve které jsem využíval časovač, určitě jsem nepoužíval _delay_ms(100)

Každopádně díky za odpověď, pokusím se tím řídit a snad to nějak dám dohromady.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zaky



Založen: Oct 30, 2010
Příspěvky: 6609
Bydliště: Praha

PříspěvekZaslal: po únor 08 2016, 9:04    Předmět: Citovat

Přistoupil bych k tomu poněkud jednodušeji. Spustil bych si timer s periodou třeba 5 ms aby při přetečení vyvolat přerušení (a znovu se spustil). V přerušení bych nastavil příznak a ten bych testoval a nuloval v hlavní smyčce. Tím máš zajištěno časování smyčky bez čekání. 100ms pak uděláš tak, že si budeš v každém 5 ms proběhu inkrementovat proměnnou a testovat, zda má hodnotu 20, pak ji vynuluješ a provedeš 100 ms operaci, tedy negaci brány s pískadlem. A mezi tím máš těch 20 protočení na ostatní akce, podmínkou je, že proběh smyčky nesmí trvat déle, než těch 5 ms, což je ale několik tisíc instrukcí, takže pro jednoduché programy je toto v pohodě použitelné. Není problém časovat takto cokoli, těch pomocných čítačů můžeš mít mnoho. Omezením je, že doba nejmenšího časového kroku (těch 5 ms) musí být proti vyžadované odezvě systému zanedbatelně krátká, tedy pro rychlejší a rychlejší odezvu máš k dispozici méně a méně času pro protočení, až se to přestane stíhat a je nutno použít jiný (složitejší) přístup, viz. příspěvek výše. Dobrý program je tzv. propustný, tedy nikde nečeká, běhá jen dopředu, zanedbatelně krátké cykly jsou samozřejmě možné.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Nikeed12



Založen: Sep 11, 2014
Příspěvky: 45

PříspěvekZaslal: po únor 08 2016, 10:33    Předmět: Citovat

tak už jsem to nějak spatlal dohromady, funguje to, ale když zmáčknu tlačítko příliš rychle jen na zlomek sekundy, tak se funkce jakdyby invertuje a pípací sekvence je spuštěna, když je tlačítko rozpojeno a při zmáčknutí sirénka utichne. Zkusím si s tím ješte pohrát

kód:

/*
 * Relay_power_system.c
 *
 * Created: 07.01.2016 11:13:24
 *  Author: Patrik
 */

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#define F_CPU 1000000

#define rel1 1 //+5V
#define rel2 2 //+12V
#define rel3 4 //zdroj A
#define rel4 8 //zdroj B
#define rel5 16 //A+B

#define BUZZ 32 //piezo

volatile unsigned int rezim=0;
volatile unsigned int i;
volatile unsigned int tl;  //promněnná tlačítko


ISR (TIMER0_OVF_vect) //přerušení od časovače každou 1ms
{
   
 TCNT0 = 131; //začátek počítání
 i++; 
 

 
  if (tl==1 && i==100) //pokud bylo tlačítko stisknuto a uběhlo 100ms
  {
  PORTC ^= (BUZZ);
  i=0;
  } 
 
  if (tl==0 || tl==2)  //pokud je tlačítko puštěno, nebo ješte nebylo stiknuto
  {
     tl=0;
     i=0;
     PORTC &= ~ (BUZZ);     //vypni sirenu
     TIMSK &= ~(1 << TOIE0); //zakaž povolení pro časovač
    
    
  } 
   
 

 }
 


ISR (INT0_vect)   //externí přerušení od INT0
{
   if (tl==0)
   {
      tl++;
   TIMSK |= (1 << TOIE0); //povol časovač
   
   }
   else
   {
      tl=0;
      
   }
   
   
}





void test (void)
{
       PORTC |= rel1; // zapni relé 1
      _delay_ms(500);
      PORTC |= rel2; // zapni relé 2
      _delay_ms(500);
      PORTC |= rel3; // zapni relé 3
      _delay_ms(500);
      PORTC |= rel4; // zapni relé 4
      _delay_ms(500);
      PORTC |= rel5; // zapni relé 5
      _delay_ms(500);
      
      PORTC &= ~ ((rel1) | (rel2) | (rel3) | (rel4) | (rel5)); // vypni relé 1 až 5
      _delay_ms(500);
      



int main(void)
{
   
   DDRC |= (1 << PC0) | (1 << PC1) | (1 << PC2) | (1 << PC3) | (1 << PC4) | (1 << PC5); //Piny PC0 až PC5 jako výstupní (log 1)
   DDRD &= ~(1 << PD2) | (1 << PD3); //piny PD0 až PD4 jako vstupní (log 0)
   DDRB &= ~(1 << PB4) | (1 << PB5); //PB jako vstupní (log 0)
   PORTD |= (1 << PD2) | (1 << PD3); //pull-up na PD2,3 jako vstupní (log 1)
   PORTB |= (1 << PB4) | (1 << PB5); //pull-up na PB5 jako vstupní (log 1)
   
   GICR |= (1 << INT0); // povolení od přerušení od INT0
   MCUCR |= (1 << ISC00) ;
   
   TCCR0 |= (1 << CS01); // preddelicka /8
    //TIMSK |= (1 << TOIE0);  // přerušení po přetečení TCNT0
   TIMSK &= ~(1 << TOIE0); //zakazani přerušení

    sei(); //povol globální přerušení
   
    while(1)
    {
      test();
      
   }
         
      
    }

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



Založen: Nov 23, 2009
Příspěvky: 312

PříspěvekZaslal: po únor 08 2016, 11:43    Předmět: Citovat

Můžeš to řešit jednoduše tak, že nastavíš některý čítač tak aby vyvolal přerušení každých 10 ms.

V ISR pak počítáš přerušení a testuješ tlačítko. Pokud je sepnuté,
tak při každém desátém přerušení invertuješ výstup.

Edit:
kód:
DDRD &= ~(1 << PD2) | (1 << PD3);
Tady máš málo závorek.
Správné je
kód:
DDRD &= ~((1 << PD2) | (1 << PD3));


Naposledy upravil AB1 dne po únor 08 2016, 12:41, celkově upraveno 1 krát.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zaky



Založen: Oct 30, 2010
Příspěvky: 6609
Bydliště: Praha

PříspěvekZaslal: po únor 08 2016, 12:34    Předmět: Citovat

Při puštěném tlačítku zapisuj do brány pro sirénu stav pro vypnutou sirénu a ne negaci předchozího.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Nikeed12



Založen: Sep 11, 2014
Příspěvky: 45

PříspěvekZaslal: po únor 08 2016, 17:08    Předmět: Citovat

Tak jsem tedy uplně vynechal externí přerušení a vše obsluhuji jen v přerušení časovače dle vašich rad a funguje to výtečně Smile díky za rady a za pomoc Wink

kód:

ISR (TIMER0_OVF_vect) //přerušení od časovače každou 1ms
{

 TCNT0 = 131; //začátek počítání
 i++; 
 
  if (bit_is_clear(PIND,2)) //pokud bylo tlačítko stisknuto
  {
     if (i==100)         //uběhlo 100ms
     {
            PORTC ^= (BUZZ);
       i=0;
     }     
  }
 else
 {
   PORTC &= ~ (BUZZ);
 }
 if (i==101)
 {
   PORTC &= ~ (BUZZ);
   i=0;
 }
}
 
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
frpr666



Založen: Dec 28, 2009
Příspěvky: 1051

PříspěvekZaslal: po únor 08 2016, 17:59    Předmět: Citovat

Mě se osvědčilo "vyrobit" si jehlové časové impulsy a ty pak používat v hlavní smyčce.
kód:

ISR (TIMER0_OVF_vect)
{
  tictac++;
}


loop()
{
  //
  time = tictac;
  time_ip = ~time & time_hf; // zde jsou jehlove impulsy
  time_hf = time; // pomocna promenna

  if (bit_is_set(time_ip,0))
  {
    // tato akce se provede jednou za 1ms
  }

  if (bit_is_set(time_ip,1))
  {
    // tato akce se provede jednou za 2ms
  } 

  if (bit_is_set(time_ip,2))
  {
    // tato akce se provede jednou za 4ms
  }   
}
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mtajovsky



Založen: Sep 19, 2007
Příspěvky: 3697
Bydliště: Praha

PříspěvekZaslal: po únor 08 2016, 22:30    Předmět: Citovat

Nikeed12 napsal(a):
Tak jsem tedy uplně vynechal externí přerušení a vše obsluhuji jen v přerušení časovače ...[/code]
V takto jednoduchém případě to jde, ale pokud by bylo více událostí, které je třeba zpracovat, bude potřeba zvolit obecnější přístup, který jsem popsal výše. To znamená například v přerušení od časovače jen vygenerovat událost a časovač restartovat. V přerušovací rutině se ze zásady má vykonat jen to nejnutnější a složitější zpracování dělat v hlavní smyčce, protože přerušovací rutina má defaultně zamaskované přerušení. Povolování přerušení v přerušovací rutině je obecně choulostivé a je třeba dávat dobrý pozor na integritu dat.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Odeslat e-mail
rob_brno



Založen: Oct 12, 2012
Příspěvky: 209

PříspěvekZaslal: út únor 09 2016, 7:59    Předmět: Citovat

frpr666:
Mám podobnou filozofii, ale místo testování bitů(možná jsem tvůj kod úplně nepochopil) dělám modulo hodnotou počtu msec, takže nejsem omezen jen na násobky dvou, ale libovolně.
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.22 sekund