Transmitting an array between two arduinos.

Hello guys, first post here so I apologize if I posted it in a wrong way…

So my goal is to transmit an array of 0’s and 1’s from my Master arduino to my Slave arduino using custom transmission protocol (I’m not allowed to use a serial communication with library). Moreover my assignment is to define clock and data using two wires that connect two arduinos (pin d10 is Data, pin d11 is Clock on both arduinos). I’m using arduino nano. My problem is I’m don’t know how to properly code that since I don’t have much experience with arduino or C,C++ language in general. I would really appreciate your assistance. Thanks in advance. I will attach my code bellow that doesn’t work (nothing appears on Serial monitor on Slave arduino). I haven’t got any errors.

Master code:

int TX_DATA = 10;
int TX_CLOCK = 11;
int i, k;
int data0[7] = {1, 1, 0, 1, 0, 0, 0};

void setup() {
    Serial.begin(9600);
    pinMode(TX_DATA, OUTPUT);
    pinMode(TX_CLOCK, OUTPUT);
}

void loop() {
    Serial.print ("\n");
    Serial.print ("For sending:");                                           //prints Final array for sending on Serial monitor
    for (i = 0; i < 7; i++) {
       Serial.print(data0[i]);
    }
    for (i = 0; i < 7; i++) {
        digitalWrite(TX_CLOCK, HIGH);
        digitalWrite(TX_DATA, 1);
        delayMicroseconds(1);                                                 //delay 1us for stability
        digitalWrite(TX_CLOCK, LOW);
    }
}

Slave code:

int i;
int RX_DATA = 10;
int RX_CLOCK = 11;

void setup() {
  pinMode(RX_DATA, INPUT);
  pinMode(RX_CLOCK, INPUT);
}

void loop() {
    digitalRead(RX_DATA);
    Serial.print ("\n");
    Serial.print ("Received:");                                           //prints received data
    Serial.print(RX_DATA);
    delay(100);
}

is this some kind of homework ?

seems to me the master is sending 1, 1, 0, 1, 0, 0, 0 - to the Serial Monitor, and then just pulses the 'clock line' every 1 uSec.

and then the slave is reading with a 100 millisecond delay ??

meanwhile

    Serial.print ("Received:");                                           //prints received data
    Serial.print(RX_DATA);

does NOT do that - it just prints '11' which is what RX_DATA is !

My problem is I'm don't know how to properly code that since I don't have much experience with arduino or C,C++ language in general.

why have you decided to use the Arduino, then ?
is it a requirement (or an option?) for an assignment ?

Thank you for your response.

It is actually a college project I volunteered to do by myself. I'm making a model of Hammings code for coding and decoding a message using two arduinos. I have managed to do everything else except this part with data transmission. I believe this part with sending an array on Master arduino is correct but I just have no idea how to properly receive and print received data on my Slave arduino.

P.S. It is obligatory to make this model with arduinos. But on the other hand I also wanted to learn more about programing in arduino since I find it very interesting.

DoxPz:
...
P.S. It is obligatory to make this model with arduinos. But on the other hand I also wanted to learn more about programing in arduino since I find it very interesting.

ok then - what example programs have you tried to do and understand.

can you blink the LED ?

can you read a button press ?

if you have understood those two programs, then you imagine the master as "blinking a LED" and slave as "reading a button press" - never mind the clock line, just try a simple single line(wire) where ; LED (ON,OFF) as an output (on the master) will be read as a button(HIGH,LOW) in other words, an input (on the slave).

Ok so far I understand what you said and also I understand both example programs. So how should I apply that on my project?

do you just understand or have you actually wired it up and see it run ?

you should then compare that code with what you are trying to do in your code and see where the differences (and bugs) are.

as i said, forget about the clock line for now - just have the data line and pretend it's an LED (for the master) and a button (for the slave).

that should give you a hint how the code should look.

Referring to the code in the Original Post …

        digitalWrite(TX_CLOCK, HIGH);
        digitalWrite(TX_DATA, 1);
        delayMicroseconds(1);                                                 //delay 1us for stability
        digitalWrite(TX_CLOCK, LOW);

First of all, slow things down to a human scale for testing - leave the clock HIGH for (say) 500 millisecs.

