mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zufallszahlen & Watch-Window (AVR-Studio)


Autor: Andreas Brunner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Folgende Situation bei mir...hab ein STK500 mit Tiny13, funktioniert 
alles prima bisher. Hier gleich eine kleine Frage am Rande: Hab 
folgendes Programm:
#include <avr/io.h> 
#include <stdint.h>
#include <avr/delay.h> 
#include <stdlib.h>
 
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) //Tasterentprellung
{
    if ( ! (*port & (1 << pin)) )
    {
        /* Pin wurde auf Masse gezogen, 100ms warten   */
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
        _delay_ms(50); 
        if ( *port & (1 << pin) )
        {
            /* Anwender Zeit zum Loslassen des Tasters geben */
            _delay_ms(50);
            _delay_ms(50); 
            return 1;
        }
    }
    return 0;
}

unsigned short get_seed() //Startwert für rand() erzeugen
{
   unsigned short seed = 0;
   unsigned short *p = (unsigned short*) (RAMEND+1);
   extern unsigned short __heap_start;
    
   while (p >= &__heap_start + 1)
      seed ^= * (--p);
    
   return seed;
}


int main (void)
{            
  DDRB = 0b001111; //PB4 als Eingang, PB0-3 als Ausgang

  PORTB &= ~ ((1<<PB2) | (1<<PB3)); // PB2 und 3 einschalten
  PORTB |= (1<<PB0) | (1<<PB4); // PB0 ausschalten, PB4 internen Pull-up deaktivieren

  uint16_t zufall;
  
  while(1)
  {
    if (debounce(&PINB, PB4))   
    {
      PORTB = PINB ^ (1<<PB1) ^ (1<<PB0);
      srand(get_seed());
      zufall = rand();  
    }
  }                       
  return 0;                 
}
Hab mit diesem Programm schon 63% des Programmspeichers vom ATtiny13 
verbraucht, hätte echt nicht gedacht, dass der so schnell voll wird. Und 
dazu meine Frage: wirken sich die inkludierten Header-Files auf die 
Größe des Programms aus oder werden nur die benötigten Funktionen am µC 
gespeichert? Das würde ja irgendwie erklären warum dieses Miniprogramm 
schon so viel Platz benötigt...

Aber jetzt zur richtigen Frage. Will letztlich mit diesem µC einen 
Würfel ansteueren. Hab mich über die Erzeugung von Zufallszahlen schon 
ausreichend informiert und mich letztendlich für die Variante mit dem 
SRAM entschieden, da sie für diese Anwendung vollkommen ausreicht. Wie 
kann ich jetzt
1) den Zufallszahlenbreich auf 1-6 eingrenzen und
2) wenn ich im Watch-Window im AVR-Studio die Variable "zufall" ansehen 
will, steht bei Value immer nur "Location not valid". Was ist hier 
falsch?

Zu 1) Wäre das eine Möglichkeit?
int zufallszahl ()
{
  int x;

  while( (x = rand()) >= RAND_MAX - (RAND_MAX % 6) )
    ; 
  return x % 6;
}

Danke schon mal,
Lg Andi

Autor: Tobias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Von Zufallszahlenerzeugung hab ich keine Ahnung, aber was die größe des 
Codes angeht, hast du die Codeoptimierung aktiviert?

Autor: Andreas Brunner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Optimierung ist auf "-Os" eingestellt.

Autor: Stefan Hennig (stefanhennig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu 1): Nach langem Nachdenken bin ich zur Überzeugung gekommen, dass 
dieser Code wahrscheinlich sehr schlau ist. Ich hätte nie daran gedacht, 
dass es nicht gleich viele Zufallszahlen kongruent zu 0,1,2,3,4,5 gibt, 
wenn RAND_MAX kein Vielfaches von 6 ist. Aber wenn der 
Zufallszahlengenerator so gut ist, wie die halt normalerweise so sind, 
dann ist dass auch nur Zuckerguss auf einem Sandkuchen. Allerdings gibst 
Du einen int zurück, wo ein uint16 erwartet wird und ein uint8 reichen 
würde. Das ist unordentlich.

