When adding a third wire for acknowledge or handshake, then it is possible.
The next code is probably what you wanted to make.
Let me know if you tried it.
With Arduino Uno boards and Arduino IDE 1.8.5.
Transmitter
// Communication with 3 wires, Transmitter
// ---------------------------------------
//
// One way communication between two Arduino boards.
//
// Using standard Arduino functions.
//
// It uses 3 pins on each board:
// CLOCK 3 output -------> input 3 rising edge is clock signal
// DATA 4 output -------> input 4
// ACK 5 input <------- output 5 rising edge is acknowledge (handshake)
//
// They are digital signals.
// The pins don't change between input and output and no pullup resistors are needed.
//
// Transmit a bit:
// Set databit at DATA.
// Make CLOCK high.
// Wait for ACK to become high.
// Make CLOCK low
// Wait for ACK to become low.
//
//
const int clockPin = 3;
const int dataPin = 4;
const int ackPin = 5;
const unsigned long timeout = 1000; // timeout in ms
byte counter;
void setup()
{
Serial.begin( 9600);
Serial.println();
Serial.println("One way communication. Transmitter");
pinMode( clockPin, OUTPUT);
pinMode( dataPin, OUTPUT);
pinMode( ackPin, INPUT);
delay( 1000); // receiver needs to start up
}
void loop()
{
Serial.print( "Sending ");
Serial.print( counter);
Serial.print( " ... ");
bool success = Send( counter);
if( !success)
Serial.println( "Fail !, timeout !");
Serial.println( "done.");
counter++;
delay( 1000);
}
// Returns false when there was a timeout.
bool Send( byte data)
{
bool success = true;
for( int i=0; i<8 && success; i++)
{
unsigned long previousMillis = millis();
while( digitalRead( ackPin) == HIGH)
{
if( millis() - previousMillis >= timeout)
{
success = false;
break;
}
}
if( bitRead( data, i) == 1)
digitalWrite( dataPin, HIGH);
else
digitalWrite( dataPin, LOW);
digitalWrite( clockPin, HIGH);
previousMillis = millis();
while( digitalRead( ackPin) == LOW)
{
if( millis() - previousMillis >= timeout)
{
success = false;
break;
}
}
digitalWrite( clockPin, LOW);
}
return( success);
}
Receiver
// Communication with 3 wires, Receiver
// ------------------------------------
const int clockPin = 3;
const int dataPin = 4;
const int ackPin = 5;
const unsigned long timeout = 5000; // 5 seconds timeout
volatile byte data;
volatile bool newData;
void setup()
{
Serial.begin( 9600);
Serial.println();
Serial.println("One way communication. Receiver");
pinMode( clockPin, INPUT);
pinMode( dataPin, INPUT);
pinMode( ackPin, OUTPUT);
attachInterrupt( digitalPinToInterrupt( clockPin), receiveISR, CHANGE);
}
void loop()
{
if( newData)
{
Serial.println( data);
newData = false;
}
}
void receiveISR()
{
static byte _index = 0;
static byte _incoming;
if( digitalRead( clockPin) == HIGH)
{
int x = digitalRead( dataPin);
int y;
if( x == HIGH)
y = 1;
else
y = 0;
bitWrite( _incoming, _index, y);
_index++;
if( _index >= 8)
{
data = _incoming;
newData = true;
_index = 0;
}
digitalWrite( ackPin, HIGH);
}
else
{
digitalWrite( ackPin, LOW);
}
}
A bytes takes about 0.5ms, which can be compared to a serial baudrate of 19200. That is not very fast, but every bit requires an acknowledge from the receiver.
Warning: the two sketches above get 0 out of 10 points from me. They are useless, because there is no mark for the beginning of a byte. They could get out of sync. In real life they can not be used.
You wanted to avoid UART or I2C/TWI hardware and make something simple with two wires. That is not possible, well, at least not reliable. With three wires it will work, but the sketches above are not enough. Do you see where this is going ?