Ich versuche neben unseren alten Magnetkartenleser (Magtek ttl) einen NFC-Reader zu installieren. Da ich nicht alle alten Karten austauschen kann müssen die zwei Dinger parallel funktionieren. Der Kartenleser dient als Input für eine Anlagensteuerung = Black-Box.
Meine Idee war es, wenn am MagTek ein Signal anliegt, dann gebe ich das 1 zu 1 weiter. Wenn ein NFC-Transponder anliegt, dann simuliere ich das TTL-Signal des Magtek. Das Signal des Magnetkartenlesers konnte ich mit dem Arduino auslesen und die Bits entsprechen dem was auf der Karte steht.
ABER:
Die Anlagensteuerung akzeptiert weder das künstliche-NFC-TTL noch das Signal, das ich "einfach" weiterleite. Es glaubt mir, dass eine Karte im Slot ist, aber nichts weiter.
Einfacher scheint mir das Weiterleiten, also versuch ich das mal zu fixen: Hat einer von Euch eine Idee wo da das Problem liegen könnte? Lt. Beschreibung gibt der MagTek max. 3750 bit/s her (wenn man die Karte ziemlich flott durchzieht). Das wären min. 250µs pro bit. Das sollte sich doch locker ausgehen, oder doch ein Performance-Problem?
int signal[2] = {1,0};
int strobe[2] = {1,0};
int backend[2] = {1,0};
// The loop function is called in an endless loop
void loop() {
signal[0] = digitalRead(CR_SIGNAL);
strobe[0] = digitalRead(CR_STROBE);
backend[0]= digitalRead(CR_BACKE);
/* Serial.print(signal);
Serial.print("\t");
Serial.print(strobe);
Serial.print("\t");
Serial.print(backend);
Serial.println(""); */
if(signal[0] != signal[1]) {
digitalWrite(OUT_SIGNAL, signal[0]);
Serial.print(".");
}
if(strobe[0] != strobe[1]) {
digitalWrite(OUT_STROBE, strobe[0]);
Serial.print(".");
}
if(backend[0] != backend[1]) {
digitalWrite(OUT_BACKE, backend[0]);
Serial.print(".");
}
signal[1] = signal[0];
strobe[1] = strobe[0];
backend[1] = backend[0];
}
Wenn Du das mit digitalRead/Write machst, dann hast Du ein Performance Problem. Die Antwort lautet direkte Portmanipulation + ausschalten der Interrupts während des Lesevorgangs.
Und falls Du dabei noch Serial.Write verwendest (wie in Deinem Code), dann bist Du völlig chancenlos. Sobald der Ausgabepuffer voll ist geht die Performance senkrecht durch die Bodenplatte bis unterhalb des Kellers nach unten.
Was für ein Signal über "BACKE" übertragen wird, ist mir unklar.
Aber soweit es es "Signal" und "Strobe" betrifft sieht es ganz klar nach einer falschen Programmlogik aus.
Aus dem Datenblatt http://www.magtek.com/docs/99875042.pdf
(keine Ahnung ob das Dein Reader ist, aber wenigstens dürfte es da ähnlich sein): The Strobe signal indicates when Data is valid. It is recommended that Data be loaded by the user with the leading edge (negative) of the Strobe.
Das heißt, in Bezug auf Signal und Strobe kommt es ganz besonders darauf an, auf das Strobe nur dann zu setzen, wenn das Data-Signal gültig ist. Und das Data-Signal ist immer dann gültig, wenn das Strobe-Signal wechselt (leading edge (negative)).
Eventuell reicht es aus, in Deinem Code nur die zwei Zeilen zu vertauschen, in denen Strobe und Signal gelesen werden:
strobe[0] = digitalReadFast(CR_STROBE);
signal[0] = digitalReadFast(CR_SIGNAL);
Also erst Strobe und danach Signal lesen und beim Setzen (so wie es ist) erst Signal setzen und dann Strobe. So dass auf jeden Fall ein gültiges Signal weitergeleitet wird.
Eventuell auch gleich nach dieser Logik pollen und Signale setzen:
In der Polling Loop die Strobe-Leitung auslesen
Nur wenn sich der Zustand der Strobe-Leitung seit dem letzten Loop-Durchlauf geändert hat ("state change" auf Strobe):
ankommende Daten-Leitung auslesen
abgehende Daten-Leitung setzen
abgehende Strobe-Leitung setzen
Üblicherweise würdest Du auf den Pegelwechsel der Strobe-Leitung wohl auch besser in einer Interrupt-Behandlungsroutine reagieren als den Leitungsstatus nur zu pollen.
Für das langsame Present-Signal müßte es so funktionieren, wie Du es jetzt auch machst.
Zum Backe-Signal kann ich gar nichts sagen, da wäre es vielleicht hilfreich zu wissen, was das ist und nach welcher Logik es gesetzt wird.
Davon abgesehen würde ich die #defines durch const Deklarationen ersetzen. Das ist sauberer. Und um den Jitter zu reduzieren würde ich mit cli() alle Interrupts sperren.