Zu 2): Das kann ich beantworten: Die Variable wurde wegoptimiert, weil 
sie nur beschrieben und nie gelesen wurde.

Aber warum verwendest Du überhaupt rand() aus der stdlib? Hast Du 
Zugriff auf die Numerical Recipes? Da gibt's doch sicherlich einen 
10-Zeiler, der gut genug ist für einen Würfel. Ich nehme mal an, dass 
sich dann auch Dein Speicherverbrauch besser in den Griff bekommen 
lässt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und solltest du bei rand() bleiben dann zieh den Aufruf der srand vor 
die while Schleife.

Zufallszahlengeneratoren funktionieren nur dann vernünftig, wenn man sie 
in Ruhe arbeiten lässt. Den ersten Seed gibt man vor (ev. in irgendeiner 
Form von einer Benutzeraktion abhängig) und dann lässt man den Seed 
tunlichst in Ruhe! Nur so kann der Generator seine Normalverteilung 
(oder was er sonst für eine Verteilung hat) aufbauen.

Autor: Andreas Brunner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also sollte "zufall" als uint8_t und nicht als uint16_t definiert sein, 
um es sauber zu machen?

Naja, aus den Numerical Recipes werd ich nicht schlau, aber diese 
Variante des Zufallsgenerators ist eh schon recht kurz. Wie könnte ich 
den am einfachsten diese Zufallszahl einfach an Port B mit 4 Leds 
(einfach in BCD Code) ausgeben?

Autor: Andreas Brunner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hatte ich ganz vergessen dass das srand() aus der Schleife raus 
gehört. Ich hab jetzt einfach mal ganz plump PORTB = zufall; 
geschrieben, so sehe ich in der Simulation, dass sich bei jedem 
Tastendruck dann an Port B etwas ändert, also dass sollte dann schon mal 
funktionieren. Jetzt fehlt nur noch die Eingrenzung auf 1 bis 6.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Brunner schrieb:
> Das hatte ich ganz vergessen dass das srand() aus der Schleife raus
> gehört. Ich hab jetzt einfach mal ganz plump PORTB = zufall;
> geschrieben, so sehe ich in der Simulation, dass sich bei jedem
> Tastendruck dann an Port B etwas ändert, also dass sollte dann schon mal
> funktionieren. Jetzt fehlt nur noch die Eingrenzung auf 1 bis 6.

Deine Funktion zufallszahl() macht das schon.
Die macht das sogar sehr gut.

Autor: Andreas Brunner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Scheint zu funktionieren. Mein Problem ist jetzt wie gesagt die Ausgabe 
über die vier Leds...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Brunner schrieb:
> Scheint zu funktionieren. Mein Problem ist jetzt wie gesagt die Ausgabe
> über die vier Leds...

Versteh ich nicht.
Das ist doch der leichteste Teil der Übung.
Einfach an den Port rausgeben, so wie du das schon gemacht hast.

   PORTB = zufall | ( 1 << PB4 );  // damit der Pullup nicht flöten geht

Autor: Andreas Brunner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, na dann scheint es doch eh irgendwie zu stimmen ^^ Aber auch eben 
nur irgendwie, denn die Leds sind wenn ich mich richtig entsinne 
active-Low, also hab ich mal geschaut, welche Werte da mit den Leds zu 
Tage kommen, und habe festgestellt, dass 6 nicht vorkommt. Es war nur 
0-5 zu sehen...hab ich doch glatt das "+1" bei der Berechnung vergessen. 
Jetzt scheint der Generator fertig zu sein!

Alles weitere wird hoffentlich kein Problem mehr...und braucht auch 
hoffentlich nicht mehr zu viel Speicherplatz ^^

Danke für die Hilfe,
Lg Andi

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.