Rutin för att blinka en LED i olika mönster

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Rutin för att blinka en LED i olika mönster

Inlägg av Korken »

Godagens!

Jag håller på och fixar med en laddare för batterier och har en LED som ska tala om hur det går för laddningen.
Dock jag kom till då jag ska skriva själva "blink" delen och funderade på hur man på bästa sätt löser detta.

Det jag ville göra var att kunna "blinka" i olika mönster, tex:
Snabb blink - Kort paus - Snabb blink - Lång paus (Repeat)
Lång blink - Kort paus - Snabb blink - Lång paus (Repeat)
osv...

(Kort = 100ms, Lång = 500ms)

Jag löste det med en timer som räknar upp en variabel med 160Hz och sedan bestämde jag hur det skulle fungera där ifrån.
Det jag funderar på är om det finns något enklare sätt att göra detta?

Kod på hur jag gör det nu:

Kod: Markera allt

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

void delay_100();
void delay_500();

volatile uint8_t cnt = 0;

int main(void)
{
	DDRB |= (1<<0);
	
	TCCR1 |= (1<<CTC1)|(1<<CS11)|(1<<CS13); 	//Timer1, CTC mode, 512 prescaler
	OCR1C = 98; 										// 8000000Hz / 512 / 98 = ~160Hz
	TIMSK = (1<<OCIE1A); 							//Compare interupt
	sei();

	while (1)
	{
		PORTB |= (1<<0);
		delay_100();
		PORTB &= ~(1<<0);
		delay_100();
	}
}

void delay_100()
{
	cnt = 0;
	while (cnt <= 16);
}

void delay_500()
{
	cnt = 0;
	while (cnt <= 80);
}

ISR(TIMER1_COMPA_vect)
{
   cnt++;
}
Senast redigerad av Korken 8 augusti 2010, 13:10:15, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Rutin för att blinka en LED i olika mönster

Inlägg av sodjan »

Det är väl en bra metod.
Man har an "bas-klocka" och sedan räknar man fram
olika tider som behövs i applikationer som multiplar av den.
Om sen just 160 "ticks" per sekund är optimalt går itne att
säga, det är i alla fall lite onödigt snabbt för dina 100/500 ms
blinkningar.
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Re: Rutin för att blinka en LED i olika mönster

Inlägg av MicaelKarlsson »

"Det jag funderar på är om det finns något enklare sätt att göra detta?"

Skulle väl i så fall vara "_delay_ms(100);" men man kan ju knappast påstå att det är en bra metod.
Håll fast vid din metod, den är både snyggare och bättre. Sedan kanske det skulle vara lättare att arbeta med en annan frekvens än just 160 Hz.

Eftersom jag blev lite nyfiken, varför just 160HZ?
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Rutin för att blinka en LED i olika mönster

Inlägg av jesse »

jag tycker också det kan vara lite krångligt... du har löst det ungefär så som jag skulle gjort. Jag har en del applikationer där flera olika saker ska blinka/pipa i olika hastighet beroende på status. Det är inte så svårt egentligen, men jag tycker det kan bli lite svårt att överblicka vad som händer ibland, särskilt om man bygger ut programmet succesivt med nya funktioner / blinkmönster.

Delay_ms är inget alternativ, då det stoppar allt annat som processorn måste göra under tiden.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Re: Rutin för att blinka en LED i olika mönster

Inlägg av Korken »

Tackar för svaren!

Personligen gillar jag inte _delay_xx funktionerna, då jag har fått alldeles för många buggar av dom. :)
Det är som att dom stoppar annat (interupts?) medan dom körs.

Varför 160Hz? Jo, de är såhär att jag har ingen aning varför jag valde det.
Eller de har jag, jag bara satte prescale bitsen till något som jag visste var stort och efter lite testande kollade jag databladet och hittade att jag körde 512 prescaler.
Så det vart 160Hz av lathet. :roll:

Fast nu när jag väl har implementerat det kör jag med 20Hz (4096 prescaler).
Senast redigerad av Korken 8 augusti 2010, 13:57:51, redigerad totalt 1 gång.
sneaky
Inlägg: 1621
Blev medlem: 22 juni 2009, 18:38:42

Re: Rutin för att blinka en LED i olika mönster

Inlägg av sneaky »

