2x interrupt werkt niet

Nee, er zijn een minimum aantal nodig voor de detector en dat kan hij terugvinden in de datasheet, hieronder een screenshot.

LDmicro user.
trix

Golden Member

ik ga de led/ontvanger als een licht sluis gebruiken.

eigenwijs = ook wijs
Arco

Special Member

Dan moet je de lengte van de burst meten; losse pulsen tellen gaat niet.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
trix

Golden Member

daar ben ik weer,
ik dacht dat ik aan de hand v/d tip van MGP de oplossing zou hebben, maar dat valt nogal tegen.
er gebeurt iets wat ik niet goed kan verklaren, ik heb de code terug gebracht tot het meest essentielen.

wat begrijp ik niet:
wanneer ik de beperking: & (khz_train_counter < 900) weglaat heb ik een mooie 38 kHz puls.
en wanneer ik deze toevoeg gaat de puls varieren tussen de 36 en de 41 kHz.

c code:


#define F_CPU 8000000UL // 8 MHz clock speed

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

int khz_train = 0;
int khz_train_counter = 0;


	ISR(TIMER1_COMPA_vect) // 38 khz
	{
		khz_train = 1;
		
		khz_train_counter = khz_train_counter +1;
	}
	
	ISR(TIMER1_COMPB_vect) // 38 khz
	{
		khz_train = 0;		
	}

int main(void)
{

	DDRD = 0b10110000;

	sei();
		
		TCCR1B |= (1 << WGM12); // CTC-mode,
		TCCR1B |= (1 << CS10); // start timer with prescaler = 0
		TIMSK |= (1 << OCIE1A) | (1 << OCIE1B) ; // timer1 A & B compare match interrupt enabled
			
		OCR1A = 209;
		OCR1B = 100;
			
		for(;;)
		{				
			
			if ((khz_train == 1) & (khz_train_counter > 750) & (khz_train_counter < 900))
			{PORTD &= ~(1 << PIND5);} else {PORTD |= (1 << PIND5);} // led aan/uit										
										
		}
}
eigenwijs = ook wijs

De variabele khz_train_counter wordt nergens op 0 gezet, deze telt altijd maar door?

LDmicro user.

Als je wilt testen op conditities dan moet je dubbele & gebruiken.

Als in

code:


if ((khz_train == 1) & (khz_train_counter > 750) & (khz_train_counter < 900))

Moet zijn

code:


if ((khz_train == 1) && (khz_train_counter > 750) && (khz_train_counter < 900))

Dat geeft subtiele verschillen.
'&' doet een bit-wise en-funktie. Waarbij de drie getallen elk als integer worden gebruikt.

'&&' is een boolean en-funktie die de drie variabelen elk afzonderlijk als true/false beschouwt.

En 'khz_train_counter' is nu een int die nooit wordt gereset. Dus die loopt van 0 naar 36767, dan naar -36768 naar 0 enz.

trix

Golden Member

Op 29 maart 2020 11:24:57 schreef MGP:
De variabele khz_train_counter wordt nergens op 0 gezet, deze telt altijd maar door?

klopt, maar die gaat weer naar 0 op het eind.

niet dus ikhad de post van dekees nog niet gelezen.

heb ik nu uint16_t khz_train_counter = 0; van gemaakt, is dat correct ?

hoera!!! :) het zat hem in de dubbele && nu blijft de freq. wel mooi op 38 kHz wanneer ik gebruik maak v/d limieten 750 & 900.
het ergste is dat ik dat eigenlijk wel een beetje wist, met de of funcie doe ik dat we dubbel (||).
en als hij het dan "gewoon" helemaal niet doet...dan vind je dat wel....nee....het geeft "subtiele" afwijkingen.

eigenwijs = ook wijs
trix

Golden Member

dit bovenstaande was natuurlijk voor 1 LED. nu wil ik een 2e toevoegen, maar dan wijkt de freq. weer enorm af. word zo toegevoegd:

c code:


if ((khz_train == 1) && (khz_train_counter > 600) && (khz_train_counter < 750))
{PORTD &= ~(1 << PIND4);} else {PORTD |= (1 << PIND4);} // led aan/uit
		
