MindGame, eller lämpligt nybörjarprojekt för AVR

Berätta om dina pågående projekt.
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

MindGame, eller lämpligt nybörjarprojekt för AVR

Inlägg av MicaelKarlsson »

Jag har precis gjort klart ett litet spel som säkert fler kan ha glädje av se. Om inte annat för att det är kul att spela en stund. Det är nästan lika roligt att spela som att bygga.
Lite information om vad det går ut på:
Fyra lysdioder blinkar i ett slumpvis mönster som man sedan skall upprepa genom att trycka på lika många knappar. Därefter markeras med grön/röd lysdiod om man gjort rätt eller fel. Efter sex rätta gissningar ökas antalet blinkningar på med ett och så vidare tills man väljer att stänga av spelet eller att vektorn fylls (10 för närvarande).

Eftersom jag tänkt göra detta som ett nybörjarprojekt har jag knåpat i hop ett litet flödesschema:
Bild
Ett litet fel i flödesschemat har smugit sig in: "Läsa in gissningar" bör också innehålla en rättningsfunktion också. Observera att detta är en skiss.
Blink är alltså vilken lysdiod som skall blinka.
Så ett kopplingsschema:
Bild
Då jag kopplat upp allt på ett experimentkort har jag inte gjort en kretslayout.
Som ni ser är det inga konstiga komponenter utan bara standard som alla har i byrålådan.

Ett litet råttbo:
Bild
Så den slutliga lilla lådan:
Bild
Jag hade inte satt fast locket ordentligt när bilden togs, därför ser det lite skevt ut.

Så lite programkod:

Kod: Markera allt

 //Mind game - eller hur man gissar rätt på blinkande lysdioder.
//Chip: Atmel AVR  ATtiny2313 @4MHz div 8 Internally
//
//Micael Karlsson
//20070225-20070302
//Push button 1: -> PD0
//Push button 2: -> PD1
//Push button 3: -> PD2
//Push button 4: -> PD3
//LED 1: -> PB0
//LED 2: -> PB1
//LED 3: -> PB2
//LED 4: -> PD6
//OK LED: -> PD4  
//Not OK LED: -> PD5  
//----------------------------------------------------------------------------------------------
#include "util/delay.h"
#include "avr/io.h"
#include "stdlib.h"
//----------------------------------------------------------------------------------------------	
short int Blink[10],PButtons[10],Ant=4,ii,NumOfCorr,AddBlink=0;
//----------------------------------------------------------------------------------------------
void Delay(short int,short int);
void RandomNumbers(short int);
void Blinky(void);
short int PushButtons(short int);
static unsigned long seed = 1; 
//----------------------------------------------------------------------------------------------
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))

#define LED_1_ON bit_set(PORTB,2);
#define LED_2_ON bit_set(PORTB,4);
#define LED_3_ON bit_set(PORTB,8);
#define LED_4_ON bit_set(PORTD,64);
#define LED_OK_ON bit_set(PORTD,16); 
#define LED_NOT_OK_ON bit_set(PORTD,32);

#define LED_1_OFF bit_clear(PORTB,2);
#define LED_2_OFF bit_clear(PORTB,4);
#define LED_3_OFF bit_clear(PORTB,8);
#define LED_4_OFF bit_clear(PORTD,64);
#define LED_OK_OFF bit_clear(PORTD,16);
#define LED_NOT_OK_OFF bit_clear(PORTD,32);

#define P_BUTTON_1 bit_get(PIND,1)
#define P_BUTTON_2 bit_get(PIND,2)
#define P_BUTTON_3 bit_get(PIND,4)
#define P_BUTTON_4 bit_get(PIND,8)


# define F_CPU 1000000UL
//----------------------------------------------------------------------------------------------
void main (void)
	{
	DDRB=0xFF;	
	DDRD=0x70;	
	for(ii=0;ii<4;ii++) //Blinkningar för att visa att spelet kan börja.
		{
		LED_OK_ON;
		for(short int jj=0;jj<2;jj++)
			_delay_ms(250);
		LED_OK_OFF;
		for(short int jj=0;jj<2;jj++)
			_delay_ms(250);
		}
	while(1)
		{	
		if(AddBlink==6) //Om man gissat rätt sex gånger ökas blinkningarna med ett.
			{
			Ant++;
			AddBlink=0;
			}
		RandomNumbers(Ant);  //Slumpgenerering.
		Blinky();	//Visar rätt blinkkombination.
		NumOfCorr=PushButtons(Ant);  //Läser in och rättar gissningarna.
		if(NumOfCorr==1)  //Om rätt rad matats in blinkar grön lysdiod.
			{
			for(ii=0;ii<5;ii++)
				{
				LED_OK_ON;
				for(short int jj=0;jj<4;jj++)
					_delay_ms(250);
				LED_OK_OFF;
				for(short int jj=0;jj<4;jj++)
					_delay_ms(250);
				}
			AddBlink++;  //Lägger till ett för att hålla reda på rätt gissningar.
			}
		if(NumOfCorr==0)  //Om fel rad matats in blinkar röd lysdiod.
			{
			for(ii=0;ii<4;ii++)
				{
				LED_NOT_OK_ON;
				for(short int jj=0;jj<4;jj++)
					_delay_ms(250);
				LED_NOT_OK_OFF;
				for(short int jj=0;jj<4;jj++)
					_delay_ms(250);

				}
			}
		}
	}	
