Display zeigt "Zeichenmatsch"

Hallo
ich habe wieder mal ein Problem das ich eigentlich der Hardware zuschreibe.
Ich messe 2 Stromsensoren aus, lasse die Werte auf einem (I2C) Display anzeigen und schreibe sie auf eine Micro SD Karte. Weil die Messreihen länger dauern wollte ich jetzt das Display auf Tastendruck nur für kurze Zeit einschalten.
Gedachtes Vorgehen:
Ich schließe die die Stromversorgung des I2C an 2 Digital Pins und versorge das Display über “D6 und D7 HIGH” für ein paar Sekunden mit Strom.
EIgentlich funktioniert das auch, wenn ich VCC des I2C bausteins an D6 und D7 anschließe, leuchtet das Display die gewünschte Zeit auf. Fehler dabei ist, daß die anzuzeigenden Werte durch scheinbar willkürlich gewählte Zeichen ersetzt werden.
Woran kann das liegen? Fehlt da ein Kondensator oder Widerstand?

Hier noch der Sketch:

/*
  Data logging to the Deek-Robot shields with RTC for the Arduino Nano.
  Btw.: Because i found no informations which card size can be used: i  use a Fat32 formated 8GB noname.
  The sketch reads the value of 2 ACS712 current sensors, writes the result as mA to an SD card und shows it at an 4 lines
  i2C display.
  The base of the storge and RTC part i found at https://publiclab.org/notes/cfastie/04-30-2017/data-logger-shield-for-nano .
  created 2021
  This code is in the public domain.
*/

#include <SdFat.h>
#include  <SPI.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>                  // LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 20, 4);             // Display Adresse und Größe deffinieren.

float mAps = 28;                                // Miliampere per analogRead Step. Wert muss an Sensor angepasst werden
float korrekturwert = 1;                    // zum Angleichen der beiden Sensoren
int adwert = 0;                                 // für Displayausgabe des durchschnittlichen AD Wertes, nur zur Kontrolle

long sensorsumme1 = 0;
long sensorsumme2 = 0;

long mAmp1 = 0;
long mAmp2 = 0;

long mAhmin1 = 0;
long mAhmin2 = 0;

unsigned int j = 0;
unsigned int k = 0;

unsigned long currentMillis;
unsigned long previousMillis = 0;
unsigned long display_on = 0;

const byte TasterPin = 4;                            // an Taster (Taster gegen GND)
const byte LCDPin1 = 6;                         // an VCC Display
const byte LCDPin2 = 7;                         // an VCC Display
byte LCD_einschalten = 0;

const int nulllage1 = 512;                        // Korrekturwert für die Nulllage. Null mA sollte bei 512 angezeigt werden.
const int nulllage2 = 509;                        // Korrekturwert für die Nulllage. Null mA sollte bei 512 angezeigt werden.

const int interval = 1000;
const int Display_an = 4000;

SdFat SD;
const byte MOSIpin {11};
const byte MISOpin {12};

RTC_DS1307 RTC;
#define DS1307_I2C_ADDRESS 0x68

char TmeStrng[20];
char mAsStrng[16];
char mAmStrng[16];

byte schalter = 0;


void setup() {
  lcd.init();                                       // LCD aktivieren
  lcd.backlight();                                  // Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus).

  pinMode(TasterPin, INPUT_PULLUP);
  pinMode(LCDPin1, OUTPUT);
  pinMode(LCDPin2, OUTPUT);

  Wire.begin();                                    // start the i2c interface
  RTC.begin();                                     // start the RTC
  //  RTC.adjust(DateTime((__DATE__), (__TIME__)));    // !! Zeile nach erstem Upload auskommentieren und Sketch noch einmal hochladen, - setzt die Zeit auf dem RTC
  SD.begin();

}                                                  // end of setup

void loop() {
  read_ampere();

  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ausgabe();
  }

  LCD_einschalten = digitalRead(TasterPin);
  if (LCD_einschalten == LOW && schalter == 0) {
    display_on = currentMillis;
    digitalWrite(LCDPin1, HIGH);
    digitalWrite(LCDPin2, HIGH);
    schalter = 1;
  }
  if (schalter == 1 && currentMillis - display_on >= Display_an) {
    digitalWrite(LCDPin1, LOW);
    digitalWrite(LCDPin2, LOW);
    schalter = 0;
  }

}

