Syntaxfehler oder ähnlich

Hallo,

irgendwie steh ich auf dem Schlauch. Ist kein echter Syntaxfehler, IDE meckert nicht rum.

Eine Unterfunktion namens
SD_write_protect();
liefert mir true oder false zurück.

in loop möchte ich das auswerten. Funktioniert aber so nicht.

if ( SD_write_protect() == false ) 
   {

Verwende ich eine Hilfsvariabel klappt das.

SD_write_protect_Zustand = SD_write_protect();   
 
 if ( SD_write_protect_Zustand == false ) 
   {

Funktioniert das nur mit Hilfsvariable für den Rückgabewert oder wie "verschachtelt" man das ohne ineinander?

Sollte eigentlich gehen, ist bei if(Serial.available()) ja auch nichts anderes, versuche mal

if(SD_write_protect()) { }
if(!SD_write_protect()) { }

oder

if(SD_write_protect() >= 1) { }
if(SD_write_protect() == 0) { }

Hallo,
"SD_write_protect_Zustand = SD_write_protect(); "

was soll das denn sein? Kannst Du mir das einmal erklären? "SchreibSchutz" von SD ist doch nur ein Schieber, der einen Kontakt
im Leser betätigt? Oder verwendest Du einen "Software" Schreibschutz, der ein bestimmtes Bit setzt?
Gruß und Dank
Andreas

Dieser "SW Schreibschutz" ist sicher dafür gedacht, falls nur microSDs zum Einsatz kommen, diese haben leider keinen Schieber an der Seite. Oder aber, dass er bei bestimmten Spannungen nicht mehr schreiben möchte (wegen Datenverlust).

Hallo,

Skoby, nicht immer gleich meckern. :wink:

Habe alle Varianten durchprobiert. Mit ! und ohne mit ==0 und >=1, funktioniert leider alles nicht.
Entweder wird die Funktion nicht aufgerufen oder die Auswertung/Rückgabewert schlägt fehl. Ich weis nicht warum. Mit der Hilfsvariable funktioniert es. :astonished:

Die Funktion soll, wie sschulteworkers schon richtig vermutet, auf äußere Einflüsse reagieren und den Zugriff auf die SD-Karte sicherheitshalber unterbinden. Entweder drücke ich einen Taster um den Zugriff zu sperren, damit ich die Karte gefahrlos entnehmen kann oder die Arduino Ub ist zu niedrig und der Zugriff wird vorsorglich gesperrt. Der Karten-Schreibschutzpin nützt mir hierbei nichts. Die Karte soll nicht generell schreibgeschützt sein. Auch eine Erkennung "Karte vorhanden oder nicht" würde mir nichts nützen, wenn ich im unglücklichen Moment die Karte entnehmen würde gerade im Augenblick wo vielleicht darauf geschrieben wird.

Kannst mal den gekürzten Sketch hier rein stellen?

Kann es sein, dass du SD_write_protect_Zustand als static deklariert hast? Was möglich ist, wenn deine Funktion es nicht schafft, in jedem Durchgang einen entsprechenden return zu schicken.

Hallo,
ach man! Ich mecker doch nicht- das hört sich anders an…

Das "SD_write_protect()" hörte sich nur so an, als wolltest Du die SD-Card
"richtig" "schreibschützen".
Du möchtest aber nur den Zugriff auf die selbe verhindern?
Gruß und Dank
Andreas

Hallo,

okay Skoby, irgendwie haste auch wieder wahr, ich steck da schon zu tief drin. :wink:
Ich werde die Namen ändern in access_protect, dann wird das verständlicher.

Code kommt gleich ....

die vielen Änderungen der Namen ist auch nicht ganz trivial und die Kommentare auch noch, sonst kommt man wieder durcheinander. So, ich hoffe das ist nicht zu sehr gekürzt, das westentlich sollte vorhanden sein. Für die Taster nutze ich die Bounce2.h Library.

Der Code ist mittlerweile ausgebaut. In der loop wird jetzt der Rückgabewert true/false der Funktion "SD_Access_Protection" ausgewertet.

global

byte Taster_SDread = 5;          // Taster an Pin 5 
byte Taster_SDread_Zustand = LOW;
byte Taster_SDread_Zustand_vorher = LOW;

byte Taster_SD_access_protect = 7;            // Taster für SD Schreibschutz an Pin 7 
byte Taster_SD_access_protect_Zustand = LOW;  // nur erneutes Taster drücken, Low Pegel, wird detektiert
boolean SD_access_protect_Zustand = true;     // Hilfsvariable, ob SD schon gesperrt wurde oder nicht

setup

// After setting up the button, setup debouncer
  debouncer1.attach(Taster_SDread);
  debouncer1.interval(50);    // Entprellzeit 50ms
  
  debouncer2.attach(Taster_BTmodul);
  debouncer2.interval(50);    // Entprellzeit 50ms
  
  debouncer3.attach(Taster_SD_access_protect);
  debouncer3.interval(50);    // Entprellzeit 50ms
      
  // digitalen Eingang mit PullUp aktivieren  
  pinMode(Taster_SDread, INPUT);                // setzt Pin als Eingang
  digitalWrite(Taster_SDread, HIGH);            // und aktiviert dessen PullUp Widerstand 
  pinMode(Taster_BTmodul, INPUT);               // setzt Pin als Eingang
  digitalWrite(Taster_BTmodul, HIGH);           // und aktiviert dessen PullUp Widerstand 
  pinMode(Taster_SD_access_protect, INPUT);      // setzt Pin als Eingang
  digitalWrite(Taster_SD_access_protect, HIGH);  // und aktiviert dessen PullUp Widerstand

loop

SD_access_protect_Zustand = SD_Access_Protection();   // SD-Karten Schreibschutz aktiv oder nicht ?

if ( actual_runtime-last_SDcard_writing >= Intervall_SD && SD_access_protect_Zustand == false )  // aller x min Daten auf SD-Karte schreiben
   {
    digitalWrite(SDcard_aktiv_LED, HIGH);        // SDcard Aktivität anzeigen 
    refresh_SD_Dateiname();                      // aktualisiert den Dateinamen auf der SD-Karte laut RTC-Datum
    if ( write_to_SDcard() == false )            // schreibe Daten auf SD-Karte und gibt Fehlerstatus zurück
      {                                          // false = fehlerfrei, true = es trat ein Fehler auf
       lcd.setCursor(0,2); lcd.print(F("  File closed   "));  
      }
    digitalWrite(SDcard_aktiv_LED, LOW);      // SD-Karten Aktivitätsende
    
    last_SDcard_writing = actual_runtime;     // aktualisiere alten Zeitpunkt
    
    SDcardLastActiveTime = millis();            // verlängere die Info Anzeige,   
    lastShow_LcdPage_1 = SDcardLastActiveTime;  // setzen der nächsten Eintrittsbedingung, gleich setzen
    lastShow_LcdPage_2 = SDcardLastActiveTime;  // gleich setzen         
   }
      
 debouncer1.update();                            // Update the debouncer
 Taster_SDread_Zustand = debouncer1.read();      // Update TasterZustand und speichern in dieser
  
 if (Taster_SDread_Zustand_vorher != Taster_SDread_Zustand)  // hat sich der Tastenzustand geändert?
    {  // aktuelle Datei der SD Karte auslesen
     if ( Taster_SDread_Zustand == LOW && SD_access_protect_Zustand == false )  {  // Tasterabfrage ob gedrückt? Nur bei erneuten Wechsel von HIGH auf LOW
        digitalWrite(SDcard_aktiv_LED, HIGH);  // SDcard Aktivität mit LED anzeigen
        refresh_SD_Dateiname(); SERIAL_IMPL.println(SD_Dateiname); // aktueller Dateiname       
        if ( read_from_SDcard() == false)  {   // lese von SD-Karte und gib Status zurück
           lcd.setCursor(0,2); lcd.print(F("  File closed   "));  
        }          
        SDcardLastActiveTime = millis();         // längere Infoanzeige, ansonsten andere Displayanzeigen          
        digitalWrite(SDcard_aktiv_LED, LOW);     // SD-Karten Aktivitätsende
        lastShow_LcdPage_1 = millis();           // setzen der nächsten Eintrittsbedingung
        lastShow_LcdPage_2 = lastShow_LcdPage_1; // gleich setzen  
     }  // Ende "Taster gedrückt?"    
     if (Taster_SDread_Zustand == LOW && SD_access_protect_Zustand == true)  {
       SERIAL_IMPL.print(RtcDateTimeBuf);             // RTC Datum und Zeit ausgeben
       SERIAL_IMPL.println(F("  SD Zugriff gesperrt"));   
       lcd.setCursor(0,2); lcd.print(F("  SD gesperrt   "));  
       SDcardLastActiveTime = millis();       // längere Infoanzeige, ansonsten andere Displayanzeigen         
     }  
     Taster_SDread_Zustand_vorher = Taster_SDread_Zustand;  // Tastenzustand meckern       
 }  // Ende: Hat sich der Tasterzustand 0/1 "dauerhaft" geändert?

Unterfunktionen

// prüft ob SD-Kartenzugriff gesperrt werden muß oder nicht
boolean SD_Access_Protection ()
{
  boolean protection_status = false;    
  if ( SD_Protect_Taster() == true || check_Arduino_Ub() == false )  {
    protection_status = true;
  }
  else  {
    protection_status = false;
  }
  //Serial.print(F("SD_Access_Protection: ")); Serial.println(protection_status);  
  return protection_status;
}  
  

// SD Karten Zugriffsschutz per Taster aktivieren oder aufheben
boolean SD_Protect_Taster()
{ // nur erneutes drücken des Tasters (Low Pegel) wird ausgewertet!
  static boolean status_protect = false;
  boolean stateChanged = debouncer3.update();    // Update the debouncer3
  int state = debouncer3.read();
  if ( stateChanged && state == LOW ) {          // Wurde Taster gedrückt?  Nur erneutes drücken wird erkannt!
    
    if ( Taster_SD_access_protect_Zustand == LOW ) {
      Taster_SD_access_protect_Zustand = HIGH;        // HIGH Schreibschutz aktiv, LOW nicht aktiv
      digitalWrite(LED1, HIGH);                       // optische Anzeige
      status_protect = true;
      SERIAL_IMPL.println(F("SD Zugriff mit Taster gesperrt")); 
    }   
    else {
      Taster_SD_access_protect_Zustand = LOW;
      digitalWrite(LED1, LOW);                        // optische Anzeige
      status_protect = false;
      SERIAL_IMPL.println(F("SD Sperre mit Taster aufgehoben"));   
    }  
  }
  //Serial.print(F("SD_Protect_Taster: ")); Serial.println(status_protect);  
  return status_protect;
}  
  
  
boolean check_Arduino_Ub ()
{
  boolean status_Ub = false;        
  // Zugriffsschutz wegen zu niedriger Arduino Ub aktiv?
  if ( Kanal_1 > 2.0 )  {           // Kanal x wird überwacht
    digitalWrite(LED_Ub, LOW);      // optische Anzeige
    status_Ub = true;               // alles i.O., Zugriffsschutz deaktiviert
   }
   else  {                          // Betriebsspannung zu niedrig
     digitalWrite(LED_Ub, HIGH);    // optische Anzeige
     status_Ub = false;             // Zugriffsschutz aktiviert, sperrt SD-Kartenzugriff
   } 
  //Serial.print(F("check_Arduino_Ub: ")); Serial.println(status_Ub);  
  return status_Ub;
}

Hmm, nun weiß ich aber auch nicht mehr weiter, warum die direkte Abfrage der Funktion nicht geht :drooling_face:

Muss jurs wohl wieder dran XD

hi,

boolean SD_Access_Protection ()
{
  boolean protection_status = false;    
  if ( SD_Protect_Taster() == true || check_Arduino_Ub() == false )  {
    protection_status = true;
  }
  else  {
    protection_status = false;
  }
  //Serial.print(F("SD_Access_Protection: ")); Serial.println(protection_status);  
  return protection_status;
}

was gibt Dir das Serial.print zurück, wenn es nicht auskommentiert ist?

ersetze
boolean protection_status = false;
durch
byte protection_status = 0;
und setze in der if auf 1 bzw. 2. was kommt dann bei serial.print raus?

gruß stefan

Hallo,

ich glaube ich habs. Das funktioniert nur scheinbar nicht. Bei mir. Und durch das Code kürzen für das Forum zum besser lesen für Euch stand nicht das da was eigentlich ab geht. Leider. Nur ist mein Sketch so groß, dass da wohl niemand anderes so recht durchblicken wird. Leider. Bei Interesse kann ich den jederzeit zur Verfügung stellen.

Wenn ich die Unterfunktion in loop mittels Hilfvariable ausführen lassen, dann wird diese zwangsweise aufgerufen, macht nette Dinge und gibt mir auch seriell Infos raus.

Baue ich die Unterfunktion in die IF Abfrage in loop ein, die wie folgt aussieht

if ( actual_runtime-last_SDcard_writing >= Intervall_SD && SD_Access_Protection() == false )

Dann weis der µC das das Intervall noch nicht abgelaufen ist und deswegen die Bedingung auf jeden Fall nicht erfüllt werden kann und bricht vorzeitig ab und prüft die zweite UND verknüpfte Bedingung erst gar nicht. Vertausche ich die UND Bedingungen sehe ich wieder alles wie man sich das vorstellt. Es hat also nur scheinbar nicht funktioniert.

Mir fiel das beim ausbauen der Unterfunktion schon einmal auf, hatte das aber nicht weiter beachtet. Jetzt hatte ich das nochmal in der loop probiert, dann fiel der Groschen. Man oh man. Der Compiler, IDE oder wer auch immer ist ganz schön schlau um Zeit bei der Abarbeitung zu sparen. Es müßte der µC selbst sein.

Edit:
seriell hatte im Einzeltest immer richtig angezeigt. Übrigens ist boolean true und byte HIGH beides "1" bzw. boolean false und byte LOW beides "0". Das hatte mir mal jurs erklärt und gezeigt. 0 und 1 wird auch in beiden Fällen seriell angezeigt. Es dient nur zum übersichtlicheren programmieren. Des wegen kann man das auch mischen. Man setzt was auf logisch true und fragt es später auf "1" ab, funktioniert wirklich. :slight_smile:

Ich danke allen für die geopferte Zeit. Ich wußte wenigstens das es nicht an falscher Schreibweise scheitert. :slight_smile:

ersetze
boolean protection_status = false;
durch
byte protection_status = 0;

In der Arduino Software gibt es eigentlich keinen eigenen Datentyp boolean. Das ist lediglich ein typedef auf uint8_t und damit identisch mit byte. Sollte also keinen Unterschied machen.

@Doc_Arduino:

Man oh man. Der Compiler, IDE oder wer auch immer ist ganz schön schlau um Zeit bei der Abarbeitung zu sparen. Es müßte der µC selbst sein.

Das ist Standard in den meisten weit verbreiteten Programmiersprachen. Nennt sich Kurzschluss Auswertung, bzw. short circuit evaluation:

Die Bit-weisen Operatoren | und & sind laut der Tabelle in C++ "eager" und werden daher vollständig getestet. Habe ich aber nicht ausprobiert.

VB. NET macht da eine interessante Unterscheidung mit And <-> AndAlso...

Übrigens ist boolean true und byte HIGH beides "1" bzw. boolean false und byte LOW beides "0".

Andersherum ist 0 false und alles was ungleich 0 ist true. Das wird z.B. ausgenutzt wenn man testet ob ein Bit gesetzt ist:

byte test = 0x80;
if(test & (1 << 8))
{
}

Hier darf man auf keinen Fall "== true" schreiben, da er dann abfragt ob das Ergebnis 1 ist. Was natürlich false ist. Aber 0x80 (0x80 & 0x80) ist true und damit passt es.

hi,

weiß schon, was Du meinst. aber ich habe keine ahnung, was passiert, wenn man eine als boolean definierte variable mit 0, 1 oder 2 belegt. und ob eine boolean-variable im seriellen monitor nicht als true oder false ausgegeben wird statt 0, 1, oder 2.

es geht ja nur um die fehlersuche und darum, daß ich drei statt zwei mögliche antworten hab'.

gruß stefan

Hallo,

man lernt nie aus, dass stimmt bei der Programmierung wirklich. :wink:

hab das mit dem boolean extra nochmal probiert. So meinst Du das sicherlich.

boolean Name_1 = true;   
boolean Name_2 = false;   
boolean Name_3 = 0; 
boolean Name_4 = 1;   
boolean Name_5 = 2;   

void setup()  {
  
  Serial.begin(57600);    
  Serial.print(F("Name 1: ")); Serial.println(Name_1);
  Serial.print(F("Name 2: ")); Serial.println(Name_2);
  Serial.print(F("Name 3: ")); Serial.println(Name_3);
  Serial.print(F("Name 4: ")); Serial.println(Name_4);
  Serial.print(F("Name 5: ")); Serial.println(Name_5);   
}

void loop()  {

}

Ergebnis im seriellen Monitor:

Name 1: 1
Name 2: 0
Name 3: 0
Name 4: 1
Name 5: 2

das hängt bestimmt was Serenifly meint mit dem typedef auf uint8_t zusammen. Deswegen ist alles was > 0 ist true.

Wie gesagt, Danke @ all.

Doc_Arduino:
das hängt bestimmt was Serenifly meint mit dem typedef auf uint8_t zusammen. Deswegen ist alles was > 0 ist true.

Alles != 0 (auch negative Zahlen!) ist true. Das allgemein definiert. Wobei es strengenommen natürlich nicht negativ sein kann, da unsigned...

Dass mit dem typedef hat damit zu tun, dass es C ursprünglich kein boolean gab. Benutzter mussten das selbst definieren. Später hat man dann in ANSI C und C99 auch boolean und entsprechende Makros eingeführt. In C++ kam dann bool hinzu. In Arduino hat man wahrscheinlich auch boolean genommen, weil es dann genauso wie in Java/Processing ist.

bool geht aber auch auf dem Arduino. Es wird lediglich vom Syntax-Highlighting nicht unterstützt. Ich habe bei mir allerdings keywords.txt so angepasst, dass es genauso behandelt wird.

Die Äquivalenz von boolean und Integern sieht man ähnlich auch bei enums. Das sind auch nur Integer und ohne Cast konvertierbar.

EDIT:
Hat erst nicht gestimmt was ich geschrieben haben, wegen der Geschichte von bool/boolean

Wobei in C++ bool nicht ein einfacher Integer ist. Das hier gibt "1" aus:

bool test = 5;
Serial.println(test);

Viele Funktionen geben den Wert -1 als Wert bei einem Fehler zurück. also ist nicht alles TRUE was nicht 0 ist.
Grüße Uwe

Bei diesen Funktionen solltest du dann besser den Rückgabe-Wert explizit auf > 0 abfragen.

Visual C++:

int func()
{
   return -1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	cout << func() << endl;

	if(func())
		cout << "true" << endl;
	else
		cout << "false" << endl;
}

Ausgabe:

-1
true

Aber, es gibt da noch eine Feinheit:

	if(func() == true)
		cout << "true" << endl;
	else
		cout << "false" << endl;

Gibt "false" aus, da -1 != 1. Genaus wenn man die Funktion z.B. 2 zurückgeben lässt