I'd like to ask for an idea about how to connect the Arduino to a bidirectional connection. Given a Controller send a TTL High signal and expects the Arduino to give back a handshake by pulsing the very same line Low and then High. How could this be accomplished?
I already asked here, but my question was tied to a specific hardware, so that's why no one had an answer I think.
Please point me to some direction, as I'm quite lost here.
Given a Controller send a TTL High signal and expects the Arduino to give back a handshake by pulsing the very same line Low and then High. How could this be accomplished?
Basically you can't.
However if the controller that sends a TTL high were to have an open collector output, you would pull up the output with an external resistor. This would allow an arduino output to pull down this signal with a logic zero on it. Without an open collector output on your controller an attempt by the arduino to pull it down would in effect short out the output and burn out something.
This arrangement is usually done using open drain (or open collector) IO connections, with a line pulled up by a resistor.
It is essentially how I²C works - one line which is controlled by any device on it. They are all passive until they drive the line low by activating their open drain output to link the line to ground.
The controller pin actually is open collector w/ pullup-resistor, and it expects to be connected to the same configuration, according to the hardware reference manual. It uses the serial register of an 8520 (SP line).
So, I'd now pull-up the AVR I/O to +5V all the time (10K resistor ok?), and use output mode/level 0 to output a 1, is that correct? And I can read the line by just switching to input mode? Ok?
You only need one pull-up resistor for the entire network. If the device at the remote end has a pull-up resistor with it you don't need one at the Arduino end.
I don't think the Arduino does open drain / open collector. The best you can hope for is to keep it in input mode all the time except when you need to toggle it, when you briefly switch to output, set to low, then switch back to input.
Ideally though you would emulate open-collector by having two IO lines - one set to input all the time so you can read the state of the line, and another connected via a resistor to the base of an NPN transistor, or the gate of an N-channel MOSFET, which is used to pull the line low.
majenko:
I don't think the Arduino does open drain / open collector. The best you can hope for is to keep it in input mode all the time except when you need to toggle it, when you briefly switch to output, set to low, then switch back to input.
This didn't work. The controller continues to send its sync pulses as if no handshake has been given. Part of the problem might be that low must be applied for at least 85ms (I tried 100ms to be on the safe side, but that's not 'briefly', right?) while the clock is high for about 140ms. BTW, w/o pullup on Arduinos side, the controller stops doing anything and needs a reset .
Also tried a second line connected via a diode, and pulled up, to no avail.
majenko:
Ideally though you would emulate open-collector by having two IO lines - one set to input all the time so you can read the state of the line, and another connected via a resistor to the base of an NPN transistor, or the gate of an N-channel MOSFET, which is used to pull the line low.
So, where to connect emitter and collector? I guess the emitter is connected to data, collector to +5V, right?
If the controller works as you described with an open collector output then the fact that it didn't work means you didn't do it right. You should be switching a pin to an output with a preloaded zero in the output register to pull the line to zero, then switch it to an input to remove it.
There is no need to implement an extra transistor, but if you must try it then:-
So, where to connect emitter and collector? I guess the emitter is connected to data, collector to +5V, right?
No, emitter to ground, collector to data line, base to a resistor, other end of the resistor to the arduino output.
The way you do "open drain" or "open collector" on the Arduino is:
void setup ()
{
pinMode (pin, INPUT) ;
digitalWrite (pin, LOW) ; // set LOW once, it stays that way
}
void send_bit (boolean b)
{
pinMode (pin, b ? INPUT : OUTPUT) ; // drive pin LOW for a zero/false and let it be input (pulled high by resistor) otherwise
}
For the sake of completeness, and if anyone finds this thread to do the same, here's the code for testing the connection. It's full of busy loops, but that doesn't matter really here. Should work for all Amiga keyboards w/ separated controller (i.e., not A1200 which would need serial registers). Clock is pin 1 (black), Data is pin 2 (brown).
#define CLK 8
#define SP 9
void setup() {
Serial.begin(9600);
pinMode(CLK, INPUT);
pinMode(SP, INPUT);
digitalWrite(SP, LOW);
pinMode(13, OUTPUT);
delay(5000);
}
void loop() {
int n;
unsigned int d;
// wait for beginning of synch-phase
while (digitalRead(CLK)==HIGH);
// wait for the clock going low
while (digitalRead(CLK)==LOW);
// Handshake must be given now
pinMode(SP, OUTPUT);
digitalWrite(SP,LOW);
delay(90);
pinMode(SP, INPUT);
// Now read 8 bit
digitalWrite(13, HIGH);
for (n=0; n<8; n++) {
while (digitalRead(CLK)==LOW);
d+=digitalRead(SP)<<n;
while (digitalRead(CLK)==HIGH);
}
digitalWrite(13, LOW);
Serial.println(d);
}