Stránka 3 z 3

Napsal: 22 dub 2017, 11:59
od FHonza
Pro přesné změření výstupní frekvence stačí okomentovat podmínku v přerušení komparátoru (přestane se pak generovat pauza):

Kód: Vybrat vše

...

ISR(TIM0_COMPA_vect)
{
   // if (pulse < pulsePercent)
   {

...


Otázkou je, jestli dolaďování má smysl. Frekvence je dána vztahem
fgener = fcpu / (2 × Presc × (1 + OCRA))
Presc je předdělička čítače a může být 1, 8, 64, 256 a 1024. Další "nejbližší" frekvence je pro (OCRA == 66) 3668.06 Hz, pro (OCRA == 64) to je 3780.92 Hz (Samotné přerušení se vykonává s dvojnásobnou frekvencí, proto je prescBr nastaven na 93: 7447.26 / 93 == 80.07). Tak jako v původním programu samozřejmě jde dodělat nastavování OCRA tlačítky.

Napsal: 22 dub 2017, 13:25
od lesana87
Proto je v tom původním programu použitá předdělička 1, aby to dolaďování smysl mělo.

Napsal: 22 dub 2017, 16:03
od FHonza
Lesana mě donutila dopočítat ty "nopy", čemuž sem se chtěl vyhnout :)

Mělo by to být takto:

Kód: Vybrat vše

#define F_CPU 3932160

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

volatile unsigned char setOCR0A  = 56;
volatile unsigned char counterBr = 0;
volatile unsigned char pulse = 0;

#define prescBr 83
#define pulsePercent 8 // delka pulzu v desitkach procentech

int i;

ISR (PCINT0_vect)
{   
   if ((PINB & (1 << PINB0)) == 0)
   {
      setOCR0A--;
   }
   if ((PINB & (1 << PINB1)) == 0)
   {
      setOCR0A++;
   }
}

ISR(TIM0_COMPA_vect)
{   
   GTCCR = (1 << TSM) | ( 1 << PSR0);     
   for (i = 0; i < 69; i++)
   {
      asm( "NOP");
   }   
   if (pulse < pulsePercent)
   {     
      PORTB ^= (1 << PINB2);
   }
         
   counterBr++;
   if (counterBr == prescBr)
   {
      counterBr = 0;
      PORTB ^= (1 << PINB1);
      pulse++;
      if (pulse > 9)
      {
    pulse = 0;
      }
   }
     
   TCNT0 = 0;
   OCR0A = setOCR0A;     
   GTCCR = 0;
}

void setup()
{
   DDRB = (1 << PINB2);   
   PORTB = (1 << PINB1) | (1 << PINB0);
     
   GTCCR = (1 << TSM) | (1 << PSR0); // zastaveni citace   
   TCCR0A = (1 << WGM01); // rezim CTC
   TCCR0B = (1 << CS00);
   OCR0A = setOCR0A;
   TIMSK |= (1 << OCIE0A); // preruseni
 
   PCMSK |= (1 << PCINT1) | (1 << PCINT0); // preruseni od tlacitek na PINB0 a PINB1
   GIMSK |= (1 << PCIE); // povoleni preruseni PCINT
   
   GTCCR = 0; // start citace (TSM nulovan)
     
   sei();
}

int main()
 {
   setup();
   while (1) ;   
   return 0;
 }


Předpokládá se že, je hardwarově ošetřen "debouncing" tlačítek. Se změnou frekvence se úměrně mění i frekvence "pauzy". Neměl sem to momentálně jak ověřit, je to čistá teorie. Tak to vyzkoušej a dej vědět.

Napsal: 25 dub 2017, 18:11
od jade
Bohužel na stisknutí tlačítek změnou frekvence nereaguje. :(

Napsal: 25 dub 2017, 20:56
od FHonza
Jak jsou zapojený ? Podle prvního programu jsem předpokládal že stisk příslušný pin přitáhne k zemi. A sedí frekvence ?

Napsal: 26 dub 2017, 19:37
od jade
Tlačítka jsou, jak říkáš. Piny 5 a 6 jsou spínány k zemi.
Pokud chci měřit frekvenci, tak musím vyřadit přerušování. Nepohne to s frekvencí?
Děkuji

Napsal: 27 dub 2017, 10:14
od FHonza
Pohne, ale minimálně. "Ozávorkuj" to takhle:

Kód: Vybrat vše

if (pulse < pulsePercent) 
{     
      asm( "NOP");
}
PORTB ^= (1 << PINB2);
 


Budu doma až v pondělí večer, pak to postavím a vyzkouším. Ať jenom neteoretizuju a konečně se to vyřeší.

Napsal: 04 kvě 2017, 22:06
od jade
Povedlo se? Taky teď mám poněkud méně času...
Prozatím jsem upravil původní program (pomocí navrhované sekvence ze začátku vlákna) a poněkud zdlouhavě, metodou pokus - omyl, došel k požadované frekvenci. Tlačítka fungují, snad by to mohlo zůstat tak?