void ausgabe()  {

  get_time();
  calc_strom();
  calc_mAhmin();
  if (schalter == 1) {
    displayausgabe();
  }
  //  write_data();

  j = 0;

}

void calc_strom()  {                                       // Strom aus Sensorwerten berechnen

  sensorsumme1 = sensorsumme1 / j;
  adwert = sensorsumme1;
  mAmp1 = sensorsumme1 * mAps;
  sensorsumme1 = 0;

  sensorsumme2 = sensorsumme2 / j;
  mAmp2 = sensorsumme2 * (mAps * korrekturwert);
  sensorsumme2 = 0;

}

void calc_mAhmin()  {                                      // Berechnen wie viele mAh in einer Minute geflossen sind.

  mAhmin1 = mAhmin1 + mAmp1;
  mAhmin2 = mAhmin2 + mAmp2;

  k = k + 1;

  if (k == 60) {
    mAhmin1 = mAhmin1 / 3600;
    mAhmin2 = mAhmin2 / 3600;
    //    write_mAhmin();
  }

}

void displayausgabe() {

  lcd.setCursor(0, 0);                                      //Display leeren
  lcd.print("                   ");
  lcd.setCursor(0, 1);
  lcd.print("                   ");
  lcd.setCursor(0, 2);
  lcd.print("                   ");
  lcd.setCursor(0, 3);
  lcd.print("                   ");

  lcd.setCursor(0, 0);                                      // Messwerte Anzeigen
  lcd.print(TmeStrng);
  lcd.setCursor(0, 1);
  lcd.print(mAmp1);
  lcd.print(" mA");
  lcd.setCursor(0, 2);
  lcd.print(mAmp2);
  lcd.print(" mA");
  lcd.setCursor(0, 3);
  lcd.print(j);
  lcd.setCursor(10, 3);
  lcd.print(adwert);

}

void get_time() {                                            //Datum und Zeit auslesen Zeit auslesen

  DateTime now = RTC.now();
  sprintf(TmeStrng, "%02d.%02d.%04d,%02d:%02d:%02d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second());
  sprintf(mAsStrng, "%04d%02d%02dAs.txt", now.year(), now.month(), now.day());
  sprintf(mAmStrng, "%04d%02d%02dAm.txt", now.year(), now.month(), now.day());

}

void write_data() {                                        //auf SD Karte schreiben

  String dataString = "";                                  //erst mal vorherigen string löschen

  dataString += TmeStrng;                                  //und neuen string zusammensetzen
  dataString += ",";
  dataString += String(mAmp1);
  dataString += ",";
  dataString += " mA";
  dataString += ",";
  dataString += String(mAmp2);
  dataString += ",";
  dataString += " mA";

  File dataFile = SD.open(mAsStrng, FILE_WRITE);
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
  }
  else {
    // Displayausgabe wenn schreiben nicht möglich
    lcd.setCursor(0, 0);                                      // Zeile löschen
    lcd.print("                   ");
    lcd.setCursor(0, 1);
    lcd.print("                   ");
    lcd.setCursor(0, 2);
    lcd.print("                   ");
    lcd.setCursor(0, 3);
    lcd.print("                   ");

    lcd.setCursor(0, 0);                                      // Messwerte mit Fehlermeldung anzeigen
    lcd.print(TmeStrng);
    lcd.setCursor(0, 1);
    lcd.print(mAmp1);
    lcd.print(" mA");
    lcd.setCursor(0, 2);
    lcd.print(mAmp2);
    lcd.print(" mA");
    lcd.setCursor(0, 3);
    lcd.print("SD Schreibfehler");

  }

}

void write_mAhmin() {                                      //auf SD Karte schreiben

  String dataString = "";                                  //erst mal vorherigen string löschen

  dataString += TmeStrng;                                  //und neuen string zusammensetzen
  dataString += ",";
  dataString += String(mAhmin1);
  dataString += ",";
  dataString += " mAh";
  dataString += ",";
  dataString += String(mAhmin2);
  dataString += ",";
  dataString += " mAh";

  File dataFile = SD.open(mAmStrng, FILE_WRITE);
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
  }
  else {

    lcd.setCursor(0, 3);
    lcd.print("SD Schreibfehler mAhmin");

  }

  k = 0;
  mAhmin1 = 0;
  mAhmin2 = 0;
}

