Atmaga 16 in C

ik heb een klein programma geschreven om een instelbare pulstrein te kunnen maken, zowel de freg. en de pulslengte.
scoop er aan en alles werkt zoals verwacht, totdat ik sneller wil als ca. 16 kHz. dan word het scoopbeeld "wazig".
scoop is goed, dit heb ik gechekt met een functie generator.
bij testen geen belasting op de PIN enkel de scoop.

verder valt mij nog iets raars op:
als ik b.v. freq. = 80 en length = 40, klopt het op de scoop exact:
doe ik 80 & 60 dan zie ik op de scoop 80 & 50 ik verwacht dutycycle 75%
doe ik 80 & 20 dan zie ik op de scoop 80 & 30 ik verwacht dutycycle 25%

alvast vriendelijk bedankt voor de reacties.

#define F_CPU 1000000UL // 1 MHz int osc
#include <avr/io.h>
#include <avr/interrupt.h>


int main(void)
{
	DDRA = 0b11111111;
	DDRC = 0b11111111;
	DDRD = 0b11111111;

	sei();
	
	TCCR1B |= 1<<WGM12; // CTC (mode 4)
	TCCR1B |= 1<<CS10; // | 1<<CS11; // prescaler = 1
	TIMSK |= 1<<OCIE1A | 1<<OCIE1B; // Timer/Counter1 Output Compare A&B match interrupt is enabled
	
	while(1)
	{
		{
			OCR1A = 80; // frequentie v/d pulstrein
			OCR1B = 20; // pulslengte v/d pulstrein
		}
				
	}

	return 0;
}

ISR(TIMER1_COMPA_vect) // frequentie v/d pulstrein
{
	PORTA |= (1 << PINA1); // maakt A.1 hoog
}

ISR(TIMER1_COMPB_vect) // pulslengte v/d pulstrein
{
	PORTA &= ~(1 << PINA1); // maakt A.1 laag
}

Ik denk dat je ongeveer 80 CPU-klokperioden kwijt bent aan je interrupt-afhandeling. Daarom kun je geen hogere frequentie.

En daarom vervormd je duty-cycle ook: De compare-B interrupt komt al terwijl de CPU nog in de compare-A interrupt zit.

Je kunt iets winnen door je ISR's in assembly te maken, maar het meeste win je door geen interupt te gebruiken maar alles vanuit main() te doen.


while(1) {
  while(counter < 20) {
     output =  hoog;
  }
  while(counter < 80) {
     output = laag;
  }
}

Een nog beter alternatief is om de timer-hardware het zelf te laten doen, maar dan zit je vast aan specifieke pinnen (iedere timer kan een of twee pinnen autonoom besturen, maar dat zijn vaste pinnen).
Kijk naar de COMnAx registers.

Nu ken ik de peripherals van deze controller niet, maar er vallen mij wel een paar dingen op.

Het lijkt of je twee timer compare interrupts gebruikt. Een on de pin hoog te maken en een om de pin laag te maken. Moet je bij één van die events niet aangeven dat je ook de timer wilt clearen? Of zit dat al in de peripheral?

Verder schrijf je continu de ocr registers. Zit daar wellicht een mechanisme achter die er voor zorgt dat je een interrupt kan missen? En of andere load logica... Meestal doe je dat herladen in een van je interrupts.

verdorie blurp, ik denk dat je gelijk hebt, ga dat eens beter bekijken, bedankt

Met een trage clock (1MHz) en veel overhead bij iedere interrupt ga je inderdaad niet tot een hoge frequentie komen.

Zit je vast aan PINA1? Zoniet dan kun je de waveform generator gebruiken, en dan gaat alles in hardware, zonder interrupts. Dan komt het signaal naar buiten op OC1B (PD4). Dat gaat wel een stuk sneller.

ja niet alleen aan die ene pin, maar ik moet straks die pulstrein op 16 pinnen beschikbaar hebben.
ik denk dat ik de clockfreq. 1 stap omhoog doe, ik moet een pulstrein van 36 kHz hebben.

Dan kun je de interrupts beter vergeten. De methode van blurp geeft dan meer kans op succes.

Moeten alle pulsen volledig onafhankelijk van elkaar ingesteld kunnen worden?

Met 16 kanalen moet je inderdaad wel een wat snellere interne klok hebben. (1MHz is wel erg weinig, dat hadden de 804x mcu's 40 jaar geleden al... ;) )
Met een PIC24 doe ik 10kHz pwm op 24 kanalen zonder probleem. (kan sneller maar heb ik niet nodig)
(wel met zelfde samplerate voor alle kanalen, alleen andere duty-cycle. Als je ook verschillende samplerates nodig hebt wordt 't dedicated hardware...)

Moet je per-se op de internet 1M clk lopen? Als je bv naar 16M kunt heb je al heel veel gewonnen.

De meeste avr's hebben een calibreerbare rc generatot die tot 8MHz gaat, voor een pulstrain van 38kHz (IR afst. bed.) heb je dan een puls en pauze tijd van 111 counts en dat gaat inderdaad rechtstreeks met de counter op de uitgangspin in CTC mode, hoef je niets aan te doen dan in je interrupt een tellertje bijhouden of je op 111 bent, of nul als je afteld, en daar heb je dan 111 cnts de tijd voor.

edit: 111cnts is voor 36kHz, 105cnts is voor 38kHz

.

[Bericht gewijzigd door trix op (100%)]

Op 10 maart 2019 13:28:23 schreef deKees:
Moeten alle pulsen volledig onafhankelijk van elkaar ingesteld kunnen worden?

nee het is een en dezelfde pulstrein voor alle pinnen.

??? Dan heb je toch niet meer dan 1 pin nodig ??? :?

Lijkt mij toch ook... ;) (16 pinnen met hetzelfde signaal heeft weinig zin)
Als je meer 'power' nodig hebt, kun je er een driver als de BD6210F achter hangen, die kan 2A leveren push-pull tot 100kHz...

[Bericht gewijzigd door Arco op (46%)]

de pinnen worden 1 voor 1 aan gestuurd, als een soort looplicht.

wat ik hier post is eigenlijk om te testen, het is nog niet zeker of ik dit ook uiteindelijk zo ga uitvoeren. dit omdat de kosten een belangrijk item zijn (300 leds). ik heb de testen tot nu toe uitgevoerd met een functie generator.