//----------------------------------------------------------------------------------------------
void RandomNumbers(short int NumRan)	
	{
	seed = seed * 1103515245 + 12345; //Generera en seed
	srand(seed);
	for(ii=0;ii<NumRan;ii++) //Generera slumpvis blinkningar
		Blink[ii]=random()%(5-1)+1;	
	}
//----------------------------------------------------------------------------------------------	
void Blinky(void)
	{
	//Blinkar rätt slumpgenererade kombination:
	for(short int ii=0;ii<Ant;ii++)
		{
		if(Blink[ii]==1)
			{
			LED_1_ON;			
			for(short int jj=0;jj<6;jj++)
				_delay_ms(250);
			LED_1_OFF;
			}
		if(Blink[ii]==2)
			{
			LED_2_ON;
			for(short int jj=0;jj<6;jj++)
				_delay_ms(250);
			LED_2_OFF;
			}			
		if(Blink[ii]==3)
			{
			LED_3_ON;
			for(short int jj=0;jj<6;jj++)
				_delay_ms(250);
			LED_3_OFF;				
			}	
		if(Blink[ii]==4)
			{
			LED_4_ON;
			for(short int jj=0;jj<6;jj++)
				_delay_ms(250);
			LED_4_OFF;
			}
		LED_1_OFF;
		LED_2_OFF;
		LED_3_OFF;
		LED_4_OFF;
		for(short int jj=0;jj<5;jj++)
			_delay_ms(250);
		}
	}
//----------------------------------------------------------------------------------------------	
short int PushButtons(short int Ant)	
	{
	//Tänder lysdioderna då det är dags att knappa in sína gissningar:
	LED_OK_ON;
	LED_NOT_OK_ON;
	ii = 0;
	while(ii<Ant)
		{
		if(P_BUTTON_1) //Om knapp 1 trycks ned.
			{
			LED_1_ON;
			_delay_ms(15);  //15 ms fördröjning som fungerar som en slags debounce.
			LED_1_OFF;
			if(P_BUTTON_1)  //debounce. Om knappen fortfarande är nedtryckt.
				{
				PButtons[ii]=1;
				ii++;
				}
			while(P_BUTTON_1)  //Medan knapp 1 är nedtryckt blinkar motsvarande lysdiod.
				{
				LED_1_ON;
				_delay_ms(25);
				LED_1_OFF;
				_delay_ms(25);
				}
			}

		if(P_BUTTON_2) //Om knapp 2 trycks ned.
			{
			LED_2_ON;
			_delay_ms(15);
			LED_2_OFF;
			if(P_BUTTON_2)  //Debounce. Om knappen fortfarande är nedtryckt.
				{
				PButtons[ii]=2;
				ii++;
				}
			while(P_BUTTON_2)  //Medan knapp 2 är nedtryckt blinkar motsvarande lysdiod.
				{
				LED_2_ON;
				_delay_ms(25);
				LED_2_OFF;
				_delay_ms(25);
				}
			}

		if(P_BUTTON_3)  //Om knapp 3 trycks ned.
			{
			LED_3_ON;
			_delay_ms(15);
			LED_3_OFF;
			if(P_BUTTON_3)	 //Debounce. Om knappen fortfarande är nedtryckt.
				{
				PButtons[ii]=3;
				ii++;
				}
			while(P_BUTTON_3) //Medan knapp 3 är nedtryckt blinkar motsvarande lysdiod.
				{	
				LED_3_ON;
				_delay_ms(25);
				LED_3_OFF;
				_delay_ms(25);
				}
			}
		if(P_BUTTON_4)  //Om knapp 4 trycks ned.
			{
			LED_4_ON;
			_delay_ms(15);
			LED_4_OFF;
			if(P_BUTTON_4)  //Debounce. Om knappen fortfarande är nedtryckt.
				{
				PButtons[ii]=4;
				ii++;
				}
			while(P_BUTTON_4)  //Medan knapp 2 är nedtryckt blinkar motsvarande lysdiod.
				{
				LED_4_ON;
				_delay_ms(25);
				LED_4_OFF;
				_delay_ms(25);
				}
			}
		}
	LED_OK_OFF;
	LED_NOT_OK_OFF;  //Inmatningen är avslutad.	
	for(ii=0;ii<Ant;ii++)//Jämför inmatade gissningar med rätt blinkrad.
		{
		if(PButtons[ii]!=Blink[ii])  //Om någon av gissningarna är fel returneras "0".
			return 0;
		}			
	return 1; //Om alla rätt returneras en "1".
	}

	

Vad tycks?

Någon som har tips på en bättre slumpgenerering tas tips gärna emot.

EDIT: Uppdaterat kod med kommentarer för läsbarhet och förståelse.
Senast redigerad av MicaelKarlsson 7 april 2007, 11:59:30, redigerad totalt 2 gånger.
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