There should be NO delay()s in the receiver code. It must be listening all the time. The sender must dictate the frequency at which bits are transmitted.

If the HIGH clock is intended to be only asserted for 1 microsec then the receiver will need to use an interrupt to be sure of detecting it.

Actually the clock will be HIGH for several microsecs because digitalWrite() is slow. For high speeds you need the digitalWriteFast library or (even better) port manipulation.

…R

Since you are volunteering your services, can you explain this restriction?

I'm not allowed to use a serial communication with library

Baby

BabyGeezer:
do you just understand or have you actually wired it up and see it run ?

you should then compare that code with what you are trying to do in your code and see where the differences (and bugs) are.

as i said, forget about the clock line for now - just have the data line and pretend it’s an LED (for the master) and a button (for the slave).

that should give you a hint how the code should look.

I have actually wired it up and tested. I have tried to implement it in my code haven’t got any positive results. I also tried to ignore clock but got same results.

Robin2:
First of all, slow things down to a human scale for testing - leave the clock HIGH for (say) 500 millisecs.

There should be NO delay()s in the receiver code. It must be listening all the time. The sender must dictate the frequency at which bits are transmitted.

If the HIGH clock is intended to be only asserted for 1 microsec then the receiver will need to use an interrupt to be sure of detecting it.

Actually the clock will be HIGH for several microsecs because digitalWrite() is slow. For high speeds you need the digitalWriteFast library or (even better) port manipulation.

…R

I have changed like what you said and got no results. I don’t know what I’m doing wrong :roll_eyes:
Code posted below.

Master code:

int TX_DATA = 10;
int TX_CLOCK = 11;
int i, k;
int data0[7] = {1, 1, 0, 1, 0, 0, 0};

void setup() {
    Serial.begin(9600);
    pinMode(TX_DATA, OUTPUT);
    pinMode(TX_CLOCK, OUTPUT);
}

void loop() {
    Serial.print ("\n");
    Serial.print ("For sending:");                                           //prints Final array for sending on Serial monitor
    for (i = 0; i < 7; i++) {
       Serial.print(data0[i]);
    }
    for (i = 0; i < 7; i++) {
        digitalWrite(TX_CLOCK, HIGH);
        digitalWrite(TX_DATA, data0[i]);
        delay(500);                                                 //delay for stability
        digitalWrite(TX_CLOCK, LOW);
    }
}

Slave code:

int i;
int RX_DATA = 10;
int RX_CLOCK = 11;

void setup() {
  Serial.begin(9600);
  pinMode(RX_DATA, INPUT);
  pinMode(RX_CLOCK, INPUT);
}

void loop() {
  if (RX_CLOCK == HIGH) {
    int value = digitalRead(RX_DATA);
    Serial.print ("\n");
    Serial.print ("Received:");                                           //prints received data
    Serial.print(value);
  }
}

jremington:
Since you are volunteering your services, can you explain this restriction?

My mentor thought it would be to easy if made it using serial communication.

DoxPz:
Baby
I have actually wired it up and tested. I have tried to implement it in my code haven't got any positive results. I also tried to ignore clock but got same results.
...

you're not "ignoring the clock" if your master code is still the same !

make it even simpler - just make the master write HIGH or LOW - and then can you make the slave echo that ?

DoxPz:
My mentor thought it would be to easy if made it using serial communication.

Ha ha ha, he probably wants you to think hard how to solve this.

So that is what you have to do: think hard.

Using an Arduino to send pulses is no problem. The Master can be programmed to do anything you want.
Using many wires with handshake is also no problem.
Using just two wires, that is not easy for the Slave. How fast should the Slave read to signal to prevent that is misses something ?

These are a few options for the Slave:

  • Connect the clock to an interrupt, then read the data in the interrupt routine.
  • Make the signals open-collector so the Slave can send information to the Master.
  • Make is very slow, so the Slave has all the time to read the signals. The Slave has to detect a rising or falling clock signal in the loop().
  • and so on.

You don't have to reach for the final, fast, and perfect solution. You can start with something small and slow.

BabyGeezer:
you’re not “ignoring the clock” if your master code is still the same !

make it even simpler - just make the master write HIGH or LOW - and then can you make the slave echo that ?

I apologize for misunderstanding. I did ignore the clock, I just didn’t post it here. The code with ignored clock has been successfully working so I moved on and got to this part which I’ll put down below.

