Communication between 2 arduinos..

Hello to all.

Im trying to send data from master Arduino to a slave by Wire library via I2C…

Seems like the bus providing only 8 bit data transfer… But what to do if my one item is 16 bit?

Sending is 0xFFFF receiving is OxFF just 8 bits are missing… Ive Try everything.

Master code:

#include <Wire.h>

const unsigned long  PROGMEM Azbuka [64] ={
0x1111, 0x2222, 0x3333, 0x4444, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffbd, 0xef5c, 0xbe19, 0x9578, 0x7cf6, 0x7cf6, 0x8d16, 0xadd8, 0xe71b, 0xffbd, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,  
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xef1b, 0x84f7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x12b2, 0x6413, 0xd699, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,  
  
};



void setup() {
  Serial.begin(115200); // UNO
  Serial.println(" Start");
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;
String Str;

void loop() {

  if(Serial.available()>0)
  {
    Str = Serial.readString();

    if(Str[0] == '1')
    {
        Serial.println("1 poluchil");
    
      Wire.beginTransmission(8); // transmit to device #8

    
     for(int i = 0; i<=63; i++)
     {      
            Serial.print(pgm_read_word_near(&Azbuka[i]),HEX);
            Serial.print(", ");
            Wire.print(pgm_read_word_near(&Azbuka[i]));
         
     }

     Wire.endTransmission();    // stop transmitting
     
    }
  }
}

Slave code:

#include <Wire.h>

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(57600);           // start serial for output
}

void loop() {
  //Wire.onReceive(receiveEvent);
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while ( Wire.available() > 1)  // loop through all but the last
 {
   // String Str = wire.readString();
   unsigned char c = Wire.read(); // receive byte as a character
    Serial.print("0x");
    Serial.print(c);         // print the character
    Serial.print(", ");
 }
  int x = Wire.read();    // receive byte as an integer
 // Serial.println(x);         // print the integer

  Serial.println(" ");
}

Break your value into two parts and join again at Rx?

Weedpharma

yee seems like that the only way can you just show me an example?

const unsigned long  PROGMEM Azbuka [64]

Why a unsigned long when you only put values < 0xFFFF. An unsigned int will do :wink: Saves halve the memory :wink:

But to send you can do something like:

Wire.write(pgm_read_word_near(Azbuka + i), 2);

//or (if it's indeed a int, not a long)
Wire.write(pgm_read_byte_near(Azbuka + i);
Wire.write(pgm_read_byte_near(Azbuka + i + 1);

(Not tested but something like that should work)

And to receive:

unsigned int receiveInt;
while(Wire.available() >= 2){
  receiveInt = Wire.read();
  receiveInt <<= 8;
  receiveInt |= Wire.read();

  //Do something with the receiveInt
}

So it works this way…

master

const unsigned int  PROGMEM Azbuka [10] ={
0x11aa, 0x22bb, 0x33cc, 0x44dd, 0xFFFF, 0xFFFF, 0xFFFF, 0xbe19, 0x9578, 0x7cf6 
  
  
};


  Wire.beginTransmission(8); // transmit to device #8

     for(int i = 0; i<=9; i++)
     {      
           int S = pgm_read_word_near(&Azbuka [i]);  
           byte c =  S >> 8;
           Serial.print(c,HEX);
           
           //int b  = S << 8;
           byte d = S;
             
               Serial.print(" ");
               Serial.print(d, HEX);

               Wire.write(c);
               Wire.write(d);
                  
             Serial.print(" ");
           
         
     }

     Wire.endTransmission();

receive

while ( Wire.available() >= 2)  // loop through all but the last
 {
   // String Str = wire.readString();
   byte c = Wire.read(); // receive byte as a character

   int total = c;
       total  <<= 8;
       c = Wire.read();
       total |= c;
     
       
    Serial.print("0x");
    Serial.print(total, HEX);         // print the character
    Serial.print(", ");
 }
  int x = Wire.read();

But this is how the slave prints it to the Serial:

0x11AA, 0x22BB, 0x33CC, 0x44DD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFBE19, 0xFFFF9578, 0x7CF6,

Why: 0xFFFFFFFF or 0xFFFF9578 if it’s 16bit int… How it’s got another 16 bits? And so randomly…

Full sketches please.

The parameter 'howMany' can be used instead of Wire.available(). Suppose 'howMany' is 2, then two bytes are received. Put them in a buffer with Wire.readBytes(). The buffer can be a pointer pointing to an integer array or a struct.

The extra bits have to do with how print works. Instead of writing a different version of print for each data type, all the integer data types get promoted to longs and then calls the print version for long. Since the data is in an int is 0xFFFF that's equal to -1 so it is printing -1 as a long which is where the other 16 bits are coming from.

Try making total a unsigned int and see what happens.

Yep, the unsigned is important :)

And by the way, why first retrieve and int from bytes in progmem and then make two bytes from that... Why not just get bytes from progmem and use that....

Bit the same for receive. Why first put it into a byte???

void receiveEvent(int howMany) {
  while ( Wire.available() >= 2)  // loop through all but the last
 {
   // String Str = wire.readString();
   byte c = Wire.read(); // receive byte as a character

  unsigned int total = c;
       total  <<= 8;
       c = Wire.read();
       total |= c;
     
       
    Serial.print("0x");
    Serial.print(total, HEX);         // print the character
    Serial.print(", ");
 }

Delta_G thanks to you … Simply works !!! I already had that in the past… It’s same mistakes of mine… Saying before thinking… :frowning:

This is output. as suppost to be

0x11AA, 0x22BB, 0x33CC, 0x44DD, 0xFFFF, 0xFFFF, 0xFFFF, 0xBE19, 0x9578, 0x7CF6,

ok now next goal is Azbuka[1024]; But maximum at once I can send 64. Thinking…

in bytes I just wanna make sure Im not exceed 255… It’s all weirdo…

And by the way, why first retrieve and int from bytes in progmem and then make two bytes from that… Why not just get bytes from progmem and use that…

Can you show what you mean?