Forum: Mikrocontroller und Digitale Elektronik Zufallszahlen und Schleifenaufruf (PIC)


von bower (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem.
Hmm zuerstmal den Code:
1
            if ((time-(timestamp+refresh))>=0)
2
            {
3
                CCPR1L=rand()/330+149;
4
                refresh=rand()/6+3000;
5
                timestamp=time;
6
            }

time ist die Zeit seit Programmstart in ms. timestamp ist zum Zeitpunkt 
der ersten aufrufs der schleife mit 0 und refresh mit 1000 
initialisiert.

Mein Ziel ist es, dass die Schleife in einem zufälligen Zeitintervall 
von 3 bis etwa 8,5s aufgerufen wird. In der Schleife soll eigentlich nur 
ein Wert zwischen 149 und 248 in CCPR1L geschrieben werden und ein neues 
Zufallsintervall bis zum nächsten Aufruf der Schleife generiert werden.

Leider funktioniert das irgendwie überhaupt nicht und ich blicks nicht 
warum :(

Programmiert wird ein PIC 18f1320 mit MPLABX und XC8

Vllt weiß ja jemand Rat :)

von bower (Gast)


Lesenswert?

Achja fast vergessen

time, refresh und timestemp sind unsigned long

von Wolfgang (Gast)


Lesenswert?

bower schrieb:
> Leider funktioniert das irgendwie überhaupt nicht und ich blicks nicht
> warum :(

Und was sagt dir dein Debugger, was genau nicht funktioniert?

von Max H. (hartl192)


Lesenswert?

bower schrieb:
> Leider funktioniert das irgendwie überhaupt nicht und ich blicks nicht
> warum :(

Was funktioniert nicht? Meine Glaskugel ist beim Polieren...

Wieso brauchst du das CCP-Modul und refresh?
Wir dieser Code in der ISR vom CCP ausgeführt?

: Bearbeitet durch User
von bower (Gast)


Lesenswert?

Das CCP Modul brauche ich für eine PWM. Die PWM ist auch korrekt 
konfiguriert wenn ich manuell werte in CCPR1L schreibe kann ich den Duty 
Cycle verändern.

In refresh soll lediglich irgend ein Wert zwischen 0 und 5460 
(((2^15)-1)/6 - von rand()) stehen. Zusammen mit den +3000 ergibt das 
dann irgendwas zwischen 5460 und 8460 was 5,46 - 8,46 Sekunden 
entspricht.

Es hängt auf jedenfall an Zufallszahlengenerierung mit rand();


Ich bin leider nicht so geübt mit dem Debugger..was meinst du genau?

von Max H. (hartl192)


Lesenswert?

bower schrieb:
> Das CCP Modul brauche ich für eine PWM
Du willst also in zufälligen Zeitabständen einen zufälligen PWM-Wert 
ausgeben?

bower schrieb:
> Es hängt auf jedenfall an Zufallszahlengenerierung mit rand();
Also funktioniert die rand() Funktion nicht. Was sagt das User's Manual 
des XC8 zur rand?

von Karl H. (kbuchegg)


Lesenswert?

bower schrieb:

> Es hängt auf jedenfall an Zufallszahlengenerierung mit rand();

WAS hängt an der Zufallszahlengenerierung mit rand()?

Woran machst du das fest? Stimmen die Zeiten nicht, oder was passiert? 
Kommen immer die gleichen Zahlen? Variieren die nicht? Stürzt das System 
ab? Compiliert der Code?


PS:
rand() ist jetzt keine wirklich wahnsinnig komplexe Funktion. Man kann 
also davon ausgehen, dass die nicht ausgerechnet auf deinem System 
fehlerhaft implementiert ist oder gar fehlt.

PS2:
Ich glaubs zwar nicht, dass es was ausmacht. Aber ich würde die 
magischen Konstanten 6 und 330 durch Ausdrücke von RAND_MAX ersetzen. 
Denn genau dazu ist es da.

: Bearbeitet durch User
von Max H. (hartl192)


Lesenswert?

>if ((time-(timestamp+refresh))>=0)
Das würde für mich so logischer aussehen:
if(refresh>=time-timestamp)

Und unser Herr Mod. hat recht: Wenn du nicht mehr Infos geben willst 
solltest du dich nach einem Wahrsager-Forum umsehen.

Der Teil des Codes den du oben gepostet hast sieht eigentlich in Ordnung 
aus.

von Dirk B. (dirkb2)


Lesenswert?

Hast du schon mal die Modulo-Rechnug statt Division probiert?
1
rand()%100+149;
2
rand()%5461+3000;

von Mark B. (markbrandis)


Lesenswert?

Meinst Du die Funktion rand() aus der C Standardbibliothek?

http://www.cplusplus.com/reference/cstdlib/rand/

Vielleicht die Initialisierung vergessen?

Dirk B. schrieb:
> Hast du schon mal die Modulo-Rechnug statt Division probiert?
>
1
rand()%100+149;
2
> rand()%5461+3000;

Oder das.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Mark Brandis schrieb:
> Meinst Du die Funktion rand() aus der C Standardbibliothek?
>
> http://www.cplusplus.com/reference/cstdlib/rand/
>
> Vielleicht die Initialisierung vergessen?

viel schlimmer wäre eine dauerender erneuter Aufruf von srand. Ob der 
seed bei 0 startet oder wo anders, ist hingegen nicht so wild.

>> Hast du schon mal die Modulo-Rechnug statt Division probiert?
>>
1
rand()%100+149;
2
>> rand()%5461+3000;
>
> Oder das.

Könnte helfen. Obwohl. Theoretisch muss es wurscht sein. Er hat seine 
Divisionskonstanten so berechnet, dass der gewünschte Wertebereich 
rauskommt. Ob allerdings RAND_MAX auf seinem System tatsächlich den Wert 
32767 hat, ist eine andere Frage. Wäre aber ungewöhnlich.

von B. S. (bestucki)


Lesenswert?

rand existiert beim XC8 Compiler (User Guide S. 376) und RAND_MAX ist 
gleich 32767.

Wie schnell läuft der Timer? Könnte es sein dass die Ausführung der ISR 
zu lange dauert. Schliesslich arbeitest du mit 32Bit Variablen auf einem 
8Bit Controller. Das Ganze könnte man auch mit 16Bit Variablen 
erledigen.

von Karl H. (kbuchegg)


Lesenswert?

Vorschlag


Ändere den Code mal testweise so ab
1
int checkTimes[] = { 5500, 8200 };
2
int checkPWM[] = { 150, 240 };
3
int checkCnt = 0;
4
5
....
6
7
8
            if ((time-(timestamp+refresh))>=0)
9
            {
10
/*
11
                CCPR1L=rand()/330+149;
12
                refresh=rand()/6+3000;
13
*/
14
                checkCnt++;
15
                checkCnt = checkCnt % 4;
16
17
                CCPR1L = checkTimes[ checkCnt / 2 ];
18
                refresh = checkPWM[ checkCnt % 2 ];
19
20
                timestamp=time;
21
            }
22
23
....

das spielt 4 Kombinationen aus kurzer und langer Zeit bzw. kleiner und 
grosser PWM durch. Wieder und immer wieder.

D.h. theoretisch tut es das. Passiert genau das nicht, dann ist rand() 
aus dem Schneider und du musst dir eine andere Codestelle suchen, der du 
die Schuld in die Schuhe schieben kannst. Passiert aber dieses 
Durchspielen der 4 Werte, dann ist rand() tatsächlich ei heißer 
Kandidat.

also: Änderung machen, compilieren, brennen, testen und das Ergebnis 
berichten.

von B. S. (bestucki)


Lesenswert?

Nochwas: Du sagtest, alle Variablen seien vom Typ unsigned long. Somit 
ist der Ausdruck
1
(time-(timestamp+refresh))>=0
immer wahr. Ein Wert vom Typ unsigned long kann nie negativ werden.

von Max H. (hartl192)


Lesenswert?

be stucki schrieb:
> ist der Ausdruck(time-(timestamp+refresh))>=0immer wahr. Ein Wert vom
> Typ unsigned long kann nie negativ werden.
Dann könnte man das probieren:
> if(refresh>=time-timestamp)

: Bearbeitet durch User
von bower (Gast)


Lesenswert?

Ich brech ab...

be stucki schrieb:
> Nochwas: Du sagtest, alle Variablen seien vom Typ unsigned long.
> Somit
> ist der Ausdruck(time-(timestamp+refresh))>=0immer wahr. Ein Wert vom
> Typ unsigned long kann nie negativ werden.

Max H. schrieb:
> be stucki schrieb:
>> ist der Ausdruck(time-(timestamp+refresh))>=0immer wahr. Ein Wert vom
>> Typ unsigned long kann nie negativ werden.
> Dann könnte man das probieren:
>> if(refresh>=time-timestamp)

Danke euch beiden....das wars.

Ouh man :D

Vielen dank!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.