Ausgänge über .txt File von SD Card steuern

Hallo zusammen,

ich bin relativ neu was Arduino und programmieren angeht.

Ich hab mittlerweile ein Programm geschrieben, das eine .txt Datei von der SD Card ausgelesen wird und im "Seriellen Monitor" auch angezeigt wird. Ich nutze hierbei ein Arduino Due und das Ethernet Shield inkl. SD Card. Das Auslesen der Datei wird per Taster aktiviert und über eine blinkende LED Signalisiert. Nachdem die Datei einmal komplett gelesen wurde wird die LED wieder deaktiviert und nach erneutem drücken des Tasters beginnt der auslese Vorgang erneut.

Die .txt Datei besteht aus vielen 0 und 1. Je Zahl ist eine extra Zeile geplant, damit die .txt Datei besser mit Excel erstellt werden kann.

Nun würde ich die Datei gerne Zeilenweise auslesen, sodass wenn eine 1 in der Datei steht eine LED an Ausgang "X" geschaltet wird. Sobald eine 0 in der Datei steht soll die LED wieder ausgeschaltet werden.

Leider stehe ich momentan etwas auf dem "Sprichwörtlichen" Schlauch und komme nicht dahinter, wie die Programmierung aussehen muss, damit dies Funktioniert.

Ich hoffe mir kann jmd. einen Denkanstoß geben.

Vielen Dank schon einmal in voraus.

Gruß

Der entsprechende Code-Block ist sehr einfach:

if (read_byte == '1') {
  digitalWrite(port, HIGH);
} else {
  digitalWrite(port, LOW);
}

Darauf wärst Du bestimmt auch gekommen. Wahrscheinlich liegt das Problem woanders, aber um das festzustellen, sollten wir Deinen aktuellen Code sehen.

der Code ist wirklich easy. Ich hatte Ihn bereits ähnlich aufgebaut. Dies funktionierte allerdings nicht.

Anbei ist mein bisher sehr einfach gehaltener und leider Kommentarloser Code den ich nutze.
LED_G an PIN 7 soll bei 0 bzw. 1 angesteuert werden.
LED_R an PIN 8 zeigt das Auslesen der SD Card an.

#include <SPI.h>
#include <SD.h>

File Text;
int LED_R = 8;
int LED_G =7;
int Taster = 2;
int Status = 0;


void setup()
{
  Serial.begin(9600);
  while (!Serial) 

  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(LED_G, OUTPUT);
  pinMode(Taster, INPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
}

void loop() { 
  Status = digitalRead(Taster);
  
 if (Status == HIGH) {{ 
  Text = SD.open("test_1.txt", FILE_READ);
  }
  if (Text) {
    Serial.println("test_1.txt:");
    while (Text.available()) {
      Serial.write(Text.read());
      digitalWrite(LED_R, HIGH);
      delay(100);
      digitalWrite(LED_R, LOW);
      delay(100);
      
    }

    Text.close();
    digitalWrite(LED_R, LOW);
    delay(5000);
    
  } else {
    Serial.println("Fehler beim öffnen von test_1.txt");
    digitalWrite(LED_R, LOW);
  }
  
  }else {
    Serial.println("Taster deaktiv");
    digitalWrite(LED_R, LOW);
    }
}

Wenn Du diesen Teil:

    while (Text.available()) {
      Serial.write(Text.read());
      digitalWrite(LED_R, HIGH);
      delay(100);
      digitalWrite(LED_R, LOW);
      delay(100);
      
    }

durch:

    uint8_t pin = 2;
    while (Text.available()) {
      uint8_t read_byte = Text.read();
      Serial.write(read_byte);
      if (read_byte < '0' || read_byte > '1') continue;
      if (pin < 20) {
        digitalWrite(pin++, read_byte == '1' ? HIGH : LOW);
      }
      digitalWrite(LED_R, HIGH);
      delay(100);
      digitalWrite(LED_R, LOW);
      delay(100);
    }

ersetzt, werden die ersten 18 Bytes im Textfile, die entweder ‘0’ oder ‘1’ sind, den entsprechenden Pin (ab 2 aufwärts, ab 14 sind es beim UNO die analogen Pins) setzen. Was natürlich noch fehlt, ist der pinMode()-Aufruf für alle Pins, damit sie Ausgänge werden.

Anbei ist mein bisher sehr einfach gehaltener und leider Kommentarloser Code den ich nutze.

Versuch mal jede geschweifte Klammer in einer eigenen Zeile und in der IDE das Auto-Format ( STRG-T ) Das hilft fast so viel wie Kommentare ;)

