Millis wird schneller

Hallo

ich habe ein etwas kurioses Problem, bei mir scheint millis() zu spinnen. Irgendwann nach ~1min, Start des Arduino, wird es schneller oder ungenau.
Also ich benutzt einen Arduino Nano(+5V), mit neuem Bootloader. Daran hängen

  • 2X Taster

  • 2X Status LED

  • 2X Fototransistor

  • 1X FRAM Chip MB85RC256V

  • 1X 0.96 Zoll OLED Display SSD1306 I2C 128x64

Elektrisch und Mechanisch läuft alles.

FRAM und Display laufen über I2C.
Für den FRAM benutzte ich Adafruit_FRAM_I2C.h von Adafruit.
Für den Display verwende ich SSD1306Ascii.h von William Greiman (glaube ich).

Also das Projekt soll am Ende mal ein Betrieb-Stunden/Zeit-Zähler für einen CO2 Lasercutter-[K40] werden.
Kurz: der Arduino stellt über die 2 Fototransistoren fest ob die Laserröhre zündet/strahlt, zählt das in Millisekunden, speichert den Wert im FRAM (hält Werte auch ohne Strom und jede Zelle/Byte kann bis zu 1-Billion Mal beschrieben werden) und zeigt den Wert im Display an.

Das ganze soll einmal die wahre Laufzeit der Röhre dokumentieren, wichtiger ist aber das ich ungefähr zählen kann wie lange der Laser wirklich läuft, damit ich weiß wann ich die Spiegel wieder mal putzen muss.

So nun zu meinem Problem. Mir ist schon früher beim Programmieren und Testen ist mir aufgefallen das die Laufschrift die ich verwende, irgendwann schneller wird. Was mich nicht sonders gestört hat (ist mir auch kaum aufgefallen)

Die Laufschrift wird über eine Schleife und einem millis() Wert gesteuert.

#define DELAY_Display        80   // Aktualisierungsintervall für Bildschirm

void loop() {
  if (int_tick_Display <= millis()) {
    int_tick_Display = millis() + DELAY_Display;
    F_TickerText();
  }
...
..
.
void F_TickerText() {
  // Should check for error. rtn < 0 indicates error.
  rtn = oled.tickerTick(&state);
  // See above for definition of RTN_CHECK.
  if (rtn <= RTN_CHECK) {
    // Should check for error. Return of false indicates error.
    oled.tickerText(&state, &str_Text[(n++) % 3]);
  }
}

Richtig schwer ist der Fehler jetzt in einer anderen Funktion zu sehen. 1 der Taster ist ein Reset-Taste, setzt den Wert des Speichers auf NULL. (Wenn man mal die Röhre tauscht o.ä.)

Der Taster sitzt auf der Platine und ich hatte mir vorgestellt das man die Taste 1X drückt und dann ein Countdown von 10 bis 0 (in Sekunden) gezählt wird, in der das Programm auf einen Bestätigung (noch mal drücken) zur Bestätigung wartet.

void F_Reset() {
  unsigned int int_Delay_Run = 0;
  int int_Runs = 10;
  oled.clear();
  while (digitalRead(PIN_Reset_Switch) == LOW) {

  }
  do {
    if (digitalRead(PIN_Reset_Switch) == LOW) {
      while (digitalRead(PIN_Reset_Switch) == LOW) {
      }
      oled.clear();
      oled.set2X();
      oled.print("");
      oled.println(" Delete!!");
      delay(DELAY_Delay * 2);
      break;
    }
    if (int_Delay_Run <= millis()) {
      oled.clear();
      oled.set1X();
      oled.println("Zum loeschen,");
      oled.println("  Taste druecken.");
      oled.set2X();
      oled.print("   ");
      oled.println(int_Runs);
      int_Delay_Run = millis() + 1001;
      int_Runs = int_Runs - 1 ;
    }
  } while (int_Runs >= 0);
  F_Display_Normal();
}

Kurz nach dem Start des Arduino zählt die Schleife auch korrekt die Sekunden runter (es sind genau genommen auch 1Sekunde +1Millisekunde [1001ms]. Nach einer Weile, so ~1 Minute zählt die Schleife aber keine Sekunden mehr, eher 1/2 oder noch weniger. (Es wird wirklich schnell).

Leider weiß ich nicht wie und ob man hier ein Video hochladen kann, sonst würde ich es vorführen.. also müsst ihr mir einfach glauben.

Hat jemand eine Idee wo der Fehler liegen könnte oder wo ich danach suchen soll?

Ich spiele auch nicht mit irgendwelchen tieferen Registern oder so rum, nur einen Hardware Interrupt brauche ich, PIN 3. Er stellt fest ob die Spannungsversorgung ausfällt, damit die letzten Werte in den FRAM geschrieben werden kann. Der Arduino und der FRAM werden währenddessen von 2 größeren Kondensatoren gestützt.

Zum Verständnis hier der aktuelle Code. Er ist A) noch nicht vollständig B) noch in Entwicklung C) in einigen Teilen bestimmt nicht schön!!!!!!


#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include "Adafruit_FRAM_I2C.h"
//
#define RTN_CHECK 1
//
#define I2C_ADDRESS_Display 0x3C  // I2C Adresse des Displays
#define I2C_ADDRESS_FRAM    0x50  // I2C Adresse des FRAMs
//
#define PIN_Power_Interrupt   3   // Interrupt PIN, falling/fallend, führt FRAM->Speichern aus bevor der Strom weg geht
#define PIN_Reset_Switch      7   // Setzt die Laufzeit auf 0 und speichert sie
#define PIN_Housing_Switch    5   // Schalter für die Abdeckung, für den Fall das es Streulicht gibt.
#define PIN_Fototransistor_1  A3  // 
#define PIN_Fototransistor_2  A2  //
#define PIN_LED_Rot           9   // Status LED Grün
#define PIN_LED_Gruen         8   // Status LED Rot
//
#define DELAY_Display        80   // Aktualisierungsintervall für Bildschirm
#define DELAY_Delay        1200   // Verzögerung Schrift
#define DELAY_Fram_Write   1000   // Aktualisierungsintervall für Schreiben in FRAM
#define DELAY_Werte       12000   // Aktualisierungsintervall für Aufbau der Laufschrift-/-String
//
#define FRAM_ADDRESS_J    0x00    // Adresse in FRAM pro Byte
#define FRAM_ADDRESS_T1   0x01    //
#define FRAM_ADDRESS_T2   0x02    //
#define FRAM_ADDRESS_Std  0x03    //
#define FRAM_ADDRESS_Min  0x04    //
#define FRAM_ADDRESS_Sek  0x05    //
#define FRAM_ADDRESS_Ms1  0x06    //
#define FRAM_ADDRESS_Ms2  0x07    //
//
struct Zeit {
  byte           byt_Jahr;
  unsigned int   int_Tag;
  byte           byt_Stunde;
  byte           byt_Minuten;
  byte           byt_Sekunde;
  unsigned int   int_Millisekunde;
};
//
SSD1306AsciiWire oled;
TickerState state;
int8_t rtn ;
unsigned int int_tick_Display;
unsigned int int_tick_Fram_Write;
unsigned int int_tick_Wert;
//
Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();
//
int n;
char str_Text[34];
Zeit stru_Zeit = {99, 364, 23, 59, 59, 999};
//

byte byt_firstByte ;
byte byt_secondByte ;

//
void setup() {
  rtn = 0 ;
  int_tick_Display = 0;
  n = 0;
  //Eingänge
  pinMode(PIN_LED_Rot, OUTPUT);
  pinMode(PIN_LED_Gruen, OUTPUT);
  //Ausgänge
  pinMode(PIN_Power_Interrupt, INPUT);
  pinMode(PIN_Reset_Switch, INPUT);
  pinMode(PIN_Housing_Switch, INPUT);
  pinMode(PIN_Fototransistor_1 , INPUT);
  pinMode(PIN_Fototransistor_2 , INPUT);
  //Interrupt für Power-Los -> Save to FRAM
  attachInterrupt(digitalPinToInterrupt(PIN_Power_Interrupt), F_Interrupt, CHANGE);
  //Schalte LED Aus
  digitalWrite(PIN_LED_Rot, HIGH);
  digitalWrite(PIN_LED_Gruen, HIGH);
  //I2C AN
  Wire.begin();
  Wire.setClock(400000L);
  //LCD
  oled.begin(&Adafruit128x64, I2C_ADDRESS_Display);
  //FRAM
  fram.begin(I2C_ADDRESS_FRAM);
  //
  Serial.begin(115200);  //Serial Port mit 115200 Speed
  //
  F_FRAM_Read();
  delay(DELAY_Delay);
  //Laufschrift
  F_Display_Normal();

}

void loop() {
  if (int_tick_Display <= millis()) {
    int_tick_Display = millis() + DELAY_Display;
    F_TickerText();
  }
  if (int_tick_Wert <= millis()) {
    int_tick_Wert = millis() + DELAY_Werte;
    F_MakeString();
  }
  if (digitalRead(PIN_Reset_Switch) == LOW) {
    F_Reset();
  }
}

void F_Reset() {
  unsigned int int_Delay_Run = 0;
  int int_Runs = 10;
  oled.clear();
  while (digitalRead(PIN_Reset_Switch) == LOW) {

  }
  do {
    if (digitalRead(PIN_Reset_Switch) == LOW) {
      while (digitalRead(PIN_Reset_Switch) == LOW) {
      }
      oled.clear();
      oled.set2X();
      oled.print("");
      oled.println(" Delete!!");
      delay(DELAY_Delay * 2);
      break;
    }
    if (int_Delay_Run <= millis()) {
      oled.clear();
      oled.set1X();
      oled.println("Zum loeschen,");
      oled.println("  Taste druecken.");
      oled.set2X();
      oled.print("   ");
      oled.println(int_Runs);
      int_Delay_Run = millis() + 1001;
      int_Runs = int_Runs - 1 ;
    }
  } while (int_Runs >= 0);
  F_Display_Normal();
}

void F_Display_Normal() {
  oled.clear();
  oled.tickerInit(&state, ZevvPeep8x16, 4, false, 0, 255);
  oled.clear();
  oled.set1X();
  oled.setFont(ZevvPeep8x16);
  oled.println("  Betriebszeit");
  oled.println();
}

void F_Interrupt() {
  F_FRAM_Write();
}

void F_Debug_Serial() {
  Serial.print("Jahr = ");
  Serial.println(stru_Zeit.byt_Jahr);
  Serial.print("Tag = ");
  Serial.println(stru_Zeit.int_Tag);
  Serial.print("Stunde = ");
  Serial.println(stru_Zeit.byt_Stunde);
  Serial.print("Minute = ");
  Serial.println(stru_Zeit.byt_Minuten);
  Serial.print("Sekunde = ");
  Serial.println(stru_Zeit.byt_Sekunde);
  Serial.print("Millisekunde = ");
  Serial.println(stru_Zeit.int_Millisekunde);
}

void F_FRAM_Read() {
  detachInterrupt(digitalPinToInterrupt(PIN_Power_Interrupt));
  //
  oled.clear();
  oled.setFont(ZevvPeep8x16);
  oled.println();
  oled.println("   Lese FRAM");
  oled.println();
  delay(DELAY_Delay);
  //
  stru_Zeit.byt_Jahr = fram.read(FRAM_ADDRESS_J);
  //
  byt_firstByte = fram.read(FRAM_ADDRESS_T1);
  byt_secondByte = fram.read(FRAM_ADDRESS_T2);

  stru_Zeit.int_Tag = int(byt_firstByte << 8) + int(byt_secondByte);
  byt_firstByte = 0;
  byt_secondByte = 0;
  //
  stru_Zeit.byt_Stunde = fram.read(FRAM_ADDRESS_Std);
  stru_Zeit.byt_Minuten = fram.read(FRAM_ADDRESS_Min);
  stru_Zeit.byt_Sekunde = fram.read(FRAM_ADDRESS_Sek);
  //
  byt_firstByte = fram.read(FRAM_ADDRESS_Ms1);
  byt_secondByte = fram.read(FRAM_ADDRESS_Ms2);
  stru_Zeit.int_Millisekunde = int(byt_firstByte << 8) + int(byt_secondByte);
  byt_firstByte = 0;
  byt_secondByte = 0;
  oled.clear();
  oled.setFont(ZevvPeep8x16);
  oled.println();
  oled.println("  FERTIG!");
  oled.println();
  delay(DELAY_Delay * 2);
  attachInterrupt(digitalPinToInterrupt(PIN_Power_Interrupt), F_Interrupt, CHANGE);
}

void F_FRAM_Write() {
  detachInterrupt(digitalPinToInterrupt(PIN_Power_Interrupt));
  byt_firstByte = 0;
  byt_secondByte = 0;
  //
  fram.write(FRAM_ADDRESS_J, stru_Zeit.byt_Jahr);
  //
  byt_firstByte = byte(stru_Zeit.int_Tag >> 8);
  byt_secondByte = byte(stru_Zeit.int_Tag & 0x00FF);
  fram.write(FRAM_ADDRESS_T1, byt_firstByte);
  fram.write(FRAM_ADDRESS_T2, byt_secondByte);
  //
  fram.write(FRAM_ADDRESS_Std, stru_Zeit.byt_Stunde);
  fram.write(FRAM_ADDRESS_Min, stru_Zeit.byt_Minuten);
  fram.write(FRAM_ADDRESS_Sek, stru_Zeit.byt_Sekunde);
  //
  byt_firstByte = 0;
  byt_secondByte = 0;
  byt_firstByte = byte(stru_Zeit.int_Millisekunde >> 8);
  byt_secondByte = byte(stru_Zeit.int_Millisekunde & 0x00FF);
  fram.write(FRAM_ADDRESS_Ms1, byt_firstByte);
  fram.write(FRAM_ADDRESS_Ms2, byt_secondByte);
  attachInterrupt(digitalPinToInterrupt(PIN_Power_Interrupt), F_Interrupt, CHANGE);
}

void F_TickerText() {
  // Should check for error. rtn < 0 indicates error.
  rtn = oled.tickerTick(&state);
  // See above for definition of RTN_CHECK.
  if (rtn <= RTN_CHECK) {
    // Should check for error. Return of false indicates error.
    oled.tickerText(&state, &str_Text[(n++) % 3]);
  }
}

void F_MakeString() {
  n = 0;
  //stru_Zeit.int_Jahr
  // 1 -> 99
  //stru_Zeit.int_Tag
  // 1 -> 99
  //stru_Zeit.byt_Stunde
  // 1 -> 23
  //stru_Zeit.byt_Minuten
  // 1 -> 59
  //stru_Zeit.byte_Sekunde
  // 1 -> 59
  //stru_Zeit.int_Millisekunde
  // 1 -> 999
  //" J99:T365:Std24:Min59:Sek59:Ms999 ";
  if (stru_Zeit.byt_Jahr != 0) {//1
    sprintf(str_Text, " J%02d:T%03d:Std%02d:Min%02d:Sek%02d:Ms%03d ", stru_Zeit.byt_Jahr, stru_Zeit.int_Tag , stru_Zeit.byt_Stunde , stru_Zeit.byt_Minuten , stru_Zeit.byt_Sekunde , stru_Zeit.int_Millisekunde);
  }
  else if (stru_Zeit.int_Tag != 0) {//2
    sprintf(str_Text, "      T%03d:Std%02d:Min%02d:Sek%02d:Ms%03d ", stru_Zeit.int_Tag , stru_Zeit.byt_Stunde , stru_Zeit.byt_Minuten , stru_Zeit.byt_Sekunde , stru_Zeit.int_Millisekunde);
  }
  else if (stru_Zeit.byt_Stunde != 0) {//3
    sprintf(str_Text, "           Std%02d:Min%02d:Sek%02d:Ms%03d ", stru_Zeit.byt_Stunde , stru_Zeit.byt_Minuten , stru_Zeit.byt_Sekunde , stru_Zeit.int_Millisekunde);
  }
  else if (stru_Zeit.byt_Minuten != 0) {//4
    sprintf(str_Text, "                Min%02d:Sek%02d:Ms%03d ", stru_Zeit.byt_Minuten , stru_Zeit.byt_Sekunde , stru_Zeit.int_Millisekunde);
  }
  else if (stru_Zeit.byt_Sekunde != 0) {//5
    sprintf(str_Text, "   Sek%02d:Ms%03d   Sek%02d:Ms%03d   ",  stru_Zeit.byt_Sekunde , stru_Zeit.int_Millisekunde,  stru_Zeit.byt_Sekunde , stru_Zeit.int_Millisekunde);
  }
  else {//6
    sprintf(str_Text, "  Ms%03d  Ms%03d  Ms%03d  Ms%03d  ",  stru_Zeit.int_Millisekunde,  stru_Zeit.int_Millisekunde, stru_Zeit.int_Millisekunde,  stru_Zeit.int_Millisekunde);
  }
}

Es Fehlen noch wichtige Ding, in der Reset Funktion werden zur Zeit nicht mal die Werte geändert!!!
Wäre es nur ein Fehler oder etwas Unschönes im Display, wäre es mir egal. Wenn millis() aber falsche Werte liefert, dann führt das das ganze Projekt (Zeit Zählen) ad absurdum!!!

Ich vermute den Fehler in einer der Bibiotheken und da die für den Display. Ich würde die aber ungerne wechseln, da genau die die coole Laufschrift bietet :: und mir fehlt das Fachwissen die Lib jetzt Zeile für Zeile zuverstehen.

Schon mal Danke fürs Nachdenken usw.

Wie soll ein 32Bit Wert in einen 16Bit Wert passen?

Wo?

Ich nenne das die AdditionsMethode.
Die ist defekt.
Tut nicht!

Ansonsten machst du da noch viel mehr komische Sachen!
z.B. viele delay()
viel define
Weg damit, auf den Haufen der Geschichte!

Nein, millis() ist voll ok.
Das Problem ist das defekte Programm.

Oh MIST...millis gibt ULong's...und ich habe int ARRRRRRRRG MIST!
Nicht

unsigned int int_tick_Display;
unsigned int int_tick_Fram_Write;
unsigned int int_tick_Wert;
unsigned int int_Delay_Run = 0;

sondern

unsigned long int_tick_Display;
unsigned long int_tick_Fram_Write;
unsigned long int_tick_Wert;
unsigned long int_Delay_Run = 0;

Was für ein dummer Fehler. Sorry

1 Like

Nehme gerne Tipps an aber ??
4X delay() die brauche ich damit der Text auf dem Display auch so lange da steht, das man ihn lesen kann.
Was stört dich an den #define ?? Einmal habe ich das so im Studium gelernt und es ist viiieeelll einfacher Code zu lesen wenn da nicht nur Zahlen stehen.

Das geht auch anders.

Alles!
Das geht auch anders.
constexpr byte PIN_LED_Rot { 9}; // Status LED Grün

Da sage ich nichts gegen!

öööööööööö

Beispiel:

#define FRAM_ADDRESS_J    0x00    // Adresse in FRAM pro Byte
#define FRAM_ADDRESS_T1   0x01    //
#define FRAM_ADDRESS_T2   0x02    //
#define FRAM_ADDRESS_Std  0x03    //
#define FRAM_ADDRESS_Min  0x04    //
#define FRAM_ADDRESS_Sek  0x05    //
#define FRAM_ADDRESS_Ms1  0x06    //
#define FRAM_ADDRESS_Ms2  0x07    //