void read_ampere()  {

  int  sensorwert1 = 0;                                                   // Sensorwert rücksetzen
  int  sensorwert2 = 0;

  sensorwert1 = analogRead(A1);
  sensorwert1 = sensorwert1 - nulllage1;
  sensorsumme1 = sensorsumme1 + sensorwert1;

  sensorwert2 = analogRead(A3);
  sensorwert2 = sensorwert2 - nulllage2;
  sensorsumme2 = sensorsumme2 + sensorwert2;

  //  delay (1);
  j = j + 1;

}

a) braucht so ein i2c display mehr strom als ein Pin sourcen kann.
b) sollst du nicht 2 pins parallel schalten um an mehr strom zu kommen.
c) schalte den Strom über einen Transistor/FET/Relais
d) immer wenn du das display wieder einschaltest musst du auch die init/begin sequenz des displays wiederholen.

e) also zusammengefasst: Konzept neu überdenken.

Zudem, was noiasca schon schrub:
Wenn Du VCC erst anbindest, wenn Du etwas sehen willst, dann musst Du das Display auch GENAU DANACH initialisieren.

Die Frage die sich stellt:
würde Dir nicht das ausschalten der Hintergrundbeleuchtung ausreichen?

Danke schon mal.

Weshalb nicht 2 Pins parallel schalten?
Das Display benötigt 38,xmA (gemessen, i2C Modul und Display zusammen) deshalb hatte ich gedacht das könnte ohne Transistor auskommen.
Ja, nur die Hintergrundbeleuchtung abschalten bringt auch schon was, - ich wollte es halt mal mit komplett abschalten probieren.

herbk:
Weshalb nicht 2 Pins parallel schalten?
Das Display benötigt 38,xmA (gemessen, i2C Modul und Display zusammen) deshalb hatte ich gedacht das könnte ohne Transistor auskommen.

Die Antwort liegt auf der Hand: 20mA je PIN sind empfohlen.
Die Gesamtgeschichte darf aber 200mA nicht übersteigen.
Da unbedingt mit 40mA reingrätschen ist kontraproduktiv.

Aber da ist bei mir auch nach den letzten Diskussionen, aus denen ich dann vorzugsweise ausgestiegen bin, rund um das was an Ströme und Verlustleistungen weggeht Ende im Gelände.
Jeder ist für seinen Braten selbst verantwortlich :wink:

Wegen der 20mA je Pin bin ich ja auf die Idee gekommen 2 Pins parallel zu schalten...

Mit

  LCD_einschalten = digitalRead(TasterPin);
  if (LCD_einschalten == LOW && schalter == 0) {
    display_on = currentMillis;
    digitalWrite(LCDPin1, HIGH);
    digitalWrite(LCDPin2, HIGH);
    lcd.init();
    lcd.backlight();
    schalter = 1;
  }

geht es jetzt wie erwartet.

Bleibt noch die Frage was gegen das Parallelschalten der Pins spricht, - ich weiß halt gerne weshalb das so ist..

Edit:
Die 200mA Limit erreiche ich sicher nicht, versorge über einen externen DC DC Wandler.
Und wenn mal so ein Nano Clon abraucht, - der kostet nicht mahl 2 Euro... ;-))

herbk:
Wegen der 20mA je Pin bin ich ja auf die Idee gekommen 2 Pins parallel zu schalten...

    digitalWrite(LCDPin1, HIGH);

digitalWrite(LCDPin2, HIGH);



Bleibt noch die Frage was gegen das Parallelschalten der Pins spricht, - ich weiß halt gerne weshalb das so ist..

Weil Du beim ersten Schaltvorgang den PIN an seine Grenze bringst.
Erst der zweite Schaltvorgang bringt Entspannung.

Du bist sehr nah an der Grenze des absoluten Maximum!

Die 200mA Limit erreiche ich sicher nicht, versorge über einen externen DC DC Wandler.

Das Eine hat mit dem Anderen nichts zu turn...

Und wenn mal so ein Nano Clon abraucht, - der kostet nicht mahl 2 Euro... ;-))

...mal ehrlich, ich bin ja auch nicht unbedingt irgendwas mit Öki, aber denk doch ma drüber nach.
Der Liter Sprit kostet gutgehend 6 cent mehr wegen Co2, Wir machen demnächst neue Labels auf Fernseher und Waschmaschinen aber lassen uns für 2 Euro Elektroschrott aus China einfliegen.

Sorry. Da fehlt mir jedes Verständnis.