Eventuell verstehst du dann, warum du den Text "Initializing SD card..." vermutlich nicht siehst. ( Oder beim Übertragen hierher ist was verloren gegangen ? )

      Serial.write(Text.read());

Dazwischen fehlt was ( nämlich Pylons Vorschlag ), wenn du mehr willst als nur den gelesenen Text anzeigen.

vielen Dank schon mal für die Hilfe.

Ich werde mir alles in Ruhe nochmal anschauen.
Habe den Code gerade mal eingefügt.
Funktioniert bisher super.

Falls ich noch Fragen habe werde ich mich nochmals kurz melden.

Hi zusammen,

vielen Dank für die Super Hilfe gestern. Das Läuft so jetzt genau so wie ich es gerne wollte.

Geht das mit Analog Werten genauso schön, das mir das Arduino eine Schöne Sinuskurve ausgibt wenn ich die Werte der Datei in 1 Schritten von z.B. 0 auf 500 und dann wieder von 500 auf 0 ändere? Dabei soll am Ausgang eine Spannung von 0 bis 5 V geschaltet werden.

Gruß

Geht das mit Analog Werten genauso schön

Noch viel schöner, ist aber schwieriger ;)

Wenn in deiner Datei eine Zeile mit "1.23" steht, musst du mindestens fünf mal uint8_t read_byte = Text.read(); aufrufen und erhältst nacheinander die Zeichen'1', '.' .... und am Ende ein oder zwei Zeichen für das Zeilenende.

  1. vergiss den Dezimalpunkt.
  2. die einfachste Dezimalzahlwandlung ( ohne Vorzeichen ) ist
   static unsigned int value  = value*10 + (read_byte - '0');  // hängt eine Ziffer an den bisherigen Wert an
  1. Beim Zeilenende-Zeichen ist die Zahl fertig
  2. Das gleiche Problem ( nur nicht von SD Karte ) gabe heut schon mal.

Wie du dann eine Sinus-Kurve darstellst, würde mich interessieren ;)

Geht das mit Analog Werten genauso schön, das mir das Arduino eine Schöne Sinuskurve ausgibt wenn ich die Werte der Datei in 1 Schritten von z.B. 0 auf 500 und dann wieder von 500 auf 0 ändere? Dabei soll am Ausgang eine Spannung von 0 bis 5 V geschaltet werden.

Der Due hat zwar als erster Arduino wirklich zwei DAC an Board und kann somit wirklich analoge Signale ausgeben, aber nicht von 0 bis 5V, sondern nur von 0 bis 3.3V.

Damit Du dort eine saubere Sinuskurve hinkriegst, müssen nicht nur die Sinus-Werte zur Verfügung stehen, sondern auch das zeitliche Verhalten stimmen. Wenn die Abstände zwischen dem Setzen der einzelnen Wert nicht genau stimmen, wird Deine Kurve ziemlich unförmig. Was willst Du hier genau machen? Wozu soll die Ausgabe dienen? Evtl. gibt es einfacher und schnellere Alternativen.

Hey,

ja da hast du recht. Bei dem Due natürlich nur 0 bis 3,3 V

Der Sinn der ganzen Sache soll sein, dass wir ein aufgenommenes Messsignal Analog/Digital von SD Karte zum testen einer elektrischen Steuerung wiedergeben können. Das ganze ist mit dem Arduino wahrscheinlich sehr aufwendig, wenn überhaupt möglich.

