Arduino Nano SD Shield

Hallo zusammen

Ich möchte mit einem Arduino Nano Daten speichern und später wieder abrufen können, auch wenn das Arduino zwischenzeitlich ausgeschaltet ist.

Ich habe dazu dieses Shield bei Reichelt gefunden:
SD Karten Shield für MKR

Das ist aber für die Arduino MKR Serie gedacht, welche, soweit ich weiss, mit 3.3 V Logikpegeln arbeitet. Der Arduino Nano hat aber 5V logkpegel, weshalb das Shield wohl nicht direkt kompatibel ist.

Fragen:

  • Gibt es ein SD Karten Shield oder Modul, das direkt für den Arduino Nano geeignet ist?
  • Alternativ, lässt sich das MKR Shield trotzdem verwenden, zum Beispiel mit Level Shiftern? Oder ist es mechanisch gar nicht kompatibel, beziehungsweise macht das technisch keinen Sinn?
  • Habt ihr eine andere Idee, wie ich sonst die Daten speichern könnte?

Ich habe bei den üblichen Händlern bisher nichts wirklich Passendes gefunden.
Ich bin dankbar für jede Empfehlung oder Lösungsidee.

Gruss
arduinobastle2004

Und es ist mir wichtig, dass es ein shield ist, damit ich es einfach zusammenstecken kann und nicht noch verdrahten muss.

Wenn es nur wenige Daten sind, bietet sich das EEPROM im Nano an.

Ich dachte immer das Nano-Format ist gut, damit man den woanders draufstecken (oder besser einlöten) kann, und der Uno ist gut, um ein Shield draufzustecken.
Eine Platine mit SD Adapter und Levelshifter, die darauf wartet, dass ein Nano draufgesteckt wird, kenne ich leider nicht.

Der EEPROM ist eben meiner meinung nach etwas klein. Ich weiss nicht ob du Geocaching kennst, aber das ist eine art Online Schatzsuche/Schnitzeljagt. und da Trägt man sich wenn man den "Schatz" gefunden hat in ein Logbuch ein (normalerweise ein kleines Notizbuch). Ich möchte aber nun etwas spezielles machen und zwar ein digitales Logbuch. Da trägt man seinen Benutzernamen ein und das Datum und ev. Uhrzeit soll auch dazu gespeichert werden. So wie ich gesehen habe hat das EEPROM vom Arduino Nano nur 1kb Speicher.

Dann bleibt dir wohl nur einen einzelnen Reader zu verwenden. Und evtl. ein Nano Steckboard als Erweiterung.

Oder der Schritt zum Uno.
Da gibt es Shields mit Cardreader und RTC. Dann kann Datum und Uhrzeit automatisch eingetragen werden. Bei der RTC solltest du aber wegen der Genauigkeit auf eine DS3231 achten.

Edit:
Da habe ich noch eins gefunden. Allerdings ist die RTC nicht zu empfehlen.

Ich glaube von der Idee alles bereits steckbar zu finden, mußt Du dich verabschieden.

Deine Anwendung ist etwas kritisch.

Zu erst mal brauchst Du wie gesagt einen Speicher und eine RTC.

Dann aber auch ein Display und ein Eingabegerät, damit der User sich eintragen kann.

Dazu kommt aber auch ein Powermanagement da, Du nicht vertrauen kannst, daß der User das elektronische Notizheft, das Du bauen willst, immer ausschaltet. Der Arduino muß nach getaner Arbeit sich selbst ausschalten können, oder wenigstens in einen Powersafe-Zustand wechseln.

Du wirst die einzelnen Teile zusammenlöten müssen ( zB auf einer Lochrasterplatine) , da Du keine Platine mit all diesen Funktionalitäten findest.

Grüße Uwe

Also die idee ist das die Benutzer den Strom selbst mitbringen (z.b via Powerbank). Ausserdem ist das Logbuch nicht das einzige. Zuerst muss man ein Simon Says lösen (das habe ich bereits Programmiert) und Anschliessend wird das Logbuch freigegeben.

Und ja von Steckbar habe ich mich verabschiedet. Ich habe jetzt vor es Trotzdem mit einem Arduino nano zu machen und dafür nicht steckbar

