Hallo zusammen,
Ich bin ein ziemlicher Noob was das Arbeiten mit Microcontrollern
angeht, deshalb versuche ich jetzt mal hier etwas Hilfe zu bekommen.
Zu meiner Ausrüstung und meinem Projekt: Ich habe einen Arduino Uno und
möchte damit die Inputs meines Controllers an einer Spielekonsole
„steuern“.
Genaugenommen möchte ich später ein Programm schreiben, dass bestimmte
Inputs abarbeitet, aber so weit bin ich noch nicht. Es handelt sich um
den Super Nintendo, da habe ich mir eine Verlängerung für den Controller
beschafft und diese mit meiner Konsole und dem Arduino verbunden.
Jetzt ist es so, dass die Konsole alle 16ms ein Latch-Signal aussendet,
nach welchem die Inputs vom Controller eingelesen werden. Habe dazu ein
Bild beigelegt. Jetzt komme ich nicht weiter und habe einfach mal ohne
großes überlegen nur Inputs an den Datenport geschickt, da passiert auch
was, aber halt nichts Kontrolliertes. Dafür müsste ich das mit dem
Latch-Signal timen. Das Problem ist, dass auch, wenn ich versuche das
Latch-Signal nur auszulesen ich gar keins wahrnehmen kann. Dazu habe ich
einfach den Latch-Port mit nem Arduino-Port verbunden und lese dauerhaft
den Zustand des Ports aus. Da gibt es aber keine Veränderungen. Ich habe
es auch schon mit Widerständen versucht, da habe ich genauso wenig
Erfolg. Ich kann einfach nichts auslesen.
Falls irgendjemand schon mal sowas in der Richtung gemacht hat und mir
bei diesem Anfangsproblem helfen kann, wäre ich schon mal sehr dankbar
:)
Kannst du mal posten, wie du das ausliest? Auf dem Diagramm sieht man,
dass das Latch-Signal 12µS lang ist. Wenn du, wovon ich mal wegen Noob
ausgehe, pollst, dann muss deine Routine also öfter als alle 12µS
abfragen, ob das Signal da ist. Wenn du langsamer liest, dann kommt nur
Quatsch.
Klar. Ja, das dachte ich mir auch, deswegen habe ich es einfach mal so
geschrieben: Da kommt dann dauerhaft 0 raus, aber es müsste doch,
unabhängig davon wie oft oder wie schnell, ab und zu eine 1 ausgegeben
werden oder irre ich mich da schon? Wie gesagt, ich hab nur in Paar
Einsteigerprojekte nachgebaut, ansonsten hab ich so gut wie keine
Erfahrung. Ich kann nur Programmieren, also zumindest da sollte ich
allein weiterkommen, sobald ich hier weitergekommen bin.
void loop() {
Serial.println(digitalRead(LatchPin));
}
Und wie lange dauert die Ausführung von Serial.println()? Bzw wie viele
Nullen kommen da so pro Sekunde?
Über welchen Zeitraum hast du dein Glück versucht eine 1 zu sehen?
Wahrscheinlich dauert println deutlich länger als 12µs und du erfasst
nur aller 1ms mal einen Wert. Ob das dann eine 1/0 ist hängt vom Glück
ab.
Btw: das Latch-Signal hat ja auch eine Häufigkeit von 1/17. also nicht
wirklich häufig. Versuch dein doch mal Clock zu erkennen. Ist häufiger
und du siehst ob du überhaupt etwas lesen kannst.
Selbst, wenn ich das in eine Bedingung packe funktioniert es nicht. Das
ist ja das eigentliche Ziel. Wenn das Signal kommt warte ich 12µs und
schicke dann zum Beispiel die Taste B zur Konsole, bzw. muss ich da noch
mit dem Clock-Signal aufpassen...
Hast du die anderen Leitungen (Clock und Data) auch angeschlossen, oder
hängen die in der Luft?
Auch wäre ein Pinchange-Interrupt meiner Meinung nach eleganter, als den
Pin die ganze Zeit zu pollen. Hast du schon mal was mit Interrupts
gemacht?
Auch das gibt keine Ausgabe...
Ich weiß nicht genau was los ist, mit einem normalen Controller
funktioniert es, also müsste es eigentlich gehen. Nach allem was ich
gelesen hab, sollte da also ein Latch-Pulse alle 16,67ms (60Hz)
geschickt werden.
"Every 16.67ms (or about 60Hz), the SNES CPU sends out a 12us wide,
positive
going data latch pulse on pin 3." - Pin 3 ist der Latch-Pin.
Also entweder mache ich was grundlegend falsch oder ich hab das nicht
verstanden. Die anderen Pins sind natürlich verbunden. Ich habe hier
nochmal den Aufbau mit angehängt. Ich kann ja über den Datenpin auch
einfach Daten schicken auf welche die Konsole dann reagiert, deswegen
weiß ich auch nicht, warum ich das Signal nicht einmal wahrnehmen kann.
Arduino DigitalRead ist fürchterlich langsam - google bitte mal "arduino
fastread". Wenn Du die von der Konsole angegeben Zeiten einhalten muß,
dürfte das relevant sein (ich kenne aus der Praxis nur den
entgegengesetzten Weg, darum kann ich nicht mehr dazu sagen, aber
vielleicht hilft's ja schon :-)
digitalRead() braucht etwa 1µS. Dabei muss eigentlich nur aus dem
Register gelesen werden, was ~0.1µS dauern sollte. digitalWrite() ist
noch langsamer.
Luther B. schrieb:> Dabei muss eigentlich nur aus dem> Register gelesen werden
Das Problem ist, dass Arduino die Pins nicht in PORTs aufgeteilt hat
sondern einfach als D0 bis Dx durchnummeriert hat und damit der read
erstmal aus der Nummer die Port-Adresse berechnen muss, dann den wert
holen und dann maskieren. Das dauert schon bischen, dann kommt noch der
overhead für die calls dazu usw.
Max D. schrieb:> Luther B. schrieb:>> Dabei muss eigentlich nur aus dem>> Register gelesen werden>> Das Problem ist, dass Arduino die Pins nicht in PORTs aufgeteilt hat> sondern einfach als D0 bis Dx durchnummeriert hat und damit der read> erstmal aus der Nummer die Port-Adresse berechnen muss, dann den wert> holen und dann maskieren. Das dauert schon bischen, dann kommt noch der> overhead für die calls dazu usw.
Nein, das Problem ist, dass sich bei Arduino niemand richtig Gedanken
gemacht hat. Die Nummer des Pins den du lesen willst ist praktisch immer
zur Kompilierzeit bekannt. In diesem Fall kann auch zur Kompilierzeit
bestimmt werden, welches Bit aus welchem Register gelesen werden muss -
das ist ja genau das was digitalReadFast macht:
https://github.com/watterott/Arduino-Libs/blob/master/digitalWriteFast/digitalWriteFast.h
Bastello schrieb:> Mann kann doch auch in der Arduino IDE den Pin in "normalem" C> abfragen,> oder?> void loop()> {> if(PIND & (1 << PIND3)) //Wenn PinD3 gesetzt ist> {> Serial.println("Latch");> }> }
Das funktioniert SO aber nur auf dem einen Arduino XYZ, auf dem Arduino
ABC ist das wieder woanders. Eine (Zero-Cose) Mindestabstraktion muss
schon rein.
void loop()
{
if(PINB & (1 << PINB1))
{
Serial.println("Latch");
}
}
Ich hab das jetzt so geschrieben, nachdem ich gecheckt habe, wie es auf
dem AtMega328 geregelt ist.
Auch hier funktioniert es nicht.
Ist der Pin auch ein Eingang?
Hast du ein Oszi zum Anschauen ob das Signal physikalisch vorhanden ist?
12µs (und nicht µSiemens) aller 16,67ms ist nicht wirklich oft. Wenn
dein Uno nicht genau diese 12µs abpasst, hat er den Latch verpasst.
Versuch es doch lieber gleich mit einem Interrupt. Den wirst du am Ende
eh verwenden müssen, mach dir also gleich die Arbeit. Damit ersparst du
dir hier Arbeit.
Wer produziert den eigentlich den Clock?
Die Konsole oder der Joystick?
Ich tippe mal auf die Konsole, da wird bestimmt durch das Latchsignal
ein Schieberegister parallel geladen und dann rausgeschoben.
Wenn das so ist brauchst du das Latchsignal eh nicht unbedingt. Dein MC
braucht dann nur auf den Clock zu hören. Was dann aber unbedingt
interruptgesteuert passieren sollte.
Der Pin ist ein Eingang, ja. Ich bekomme auch Signale, bei bsp.
void loop()
{
if(PINB & (1 << PINB1))
{
Serial.println("Latch");
}
}
wenn ich die Konsole anschalte. So ca. 2-3 Sekunden lang. Allerdings
bekomme ich die auch bei digitalRead. Ich weiß nicht genau, was die
Konsole da macht.
Oszilloskop habe ich leider keins.
Mit Interrupt werde ich es mal versuchen.
Ich nehme an, dass die Konsole sowohl Clock als auch Latch produziert.
Das Latchsignal brauche ich insofern, da ich mich ja orientieren muss.
Wenn ich später die Befehle rausschicke, muss ich ja wissen, wann das
letzte Latchsignal kam um den richtigen Button zu "drücken".
Hier mal ein Auszug:
"
Every 16.67ms (or about 60Hz), the SNES CPU sends out a 12us wide,
positive
going data latch pulse on pin 3. This instructs the ICs in the
controller
to latch the state of all buttons internally. Six microsenconds after
the
fall of the data latch pulse, the CPU sends out 16 data clock pulses on
pin 2. These are 50% duty cycle with 12us per full cycle. The
controllers
serially shift the latched button states out pin 4 on every rising edge
of the clock, and the CPU samples the data on every falling edge.
Each button on the controller is assigned a specific id which
corresponds
to the clock cycle during which that button's state will be reported."
Ich hab das schon mal gelesen, kann es nur gerade nicht finden, es war
ein Schieberegister.
Wenn das so ist, werde ich das mal mit einem Interrupt versuchen und
mich dann wieder hier melden.
Danke schonmal an alle, die mir bis hierhin Tipps gegeben haben.
Ich sehe gerade, dass in dem Diagram Data auf High liegt und nur beim
entsprechenden Signal für 12 µs auf low geht. Vielleicht ignoriert dein
SNES deinen "Controller", weil Data während der initialisierung nicht
auf High liegt?
Thomas M. schrieb:> Zu meiner Ausrüstung und meinem Projekt: Ich habe einen Arduino Uno
Schon geloosed. Jedenfalls dann, wenn du das Arduino-Software-Framework
verwendest. Das ist sowas von extrem ineffizient, daß es einfach nicht
in der Lage ist, auch nur die bloße Erkennung eines 12µs langen Pulses
zu garantieren, geschweige denn die phasenrichtige Einspeisung eines
Signals über mehrere Zyklen des durch den Puls definierten 12µs-Taktes.
Arduino-Software ist völliger Dreck. Dagegen ist selbst pure C schon die
blanke Erleuchtung. Das Optimum (für das konkrete Problem alleine
allerdings noch längst nicht zwingend erforderlich) ist natürlich, wie
immer, pure Assembler.
Tja, Assembler kann ich nicht.
Ich sehe solangsam, dass ich anscheinend mit dem Arduino nur schwer oder
nicht, eben jene 12µs abfragen kann. Was würdest du denn vorschlagen,
ausgehend von meinem Projekt?
Der Arduino UNO ist nicht das Problem. Eher Arduino als "Sprache" und
die Herangehensweise.
Wenn du den Arduino in C programmierst und Interrupts statt Polling
benutzt, sollte das schon klappen.
Wenn du bei den Arduino-Libs bleiben willst, brauchst du einen
leistungsfähigeren Arduino, bei dem es dann nicht auf ein paar
verplemperte Takte ankommt. Interrupts würde ich in dem Fall aber
trotzdem empfehlen.
Knut B. schrieb:> Pullup-Widerstand nach 5V angeschlossen
Ist der Port.pin auch als Eingang geschaltet?
In arduino ist es glaube ich pin.mode(pinnr,Input)
Das ganze sieht so aus, natürlich war der pin im richtigen Modus.
1
int ClockPin = 4;
2
int DataPin = 8;
3
volatile int LatchPin = 0; //Arduino Digital Pin 2
4
5
void setup() {
6
Serial.begin(57600);
7
pinMode(ClockPin,INPUT);
8
pinMode(DataPin,OUTPUT);
9
pinMode(LatchPin,INPUT);
10
attachInterrupt(0,switchf,CHANGE);
11
12
}
13
14
void loop()
15
{
16
if(LatchPin){
17
Serial.println(":)");
18
}
19
}
20
21
22
23
void switchf(){
24
LatchPin = !LatchPin;
25
}
Hab mal Change benutzt, da ich ja nicht weiß, was genau passiert, bzw.
es mir ja erstmal egal ist, was passiert, ich will ja nur rausfinden
wann das Signal kommt. Aber auch hier bekomme ich keine Ausgabe. println
müsste ja jetzt auch funktionieren, da das Programm davor ja nicht
weitermacht, bzw. ich es ja nur ausführe, wenn sich der Zustand am Pin 2
geändert hat.
Dein Interrupt-Code hat das gleiche Problem wie alle Varianten vorher,
auch hier kannst du das Signal verpassen. Dein switchf() kopiert nur den
Pin-Status in eine Variable um, die du dann wieder mit grossen Delais
aus loop() abfragst.
Mal abgesehen davon, dass du LatchPin zwei Mal fuer verschiedene Sachen
benutzt und die Pins durcheinander gebracht hast.
Mach das so:
1
void setup() {
2
Serial.begin(57600);
3
4
pinMode(9,INPUT);
5
}
6
7
void loop()
8
{
9
while( true)
10
{
11
if(PINB & (1 << PINB1))
12
{
13
Serial.println("Latch");
14
}
15
}
16
}
Wenn das nicht geht:
* Probiere es mit dem Controller parallel zum Arduino
* Schicke aussagekraeftige Bilder deines Versuchsaufbaus
Ich verstehe nicht ganz, was der Unterschied deiner Variante zum
ursprünglichen ist, also dem hier:
1
void loop()
2
{
3
if(PINB & (1 << PINB1))
4
{
5
Serial.println("Latch");
6
}
7
}
Bei deinem Code habe ich doch nur eine zusätzliche Dauerschleife, die
nicht unterbrochen wird? Funktioniert aber auch mit dieser Variante
nicht.
Habe keine Kamera da, aber der Versuchsaufbau ist momentan nur, dass ich
den Controller vom Kabel entfernt habe und die im Bild gezeigten Kabel
mit den Ports verbunden habe. Dabei habe ich vorerst nur Latch,Clock und
Data verbunden. Dazwischen ist momentan nichts, keine Widerstände oder
sonstiges, da es auch so nicht funktioniert hat. Controller hängt also
keiner mehr dran.
Wie meinst du das denn, ich soll den Controller paralell zum Arduino
anschließen?
dast du mal versucht, den Data-Pin auf High zu stellen? Vielleicht
schickt der SNES nur das Signal raus, wenn er meint, dass auch ein
Controller am Port hängt und laut deinem Bild aus dem ersten Posting ist
Data aktive Low, also standardmäßig high und beim Signal low.
Ja, den Data-Pin auf High zu stellen habe ich auch mit im Code, auch da
funktioniert es nicht.
GND liegt natürlich am GND-Port vom Arduino, den habe ich nur vergessen
zu zeichnen^^.
Bevor das hier weitergeht, kannst du bitte bestätigen, dass in deinem
Aufbau der Controller gleichzeitig noch an einer SNES hängt, auf der ein
Spiel läuft, welches aktuell mit dem Controller gesteuert werden kann
und du mit dem Arduino nur Signale abgreifst?
Thomas M. schrieb:> Bei deinem Code habe ich doch nur eine zusätzliche Dauerschleife, die> nicht unterbrochen wird?
Exakt das: Eine Dauerschleife, die durch nichts unterbrochen wird, also
maximal schnell laeuft und so auch keine Signale verpasst.
In deiner Variante sieht das so aus:
<Arduino-Framework macht irgendwas mit unbestimmter Dauer>
loop()
{
...
}
<Arduino-Framework macht irgendwas mit unbestimmter Dauer>
Wie viel Zeit wohl das Framework fuer sich selbst braucht und wie viele
Signale du dabei verpasst...?
Noch besser waere natuerlich, gleich was ohne das Arduino-Framework zu
machen, um diesen Unsicherheitsfaktor auszuschliessen.
> Wie meinst du das denn, ich soll den Controller paralell zum Arduino> anschließen?
Controller mit einem Zwischenstecker an die Console anschliessen. An den
Zwischenstecker den Arduino fummeln, so dass er Latch beobachten kann.
Anhand eines Spiels beweisen, dass der Controller so funktioniert. Gibt
der Arduino dann immer noch nichts aus, machst du irgendwas fundamental
falsch, was du uns hier nicht zeigst.
Wenn du wirklich weiter kommen willst, musst du deine Versuche
ordentlich dokumentiert - ein Bild zeigen, auf dem dein Versuchsaufbau
erkennbar ist und den Code posten, der verwendet wurde. Bisher war jeder
von dir gezeigt Code in diesem Thread falsch und es blieb stets unklar,
was du ueberhaupt genau gemacht hast.
So, jetzt hab ich mal umgebaut:
Ich habe jetzt den Controller mit angeschlossen und den Arduino paralell
angeschlossen. Bild liegt oben bei. Ich bekomme mit folgendem Code:
1
int latchpin = 9;
2
int datapin = 8;
3
int clockpin = 7;
4
5
void setup() {
6
Serial.begin(57600);
7
8
pinMode(latchpin,INPUT);
9
pinMode(datapin,INPUT);
10
pinMode(clockpin,INPUT);
11
}
12
13
void loop()
14
{
15
while( true)
16
{
17
if(PINB & (1 << PINB1))
18
{
19
Serial.println("Latch");
20
}
21
}
22
}
jetzt die Ausgabe "Latch". Ich kann den Controller auch benutzen und die
Konsole reagiert darauf.
Wenn es funktioniert, sobald ein Controller dran hängt, dann muss wohl
der Controller der SNES zeigen, das er da ist. Ich vermute ebenfalls die
Erkennung läuft über den High-Pegel an Data Out. Teste mal ohne
Controller aber mit Data Out auf High Pegel
Das wurde ja schon öfter vorgeschlagen, habe ich auch probiert, das hat
nicht funktioniert. Ich nehme mal an, dass der SNES anders erkennt, ob
ein Controller angeschlossen ist.
Habe es aber auch glaube ich nicht geschrieben.
Eine Frage hätte ich vorerst noch. Es ist ja so, dass ich wissen muss,
wann das Signal kommt oder aufhört, bei attachInterrupt kann ich als
Parameter ja übergeben, ob der Interrupt ausgeführt werden soll bei
CHANGE,HIGH,LOW, usw.
Kann ich das auch mit einer schnelleren Methode abfragen?
Wie schneller? Die ISR wird sofort ausgeführt, wenn am entsprechenden
Pin das entsprechende Ereignis auftritt.
Wenn du also auf einen Wechsel von Low auf High einstellst, wird die ISR
immer genau dann gestartet, wenn dein Latch-Signal startet. Bei einem
Wechsel von High auf low, wenn das Signal wieder vorbei ist.
Thomas M. schrieb:> Das wurde ja schon öfter vorgeschlagen, habe ich auch probiert, das hat> nicht funktioniert.
Wie hast du das gemacht? Per Pullup vom Controller oder wie? Kannst du
bitte dafuer den Code zeigen?
Bastello schrieb:> Wie schneller? Die ISR wird sofort ausgeführt, wenn am entsprechenden> Pin das entsprechende Ereignis auftritt.
Schön wäre es. Tatsächlich ist es aber so, dass eine ISR dann ausgeführt
wird, wenn sie ausgeführt werden kann.
Beim AVR8 bedeutet das:
1) Das entsprechende IRQ-Flag muß gesetzt sein und das globale I-Flag
muss gesetzt sein
2) die zweite Bedingung ist nicht gegeben, wenn
a) eine andere ISR exclusiv werkelt
b) irgendein cli/sei-Konstrukt im laufenden Code aktiv ist, also noch
nicht das abschließende sei erreicht hat.
3) nicht wenigstens eine Instruktion in nichtexclusivem Code ausgeführt
wurde, nachdem eine Interruptsperre wirksam war.
Der gesamte Problemkreis nennt sich: "variable Interuptlatenz". Solltest
du dich ernsthaft mal drüber aufschlauen...
Das Problem ist aber, dass ich ja jetzt auf das latch-Signal warte und
dann 12µs warte und dann den datenpin 12µs auf HIGH stelle um den B
Knopf zu drücken. Jetzt sollte eigentlich immer das gleiche passieren,
tut es aber nicht. Manchmal wird Start gedrückt, manchmal der R-Button.
Also dachte ich, ich time das doch noch mit der Clock, nur kann ich auch
diese nicht am Arduino abnehmen. Egal wie. Obwohl da was ist, weil wenn
ich den Pin abziehe, kann ich mit dem Controller nicht mehr steuern.
Ich hab da gerade was gefunden:
http://assemblergames.com/l/threads/my-attempt-at-a-snes-bot-couple-of-questions.47983/
Da benutz einer einen RasPi, um den SNES zu steuern. Eigentlich ganz
einfach. Zwei 4021 Schift Register un du brauchst dir um Timing gar
keine Gedanken mehr zu machen. Du brauchst nicht mal die Levelshifter,
die er noch hat, um die 3,3V des Raspi auf die 5V des SNES zu bekommen.
Wenn du eine Taste drücken willst, einfach den Eingang des
Shift-Registers schalten und gut ist.
Nein, der Hinweis von Bastello nutzt dir nichts. Der Pi kann nicht auf
das Clock Signal reagieren, weil er unter einem nicht-Echtzeitfähigem OS
läuft, der Arduino kann das sehr wohl. 3.3V <-> 5V Problem hast du auch
nicht. Der Ard. braucht daher dieses Shift-Register nicht. Dein Problem
lässt sich mit Programmierung lösen, deine Lernaufgabe besteht darin
herauszufinden wie.
Der Uno braucht für jede Taste, die du emulieren willst, einen Ausgang.
Wenn ich mich nicht verzählt habe, sind das in der verlinkten Seite 13
IOs. Das ist mit einem UNO machbar (der hat 14 Digitale IOs und 6
Ananog-Pins, die du auch als digitale Outputs benutzen kannst).
Das mit den Schiebe-Registern ist nicht weiter wild. Das sind PiSo
Register, also Parallel In Serial Out. Das heist, das was du auf der
Input-Seite gleichzeitig eingibst, kommt auf der Output-Seite seriel
raus.
Die beiden Register sind kaskadiert (also hintereinander geschaltet) und
werden dann von der Kobsole getacktet. Da brauchst du dir um die
Ansteuerung gar keine Gedanken zu machen.
Sicherlich braucht man die beiden Shift-Register mit einem Arduino
nicht, aber es macht die Sache für einen Anfänger um einiges einfacher,
weil man sich um das Timing keine Gedanken machen muss.
Wenn man sich in Interrupts und Timer einarbeiten will, schafft man das
auch ohne. Aber vielleicht nicht als erstes eigenes Projekt.
Wird sich zeigen, was besser funktioniert, hab mir die Shifter mal
bestellt, die kosten ja nichts, ist sicher sowieso nicht verkehrt, wenn
man welche hat.
Ich habe mal folgendes Programm laufen lassen:
1
void loop()
2
{
3
while(true)
4
{
5
if(!(PINB & (1 << PINB1)))
6
{
7
Serial.println(timer);
8
timer = 0;
9
delayMicroseconds(0);
10
digitalWrite(datapin,LOW);
11
delayMicroseconds(12);
12
digitalWrite(datapin,HIGH);
13
}
14
timer++;
15
}
16
}
Und mir ausgeben lassen, wann denn das latch-Signal auftritt. Ich
bekomme hier ausgaben von 19536 bis 19557. Meine Frage: Ist das zu
vernachlässigen?
Und da ich das Clocksignal nicht abgreifen kann: Hat noch jemand eine
Idee, warum ich jetzt das Signal nicht abgreifen kann?
PS: Nochmals danke für eure Hilfe bis hierher :)
Es ist außerdem der Fall, dass der R-Knopf gedrückt wird, wenn die Clock
nicht angeschlossen ist, aber der Controller oder das Programm ein
Signal über Data schickt. Der R-Knopf ist der letzte Knopf, der vom SNES
eingelesen wird. Soweit ich weiß sind alle Signale auch 5V Signale, also
müsste das eigentlich genau wie beim Latch erkennbar sein.
Habe jetzt auch mal die Clock im Arduino abgegriffen und schicke sie
durch einen Output am Arduino weiter zum SNES und nicht paralell dazu.
Auch hier funktioniert noch alles. Habe mir auch das Signal anzeigen
lassen, dass ich zur Konsole schicke, aber auch hier bekomme ich immer
ein HIGH.
So wie ich das aus deinem Bild vom ersten Post sehe, ist Data active
Low. Also die ganze Zeit High und nur bei entsprechendem Signal für 12us
low. Kann es sein, dass du das verpasst? Hast du versucht, es per
Interrupt oder per Polling auszulesen?
Thomas M. schrieb:> Das Problem ist aber, dass ich ja jetzt auf das latch-Signal warte und> dann 12µs warte und dann den datenpin 12µs auf HIGH stelle um den B> Knopf zu drücken.
Das ganze mit dem Timing wird so nichts. Du must auf das Clocksignal
Signal reagieren. Du must da die Clocks mit einem Interrupt zählen.
Kenn mich da nicht so aus mit den Adurinos, aber kann man die nicht auch
mit normales C oder Assembler programmieren?
Hab mal hiermit geschaut.
Ab und zu kommt Datalow, auch bei keiner Eingabe. Eigentlich müsste das
bei keiner Eingabe ja die ganze zeigt auf HIGH stehen, aber ich weiß
natürlich auch nicht, was der SNES bei den nicht belegten Tasten für
Data schickt. Allerdings bekomme ich auch immer nur einmal Datalow, egal
ob ich eine Taste drücke oder nicht.
Habe auch getestet was passiert, wenn ich nur Augaben bekomme, wenn ich
einen Knopf drücke.Auch da kommen die Ausgaben eher unregelmäßig. Wenn
ich den B-Knopf die ganze Zeit gedrückt habe, sollte eigentlich
regelmäßig Datalow ausgeben werden, wird es aber nicht. Womöglich
verpasse ich auch hier immer mal wieder die 12µs in der ich den Knopf
drücke.
1
void loop()
2
{
3
while(true)
4
{
5
digitalWrite(clockout,digitalRead(clockpin));
6
// Serial.println(digitalRead(clockout));
7
if(!(PINB & (1 << PINB1)))
8
{
9
delayMicroseconds(12);
10
digitalWrite(datapin,LOW);
11
delayMicroseconds(12);
12
digitalWrite(datapin,HIGH);
13
}
14
}
Auch bei diesem Code verstehe ich nicht, warum nicht dauerhaft der
B-Knopf gedrückt wird.
Heizer schrieb:> Thomas M. schrieb:>> Das Problem ist aber, dass ich ja jetzt auf das latch-Signal warte und>> dann 12µs warte und dann den datenpin 12µs auf HIGH stelle um den B>> Knopf zu drücken.>> Das ganze mit dem Timing wird so nichts. Du must auf das Clocksignal> Signal reagieren. Du must da die Clocks mit einem Interrupt zählen.>> Kenn mich da nicht so aus mit den Adurinos, aber kann man die nicht auch> mit normales C oder Assembler programmieren?
Stimmt, aber ich kann ja das Clocksignal nicht am Arduino abgreifen. Ja,
C und Assembler sind beim Arduino möglich.
Warum kannst du das Clock-Signal nicht abfreifen? Um das ohne
dieSchiebe-Register zu machen, wäre das essentiell. Die Geschichte mit
Delay zu lösen, wird nicht sicher klappen.
Der UNO hat zwei Interrupt-Pins.
An den einen würde ich das Latch-Signal legen, an den anderen die Clock.
Dann legst du zwei ISRs an. Eine beim Wechsel von High auf Low am Latch
Pin und eine beim Wechsel von Low auf Hig beim Clock-Pin.
In der Latch-ISR stellst du einen Counter auf 0 und ggf. Data auf Low,
falls du ein B senden willst.
In der Clock-ISR zählst du den Counter eins weiter und prüfst, ob du
z.b. bei 1 ein Y senden willst. Dann Data auf Low. Ansonten auf High.
Wenn der Counter auf >11 ist, Data auf High.
ISRs sollten zwar so wenig Code wie möglich enthalten, aber diese
Abfragen dauern ja nicht lange.
Wenn du dir am Anfang noch ein Array anlegst mit deinen Tasten, kannst
du den Counter gleich als Index für das Array nehmen, um abzufragen, ob
die entsprechende Taste gedrück werden soll, oder nicht.
Hab mal ein neues Programm geschrieben um mit der Clock zu
experimentieren. Aber auch hier bekomme ich keine Ausgabe. Ich kann
einfach das Clocksignal nicht warnehmen, dass ist momentan mein Problem.
Ich weiß nicht warum der Arduino kein Signal warnimmt, obwohl es da ist.
Deine Idee ist ziemlich genau das, was ich machen werde/würde.Dazu muss
ich aber das Signal am Arduino abnehmen können, was ich nicht
hinbekomme.
Sehe ich das richtig, dass du das Clock-Signal durch den Arduino durch
schleust? Also hängt der Arduino nicht parallel zum Controller, sondern
in Reihe (Clock an Pin2 rein und an Pin6 raus?)
Ein Clock-wechsel kommt alle 6us. Ich denke, da kommt das Serial.println
nicht mit.
Das du das Clock-Signal durch den Arduino durch führen kannst, zeigt ja,
das es erkannt wird.
Das ist übrigens genau das, was ich damit meinte, die ISR möglichst kurz
zu halten. Das Serial.println ist zwar in der Arduino-IDE nur ein
Befehl, braucht aber reichlich Systemtakte. So wird die ISR immer wieder
aufgerufen, bevor sie überhaupt abgearbeitet wurde.
Setze im Interrupt doch einfach nur ein Bit wenn ein Clock auftritt.
Im Main fragst du dieses Bit ab, sendest dann deinen Text und löscht das
Bit.
Das wird dann zwar jede menge Clocks verpassen während du den Text
sendest, aber das ist zum Probieren ja erstmal egal.
Das verstehe ich nicht. Das attachInterrupt(0, clockf, CHANGE) sorgt
doch dafür, dass eben die clockf nur ausgeführt wird, wenn sich was am
Pin ändert. Aber da tut sich ja nichts. Oder meinst du, die Funktion
wird ausgeführt, aber so schnell, dass Serial.println nicht
hinterherkommt?
In dem Fall weiß ich nicht, was ich machen könnte um das Signal
warzunehmen.
Entweder, wie Heizer schrieb, eine Variabel auf true setzen und im
Main-Loop abfragen, ob true, dann Serial.println("clock") und die
Variabel wieder auf false setzen. Dann erwischt du beim Testen nur jede
x-tes Clock-Signal, oder in der ISR einen Ausgang, an dem eine LED hängt
toggeln. Wenn die LED mit halber kraft leutet, ust das Clock-Signal da
(Vorwiderstand nicht vergessen).
Hat weder mit dieser Methode noch mit der Variable funktioniert. Die
Lampe leuchtet nicht. Die Lampe leuchtet nur, wenn ich keinen Ausgang
vom Arduino nehme, sondern ich die Lampe paralell zur Clock schalte.
Dann leuchtet sie, aber auch mit voller Helligkeit...
Grad gesehen, dass nur Pin2 und Pin3 als externe Interruptquelle
funktionieren. Bau doch den Aufbau und das Programm mal entsprechend um
(also Clock an Pin2).
Das Programm schon mal getestet wenn du den Clock per Hand simulierst?
Also z.B. 10k Widerstand gegen Plus und dann den Eingang mit einen Draht
gegen GND tackten.
Die Konsole dann natürlich nicht anschliessen.
So, hab jetzt einiges geschafft.
Da ich die Clock gestern immernoch nicht warnehmen konnte, habe ich
einfach mal 2*1k Widerstände zwischen die Clock geschalten, jetzt kann
ich sie abnehmen und dementsprechend mit untenstehendem Code Buttons
drücken. Funktioniert nur nicht ganz. Das Problem ist, dass manchmal
nicht der richtige Button gedrückt wird, sondern der nächste. Das heißt,
drücke ich B, wie hier, dann wird alle paar frames auch mal ein Y
gedrückt.
An meiner Schleife zum auslesen des Inputarrays liegt es nicht,
funktioniert ohne auch noch nicht richtig. Also da scheint manchmal was
mit dem Timing nicht zu stimmen.
Allerdings weiß ich nicht genau, warum das Timing manchmal nicht passt.
Das Spiel läuft mit 50Hz und das passiert relativ oft pro Sekunde, dass
der Button verpasst wird, egal welcher.