Welche Bandbreite hat das Signal denn? Und wie lange soll die Simulation dauern bzw. nach welcher Zeit wiederholt es sich?

Optimal wäre eine Geschwindigkeit von 100 bis 500 Hz. Die Länger der Aufzeichnung variiert. Das hängt letztendlich von der Machbarkeit ab.

Soll das die Frequenz der Sinuskurve sein oder die Abtastfrequenz? Beides sollte mit dem Due machbar sein, ich sehe keine grundlegenden Probleme. Die DAC arbeiten mit bis zu 1MS/s, was also mehr als ausreichend ist. Das Einlesen der Daten von der SD-Karte neben der Ausgabe zu machen, dürfte hingegen eher trickreich sein, deshalb würde ich die Daten von der Karte in den Speicher einlesen und die Stücke so kurz halten, dass sie in's RAM des Due passen.

Die Frequenz ist die Abtastrate. Also so ca. 10ms pro neuem Wert.

Ich denke ich bekomme das mit testen und tüfteln schon hin. Nähere mich Schrittweise der lösung :D Aber "learning by doing" ist immer noch das beste 8)

Edit: Es hat geklappt :D :D Das Arduino Due gibt eine Vorgegebene Kurve -499 bis 499 am DAC0 Port mit 0,55V - 2,57V aus. Dies klappt auch Sinusförmig (je nach Vorgabe der Werte der Textdatei von der SD Karte)

Ich werde euch mein Ergebnis demnächst mal Präsentieren, falls jemand ähnliche Funktionen abbilden möchte.

Der nächste Schritt wird sein: Auslesen von 2 verschiedenen Analogwerten von SD Karte und ansteuern der beiden Analog Ausgänge (DAC0 und DAC1)

Hi zusammen,

ich habe nochmal eine kurze Frage:

Ist es möglich, das Ausgangssignal eines PWM Ausgangs (z.B. PIN 9) so zu steuern, dass er eine Variable Frequenz ausgibt? Momentan läuft der Ausgang dauerhaft mit ca. 1 kHz. Ausgegeben wird ein Rechteck Signal Ich würde den Ausgang aber gerne, abhängig vom Wert der von SD Karte gelesen wird, von 0 bis 200 Hz takten.

z.B. bei 1 = 2,22 Hz / bei 2 = 4,44 Hz usw. bis 90 = 199,8 Hz Also immer in 2,22 Hz schritten.

Wäre super wenn mir jmd. einen Lösungsansatz aufzeigen könnte, da ich momentan etwas ratlos bin

Gruß

199,8 und 197,6 Hz sind nicht sehr unterschiedlich: 5050 und 5060 µs
Der Unterschied zwischen 2,2 Hz und 4,4 Hz ist da deutlich größer :wink:
( Sicher dass du da nichts mit dem Kehrwert willst ? )

Ansonsten hat das mit PWM nicht viel zu tun, sondern eher mit Frequenzgenerator ( s. tone )

Hey,

der Unterschied bei 199,8 und 197,6 Hz ist zwar nicht so groß, bei unserer Anwendung allerdings teilweise von Bedeutung.

Ich versuche mal grob zu erklären was der Sinn der ganzen Sache ist. Ich benötige das Signal für ein Steuergerät was ein Geschwindigkeitssignal eines Tachographen auswertet. Dieser Tachograph hat 8000 Impulse pro Kilometer. Dies entspricht 2,22 Hz pro km/h. Somit sind 199,8 Hz = 80 km/h und 197,6 Hz = 79 km/h. Dieses Signal benötigt dabei eine Pulsbreite von 2 ms.

Ich hänge mal drei Bilder an, um das ganze besser zu verdeutlichen.

Geschwindigkeit 8 km/h

Geschwindigkeit 32 km/h

Geschwindigkeit 61 km/h