Ich dachte ich frage mal nach ob es steckbar möglich ist (die taster und LED's hätte ich sowiso löten müssen).

Die eingabe des Benutzernamens mache ich sehr einfach mit 3 Taste. Einer für das weiterschalten des buchstabens, einer für zum nächsten buchstaben und einer für das abschliessen der eingabe.

Unten Siehst du der aktuelle Aufbau (Aktuell ist da noch ein UNO aber geplant ist ein Nano). Auch das Display etc sind nicht fest genau diese aber diese waren halt die einzigen bei Wokwi. Da ich keine Analoge Eingänge benötige, missbrauche ich diese als Digitale Eingänge, da ich sonst zu wenig pins habe. Im Bild fehlen jetzt noch die 3 Buttons für das Eintragen am arduino (diese würden dann noch an den Pins D7 - D9 angeschlossen werden).

Falls noch jemand mein bisheriger Simon Says code Sehen und ev. Korrigieren möchte :slight_smile::

/*

Simon Says Spiel für ein Geocache

Simon Says Anleitung:

Simon Says ist ein Reaktions- und Gedächtnisspiel, bei dem eine Abfolge von blinkenden LEDs gezeigt wird. 
Der Spieler muss diese Reihenfolge durch Tastendrücke korrekt wiederholen. 
Mit jeder Runde wird die Sequenz länger und dadurch schwieriger.

*/

//Eingänge
const int StartButton = A6; //Button der ein Versuch startet
const int InputButtons[] = {A0, A1, A2, A3}; //Buttons welche vom Benutzer anhand der LED Abfolge gedrückt werden müssen
//Ausgänge
const int LEDs[] = {0, 1, 2, 3}; //LED's welche die Abfolge welche der Benutzer nachmachen muss Visualisiert sowie Visualisiert welchen Button gedrückt wurde
const int RightLED = 4; //LED welche am Ende jeder Runde Visualisiert, dass die Runde erfolgreich abgeschlossen wurde
const int FalseLED = 5; //LED welche Visualisiert das ein Fehler gemacht wurde
const int Buzzer = 6; //Passiver Buzzer der Passend einen Ton macht

//Konstante Merker
const int NumberOfRounds = 8; //Anzahl der Runden
const int Time = 500; //Verzögerung LED Ein/Aus
const int Tones[4] = {261, 329, 392, 523}; //Tonhöhen bei bestimmten LED's bzw Buttons

//Merker
int Step; //Variable für Schrittkette
int PressedButton; //Index des Letzten Gedrückten Buttons
int InputCount; //Anzahl der Gedrücken Buttons Innerhalb einer Runde
int Round; //Aktuelle Runde
int SavedSequence[NumberOfRounds]; //Array um die Reihenfolge der LED's zu Speichern

//Setup wird nur beim Start einmal ausgeführt
void setup() 
{

  //Eingänge / Ausgänge definieren
  pinMode(StartButton, INPUT_PULLUP);
  pinMode(RightLED , OUTPUT);
  pinMode(FalseLED , OUTPUT);
  pinMode(Buzzer , OUTPUT);
  for (int i = 0; i < 4; i++) 
  {
    pinMode(InputButtons[i], INPUT_PULLUP);
    pinMode(LEDs[i], OUTPUT);
  }

  //Ausgänge Initialisieren
  digitalWrite(RightLED, LOW);
  digitalWrite(FalseLED, LOW);
  digitalWrite(Buzzer, LOW);

  for (int i = 0; i < 4; i++) 
  {
    digitalWrite(LEDs[i], LOW);
  }

  //Merker Initialisieren
  Step = 0;
  Round = 0;
  PressedButton = 0;
  InputCount = 0;
  for (int i = 0; i < NumberOfRounds; i++) 
  {
    SavedSequence[i] = 0;
  }

  //Zufallsgenerator Initialisieren
  randomSeed(analogRead(A7));
}

//Loop wird immer wieder wiederholt
void loop() {

  //Srittkette
  switch (Step) {

    case 0: //Initialisieren vor dem Start

      //Ausgänge Initialisieren
      digitalWrite(RightLED, HIGH);
      digitalWrite(FalseLED, LOW);
      digitalWrite(Buzzer, LOW);

      for (int i = 0; i < 4; i++) 
      {
        digitalWrite(LEDs[i], LOW);
      }

      //Merker Initialisieren
      Round = 0;
      PressedButton = 0;
      InputCount = 0;
      for (int i = 0; i < NumberOfRounds; i++) 
      {
        SavedSequence[i] = 0;
      }

      if (digitalRead(StartButton) == LOW) 
      {
        digitalWrite(RightLED, LOW);
        delay(Time);
        Step = 1;
      }

      //Schritt beenden
      break;

    case 1: //Bisher Gespeicherte Abfolge Abspielen

      //Variable InputCount Initialisieren
      InputCount = 0;

      //Bisher Gespeicherte Abfolge Abspielen
      for (int i = 0; i < Round; i++) 
      {
        digitalWrite(LEDs[SavedSequence[i] - 1], HIGH);
        tone(Buzzer, Tones[SavedSequence[i] - 1]);
        delay(Time);
        digitalWrite(LEDs[SavedSequence[i] - 1], LOW);
        noTone(Buzzer);
        delay(Time);
      }

      //in Schritt 2 Wechseln
      Step = 2;

      //Schritt beenden
      break;

    case 2: //Neue Zufalls-LED Aufleuchten und Speichern lassen

      //Zufallszahl Speichern
      SavedSequence[Round] = random(1, 5);

      //Zuffällige LED Anzeigen anhand des oben Gespeicherten Wertes
      digitalWrite(LEDs[SavedSequence[Round] - 1], HIGH);
      tone(Buzzer, Tones[SavedSequence[Round] - 1]);
      delay(Time);
      digitalWrite(LEDs[SavedSequence[Round] - 1], LOW);
      noTone(Buzzer);

      //in Schritt 2 Wechseln
      Step = 3;

      //Schritt beenden
      break;

    case 3: //Überprüfen welcher Button vom Spieler gedrückt wurde und die Entsprechende LED Aufleuchten lassen

      for (int i = 0; i < 4; i++)
      {
        if (digitalRead(InputButtons[i]) == LOW) 
        {
          PressedButton = i + 1;
          InputCount = InputCount + 1;
          digitalWrite(LEDs[i], HIGH);
          tone(Buzzer, Tones[i]);
          delay(Time);
          digitalWrite(LEDs[i], LOW);
          noTone(Buzzer);

          //Entprellen
          while (digitalRead(InputButtons[i]) == LOW) 
          {
            delay(10);
          }
          delay(50);

          //in Schritt 4 Wechseln
          Step = 4;
        }
      }

      //Schritt beenden
      break;

    case 4: //Überprüfen ob der Spieler den Richtigen Button gedrückt hat und demensprechend handeln

      //Falls der Richtige Button gedrückt wurde und die Anzahl der Gedrückten Buttons innerhalb der Runde der Anzahl gespielten Runden entspricht dann Leuchtet die Grüne LED kurz auf und eine neue Runde Startet
      if (PressedButton == SavedSequence[InputCount - 1])
      {
        if (InputCount >= Round + 1)
        {
          delay(Time / 2);
          digitalWrite(RightLED, HIGH);
          Round = Round + 1;

          //Falls die Gewünschte Anzahl Runden Erreicht ist und der Spieler bis hier erfolgreich war, wird eine Melodie gespielt und das Logbuch freigegeben
          if (Round >= NumberOfRounds)
          {
            int Melody[]   = {523, 659, 784, 523, 523, 659, 784, 1047};
            int Duration[] = {200, 200, 200, 400, 200, 200, 200, 600};

            for (int i = 0; i < 8; i++) 
            {
              tone(Buzzer, Melody[i]);
              delay(Duration[i]);
              noTone(Buzzer);
              delay(50);  
            }

            digitalWrite(RightLED, LOW);
            delay(Time / 2);
            
            Step = 5;
          }

          //Falls die Gewünschte Anzahl Runden noch nicht erreicht ist, wir eine kurze Melodie gespielt und eine Neue Runde Startet
          else
          {
            //Melodie Abspielen für Richtige Runde
            int Melody[] = {587, 698, 880};
            for (int i = 0; i < 3; i++) 
            {
              tone(Buzzer, Melody[i]);
              delay(200);
              noTone(Buzzer);
              delay(50);
            }

            digitalWrite(RightLED, LOW);
            delay(Time / 2);

            Step = 1;
          }
        }

        //Falls der Richtige Button gedrückt wurde, aber die Anzahl der Gedrückten Buttons innerhalb der Runde der Anzahl gespielten Runden nicht entspricht dann wird auf eine weitere Tasteneingabe gewartet
        else
        {
          Step = 3;
        }
      }

      //Falls der Falsche Button gedrückt wird dann muss das Spiel nochmal ganz von neu gestartet werden
      else 
      {
        delay(Time / 2);
        digitalWrite(FalseLED, HIGH);

        //Melodie Abspielen für Falsche Runde
        int melody[] = {196, 130, 98};
        for (int i = 0; i < 3; i++) 
        {
          tone(Buzzer, melody[i]);
          delay(300);
          noTone(Buzzer);
          delay(100);
        }

        digitalWrite(FalseLED, LOW);
        delay(Time);
        Step = 0;
      }

      //Schritt beenden
      break;

    case 5: //Logbuch Freigabe

      Step = 0;

      break;

    default: //Schrittkette Initialisieren bei enem Fehler
      Step = 0;
      break;
  }
}

Also Step 5 ist noch nicht fertig Programmiert. das wäre dann der Bereich wo das Logbuch freigegeben wird. Eigentlich wollte ich nicht mit delay arbeiten sonder mit millis() aber irgendwie habe ich es nicht geschafft das es so funktioniert wie es soll. Eingang A6 gibt es beim UNO natürlich nicht aber wie gesagt es ist mit dem Nano geplant

Mitt den LED 0 und 1 bekommst du Probleme den dort sitzt die USB Verbindung, sieht auch drauf TX, RX.
Der Taster 0 mus weg vom A5 dadrauf hängt I2C, die oben links sind ja verbunden mit A4 und A5.

Edit:
Da habe ich noch eins gefunden. Allerdings ist die RTC nicht zu empfehlen.Blockzitat

Das habe ich auch gesehen, aber ich verstehe nicht wo da genau der SD karten slot ist. und wegen genauigkeit: Das spielt nicht so eine Grosse Rolle. Wahrscheinlich werde ich sowiso nur das Datum loggen (ist eigentlich üblich bei Geocaching, aber manchmal wird die Zeit auch eingeschrieben). Dann muss man es halt ab und zu korrigieren.

Edit:
Ich habe jetzt gesehen wo die SD karte angeschlossen wird. Jedoch werde ich warhscheinlich trotzdem das andere nicht steckbare nehmen, weil dieses ist schon sehr lang gebaut und benötigt viel Platz. Bei dem könnte ich dann genau so gut einen UNO verwenden.

Ich kaufe mir aktuell STREIFENRasterplatinen. 100 x 160 mm für unter 2 Euro.
Dann braucht man nur noch ein scharfen Cutter und ein Lineal aus Metall.

An den richtigen Stellen die Streifen durchschneiden und danach aus Sicherheitsgründen eine "Durchgangsprüfung" machen damit man sicher ist, das es ein sauberer Schnitt ist.

Den Nano stecke ich aber in 2 Steckleisten , finde ich die bessere Lösung.

Fertig ist.

Gruß

Pucki

Mitt den LED 0 und 1 bekommst du Probleme den dort sitzt die USB Verbindung, sieht auch drauf TX, RX

ich dachte solange ich den Seriellen Monitor nicht verwende sollte das kein Problem sein?

Der Taster 0 mus weg vom A5 dadrauf hängt I2C, die oben links sind ja verbunden mit A4 und A5.

Ja das war da noch falsch verdrahtet. Aber wie du siehst ist es im Code richtig (A6). Und wie gesagt eigentlich verwende ich einen Arduino Nano da geht es bis A7.

Ich kaufe mir aktuell STREIFENRasterplatinen

Gute idee :+1:

Habe nur auf den Plan geschaut.
Ja we mann Serial Monitor nicht nutzt geht das.

Ja we mann Serial Monitor nicht nutzt geht das.

Okay gut Danke kein Problem. Habe ich eben beim Testen mit Wokwi auch bemerkt das es zuerst Probleme machte, dann kam mir das mit dem seriellen Monitor in den sinn und hab dann den deaktiviert weil ich ihn sowiso nicht brauchte.

ja hätte ich auch so gemacht :+1: Hab den Nano einmal fix verlötet auf einer Lochrasterplatine und dann ausversehen einen Kurzschluss zwischen 5V und GND ausgelöst als etwas nicht funktionierte und ich es ausmessen wollte. Nie mehr verlöte ich den direkt :slight_smile: .

Draufsetzen, persönlich nutzte ich Schraubklemmenadapter so was
Mittlerweile bin von 5V Systemen weg nutze nur ESP32 alle Sorten.
Am ESP32 kann man vernünftigen Display nutzen nicht do mini Ding :wink:

Die Pins D0 und D1 solltest du besser generell frei lassen, denn auch das Flashen wird darüber erledigt und wenn du eine schaltungsbedingte Last auf den Pins liegen hast, wird dein Programmieren des Chips verhindert.
Und noch ein Tipp zu den Lochraster-Platinen. Nimm nicht das billige Pertinax Material. Wenn du nicht sehr geübt mit dem Löten bist, dann löst du die Streifen oder Lötaugen vom Platinen Material ab und baust gleich weitere Fehler. Hier ist Geiz an der falschen Stelle. Nimm doppelseitige Epoxydplatinen, da hast du länger was von deinen Projekten.

Ich auch, aber die alten Nanos müssen weg. Und da viele Module noch 5 Volt brauchen, gehören halt Level-Shifter einfach oft dazu.

Die ESP32 sind halt schneller und haben aber mehr Speicherplatz was mir mehr Möglichkeiten gibt, ist mein Hauptgrund.

@TO Für SD-Module (und alle anderen Module dieser Bauart wie z.b. i2c-Anschluss vom Display) schneide ich meist ein der "üblichen" Steckboardkabel durch, isoliere die eine Seite ab, und löte sie dann auf der Platine fest.

Grund: Sollte das Projekt reif für die Müll sein, kann ich so kostengünstig vieles wiederverwenden.

Gruß

Pucki

Na, ja wer massenweise kauft nur das er 1€ Spart ist selber schuld :wink: