[SOLVED] Türöffnung mit iButtons revisited

Werte Foristi,

ich versuche mich grade an einer "Türöffnung" ähnlich der in diesem Thread beschriebenen. Den Sketch habe mich mir aus diversen Quellen zusammenstückeln können und grundsätzlich funktioniert es auch - leider komme ich mit dem Array nicht klar, und das übersteigt meine bestenfalls rudimentären Programmierkenntnisse dann doch erheblich.

Zunächst mal zur Problembeschreibung: Im Array sind wie im verlinkten Beispiel die iButton-IDs hinterlegt. Allerdings löst nur die jeweils erste ID im Array die gewünschte Aktion aus - und das auch nur, wenn der Wert für SCHLUESSEL der Anzahl der eingepflegten IDs entspricht. Ändere ich die Reihenfolge der IDs, wandert das Problem nicht mit, es bleibt immer die erste ID (insofern kann ich Tippfehler bei den IDs als naheliegendste Ursache ausschließen).

Vollends irritiert mich dann aber, dass JEDE iButton-ID die gewünschte Aktion dann auslöst, wenn der Wert für SCHLUESSEL größer ist als die Anzahl der im Array befindlichen IDs - und dann aber auch solche, die gar nicht eingepflegt sind, also jeder x-beliebige iButton, der als solcher erkannt wird (ein simpler Kurzschluss am iButton-Reader triggert nix, immerhin)

Meine konkrete Frage zu meinem Sketch lautet dementsprechend, was am Array bzw. an der Vergleichs-Schleife falsch sein könnte?


const byte SCHLUESSEL = 4;  // Anzahl der gueltigen Schluessel
byte ibuttonid[SCHLUESSEL][10] = {{1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,2}, {1,1,1,1,1,1,1,3}, {1,1,1,1,1,1,1,4}}; 
byte buffer[10]; //ibutton ID-Ablage

boolean result;  // Ergebnis der iButton-Abfrage

...

// iButton-ID vergleichen

 result = false;
  for (int b = 0; b < SCHLUESSEL; b++) {
    result = true;
    int x = 0;
    do {
      int compare1 = ibuttonid[b][x];// Array vergleichen
      int compare2 = buffer[x];
      if (compare1 != compare2) { // ID nicht im Array
        result = false;
      }
      x++;
    } while (result && (x < SCHLUESSEL));
    if (result) {
      b = SCHLUESSEL;
      result = true; 

    }

  if(result == true) { // ID ist im Array

...

Um nicht nur etwas zu erfragen, sondern als kleiner Beitrag meinerseits hier noch die komplette Beschreibung und der entsprechende Sketch, evtl. hilft's ja jemand: Es geht um die Ansteuerung von Zentralverriegelungsaktoren aus dem KFZ-Bereich, die man recht günstig bekommt. Damit werden zwei Zusatzriegel einer Fahrradschuppen-Tür angetrieben. Man braucht zwar immer noch den mechanischen Schlüssel, die Riegel sind eher als "zweite Verteidigungslinie" gedacht. Ein weiteres Projekt mit demselbem Aufbau wird eine Entriegelung für mehrere Werkstattschränke.

Wer diese ZV-Antriebe nicht kennt: Das sind kleine Gleichstrom-Motoren, die mit einer zwischenübersetzung eine Zahnstange von einem zum anderen Anschlag fahren, ein paar N können die schon stemmen. Es gibt zwei Varianten, einmal mit Endlagen-Schaltern, einmal ohne. Der Motor wird einfach umgepolt zur Drehrichtungsumkehr, ich habe das mit einer L298n-H-Brücke gelöst, die die Motoren für 200ms bestromen (die Dinger haben ein ulkiges elektromechanisches Verhalten, bei Dauerplus fahren sie einmal in den Anschlag und zucken dann ryhthmisch immer wieder in die Richtung, nicht unbedingt das, was ich als Elektro-Laie erwartet hätte).

Sobald ein (berechtigter) iButton erkannt wird, fahren die (in meinem Fall) zwei Motoren in die jeweils andere Endlage. Dazu wird abgefragt, ob der dem Status "eingefahren" entsprechende Endlage-Schalter Kontakt hat. Derzeit wird nur der eine Schalter abgefragt, wenn die beiden Motoren also von Hand "asynchron" sind, ist also eine zweite Schleife notwendig, bis die Dinger sich synchronisiert haben. Die Verzögerung von zwei Sekunden am Ende ist dazu gedacht, dass der iButton entfernt wird.

Es fehlen noch ein paar Details, u.a. will ich de zweiten Endlagen-Schalter auslesen und die beiden Werte vergleichen, so dass die Motoren schon in der ersten Schleife synchronisiert werden. Und dann noch ein paar nette Gimmicks wie Rückmeldungen per LEDs und Buzzer, ein Taster parallel zum iButton-Leser, wenn man von innen entriegeln will (den Fahrradschuppen, nicht die Werkstattschränke) und das Ansteuern eines Relais fürs Licht im Schuppen (nicht im Schrank).


//iButton

#include <OneWire.h>

OneWire ibutton (2); // iButton zugewiesen an PIN 2.

const byte SCHLUESSEL = 4;  // Anzahl der gueltigen Schluessel
byte ibuttonid[SCHLUESSEL][10] = {{1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,2}, {1,1,1,1,1,1,1,3}, {1,1,1,1,1,1,1,4}};
byte buffer[10]; //ibutton ID- "Ablage".

boolean result;  // Diese Variable enthaelt das Ergebnis der iButton-Abfrage

// Gleichstrommotor 1

int GSM1 = 10;
int in1 = 9;
int in2 = 8;
int out1 = 11;

// Gleichstrommotor 2

int GSM2 = 5;
int in3 = 7;
int in4 = 6;
int out2 = 12;

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

// Pinmodes

  pinMode(GSM1, OUTPUT);    
  pinMode(GSM2, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(out1, INPUT_PULLUP);
  pinMode(out2, INPUT_PULLUP);
}

void loop(){

 if (!ibutton.search (buffer)){//iButton auslesen und Ergebnis in Buffer schreiben
    ibutton.reset_search();
    delay(100);
    return;
 }
  
  for (int x = 0; x<8; x++){  
    Serial.print(buffer[x],DEC); //Buffer in Monitor ausgeben
    Serial.print(" "); // Leerzeichen
   }
   Serial.println("\n"); // Neue Zeile
   
   // iButton-ID vergleichen

 result = false;
  for (int b = 0; b < SCHLUESSEL; b++) {
    result = true;
    int x = 0;
    do {
      int compare1 = ibuttonid[b][x];// Array vergleichen
      int compare2 = buffer[x];
      if (compare1 != compare2) { // ID nicht im Array
        result = false;
      }
      x++;
    } while (result && (x < SCHLUESSEL));
    if (result) {
      b = SCHLUESSEL;
      result = true; 

    }

  if(result == true) { // ID ist im Array

 // Motor 1

  if(digitalRead(out1) == HIGH) { //Auslesen des Positionsschalters Motor 1
  
  digitalWrite(in1, HIGH);  // Motor 1 
  digitalWrite(in2, LOW);
  analogWrite(GSM1, 255);   // Motor 1 PWM
  Serial.println("Entriegeln Motor 1"); 

  } else {

  digitalWrite(in1, LOW);  // Motor 1 gegensinnig
  digitalWrite(in2, HIGH);
  analogWrite(GSM1, 255);   // Motor 1 PWM
  Serial.println("Verriegeln Motor 1"); 
  }

 // Motor 2

  if(digitalRead(out1) == HIGH) { //Auslesen des Positionsschalters Motor 1 -> Motor 2 folgt später

  digitalWrite(in3, HIGH);  // Motor 2
  digitalWrite(in4, LOW);
  analogWrite(GSM2, 255);   // Motor 2 PWM
  Serial.println("Entriegeln Motor 2");

  } else {

  digitalWrite(in3, LOW);  // Motor 2 gegensinnig
  digitalWrite(in4, HIGH);
  analogWrite(GSM2, 255);   // Motor 2 PWM
  Serial.println("Verriegeln Motor 2");

  }

  delay(200);

   digitalWrite(in1, LOW);   // Motoren werden abgeschaltet
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW); 

  delay(2000); // zwei Sekunden Zeit, den iButton zu entfernen
 }
  
    //Buffer auf 0 zuruecksetzen
      for (int x=0; x<10; x++){
     buffer[x] = 0 ;
    }                
}
}

ich würde einfach mit memcmp vergleichen und die For Schleife beenden wenn gefunden:

ungetestet:

  bool result = false;
  int foundId = -1; // irgend ein Wert für "nicht gefunden"
  for (int b = 0; b < SCHLUESSEL; b++) {
    result = true;
    if (!memcmp(buffer, ibuttonid[b], 10 ))
    {
      result = true;
      foundId = b;
      break; // aus For schleife ausbrechen
    }
  }
1 Like

Mit dieser irreführenden Bezeichnungsweise (in für OUTPUT und out für INPUT) schießt Du Dir am Ende selbst ins Knie.

Gruß Tommy

Das hab ich nicht nachgeschaut.
Da gab es vorher schon Ungereimtheiten und es geht alles viel einfacher.
Warum setzt Du die Arrays mit 10 Elementen, wenn Du nur 8 brauchst? Und dann nutze die Größe der Arrays auch in den Schleifen etc. und schreib da nicht hart die 10 oder 8 rein.

Der kompiliert:

//iButton

#include <OneWire.h>

OneWire ibutton (2); // iButton zugewiesen an PIN 2.

const byte SCHLUESSEL = 4;  // Anzahl der gueltigen Schluessel
const byte iButLength = 8;
byte iButtonId[SCHLUESSEL][iButLength] = {{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 2}, {1, 1, 1, 1, 1, 1, 1, 3}, {1, 1, 1, 1, 1, 1, 1, 4}};
byte buffer[iButLength]; //ibutton ID- "Ablage".

boolean result;  // Diese Variable enthaelt das Ergebnis der iButton-Abfrage

// Gleichstrommotor 1

int GSM1 = 10;
int in1 = 9;
int in2 = 8;
int out1 = 11;

// Gleichstrommotor 2

int GSM2 = 5;
int in3 = 7;
int in4 = 6;
int out2 = 12;

void setup()
{
  Serial.begin(9600);
  // Pinmodes
  pinMode(GSM1, OUTPUT);
  pinMode(GSM2, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(out1, INPUT_PULLUP);
  pinMode(out2, INPUT_PULLUP);
}

void loop()
{
  if (!ibutton.search (buffer)) //iButton auslesen und Ergebnis in Buffer schreiben
  {
    ibutton.reset_search();
    delay(100);
  }
  for (int x = 0; x < iButLength; x++)
  {
    Serial.print(buffer[x], DEC); //Buffer in Monitor ausgeben
    Serial.print(" "); // Leerzeichen
  }
  Serial.println("\n"); // Neue Zeile
  // iButton-ID vergleichen
  result = false;
  for (byte b = 0; b < SCHLUESSEL; b++)
  {
    if (!memcmp(buffer, iButtonId[b], iButLength))
    {
      Serial.println(b);
      result = true;
    }
  }
  if (result == true)  // ID ist im Array
  {
    // Motor 1
    if (digitalRead(out1) == HIGH)  //Auslesen des Positionsschalters Motor 1
    {
      digitalWrite(in1, HIGH);  // Motor 1
      digitalWrite(in2, LOW);
      analogWrite(GSM1, 255);   // Motor 1 PWM
      Serial.println("Entriegeln Motor 1");
    }
    else
    {
      digitalWrite(in1, LOW);  // Motor 1 gegensinnig
      digitalWrite(in2, HIGH);
      analogWrite(GSM1, 255);   // Motor 1 PWM
      Serial.println("Verriegeln Motor 1");
    }
    // Motor 2
    if (digitalRead(out1) == HIGH)  //Auslesen des Positionsschalters Motor 1 -> Motor 2 folgt später
    {
      digitalWrite(in3, HIGH);  // Motor 2
      digitalWrite(in4, LOW);
      analogWrite(GSM2, 255);   // Motor 2 PWM
      Serial.println("Entriegeln Motor 2");
    }
    else
    {
      digitalWrite(in3, LOW);  // Motor 2 gegensinnig
      digitalWrite(in4, HIGH);
      analogWrite(GSM2, 255);   // Motor 2 PWM
      Serial.println("Verriegeln Motor 2");
    }
    delay(200);
    digitalWrite(in1, LOW);   // Motoren werden abgeschaltet
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    delay(2000); // zwei Sekunden Zeit, den iButton zu entfernen
  }
  //Buffer auf 0 zuruecksetzen
  memset (buffer, 0, iButLength);
}

Allerdings geht da noch mehr.

1 Like

Weil wie erwähnt meine Programmierkenntnisse derzeit nur zum halbwegs sinnentnehmenden Kopieren und zusammensetzen etc. reichen (zuletzt halbwegs ernsthaft programmiert hab ich gegen Ende des letzten Jahrtausends im Studium, und ich bin Maschbauer). Und bei dem Array bin ich halt völlig aufgelaufen. Ich war ehrlich gesagt baff, dass das Ding überhaupt ansatzweise das macht, was ich will.

Und funktioniert auch exakt wie gewünscht, die eingetragenen iButtons triggern, andere nicht.

Vielen Dank dafür!

Definitiv, würde ich auch nie bestreiten. Aber ich will damit ja auch nicht grade in Großserie gehen... :wink:

Tim

Das "in/OUTPUT" kommt aus einem Beispiel-Sketch für die L298n-Brücke, deren Input ist nunmal des Unos Output. Ich bin dann eben dabei geblieben.

Tim

So hab ich auch mal geschaut....
Passt schon.
Wenn Du hier:

änderst in:

void loop()
{
  if (!ibutton.search (buffer)) //iButton auslesen und Ergebnis in Buffer schreiben
  {
    ibutton.reset_search();
    delay(100);
    for (int x = 0; x < iButLength; x++)
    {
      Serial.print(buffer[x], DEC); //Buffer in Monitor ausgeben
      Serial.print(" "); // Leerzeichen
    }
    Serial.println("\n"); // Neue Zeile
  }

sieht wenigstens die Ausgabe besser aus....
Rest gibt es auf Anfrage.

1 Like

Vielen Dank nochmals - ich freu mich aber grade eher, dass das Ding jetzt erstmal exakt das tut, was ich will und werde a) versuchen zu verstehen warum und b) weiter rumbasteln - Learning by rumstümpering, sozusagen. :wink:

Ggf. komme ich dann drauf zurück!

Tim

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