I2C Truncated Data

I am using a MEGA as a Master and Uno as a Slave.

I have an encoder whose counter has been scaled via math to 360 degrees. This checks out via Serial.print

I am trying to transmit that degree value from the Uno to the MEGA via I2C.

What I get is a max value of 255 at the MEGA which suggests to me that I am only reading one byte of data from the Uno. I am unsure why as I have requested 2. Any advice would be greatly appreciated.

Master Code:

#include <SyRenSimplified.h>
#include <LiquidCrystal.h>
#include <Wire.h>
// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 33, 32
LiquidCrystal lcd(12, 11, 10, 5, 4, 33, 32);

int backLight = 13;
volatile long curPos = 0;
int tgtPos = 225;

SyRenSimplified SR;

const int BUTTON1 = 52; //ccw direction button
const int BUTTON2 = 53; //cw direction button
const int LED1 = 22;    //input confirmation light for B1
const int LED2 = 23;    //input confirmation light for B2
int BUTTONstate1 = 0;
int BUTTONstate2 = 0;
int power = 0;

volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder


void setup()
{
  pinMode(BUTTON1, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode (LED2, OUTPUT);
  SyRenTXPinSerial.begin(9600);
  Wire.begin();

  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(16, 2);             // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0, 0);          // set cursor to column 0, row 0 (the first row)
  lcd.print("Tgt Pos:");    // change text to whatever you like. keep it clean!
  lcd.setCursor(13, 0);
  lcd.print("DEG");
  lcd.setCursor(0, 1);
  lcd.print("Cur Pos:");    // change text to whatever you like. keep it clean!
  lcd.setCursor(13, 1);
  lcd.print("DEG");

  pinMode(2, INPUT_PULLUP); // internal pullup input pin 2

  pinMode(3, INPUT_PULLUP); // internal pullup input pin 3
  //Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 18 on moust Arduino.
  attachInterrupt(0, ai0, RISING);

  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 19 on moust Arduino.
  attachInterrupt(1, ai1, RISING);
}

void loop()

{
  Wire.requestFrom(8, 2);

  curPos = Wire.read();
  lcd.setCursor (9, 1);
  lcd.print(curPos);
  Serial.println(curPos);

  digitalWrite(LED1, LOW);
  digitalWrite(LED2, LOW);


  while (digitalRead(BUTTON1) == HIGH && digitalRead(BUTTON2) == LOW) //ramp up in positive direction with B1 pressed
  { //but return speed to zero if conflicting inputs
    digitalWrite(LED1, HIGH);
    if (power <= 100) {
      power++;
    }
    SR.motor(power);
    delay(40);
  }

  while (power > 0 && digitalRead(BUTTON1) == LOW || power > 0 && digitalRead(BUTTON1) == HIGH && digitalRead(BUTTON2) == HIGH)
  {
    power--;
    SR.motor(power);
    delay(40);
  }

  while (digitalRead(BUTTON2) == HIGH && digitalRead(BUTTON1) == LOW) //ramp up in negatvie direction with B2 pressed
  { //but return speed to zero if conflicting inputs
    digitalWrite(LED2, HIGH);
    if (power >= -100) {
      power--;
    }
    SR.motor(power);
    delay(40);
  }

  while (power < 0 && digitalRead(BUTTON2) == LOW || power < 0 && digitalRead(BUTTON1) == HIGH && digitalRead(BUTTON2) == HIGH)
  {
    power++;
    SR.motor(power);
    delay(40);
  }



  lcd.setCursor (9, 0);
  lcd.print(tgtPos);

}

void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if (digitalRead(3) == LOW) {
    counter++;
  } else {
    counter--;
  }
}

void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if (digitalRead(2) == LOW) {
    counter--;
  } else {
    counter++;

Slave Code:

# include <Wire.h>

volatile long temp, counter, aziTemp = 0; //This variable will increase or decrease depending on the rotation of encoder
volatile long azi = 0;
void setup() {
  Wire.begin(8);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP); // internal pullup input pin 2

  pinMode(3, INPUT_PULLUP); // internal pullup input pin 3
  //Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 18 on moust Arduino.
  attachInterrupt(0, ai0, RISING);

  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 19 on moust Arduino.
  attachInterrupt(1, ai1, RISING);

}

void loop() {
  // Send the value of counter
  if ( counter != temp ) {

    temp = counter * 1.8;
    aziTemp = temp % 360;
  }
  if (aziTemp < 0) {
    azi = aziTemp + 360;
  }
  else {
    azi = aziTemp;
  }

}

void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if (digitalRead(3) == LOW) {
    counter++;
  } else {
    counter--;
  }
}

void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if (digitalRead(2) == LOW) {
    counter--;
  } else {
    counter++;
  }
}

void requestEvent() {
  Wire.write(azi);
  Serial.println(azi);

}

The way you have it coded you only transmit one byte and you only receive one byte. You should look at the wire library examples. An unsigned byte can only hold a value of 255. You will have to transmit each byte of the integer separately then reassemble the bytes into an integer on the receiver.

This reads one byte:

curPos = Wire.read();

ToddL1962:
The way you have it coded you only transmit one byte and you only receive one byte. You should look at the wire library examples. An unsigned byte can only hold a value of 255. You will have to transmit each byte of the integer separately then reassemble the bytes into an integer on the receiver.

I’ve looked though the examples, and several at other sources now, and I’m just not getting it. I’ll keep digging I guess.

I don’t suppose just changing the variable type to INT will solve this. Right?

fyrfytr310:
I’ve looked though the examples, and several at other sources now, and I’m just not getting it. I’ll keep digging I guess.

I don’t suppose just changing the variable type to INT will solve this. Right?

Nope. The wire.read() method reads a single byte. You could implement the write like below:

  Wire.write(azi & 0xff);
  Wire.write(azi>>8 & 0xff);

And the read as follows:

curPos = Wire.read();
curPos = curPos | Wire.read()<<8;

1. Master issues request command to Slave for 2-byte data and you are supposed to finish reading the asked 2-byte:

int curPos = 0;
Wire.requestFrom(8, 2);
byte x = Wire.read();  //assume higher byte comes first
byte y = Wire.read();
curPos = (int)x<<8 | (int)y; //x7......x0 00000000 | 00000000y7......y0 = x7......x0y7......y0 = 16-bit
Serial.println(curPos, HEX);    //you should see 2-byte data on Serial Monitor

2. In response to Wire.requestFrom() command, the Slave is supposed to put 2-byte data on the I2C Bus for onwards transmission to Master:

volatile int azi = 0 ;
void sendEvent()
{
    Wire.write(highByte(azi)); // higher byte being sent firts
    Wire.write(lowByte(azi));
}

ToddL1962:
Nope. The wire.read() method reads a single byte. You could implement the write like below:

  Wire.write(azi & 0xff);

Wire.write(azi>>8 & 0xff);




And the read as follows:



curPos = Wire.read();
curPos = curPos | Wire.read()<<8;

GolamMostafa:
1. Master issues request command to Slave for 2-byte data and you are supposed to finish reading the asked 2-byte:

int curPos = 0;

Wire.requestFrom(8, 2);
byte x = Wire.read();  //assume higher byte comes first
byte y = Wire.read();
curPos = (int)x<<8 | (int)y; //x7…x0 00000000 | 00000000y7…y0 = x7…x0y7…y0 = 16-bit
Serial.println(curPos, HEX);    //you should see 2-byte data on Serial Monitor




**2.** In response to Wire.requestFrom() command, the Slave is supposed to put 2-byte data on the I2C Bus for onwards transmission to Master:


volatile int azi = 0 ;
void sendEvent()
{
   Wire.write(highByte(azi)); // higher byte being sent firts
   Wire.write(lowByte(azi));
}

Thank you both very much! I will keep these responses in mind the next time I try to bring 2 arduinos together. That said, in my frustration, I finally figured out how to use millis() to keep everything on one Arduino.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.