Jag vet inte om jag läser koden rätt men jag tycker det ser ut som en glorifierad "busy delay" om ni förstår hur jag menar. Programmet blir ju upplåst precis som om man hade "pausat" med en drös for-loopar. När du nu ändå har en timer med interrupt snurrande varför inte lägga jobbet i interrupten istället så att resten av programmet kan pyssla med bättre saker? Ha en variabel som bestämmer vilket mönster som skall blinkas och sköt sedan jobbet med att tända och släcka lysdioden i interrupten.

Hoppas att i alla fall någon därute förstod mina luddiga tankar :lol:
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Rutin för att blinka en LED i olika mönster

Inlägg av jesse »

Jo, så ska de givetvis vara:
grunden är då att man inuti interruptet jämför cnt med ett förinställt värde...

Kod: Markera allt

ISR(TIMER1_COMPA_vect)
{
   static uint8_t pekare;
   static uint8_t cnt;

   cnt++;
   if (cnt > count) {
      cnt = 0;
      count = new_value;
      // toggle LED;
   }
}
sen får man ha nåt slags system att ladda "count" med nya värden så att det blir en bra blink-sekvens. Man kan tänka sig att man har en pekare till en array som innehåller ett antal olika sekvenser. Pekaren räknas upp, och när sekvensen är slut (kan t.ex. indikeras genom att värdet = 0) börjar den om från början igen.. i så fall blir det något i stil med:

Kod: Markera allt

//globala variabler
uint8_t sekvens =0;
uint8_t blinklist[] = { 0 , 10,20,10,20,0,   10,10,10,20,20,20,0 }
#define BLINK_STOP         0;
#define BLINK_SEKVENS1 1;
#define BLINK_SEKVENS2 6;

ISR(TIMER1_COMPA_vect)
{
   static uint8_t pekare = 0;
   static uint8_t cnt = 0;

   cnt++;
   if (cnt > count) {
      cnt = 0;
      count = blinklist[pekare++];
      if (count == 0) { 
         pekare = sekvens; // börja från början igen på vald sekvens.
         LED_OFF; // ny blinksekvens starar alltid med LED släckt.
      }
      TOGGLE_LED;
   }
}

// main...

   sekvens = BLINK_SEKVENS1;

// byt sekvens...

   sekvens = BLINK_SEKVENS2;

// stäng av

   sekvens = BLINK_STOP;

Här har jag gjort "pekare" som en vanlig 8-bitars integer som ett index i en array, men ännu smartare (?) kan ju vara att göra en *riktig* pekare istället och dela upp de olika sekvenserna i var sin namngiven array. Arrayerna kan dessutom placeras i flashminnet med PROGMEM så att man inte slösar RAM-minne i onödan, men då måste värdet avläsas genom en funktion ( tror det heter readbyte_pgm(*pointer) eller nåt sånt)
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Re: Rutin för att blinka en LED i olika mönster

Inlägg av Korken »

Riktigt smart dedär!
Det ska testas och se om jag får snurr på liknande metod också. :)
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Re: Rutin för att blinka en LED i olika mönster

Inlägg av Korken »

Jag gjorde klart min (baserad på din).
Då jag bara har 4st blinkningar, där 3 av dom är väldigt snarlika så vart din metod riktigt bra.
Tackar så mycket för hjälpen!

Kod (lämnade ute timer-init koden):

Kod: Markera allt

#define LED_PORT 		PORTB
#define LED_PIN			1
#define BLINK_STOP 		0
#define BLINK_SEQ_ERR3	1
#define BLINK_SEQ_ERR2	3
#define BLINK_SEQ_ERR1	5
#define BLINK_SEQ_CHG	8

volatile uint8_t seq = 0;

ISR(TIMER1_COMPA_vect) 	//Körs i 20Hz
{
	static uint8_t blinklist[] = {0,3,3,3,3,3,20,0,20,20,0};
	static uint8_t cnt = 0;
	static uint8_t count = 0;
	static uint8_t ptr = 0;

	cnt++;

	if (cnt >= count)
	{
		cnt = 0;
		count = blinklist[ptr++];
		if (count == 0)
		{
			LED_PORT &= ~(1<<LED_PIN);
			ptr = seq;
		}
		else
			LED_PORT ^= (1<<LED_PIN);
	}
}

int main(void)
{
	....
	seq = BLINK_SEQ_ERR3;
	....
}
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Rutin för att blinka en LED i olika mönster

Inlägg av jesse »

kul att det blev bra :tumupp:
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Re: Rutin för att blinka en LED i olika mönster

Inlägg av Korken »

Japp!
Så nu äre bara att slänga sig över nästa problem i projektet. :lol:
Skriv svar