Arduino-Pins und generel alle Signalausgänge können nicht als Spannungsversorgung für andere Elektronik verwendet/mißbraucht werden.
Außerdem nehmen es die Meisten IC übel wenn man die Versorgungsspannung wegnimmt man aber Signalspannungen noch anliegen läßt. In diesem Fall fleißen Ströme über die Schutzdioden, die alle Pins haben.
Manchmal Überleben die IC aber oft gehen sie auch kaputt.

LCD Module auf Basis vom HD44780 bzw seiner Nachbauten verbrauchen wenig Strom (ca 1mA) der Hauptstromverbraucher ist die Hintergrundbeleuchtung. Du kannst die Beleuchtung abschalten oder ein Modell aussuchen ( schwarze Schrift auf grünen Hintergrund) die man auch gut ohne Beleuchtung nur durch das Umgebungslicht sieht.

Wenn eine Schaltung abgeschaltet werden kann dann bitte mittels P-MOSFET die Versorgungsspannung abschalten.

Viele IC haben einen Enable Eingang die es in einen Power Down Zustand versetzten und so wenig Strom verbrachen. Genaueres in den jeweiligen Datenblättern

Grüße Uwe

Guten Morgen,

Danke, so erklärt kann auch ich das verstehen.

Bei dem "Messprojekt" kann ich mit dem Abschalten der Hintergrundbeleuchtung gut leben, mache ich im Moment über einen Schalter.
Die "Anzeige nach Tasterdruck" will ich für ein anderes Projekt, bei dem auf Tastendruck verschiedene Messwerte auf dem Display angezeigt werden sollen. Soll in mein Wohnmobil eingebaut werden und mir Infos über z.B. den Inhalt der Tanks liefern. Weil dort eh schon ein Pro Mini die Spannung der Versorgungsbatterie überwacht (und damit eigentlich deutlich unterfordert ist) will ich den halt zwischendurch aufwecken damit er mir die gewünschten Infos zeigt.

@ my_xy_projekt:
ich schrotte die Dinger ja nicht vorsätzlich, aber wenn mal einer kaputt geht ist das auch kein Drama. Und über die Sinnigkeit von solchen Labels, bzw. den Umständen/Bedingungen unter denen sie vergeben/erreicht werden möchte ich hier nicht diskutieren, würde m.E. den Rahmen dieses Forums sprengen :wink:

Außerdem nehmen es die Meisten IC übel wenn man die Versorgungsspannung wegnimmt man aber Signalspannungen noch anliegen läßt.

D.h. ich müsste SDA und SCL auch trennen...? Könnte man da im Sketch die Pins deaktivieren?
Ich bin davon ausgegangen dass es genügt wenn ich "Displayausgabe" nur ausführe nachdem das Display aktiviert ist...

grundsätzlich würde ich hardwaremäßig einfach alles - incl dem Controller abschalten.

Die Messwerte sind ja eh rasend schnell am Arduino verarbeitet.
Das “langsame” ist ohnehin das Initalisieren des Character-LCD.

Ansonsten, es gibt auch lcd.backlight() und lcd.noBacklight()

grundsätzlich würde ich hardwaremäßig einfach alles - incl dem Controller abschalten.

Das war Plan A... Aber dann müsste ich dafür einen eigenen Controller mit eigenem Display einbauen.

Und wie geschrieben: Einer, der nichts anderes macht als die Batteriespannung zu überwachen (Tiefentladeschutz), ist schon eingebaut. Auch der hat ein Display, weil ich ja auch die Batteriespannung ein paar mal im Jahr abfragen möchte.
Einen zweiten Controller unter zu bringen ist nicht das Problem, ein zweites Display schon...

Mein Display zieht auch mit abgeschaltener Hintergrundbeleuchtung noch 5,8 mA, - ich denke da braucht das I2C modul schon viel davon, habe aber gerade kein loses um nachzumessen.

Wenn dir die verbliebenen 5.8mA fürs LCD zu viel sind, was zieht dann die restliche Schaltung? Der Nano ist ja auch kein Stromsparer, Power-LED entfernt? vermutlich hast auch einen Step-Down Wandler irgendwo, oben lese ich SD Karte - auch ohne LED?

Wenn (Akku-)Dauerbetrieb könnte man ein ePaper Display verwenden
oder den Arduino in Deepsleep versetzen - dann aber auch keinen Nano verwenden

Du schreibst dass deine Messungen "länger" dauern, das heißt wie lange konkret? In welchem Intervall machst du deine Messungen? Wie oft schreibst du auf die SD?

