PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : keine vollständige Serial.print Ausgabe



HaWe
30.11.2018, 19:42
hallo ,
der folgende Code ergibt keine vollständige Serielle Ausgabe
(original Code von hier, angepasst: https://stackoverflow.com/questions/26516577/pseudo-random-number-genetor-based-on-lcg)



//********************************************
// randomize functions
//********************************************


uint32_t getSeed() {
return (millis() + analogRead(A0)) ;
}


//-----------------------------------------------------
// Linear Congruence Generator, LCG
//-----------------------------------------------------

static uint32_t _RandNum_ = 1;

int rand_LCG() {
uint32_t a = 1103515245ul, c = 12345;
_RandNum_ = a * _RandNum_ + c;
_RandNum_ = (uint16_t)(_RandNum_ / 65536);
return (_RandNum_ % 32768) ;
}


void srand_LCG(uint32_t seed) {
_RandNum_ = seed;
}


//--------------------------------------------
// setup
//--------------------------------------------
void setup() {

Serial.begin(115200);
delay(2000);

Serial.println("starting...");
Serial.println();

volatile uint32_t prng, seed;
int16_t i;
char buf[30];

Serial.print("srand_LCG() seed=");
seed=1;
Serial.println(seed);
srand_LCG(seed);
//Serial.println(_RandNum_);
for(i==0; i<10; i++) {
prng=rand_LCG();
Serial.print(i); Serial.print(" "); Serial.println(prng);
}
Serial.println();


Serial.print("srand_LCG() seed=");
seed=2;
Serial.println(seed);
srand_LCG(seed);
//Serial.println(_RandNum_);
for(i==0; i<10; i++) {
prng=rand_LCG();
Serial.print(i); Serial.print(" "); Serial.println(prng);
}
Serial.println();
}

//--------------------------------------------
// loop
//--------------------------------------------
void loop() {
delay(2000);
}




auf dem esp8266 wird nur die erste, aber nicht die 2. for-Schleife angezeigt, dann hängt er sich auf:


starting...

srand_LCG() seed=1
0 16838
1 14666
2 10953
3 11665
4 7451
5 26316
6 27974
7 27550
8 31532
9 5572

srand_LCG() seed=2



auf dem Due aber wird gar keine for-Schleife mehr angezeigt:


starting...

srand_LCG() seed=1

srand_LCG() seed=2




Wo zum .... steckt der Fehler?

Moppi
30.11.2018, 21:02
So würde ich das machen:

//********************************************// randomize functions
//********************************************


uint32_t getSeed() {
return (millis() + analogRead(A0)) ;
}


//-----------------------------------------------------
// Linear Congruence Generator, LCG
//-----------------------------------------------------

static uint32_t _RandNum_ = 1;

int rand_LCG() {
uint32_t a = 1103515245ul, c = 12345;
_RandNum_ = a * _RandNum_ + c;
_RandNum_ = (uint16_t)(_RandNum_ / 65536);
return (_RandNum_ % 32768) ;
}


void srand_LCG(uint32_t seed) {
_RandNum_ = seed;
}


//--------------------------------------------
// setup
//--------------------------------------------
void setup() {

Serial.begin(115200);
delay(2000);

Serial.println("starting...");
Serial.println();

volatile uint32_t prng, seed;
int16_t i;
char buf[30];

Serial.print("srand_LCG() seed=");
seed=1;
Serial.println(seed);
srand_LCG(seed);
//Serial.println(_RandNum_);
for(int i=0; i<10; i++) {
prng=rand_LCG();
Serial.print(i); Serial.print(" "); Serial.println(prng);
}
Serial.println();


Serial.print("srand_LCG() seed=");
seed=2;
Serial.println(seed);
srand_LCG(seed);
//Serial.println(_RandNum_);
for(int i=0; i<10; i++) {
prng=rand_LCG();
Serial.print(i); Serial.print(" "); Serial.println(prng);
}
Serial.println();
}

//--------------------------------------------
// loop
//--------------------------------------------
void loop() {
delay(2000); }

HaWe
30.11.2018, 21:26
warum ist das besser?
(vorher hatte ich ja int16_t i)

- - - Aktualisiert - - -

update:
komisch, jetzt läuft es auf dem Due auch mit int16_t wie zuvor im ersten Code.... :confused:
und auf dem esp8266 auch ... :confused: :confused:


hast du noch was anderes abgeändert?

Moppi
30.11.2018, 22:07
Nein, habe ich nicht. Deswegen habe ich das Rot markiert.

"I==0" ist falsch weil "==" ein Vergleichsoperator ist. Bin leider auch schon mindestens einmal drauf reingefallen. Den Typ schreibe ich davor, damit der Compiler weiß, was er genau für eine Variable anlegen soll. Ob das notwendig ist? - Keine Ahnung, schadet aber nicht.

HaWe
30.11.2018, 22:32
ogottogottogott, dass mir sowas noch passiert ist ... ](*,) :Haue

aber nein, wenn das int i dafür bereits außerhalb deklariert wurde, muss man das nicht unbedingt innen auch noch mal neu für die Schleife lokal als int deklarieren.

Moppi
30.11.2018, 23:18
Ich habe nur schnell drüber geschaut und das "int i" außen nicht gesehen. Weil Du das wieder mit Deiner Lieblingsmethode gemacht hast: int16_t i;

:)

Klebwax
01.12.2018, 01:13
aber nein, wenn das int i dafür bereits außerhalb deklariert wurde, muss man das nicht unbedingt innen auch noch mal neu für die Schleife lokal als int deklarieren.