Der Brocken ist komplett überflüssig!

Warum?
Du schreibst und liest sowieso die ganze Struktur...
Dann mach das doch auch in einem Brocken.

Adressen händisch zu vergeben ist (fast) immer eine dumme Idee!
viel zu schnell vertut man sich.

C?
Wie lange ist das her?
Wir sind bei AVR Arduinos bei C++11

Wie gesagt ich versuche immer dazu zu lernen aber mhhhhh??? ::

Also Punkt für Punkt. Delay()

Ähm, ja bestimmt mir fallen 1-2 Wege ein aber die sind viel komplizierter. Wieso sollte ich das tun? Was ist an delay() so schlimm/falsch? Wenn ich eine Verzögerung und Halt brauche..dann benutze ich es auch.

#define vs. constexpr. constexpr Habe ich schon mal gesehen und schnell gelesen wo der Unterschied liegt. Für mich sehe ich jetzt nicht wo der Gewinn liegen soll. Verbraucht man damit weniger Speicher o.ä....

Ja der Block mit den define's der FRAM Adressen... einmal ist das der/meiner Entwicklung geschuldet. Zum Teil ist er etwas überflüssig oder überzogen, hat aber den Hintergrund das die Lib zum schreiben eine Adresse und ein Byte erwartet. So was wie ein Serielles Lesen gibts da nicht.
Man könnte für jeden Schreibvorgang die Adresse um +1 hoch zählen oder so. So weiß ich oder auch mal andere wo genau ein Wert/Byte steht. Wie gesagt der Chip kann min 1-Biilionen mal auf jedes Byte schreiben.
Wenn ich das nicht falsch überschlagen hab, kann ich, wenn ich jede Sekunde schreibe, das Gerät ~31709 Jahre laufen lassen. 10 Hoch 12 Schreibvorgänge sind echt ne Menge und da so ne Röhre ca ~2Jahre laufen soll (so ließt man das immer mal wieder), kann ich gut die ersten 8 Bytes kaputt schreiben.

Wir haben mal ganz old School ANSI C gelernt ist schon mehr als 10 Jahre her und da das ein privates Projekt ist, lerne ich dafür kein neues C++11 o.ä., da liegt so meine Grenze.

Und die Structs...ja so habe ich das halt mal gelernt...und da ist es einfach tief drin und wenn ich das richtig gesehen habe verbrauchen Structs keinen Speicher, der Code sieht halt nur anders aus (für manche bestimmt komisch) ich kann es aber besser lesen und im Kopf herumschieben.

Vorschlag abgelehnt!
(verstanden)

Typesicherer!
Der Compiler beschützt dich vor dummen Fehlern.
Wie wir eben gesehen haben, bist auch du nicht gefeit.

Vorschlag abgelehnt!
(verstanden)

Hmmm...
Du schreibst C++11 Programme, willst aber die Sprachen nicht lernen, welche du verwendest.
Aha...
Scheint mir nicht logisch.....

Vorschlag abgelehnt!
(verstanden)

Ich habe nichts gegen struct!
Hättest du sie nicht drin, hätte ich sie dir empfohlen.

Falsch!
bool Adafruit_EEPROM_I2C::write(uint16_t addr, uint8_t *buffer, uint16_t num)

Jetzt kannst du natürlich sagen: "Ich habe doch kein EEPROM!"
Allerdings: class Adafruit_FRAM_I2C : public Adafruit_EEPROM_I2C

Das weißt du auch auf anderem Wege!
Tipp: offsetof() wurde nicht ohne Grund erfunden,

Vorschlag abgelehnt!
(verstanden)

Insgesamt:
Ich spüre bei dir ein ausgeprägtes Beharrungsvermögen.
Im Grunde ist mir das egal, ich finde es nur schade, dass du dir damit selber im Wege rum stehst.!

Vorschläge abgelehnt!
(verstanden)
Du hast nun deine Ruhe vor mir.

Erst mal Danke für den Input.

Das mit dem Delay.. einmal hast du in allen Antworten nicht gesagt was du benutzten würdest und was daran besser ist. So lange bleibe ich bei meiner Meinung das ich delay() benutzt, wenn ich es brauche und so lange es nicht als 'Ab-gekündigt' gekennzeichnet ist.
Mir fallen sonst nur irgendwelche Schleifen ein, wo ich wieder millis vergleiche. Aber wozu sollte ich das machen?

constexpr: Das das Typensicher ist hatte ich nicht auf dem Schirm. Da hast du recht, es ist besser. Da ich #define hier aber eher zum Ersetzten und zum (besser)Lesen benutzte...naja...ich überlege es mir ob ich es ändere. Mal sehen, wenn ich aber mal mit so etwas rechnen oder vergleichen sollte, dann benutzte ich ab jetzt constexpr. Danke dafür.

C++11
Ich bin nicht dagegen was neues zu lernen aber so lange meine Wege funktionieren und ich muss zugeben, wenn ich was nicht weiß, lese ich es hier unter Arduino nach und nicht auf C++ Seiten. Da lese ich wenige "Neuigkeiten".

FRAM Adresse
Ja es gibt auch ein Beispiel das Objekte Speichert, habe es mir angesehen. Aber ich brauche nur 8 Byte. Daher fand ich meinen Weg einfacherer.
So muss ich "nur" zwei int's in Bytes zerlegen, den Rest kann ich 1:1 wegschreiben.
Die Write Funktion ist die einzige Sache an dem ganzen Projekt das etwas Zeitkritisch ist. Die Kondensatoren liefern nicht ewig Saft, daher wollte ich etwas benutzten das ich 100% verstehe und die Kontrolle habe.

Ja ich weiß das Adafruit_FRAM_I2C von Adafruit_EEPROM_I2C erbt.

Aber ich muss gestehen das ich den Grund, man sollte die Funktion benutzten, weil es sie gibt, eher so lala finde. Das IC ist intern in Bytes organisiert, wieso sollte ich also nicht damit arbeiten?

Ich verstehe das du mich als sagen wir mal "Beratungsresistent" empfindest. Aber ich muss auch sagen Ich liebe diese Forums Kommentare wie [Das ist Falsch] ohne Kommentar und Hintergrund

Ich empfinde wirklich HOCHACHTUNG für Leute die sich in Foren um andere kümmern, weil ich weiß wie viel Arbeit und Nerven das kosten kann. Wenn ich das mache, versuche ich aber immer zu verstehen wo der Denkfehler liegt und ich gehe immer davon aus das der andere nicht weiß wie eine Lösung aussieht, sonst würde er ja nicht fragen. Ihm zu sagen das es falsch ist, bringt ihm nichts.

Deine Byte-Schreib-Kaskade dauert rund 30 mal solange wie der Blockwrite.
Aber egal, wer nicht will, der hat schon.
(mögen die Gründe auch noch so wirr sein)

Das ist gut, wenigstens in dem Punkt sind wir uns einig.

Schau auf meinen Zweitnamen "DokuVorLeseVerweigerer", den trage ich nicht ohne Grund.

Das stimmt, wenn die Person DenkVerweiger ist, dann hast du Wahr.

Übrigens:
Dein Name, also du, stehst seit geraumer Zeit auf meiner Liste und bist dort mit Warnzeichen versehen.
Siehe: Setup nach WatchDog-Reset - #7 by MagierPhil
All zuviel "Service" darfst du nach der Anmache nicht von mir erwarten.

Was ist eine nichtblockierende Alternative für delay() ?

Ja millis();

Interessant finde ich, dass ihm das schon nutzt, aber es eben nicht konsequent, bzw. fehlerhaft durchzieht.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.