Ich finde halt diese "Teilabschaltung" für 5.8mA ist eine Teil-Optimierung. (Strom-)Sparen am falschen Ort.

Oder besser: worum gehts den wirklich?

Halt, - Halt...
Das sind 2 verschiedene Projekte für 2 ganz unterschiedliche Anwendungen (hatte ich oben schon mal wo geschrieben).

Ich habe das "LCD abschalten" nur zum Probieren in eine meiner Messanwendungen integriert, das macht praktisch da keinen Sinn weil ich hier eh so oft pro Sekunde messe wie es nur geht.

Für das "Wohnmobilprojekt" ist ein Pro Mini vorgesehen (ist schon eingebaut). Hier wird nichts aufgezeichnet und auch nur alle 5 Minuten mal gemessen, den Rest schläft der Pro Mini.
Deshalb wollte ich den ja auch noch ein wenig mehr beschäftigen, aber halt auch nur ab und zu mal.

Bei dem "Messgeräte Projekt" wird von 2 Stromquellen, z.B. Solarmodulen oder kleinen Windrädern, gleichzeitig der Kurzschlussstrom gemessen um diese unter natürlichen Bedingungen vergleichen zu können.
Auch hier verwende ich inzischen einen Pro Mini (deshalb das Problem von vor ein paar Tagen mit den 8MHz) und umgebaute INA282 Sensoren zum Messen des Stromes.
Hier habe ich kein Problem mit der Stromversorgung, weil ich einen sehr großen Akku verwende, welcher auch noch mittels Solarzelle geladen wird. Ganz ohne Sonne kann ich rechnerisch etwa 55 Tage am Stück messen.
Dieses Messgerät funktioniert inzwischen recht gut, da "kämpfe" ich eigentlich nur noch an Kleinigkeiten...

wenn der pro mini nur alle 5 min aufwacht, müsstest du auch etwas vorsehen "Wach jetzt auf" wenn du vor dem display stehst - oder willst da 5 min warten bis du was ablesen kannst?

Ansonsten wären wir wieder bei e-paper, alle 5min aktualiseren - pro mini geht schlafen, display-Anzeige bleibt (ohne Stromverbraucht).

was meinst Du mit e-paper ?
OK, hab was gefunden, - sieht interessant aus...

Aufwecken müsste ich ihn aber dennoch, ich möchte nicht immer alle Infos gleichzeitig auf dem Display...

es gibt doch sicher eine Variante aus dem deepsleep entweder per 8sec Timer oder per Pin -State Change aufzuwachen.
(halbwissen, weil ich es selber in dieser Kombination noch nicht gemacht habe)

Die e-paper Displays gefallen mir.
Für das WoMo Projekt muss ich eh erst noch ein Pflichtenheft erstellen was da alles rein soll. Sinn würde da evtl auch machen den deepsleep nur dann anzuwenden wenn das WoMo gerade nicht genutzt wird.
Was ich dazu im Moment so mache ist eher herauszufinden was (für mich) machbar ist und was man wie machen könnte...
Von Anfang März bis Ende Oktober ist auch im WoMo die Stromversorgung kein Problem , - nur im Wnter halt wenn das Teil unter Dach steht

herbk:
Für das WoMo Projekt muss ich eh erst noch ein Pflichtenheft erstellen was da alles rein soll.

so fangen gute Programme an!

Du könntest einen extra "Winterschalter" - machen.
Oder unterscheiden zwischen WoMo versperrt und WoMo offen. Vieleicht bei "versperrt" noch einen Präsenzmelder und erst bei mehreren Stunden Inaktivität in den Deepsleep (versperrt und verlassen) gehen.

Wenn du das WoMo im Winter nicht an eine Erhaltungsladung hängen kannst, würde ich die Batteriespannung mittels LoRa "nach Hause" senden lassen. Einmal am Tag reicht da sicher.

Oder unterscheiden zwischen WoMo versperrt und WoMo offen. Vieleicht bei "versperrt"

So etwa hatte ich auch überlegt, - evtl auch "wenn kein Strom mehr vom Dach kommt und innen kein Licht mehr brennt"...
Aber wie gesagt, da muss ich noch viel überlegen, weil ich auch den Kühlschrank und den Warmwasserboiler mit Strom aus Akku und Solarzellen betreiben möchte, - aber halt so dass auch immer noch genug Reserve für 1 Tag ohne Sonne da ist.