Das ist so nicht richtig. Wenn man eine Variable innerhalb eines Blocks, einer Schleife, deklariert, wird eine neue lokale Variable angelegt. Und das auch, wenn außerhalb des Blocks schon eine des gleichen Namens existiert. Es gibt da kein "nicht unbedingt".

MfG Klebwax

HaWe
01.12.2018, 10:02
Das ist so nicht richtig. Wenn man eine Variable innerhalb eines Blocks, einer Schleife, deklariert, wird eine neue lokale Variable angelegt. Und das auch, wenn außerhalb des Blocks schon eine des gleichen Namens existiert. Es gibt da kein "nicht unbedingt".

MfG Klebwax

ich meinte das anders: nicht unbedingt dann, wenn man das i außerhalb der Schleife nicht unbedingt für andere Zwecke braucht als nur für einen Schleifenzähler dann und wann. Aber ich verstehe schon, was du meinst:
dass für for(int i....) immer wieder eine neue lokale Schleifenvariable angelegt wird, was ich bei mir allerdings nicht unbedingt brauchte ;)

@moppi: int16_t verwende ich gerne dann, wenn ich vermeiden will, dass bei größeren MCUs der Compiler für ein int 32bit Speicher reserviert, was ansonsten bei 32bit ARM cpus passiert.

Moppi
01.12.2018, 10:49
Streng genommen sollte für die Schleife eine neue Variable erzeugt werden, die nur innerhalb der Schleife gültig ist. Weiß aber nicht, ob das hier in diesem C-Programmierkram auch so ist. Wenn es keine Warnung vom Compiler gibt, dass >>i<< schon existiert, müsste das schon so sein, ich weiß es hier aber auch nicht genau. Ich programmiere zwar schon 28 Jahre, die ersten 10 bis 20 fast täglich als Hauptbeschäftigung, aber C/C++ und Java zusammengenommen davon nur wenige Monate. In C/C++ habe ich eigentlich nie was gemacht, nur immer versuchsweise, mal ein paar Tage oder eine Woche, hin und wieder. Jetzt für Arduino ist, dass ich es mal intensiver verwende. Deshalb, wenn ich den Code so überfliege, springen mir die Sachen dann nicht sofort ins Auge, weil ich mehr nach "int i=...;" Ausschau halte und da ist es mir nicht aufgefallen.

MfG

HaWe
01.12.2018, 11:03
Streng genommen sollte für die Schleife eine neue Variable erzeugt werden, die nur innerhalb der Schleife gültig ist.

warum sollte das der Fall sein, wenn ich nur 1 int Zähler-Variable für ein paar Dutzend Einsatzzwecke nacheinander brauche?

(dass du das mit meinem int16_t verstanden und hier nur übersehen hast, war mir schon klar, ich wollte nur begründen, warum ich grundsätzlich (fast immer) die stdint-Variablentypen int16_t (und daneben auch weitgehend int8_t, int32_t, selten sogar auch int64_t etc.) verwende. )

Moppi
01.12.2018, 11:41
Ich hatte geschrieben:


for(int i=0; i<10; I++){}

Hier soll die Variable nur innerhalb der for-Schleife existieren und keine in einem übergeordneten Scope überschreiben.

Wenn Du das anders haben möchtest, machst Du das so, wenn die Programmiersprache das zulässt. Das ist so gesehen ja kein Fehler. Ich halte es nur für ungünstig. Der Vorteil dabei ist, dass Programmteile (die oft auch Schleifen beinhalten) einfach mal von einem Codemodul in ein anderes kopiert werden können, ohne die Umgebung zu ändern - weil die Zählervariable nur lokal in der Schleife existent ist.

Wenn die Programme immer größer werden und mehr und mehr Module zusammenkommen, ist es irgendwann einfacher lokale Variablen zu verwenden, dafür dann aber für bestimmte Zwecke immer mit dem selben Namen. Das vereinfacht die Fehlersuche, weil man sich dann auf einen bestimmten Bereich beschränken kann. Man hat immer in einem recht übersichtlichen Bereich die Variablen, die man für einen Programmabschnitt benötigt. Wenn die Projekte größer und größer werden, dann werden Variablen weiter und weiter verstreut (je nachdem, in welchem Scope die angesiedelt sind), die kann man dann teilweise wirklich suchen gehen, wenn mal was nicht hin haut, das macht es dann teils sehr viel aufwendiger.

Wenn ich ein Problem mit einer Schleife habe, ist es meine Angewohnheit, erst mal dafür zu sorgen - zum Ausprobieren, dass dort wo es nicht funktioniert, klare Verhältnisse herrschen. Also wurde aus dem "for(i==0..." ein "for(int i=0...". Das war der Einfachheit halber, ich wollte mich so lange damit eigentlich nicht beschäftigen ;) Und es gab natürlich den Grund, dass ich die Deklaration von "i" außerhalb der Schleife übersah.

MFG

HaWe
01.12.2018, 11:55
ja, da gebe ich dir Recht.
Ich hatte auch intuitiv vermutet, dass wenn ich 100x eine for-Schleife mit nur 1 einzigen übergeordneten Zählervariablen verwende, dann weniger Speicher bräuchte als wenn ich 100x for-Schleifen mit jeweils 1 eigenen internen for-Zähler hätte (also insgesamt 100 internen Zählern)
- was aber durchaus ein Irrtum meinerseits gewesen sein wird.
Der gpp Compiler ist offenbar schlauer als ich dachte... 8)