if ((khz_train == 1) && (khz_train_counter > 750) && (khz_train_counter < 900))
{PORTD &= ~(1 << PIND5);} else {PORTD |= (1 << PIND5);} // led aan/uit

[Bericht gewijzigd door trix op 29 maart 2020 12:13:03 (100%)

eigenwijs = ook wijs

Ik ben bang dat je wat te veel vraagt van de processor.

Die loopt nu op 8 MHz. Dan heb je 210 cpu cycles binnen de tijd van een pulse. En binnen die tijd wil je 2 interrupts afhandelen en een stukje main loop laten lopen.

Interrupts geven nogal veel overhead.
Ik zou eens proberen met een kristal van 16MHz.

trix

Golden Member

dat word een probleem, omdat de hardware al min of meer bepaald is. ik gebruik ook uart (RS 485) die met 2 andere atmega's werkt, en die hebben ook een 8 MHz X-tal.
die 2 led's worden er uiteindelijk 24. zou dan 16 MHz wel voldoen ?

is er een andere manier om het geen ik wil voor elkaar te krijgen ?

eigenwijs = ook wijs

Zoals ik eerder al geschreven heb, vermijd het tellen of vergelijken van de 38khz pulsen.
Naarmate uw programma groter wordt heb je veel kans dat deze niet meer gevolgd kunnen worden.

Toggle 1 pin van uw controller binnen de ISR en gebruik dat signaal om alle leds aan te sturen, je kunt ook de ingebouwde hardware pwm gebruiken.

Als je dat doet moet je nooit meer denken aan de lengte van het programma.
Zie bijlage hoe het kan, hou er rekening mee dat PORTB dan invers werkt, tenzij je nog een NPN erachter plaatst.

LDmicro user.
trix

Golden Member

ja, dat klopt, dat zal inderdaad wel werken, maar dat vergt een hardware aanpassing.
ik zat zelf ook al te denken aan een externe 38kHz bron en die dan te AND-en met de outputs.

maar die 24 LED's aansturen is het enige wat hij hoeft te doen, meer niet, nou ja vooruit, wellicht nog een "i'm alife" LED. dus die code worde echt niet langer of korter.

eigenwijs = ook wijs

Je kunt ook een externe frequentie aan de transistor verbinden anders moet je nog een AND-ic bijplaatsen.

Je bent eigenlijk verkeerd begonnen maar je hebt veel bijgeleerd en dat is onbetaalbaar ;)

Maar dan nog versta ik niet hoe de rest zal verlopen, ik geraak er nog niet aan uit, vooral uw tekening met die pulstrein, led1, led2 enz...
Maar dat is voor later.

LDmicro user.
trix

Golden Member

dat is het zeker, (dat bij geleerd)

ik ben nu bezig om in de normal-mode een pulse trein te maken. dan geen interrupts nodig.

LED's hangen trouwens rechtstreeks aan de output PIN.

[Bericht gewijzigd door trix op 29 maart 2020 14:00:43 (18%)

eigenwijs = ook wijs

Ander kristal zou geen probleem moeten zijn. Dan krijg je wel een ander getal in het baudrate register maar dan kunnen de processors best wel met elkaar communiceren.

Je kunt proberen om met een minimum aan instrukties te werken.

Probeer het zo eens:

code:


#define F_CPU 8000000UL // 8 MHz clock speed

#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

uint8_t PulseCounter = 150;
uint8_t BitCounter   = 0;

uint8_t CopyPortD = 0;


ISR(TIMER1_COMPA_vect) // 38 khz
{
   if(PulseCounter == 0)
   {  PulseCounter = 150;

      switch(BitCounter++)
      {  case   0: CopyPortD = (1 << PIND4); break;
         case   1: CopyPortD = (1 << PIND5); break;
         case   2: CopyPortD = (1 << PIND7); break;
         default : BitCounter = 0;
      }
   }
   else
   {  PulseCounter -= 1;
   }
   PORTD |= CopyPortD;
}

ISR(TIMER1_COMPB_vect) // 38 khz
{
   PORTD &= ~CopyPortD;
}

int main(void)
{
   DDRD = (1 << PIND4)
        | (1 << PIND5)
        | (1 << PIND7);

   TCCR1B |= (1 << WGM12); // CTC-mode,
   TCCR1B |= (1 << CS10); // start timer with prescaler = 0

   TIMSK  |= (1 << OCIE1A)
           | (1 << OCIE1B) ; // timer1 A & B compare match interrupt enabled

   OCR1A = 209;
   OCR1B = 100;

   sei();

   for(;;)
   {
   }
}
trix

Golden Member

ha,..dat gaat een stuk beter, ik heb de case's even uitgebreid naar 8, en het blijft keurig rond de 38 kHz.

even wachten dan post ik een printscreen v/d LA.
ik heb 2 monitoren in gebruik, vandaar deze printscreen, zie je meteen ook de code.
onderin de LA zie je de outputs D4, D5 en D7. (niet D6 dus vandaar dat gat)

[Bericht gewijzigd door trix op 29 maart 2020 14:37:27 (13%)

eigenwijs = ook wijs
trix

Golden Member

dat is nou het verschil tussen recht toe en recht aan programmeren, en efficient programeren.
ik ga straks de code even goed doorgronden, ik moet nog wat wijzigen, zo'n groot blok komt nu om de 35mS en dat moet 4 mS worden en ik moet het nog uitbreiden naar de 24 LED's.
dekees enorm bedankt voor de genome moeite.

eigenwijs = ook wijs

De truuk is dat de switch() maar 1 keer in de 150 interrupts wordt uitgevoerd. De andere 149 interrupts hoeven bijna geen instrukties uit te voeren en gaan dus snel.

Idd heel mooi gemaakt, zou ik niet meer kunnen, een dikke duim.

Waarschijnlijk zullen de programmaregels binnen de ISR nog heel wat uitgebreider worden als ik zijn doelstellingen goed begrijp maar ben nog niet zeker wat hij van plan is.

LDmicro user.
trix

Golden Member

dat moet inderdaad 24 LED's worden. maar als ik het goed heb begrepen heeft dat geen invloed op de timing.
maar meer gaat het ook niet worden (behalve een "i'm alive" LED)

[Bericht gewijzigd door trix op 29 maart 2020 15:35:42 (24%)

eigenwijs = ook wijs

Dus gaat er maar 1 led per poort oplichten? 2leds of meer tezelfdertijd per poort is niet nodig?

LDmicro user.
trix

Golden Member

van de 24 LED's licht er maar 1 op.

eigenwijs = ook wijs

Ok, dan heb je een mooie tool in handen.

LDmicro user.
trix

Golden Member

plaatje nog maar 1x plaatsen, dat wat de kees heeft gemaakt doet gewoon wat er in het plaatje staat, alleen moet ik dan nog uitbreiden van 8 naar 24 LED's.

hier tegen over komt zo'n zelfde constructie, nu echter met 24x ontvanger. die 1 voor 1 actief worden ook 4mS lang.
in die 4 mS detecteer ik dan of de ontvanger donker of licht is.
dit kun je scannen noemen, zo'n scan actie duurt dan 24x 4 mS = 96 mS
omdat het looplicht aan beide zijde even lang duurt (96 mS), hoef ik alleen maar te zorgen dat het start moment gelijk is, en die komt over de uart binnen (RS485), mocht er dan nog een klein verschil zijn in het startmoment dan kan je de snelste dus met een delay een beetje later laten starten.

eigenwijs = ook wijs

Dat is niet hoe je zoiets voorstelt, dat zijn 24 vast geklokte pulsen van 4mS die in serie verzonden worden en die aan de andere kant terug gedecodeerd worden.

Vandaar dat immense misverstand, maar het is toch goedgekomen.

In bijlage hoe het moest volgens mij.

edit: als je 24 zenders en 24 ontvangers hebt zullen ze mekaar niet mogen zien, want de ontvanger kan zo niet weten welke zender oplicht, maar we zullen ervan uitgaan dat dit via RS485 zal gaan.

[Bericht gewijzigd door MGP op 29 maart 2020 19:10:25 (27%)

LDmicro user.