Master code:

int TX_DATA = 10;
int TX_CLOCK = 11;
int i, k;
int data0[7] = {1, 1, 0, 1, 0, 0, 0};

void setup() {
    Serial.begin(9600);
    pinMode(TX_DATA, OUTPUT);
    pinMode(TX_CLOCK, OUTPUT);
}

void loop() {
    Serial.print ("\n");
    Serial.print ("For sending:");                                           //prints Final array for sending on Serial monitor
    for (i = 0; i < 7; i++) {
       Serial.print(data0[i]);
    }
    for (i = 0; i < 7; i++) {
      digitalWrite(TX_DATA, 'data0[i]');
      delay(1000);  
    }
}

Slave code:

int i;
int RX_DATA = 10;
int RX_CLOCK = 11;

void setup() {
  Serial.begin(9600);
  pinMode(RX_DATA, INPUT);
  pinMode(RX_CLOCK, INPUT);
}

void loop() {
    int value = digitalRead(RX_DATA);
    Serial.print ("\n");
    Serial.print ("Received:");                                           //prints received data
    Serial.print(value);
}

So I tried to do it like this. Now problem is that for some reason I get always 1s in my Serial monitor on Slave arduino (pic below).

Koepel:
These are a few options for the Slave:

  • Connect the clock to an interrupt, then read the data in the interrupt routine.

Thank you for your response. This is the part that troubles me. I’m not sure how to properly implement that.

P.S. I apologize for the time you waited for my response. I had to do things for college so I didn’t have time to reply sooner.

Arduino has a function for interrupt : attachInterrupt() - Arduino Reference.
Your Arduino Nano can use pin 2 and 3 with attachInterrupt().

Ok guys, I did solve the problem and I just wanted to post the solution here in case someone needs it. I just wanted to say thanks everyone for help and invested time, I appreciate it. I will leave you positive karma points. :slight_smile: So here is the solution:

Master code:

int TX_DATA = 10;
int TX_CLOCK = 11;
int i;
int data0[7] = {1, 1, 0, 1, 0, 0, 0};


void setup() {
    
    Serial.begin(9600);
    
    pinMode(TX_DATA, OUTPUT);
    pinMode(TX_CLOCK, OUTPUT);

}


void loop() {

    for (i = 0; i < 7; i++) {
      if (data1[i] == 1) {                                                   //runs this function if value in array is 1
        digitalWrite(TX_CLOCK, HIGH);                                        //sets clock high
        delayMicroseconds(1);                                                   
        digitalWrite(TX_DATA, HIGH);
        delayMicroseconds(20);                                               //delay for stability
        digitalWrite(TX_CLOCK, LOW);                                         //sets clock low
        delayMicroseconds(20);
        Serial.print("PIN VALUE: ");
        Serial.println(digitalRead(TX_DATA));                                //reads output of data pin 
        delayMicroseconds(20);
      }
      else {                                                                 //runs this function if value in array is 1
        digitalWrite(TX_CLOCK, HIGH);
        delayMicroseconds(1);
        digitalWrite(TX_DATA, LOW);
        delayMicroseconds(20);                                                 
        digitalWrite(TX_CLOCK, LOW);
        delayMicroseconds(20);
        Serial.print("PIN VALUE: ");
        Serial.println(digitalRead(TX_DATA));                                  
        delayMicroseconds(20);
      }
    }

}

Slave code:

int i;
int RX_DATA = 10;
int RX_CLOCK = 11;
int clockState = 0;
int lastClockState = 0;


void setup() {
  
  Serial.begin(9600);
  pinMode(RX_DATA, INPUT);
  pinMode(RX_CLOCK, INPUT);

}


void loop() {

  clockState = digitalRead(RX_CLOCK);
  
  if (clockState != lastClockState) {                           //prevents reading multiple data values during high clock
    while (clockState == HIGH) {                                //only reads data when clock is HIGH
      delayMicroseconds(1);
      Serial.print ("Received:");
      int value = digitalRead(RX_DATA);                         //reads data from master arduino
      Serial.print(value);
      Serial.print("\n");
      break;
    }
  }
  lastClockState = clockState;                                  //updates clock state

}

I don’t if this is the best way to do it but nevertheless it gets the job done.