Dendär koden var inte kul att läsa utan kommentarer!

Fungerar allt som det ska nudå?

Den slumpgenerering som finns tillgänglig genom rand() duger, men du måste ge den olika seed varje gång den startar upp, annars kommer den köra samma slumpslinga varje gång. Jag brukar lösa det genom att använda en plats i EEPROMet:
Välj en cell i EEPROM som du ska lagra din seed i.
Vid varje uppstart, läs värdet från cellen.
Mata in värdet i srand() för att få ett nytt.
Spara det nya värdet i EEPROM som seed till nästa uppstart.
Klar.

På detta vis lär du aldrig känna igen när du får samma slinga igen!
Användarvisningsbild
JimmyAndersson
Inlägg: 26532
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Kul projekt! :)

Märkligt att det inte görs fler spel här.


När kommer PIC-versionen? :D
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

$tiff skrev:Dendär koden var inte kul att läsa utan kommentarer!

Fungerar allt som det ska nudå?
För det första så skrev jag ju att jag slarvat med kommenterandet. Vilket jag skall ändra på.
För det andra så fungerar det betydligt bättre efter en enkel debouncekoden (oj vilket snyggt ord!).

>>När kommer PIC-versionen?
Jadu Jimmy när har du gjort den klar? :D
Får nog bli du eller någon annan PIC-fantom!!
Mindmapper
Inlägg: 7093
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Inlägg av Mindmapper »

Började bygga lite på ditt fantastiska mindgame idag.
Jag kom då på att det går att rationalisera bort 4st resistorer.
Pull-up resistorerna till tryckknapparna behövs inte eftersom
man kan aktivera intern pull-up i kretsen.
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Jag använder de externa pull-up resistorerna av följande anledningar:

- Minimera strömförbrukning.
- Begränsa strömmen in till AVR.
- Av gammal och ohejdad vana. :)

Mindmapper: Hur kopplar du in tryckknapparna då?

Kul att du gillar mitt lilla spel! :D
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Inlägg av Micke_s »

AVR har ett pull up som är ca 10k-50k stort. antar att Mindmapper kopplar tryckknapparna som schemat ditt fast utan R1-R4.
Mindmapper
Inlägg: 7093
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Inlägg av Mindmapper »

Ta bara bort resistorerna mellan tryckknapparna och +5V. Tryckknapparna sitter alltså bara inkopplade mellan ingång och GND, precis som dom gör nu.

Interna pull-up motstånden är min. 20kΩ och max. 50kΩ i tiny2313.
- Eftersom du inte satt ut något motståndsvärde i schemat är det svårt att se om strömförbrukningen blir större eller mindre. :wink:
- De interna pull-up resistorerna begränsar också strömmen :D
- det betalar sig oftast att börja med något nytt :)
Edit: Micke_s alldeles riktigt. OCH Glöm ej aktivera pull-up i programmet.
Edit2: Har ej hunnit göra det än. Jobbar väldigt långsamt ska ni veta :roll:
Senast redigerad av Mindmapper 18 april 2007, 15:12:31, redigerad totalt 1 gång.
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

:humm:
Upptäckte att jag vänt lite på tryckknapparna i kopplingsschemat ovan, vilket gör att koden inte kommer att fungera med den inkopplingen.

Har uppdaterat kopplingsschemat så det bör stämma överens med koden..
Mindmapper
Inlägg: 7093
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Inlägg av Mindmapper »

Det var bättre förr :!: :evil: :( :(
Jag kommer att köra som du kopplade först (utan resistorer naturligtvis) och invertera i koden. :lol:
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Vad då bättre förr?!? skall du säga som skrev "det betalar sig oftast att börja med något nytt" :rofl



>>- Eftersom du inte satt ut något motståndsvärde i schemat är det svårt att se om strömförbrukningen blir större eller mindre.
Pull-up brukar jag köra med 10k

>> - De interna pull-up resistorerna begränsar också strömmen
Helt sant, men gammal vana :lol:

>> - det betalar sig oftast att börja med något nytt
För gammal för att lära om och så lider jag av hängslen-och-livremssyndromet.
Mindmapper
Inlägg: 7093
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Inlägg av Mindmapper »

Eftersom jag är både snål och lat (ibland) kommer jag att spara in både kostnaden och besväret att koppla in 4st resistorer. Därav "bättre förr" kommentaren.

Enligt gamla schemat var intern-pull-up minst hälften så strömkrävande (gentimot dina 10k) när trycknappen påverkades. Nu är det lite fusk tycker jag.

Edit: tog bort fel
Användarvisningsbild
MicaelKarlsson
Inlägg: 4669
Blev medlem: 18 juni 2004, 09:16:07
Ort: Aneby
Kontakt:

Inlägg av MicaelKarlsson »

Fusk? Hur då?
Mindmapper
Inlägg: 7093
Blev medlem: 31 augusti 2006, 16:42:43
Ort: Jamtland

Inlägg av Mindmapper »

Ursäkta! Hade för bråttom och läste fel på ditt nya schema :shock:

Edit Samma som gällde energikommentaren gäller nu också enligt det nya schemat.
Skriv svar