- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 6 von 6

Thema: probleme mit led-cube-programm, und mit uint8_t

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    28.12.2007
    Ort
    Wien
    Alter
    29
    Beiträge
    96

    probleme mit led-cube-programm, und mit uint8_t

    Anzeige

    Praxistest und DIY Projekte
    Hi!

    ich habe mir einen 3x3x3-LED-Cube gebaut und programmiert. Funktioniert auch ganz gut.

    Hier der Quellcode:

    Code:
    /*
    #####################################################
    pin D0-7:LED1-8
    pin C0: Led9
    pin C1-3: ebene 1-3
    
    
    
    led_cube_3x3x3_v5
    4bit-helligkeitsstufen (16, 0-15)
    
    
    Erklärung:
    wenn die jeweilige ebene aktiv ist, dann wird jede led der ebene so lange eingeschltet, wie es der helligkeit im array entspricht
    
    Ebene aktiv:		________----------________----------________----------________----------________----------
    
    led: 100%			________----------________----------________----------________----------________----------
    
    led: 80%:			__________--------__________--------__________--------__________--------__________--------
    
    led: 50%:			_____________-----_____________-----_____________-----_____________-----_____________-----
    
    led: 20%:			________________--________________--________________--________________--________________--
    
    led: 0%:			__________________________________________________________________________________________
    
    #####################################################
    */
    
    
    
    
    
    
    
    #include <avr\io.h>
    #include <avr\interrupt.h>
    #include <stdint.h>
    #include <stdio.h> 
    #define outp(a,b) b=a;
    #define F_CPU 8000000UL  //zum testen
    #include <util/delay.h>  //zum testen
    
    
    
    
    
    //ich will uint8_t oder besser was mit 4bit
    int zaehler_helligkeit=15;
    int ebene=0;
    
    
    
    //ich will uint8_t oder besser was mit 4bit, aber es geht nicht	
    int led[3][9]=	{{15, 15, 15, 15, 15, 15, 15, 15, 15},		//Array in dem die Helligkeiten der leds gespeichert sind, Die 3 zeilen sind die 3 ebenen im würfel, und die 9 spalten die 9 türme. 0=dunkel, 15=hell
      		   		 {15, 15, 15, 15, 15, 15, 15, 15, 15},
    		    	 {15, 15, 15, 15, 15, 15, 15, 15, 15}};
    
    int portd=0;
    int portc=0;
    
    int i;		//zählervariable
    
    void init(void)
    {
    	DDRD = 0b11111111; 
    	DDRC = 0b11111111; 
    	DDRB = 0b11111111; 
    	//Timer-Einstellungen
    	outp((1<<TOV0), TIMSK);			//Timer Overflow Interrupt einschalten
    	TCNT0=0x00;						//Zähler-Startwert setzen
    	outp((1<<CS00), TCCR0);			//vorteiler: 1
    	sei();							//Interrupts einschalten
    }
    
    
    
    
    
    
    ISR(TIMER0_OVF_vect) 	/*Interrupt-Routine*/
    {
    
    	//ebenen-multiplex-frequenz=interrupt-frequenz/(16*3)
    
    	//zählt 15-0_15-0
    	if(zaehler_helligkeit==0)		//wenn der durchlauf fertig ist...
    	{
    		zaehler_helligkeit=15;		//..., dann wieder von vorne beginnen und
    				
    		if (ebene==2)				//wenn alle ebenen dran waren...
    		{
    			ebene=0;				//..., dannn wieder von vorne beginnen
    		}
    		else						//wenn noch nichd alle dran waren, dann...
    		{
    			ebene++;				//...nächste ebene aktivieren
    		}
    	}
    	else
    	{
    		zaehler_helligkeit--;		//wenn der durchlauf noch nicht fertig ist, dann runterzählen
    	}
    
    
    	//ebene_? aktivieren, die anderen deaktivieren
    	portc=(1 << (ebene+1));
    
    
    	portd=0;
    
    
    	for(i=0;i<8;i++)			//für jeden led ausgang machen, bis auf den letzten
    	{
    
    		if(led[ebene][i]>zaehler_helligkeit)
    		{		
    			portd=portd | (1 << i);
    		}
    
    	}
    
    
    
    	if(led[ebene][8]>zaehler_helligkeit)		//letzter led-ausgang auf anderem port (c statt d)
    	{
    		portc=portc | 0b00000001;
    	}
    
    
    
    	PORTC=portc;
    	PORTD=portd;
    
    
    }
    
    
    
    
    
    
    
    
    int main(void) 
    {
    
    	init();	//init() starten
    
    	while (1)
    	{
    		//Hier kommt was hin, das immer neue werte in das array schreibt, um die leds zu verändern, um Muster zu erzeugen
    		PORTB = 0b00000001;	//test
    		_delay_ms(500);	
    		PORTB = 0b00000000;	//test
    		_delay_ms(500);
    	}
    
    }
    ich habe jetzt 2 Probleme:

    1. Ich habe zu Testzwecken eine LED an B0, die ich mit der _delay_ms() Funktion blinken lassen will (f=1Hz). In Wirklichkeit dauert das blinken aber ca. 260 Mal länger. Wieso? Kann es daran liegen, dass die _delay_ms() Funktion dauernd vom Interrupt unterbrochen wird, und so nicht weiterkommt? Oder woran kann es sonst noch liegen?

    2. Ich will für manche Variablen ein uint8_t statt einem int verwenden, da ein int Speicherverschwendung ist. Wenn ich aber die Variable als uint8_t deklariere, dann wird das uint8_t irgendwie nicht erkannt, dh. nicht blau gefärbt, wie z.B. int. Wieso nicht?

    Und gibt es vllt. einen Datentyp mit nur 4bit? dann könnte ich noch mehr Speicher sparen...


    ich hoffe, ihr könnt mir helfen.


    MfG

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Zu 1: Deine ISR wird 8000000/256=31250 mal in der Sekunde ausgeführt. Das sind 31250 Unterbrechungen von _delay_ms mit der Ausführungsdauer deiner ISR. Das bremst sicher. Um solche Probleme zu vermeiden, verwende ich die _delay_ms()-Funktion nicht, wenn ich im Hintergrund sowieso eine ISR tickern habe. Mit ein paar zusätzlichen Codezeilen kann man da noch eine Variable runterzählen und diese in einer eigenen Wartefunktion abfragen.

    Zu 2: Dein Editor kennt die neuen Bezeichnungen nicht und markiert sie deshalb auch nicht. Trotzdem kannst du die Bezeichnungen verwenden, der Kompiller kann es übersetzen (wenn er motzt, dann fehlt inttypes.h in den includes). Beim GCC kannst du aber auch die alten Schreibweisen verwenden:

    char - 8 Bit mit Vorzeichen
    unsigned char - 8 bit ohne Vorzeichen
    int - 16 Bit mit Vorzeichen
    unsigned int - 16 Bit ohne Vorzeichen

    Zu 2b: Nein, einen Datentyp mit vier Bit gibt es nicht in C.

    Allgemein finde ich deinen Cube schon recht nett. Da ich mit meinen Pong-Spielereien im Moment ähnliche Probleme habe, finde ich es sehr spannend zu lesen, wie andere an das Thema rangehen. Das Pong hat auch einen 8MHz-Mega8, allerdings mit 120 LEDs in 12 Ebenen. Da du ja offensichlich gut weiterkommst und ich deinen Ansatz mit meinen Ideen nicht verfälschen möchte, halte ich mich mit weiteren Kommentaren zurück ;)

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Noch ein paar Anmerkungen zum Code:

    1. Das ganze delay-Zeugs ist wie bereits gesagt bäh. Von ganz wenigen Ausnahmen abgesehen sollte man die Finger davon lassen. Überleg die zum Beispiel, wie eine LED mit 1 Hz blinken kann und gleichzeitig eine zweite LED mit 1.1 Hz. Mit delay funzt das nicht; am ehesten passen da eigene (Countdown-)Zähler, die in einer ISR runtergezählt werden.
    2. outp verschleiert mehr als es nutzt oder klar macht. Wird es einfach raus. Zudem erzeugt es am eine zwei Strichpunkte, was bei if/else Probleme macht.
    3. Laufvariable i ist besser eine lokale Variable in der ISR, dito für portc und portd.
    Disclaimer: none. Sue me.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    28.12.2007
    Ort
    Wien
    Alter
    29
    Beiträge
    96
    Hi!

    Danke für eure antworten!

    Das mit der blinkenden LED war eigenrlich nur als Test gedacht, ob die Dinge, die später in die Main kommen, schnell genug ausgeführt werden.
    Ich werde einfach einen Vorteiler einstellen, dann gibt's nicht mehr so viele Interrupts, und die Multiplexfrequenz sollte trotzdem noch hoch genug sein.

    Kann man dem Editor (AVR- Studio 4 mit WinAVR) eigentlich die Datentypen beibringen? Oder vllt. Habe ich auch nur eine alte Version, ich werde mal schauen.

    Und das outp werde ich weg machen, und die Variablen lokal.


    Nochmal danke für eure Antworten!


    MfG

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Letztlich beruhen die verschiedenen Datentypen auf den Vorgaben durch den Kontroller. Und die AVRs kennen eben keine Speichereinheiten (Register?) mit 4 Bit. Natürlich kann man C den Datentyp auch beibringen, der Kompiller wandelt aber letzlich alles in die Registergrößen des Kontrollers um.

    Das sind 31250 Unterbrechungen von _delay_ms mit der Ausführungsdauer deiner ISR.
    Das hatte ich heute Nacht noch nicht wirklich zuende gedacht. Für deine ISR hast du 256 Kontrollertakte lang Zeit, abzüglich des Codes für den Aufruf der ISR. Jetzt kenne ich mich mit den Ausführungszeiten der einzelnen Machinenbefehle nicht so aus, aber Verzeigungen und Arrays und For-Schleifen zusammengezählt ergeben möglicherweise deutlich mehr Takte als zur Verfügung stehen. Deshalb würde ich auch einen größeren Prescaler vorschlagen, bei 27 Leds würden /8 vollkommen ausreichen. Je nach Codeoptimierung in der ISR reicht dann vielleicht auch nur /64 in CTC.

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    28.12.2007
    Ort
    Wien
    Alter
    29
    Beiträge
    96
    Letztlich beruhen die verschiedenen Datentypen auf den Vorgaben durch den Kontroller. Und die AVRs kennen eben keine Speichereinheiten (Register?) mit 4 Bit. Natürlich kann man C den Datentyp auch beibringen, der Kompiller wandelt aber letzlich alles in die Registergrößen des Kontrollers um.
    Mit dem Beibringen meinte ich, ob man den die neueren Datentypen (uint8_t z.B.) irgendwie wo eintragen kann, damit sie vom Editor auch blau hervorgehoben werden. Geht das? Das würde das ganze übersichtlicher machen.

    und ich habe jetzt den Prescaler auf 8 eingestellt, und jetzt funktioniert alles so, wie es soll.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test