Problem bei Zeitanzeige auf OLED-Display

Hallo,
ich habe für meinen Nano ein Script geschrieben, welches mir Primzahlen berechnet und diese auf einem OLED-Display ausgibt. In der dritten Zeile wird außerdem die vergangene Zeit der Berechnung angezeigt. Ich verwende millis() als Ausgangszahl und rechne diese in 1/10-Sekunden, Sekunden, Minuten, ... um. Wie auf dem Bild zu sehen gibt es jedoch nach ca. 13 1/4h das Problem, dass die 1/10-Sekunden nicht mehr umgerechnet werden und es zeigt dann einen sehr große Zahl dafür an. Kann mir jemand sagen, woran das liegen könnte? Danke im voraus, 3Domse3.

Code:

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

long start = 0;
long i = 2;

int s = 0;
int m = 0;
int h = 0;
int d = 0;

void setup() {
 pinMode(LED_BUILTIN, OUTPUT);
 
 start = millis();
 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

}

long found = 0;

void loop() {
 long prime = is_prime(i);
 long y = (millis() - start) / 100;

 digitalWrite(LED_BUILTIN, LOW);

 if (y == 10) {
   s++;
   y = 0;
   start = millis();
 }
 
 if (s == 60) {
   digitalWrite(LED_BUILTIN, HIGH);
   
   m++;
   s = 0;
 }

 if (m == 60) {
   h++;
   m = 0;
 }

 if (h == 24) {
   d++;
   h = 0;
 }

 
 if (prime == 1) { 
  
     display.clearDisplay();
 
     display.setTextColor(WHITE);
     display.setTextSize(1);
     display.setCursor(1,0);
     display.println("N: ");
     display.setCursor(17,0);
     display.println(found);
     display.setCursor(1,11);
     display.println("P: ");
     display.setCursor(17,11);
     display.println(i);
     display.setCursor(1,22);
     display.println("T: ");
     display.setCursor(17,22);
     display.println(d);
     display.setCursor(49,22);
     display.println(h);
     display.setCursor(61,22);
     display.println(":");
     display.setCursor(66,22);
     display.println(m);
     display.setCursor(78,22);
     display.println(":");
     display.setCursor(83,22);
     display.println(s);
     display.setCursor(100,22);
     display.println(".");
     display.setCursor(105,22);
     display.println(y);
     display.display();    

     found++;
 }

 i++;
}

long is_prime(long num) {
 long upper = sqrt(num);
 for (long cnum = 2; cnum <= upper; cnum++) {
   long mod = num % cnum;

   if (mod == 0) { 
     return 0; 
   }
 }

 return 1;
}

Warum 2 mal?
https://forum.arduino.cc/index.php?topic=481991.msg3290328#msg3290328

Das Problem dürfte hier liegen:

long prime = is_prime(i);
  long y = (millis() - start) / 100;

  digitalWrite(LED_BUILTIN, LOW);

  if (y == 10) {
    s++;
    y = 0;
    start = millis();
  }

Die Abfrage auf y==10 ist kritisch. Das gilt ja nur für 1/10sec. Sobald deine Primzahlberechnungen länger als diese zehntel Sekunde dauern, kannst Du nicht mehr sicher sein, diesen Zeitpunkt zu erwischen. Und wenn Du ihn einmal verpasst hast, wird er nie mehr erreicht, da y dann immer >10 ist

Und wenn Du ihn einmal verpasst hast, wird er nie mehr erreicht, da y dann immer >10 ist

Alle ca 25 Tage wechselt das Vorzeichen.
So wird y nur ca die Hälfte aller Abfragen > 10 sein
Und y == 10 ist dann bestenfalls nach ca. 50 Tagen wieder wahr

MicroBahner:
Die Abfrage auf y==10 ist kritisch.

Scheint den Nagel auf den Kopf zu treffen:

IMG_6552.png

Hat jmd. eine Idee, wie ich das y == 10-Problem umgehen kann?

Ich habe es mit y >= 10 gemacht, läuft seit einem Tag und über 20 Stunden.

Ich habe es mit y >= 10 gemacht, läuft seit einem Tag und über 20 Stunden.

Super. Vielen Dank :smiley:

ok. Ich setzte mich dann mal ans coden XD. thx

Wenn Du einen schnelleren Algorithmus für die isPrime-Prüfung brauchst, dann schreibe Dir das auf C++-Code für uint_32 als Variablentyp um:

Wäre super :). Könntest du ihn direkt in mein vorhandenes Script einbauen? Bin noch ein ziemlicher Programmier-Neuling ;). Habe auch dieses Script mit Hilfe erstellt.

Super. Vielen Dank! :smiley:

Tag nochmal. Ich versuche jetzt schon seit 30 min die neue Suchfunktion einzubauen, jedoch gibt es immer wieder Fehlermeldungen. Muss ich irgendetwas bestimmtes beachten oder ändern? Copy & Paste und Variabel-Anpassungen reichen nicht aus. Oder hast du es schon in das Script eingebaut und kannst mir den gesamten Code geben? Bin gerade ziemlich ratlos :-?

Ich habe den Code direkt kopiert. Das ist die Fehlermeldung:

E:\Dokumente\Arduino\prime_calc_3_oled_out_time_calc_new_1.ino\prime_calc_3_oled_out_time_calc_new_1.ino.ino: In function 'void loop()':

prime_calc_3_oled_out_time_calc_new_1.ino:27: error: 'is_prime' was not declared in this scope

long prime = is_prime(i);

^

E:\Dokumente\Arduino\prime_calc_3_oled_out_time_calc_new_1.ino\prime_calc_3_oled_out_time_calc_new_1.ino.ino: At global scope:

prime_calc_3_oled_out_time_calc_new_1.ino:99: error: expected initializer before 'if'

if(n<=1) return false;

^

prime_calc_3_oled_out_time_calc_new_1.ino:100: error: expected unqualified-id before 'else'

else if (n<=3) return true;

^

prime_calc_3_oled_out_time_calc_new_1.ino:101: error: expected unqualified-id before 'else'

else if(n%2==0 or n%3==0) return false;

^

prime_calc_3_oled_out_time_calc_new_1.ino:102: error: conflicting declaration 'uint32_t i'

uint32_t i= 5;

^

E:\Dokumente\Arduino\prime_calc_3_oled_out_time_calc_new_1.ino\prime_calc_3_oled_out_time_calc_new_1.ino.ino:9:6: note: previous declaration as 'long int i'

long i = 2;

^

prime_calc_3_oled_out_time_calc_new_1.ino:103: error: expected unqualified-id before 'while'

while (i * i <=n)

^

prime_calc_3_oled_out_time_calc_new_1.ino:108: error: expected unqualified-id before 'return'

return true;

^

prime_calc_3_oled_out_time_calc_new_1.ino:109: error: expected declaration before '}' token

}

^

exit status 1
'is_prime' was not declared in this scope

Bin gerade echt ratlos :-?

Zeige uns deinen aktuellen kompletten Sketch.
Sonst sind wir auch ratlos.

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

long start = 0;
long i = 2;

int s = 0;
int m = 0;
int h = 0;
int d = 0;

void setup() {
pinMode(LED_BUILTIN, OUTPUT);

start = millis();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

}

long found = 0;

void loop() {
long prime = is_prime(i);
long y = (millis() - start) / 100;

digitalWrite(LED_BUILTIN, LOW);

if (y == 10) {
s++;
y = 0;
start = millis();
}

if (s == 60) {
digitalWrite(LED_BUILTIN, HIGH);

m++;
s = 0;
}

if (m == 60) {
h++;
m = 0;
}

if (h == 24) {
d++;
h = 0;
}

if (prime == 1) {

display.clearDisplay();

display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(1,0);
display.println("N: ");
display.setCursor(17,0);
display.println(found);
display.setCursor(1,11);
display.println("P: ");
display.setCursor(17,11);
display.println(i);
display.setCursor(1,22);
display.println("T: ");
display.setCursor(17,22);
display.println(d);
display.setCursor(49,22);
display.println(h);
display.setCursor(61,22);
display.println(":");
display.setCursor(66,22);
display.println(m);
display.setCursor(78,22);
display.println(":");
display.setCursor(83,22);
display.println(s);
display.setCursor(100,22);
display.println(".");
display.setCursor(105,22);
display.println(y);
display.display();

found++;
}

i++;
}

bool is_prime(uint32_t n)
//umgesetzt nach dem Algorithmus von //Primality test - Wikipedia
if(n<=1) return false;
else if (n<=3) return true;
else if(n%2==0 or n%3==0) return false;
uint32_t i= 5;
while (i * i <=n)
{
if(n%i== 0 or n%(i + 2) == 0) return false;
i+=6;
}
return true;
}

3Domse3:
}

Setze mal am Anfang der auskommentierten Zeile eine öffnende geschweifte Klammer:

{//umgesetzt nach dem Algorithmus von //Primality test - Wikipedia

die Klammer scheint mir beim Kopieren verloren gegangen sein.

Sorry, aber aus diesem Thema bin ich raus und habe meine vorangegangenen Beiträge gelöscht, weil sie dir offenbar überhaupt nichts genützt haben und mir zum Schluss auch noch der Kopierfehler mit dergeschweiften Klammer passiert ist, den Du nicht selbst debuggen konntest.

BYE

Ok. Vielen Dank :smiley: