I2C issues sending values

I am trying to make a helicopter twin throttle/collective lever using a pro mini sending data. Just to test it, I’m using an Mega to receive the data. 3 Pot values and a few switches. Everything works fine on the pro mini when I read the pot’s and the switches, but when I try to send it over the I2C bus, Pot’s on A0 and A1 work fine but if I move the one on A2 it freezes. Same if I put the third pot on A3.

//222_Throttle_slave

#include <Wire.h>
#define DEBUG
#define I2C_ADDRESS 10

uint8_t b=0b00000000;

uint16_t coll,t1,t2;
byte pins = 9;
byte data[7];

void setup() {
 // put your setup code here, to run once:

  Wire.begin(I2C_ADDRESS);

  Wire.onRequest(requestEvent);

  #if defined(DEBUG) 
  Serial.begin(9600);
  #endif

 for (int i=2;i<=pins;i++){
    pinMode(i,INPUT_PULLUP);
    }
  
  }

void loop() {

  // put your main code here, to run repeatedly:

  for (int i=2;i<=pins;i++){

  bool pin=!digitalRead(i);

  if(pin==1)

    { 

    b |=(1<<i-2);

  }

  else{

    b &= ~(1<<i-2);

  }

}

  coll=analogRead(A0);
  t1=analogRead(A1);
  t2=analogRead(A2);
 
 coll = map(coll,0,1023,1023,0);

 t1 = map(t1,120,900,1023,0);

 t2 = map(t2,120,1023,1023,0);

  #if defined(DEBUG)

    Serial.print(coll);
    Serial.print(" ");
    Serial.print(t1);
    Serial.print(" ");
    Serial.println(t2);
    printBits(b);
    Serial.print(" ");

    #endif

  }

void requestEvent() {

  data[0] = b;
  data[1] = (coll >> 8) & 0xFF;
  data[2] = coll & 0xFF;
  data[3] = (t1 >> 8) & 0xFF;
  data[4] = t1 & 0xFF;
  data[5] = (t2 >> 8) & 0xFF;
  data[6] = t2 & 0xFF;

  Wire.write(data,7);

 
}

void printBits(byte myByte){

  for(byte mask = 0x80; mask; mask >>= 1){

   if(mask  & myByte)

       Serial.print('1');

   else

       Serial.print('0');

  }

}
// 222_Throttle_Master

#define I2C_ADDRESS 10
#include <Wire.h>
#define DEBUG

byte s ;
uint16_t coll,throttle1,throttle2;

void setup() {
 // put your setup code here, to run once:
  Serial.begin(9600);
  delay(50);
}

void loop() {

  // put your main code here, to run repeatedly:

  poll_222_throttle();
  DELAY(100);
}

void poll_222_throttle(){

  byte sw;
  uint16_t coll;
  uint16_t throttle1;
  uint16_t throttle2;

   Wire.requestFrom(I2C_ADDRESS,7);

   while (Wire.available()){
    Serial.println("initialize");
    delay(100);
    byte b1 = Wire.read();  
    byte b2 = Wire.read();  
    byte b3 = Wire.read();  //receive byte as character
    byte b4 = Wire.read();  
    byte b5 = Wire.read();  
    byte b6 = Wire.read();  
    byte b7 = Wire.read();  

    sw= b1;
    coll = b2;
    coll = (coll << 8) | b3;
    if (coll > 60000){
      coll = 0;
    }
    throttle1 = b4;
    throttle1 = (throttle1 << 8) | b5;
       if (throttle1 > 60000){
        throttle1 = 0;
    }
    throttle2 = b6;
    throttle2 = (throttle2 << 8) | b7;  
        if (throttle2 > 60000){
        throttle2 = 0;

    }

   }

   Serial.print(sw);
   Serial.print(" ");
   Serial.print(coll);
   Serial.print(" ");
   Serial.print(throttle1);
   Serial.print(" ");
   Serial.println(throttle2);
  delay(1); 

  }

When showing a sketch, please show the sketch between code-tags. The ‘< / >’ button is for code-tags.

I suggest to improve the overall quality of the sketch. That way the bug falls out of the sketch.

  1. We like to see the code of the Master and the Slave.

  2. The digitalRead() returns HIGH or LOW, a ‘bool’ is ‘true’ or ‘false’, a bit is 0 or 1. You mix those three things together. I prefer to keep them seperate.

  3. When changing a variable in a interrupt routine (requestEvent, receiveEvent) and also in the loop(), then that variable should get the keyword “volatile”.

  4. Pin 0 and 1 are for the serial port to the computer. You have DEBUG turned on and make pin 0 and 1 also INPUT_PULLUP after Serial.begin(). That will probably prevent the TX to transmit data to the computer.

  5. How many pins need to go into a byte ? I assume 8. Are those pin 2,3,4,5,6,7,8,9,10 ? That are 9 bits, they don’t fit in a byte.

  6. The analogRead() returns 0…1023, there is no need to test if it is larger than 60000.

  7. It is possible to use a single array or struct and fill it with data in the loop(). In the requestEvent(), a single Wire.write() would be enough. The Master should have the same LSB-MSB order of the bytes, but that is no problem when using a Arduino Mega 2560 and a Pro Mini. They are both of the AVR family microcontrollers.

  8. Arduino has macros to handle bits and bytes. Using normal ‘c’ language is of course no problem. If you want to take a look at them, take a look at the “Bits and Bytes” section and the “word()” on this page: Arduino Reference - Arduino Reference. The “word(h, l)” is not really a cast, it is a macro that combines two bytes into a word.

  9. Standard questions for the I2C bus: How long are the wires for the I2C bus ? Did you connect the GNDs ? Do you use a cable for the I2C bus ? What are your pullup resistors ?

Everything works as intended the way it is, until I move the pot on A2, or A3 if there is one there.
The debug statement is only used when checking the pot values on the slave, by itself. It's commented out when sending data. 2 thru 10 is only 8 bits, so it fits in one byte, didnt use 0&1 because of the serial port.

Did you use “Modify” for your top post ?
Can you try again ? The code tags are [ code ] and [ / code ].
The button for the code tags is the first button on the upper-left above the text field, it is the ‘< / >’ button. Please put your sketches between code tags.
Perhaps you need to copy your sketch again, to get rid of all the empty lines.

The Master requesting data 10 times per second is okay, that is not fast.

When you do this: for (int i = 2; i <= pins; i++), then you use the pins 2,3,4,5,6,7,8,9,10, as I wrote. That are 9 pins, not 8. Nine, as in the number of lives of a cat.

After a Serial.begin(), please don’t do a pinMode() with pin 0 and 1. They are already in use.

There is a chance that there is a hardware issue with the wiring or something is damaged. But with the issues in the sketch, I think it is better to fix that first.

Think I got the code in the right place now..

Problem solved :slight_smile: Added another analogRead on A3, and tied the pin to ground. Then changed byte data to from 7 to 9.

//222_Throttle_slave

#include <Wire.h>
//#define DEBUG
#define I2C_ADDRESS 10

uint8_t b=0b00000000;
uint16_t coll,t1,t2,t3;
byte pins = 9;
byte data[9];
#define collPin A0
#define throttlePin1 A1
#define throttlePin2 A2
#define throttlePin3 A3
void setup() {
 // put your setup code here, to run once:

  Wire.begin(I2C_ADDRESS);
  Wire.onRequest(requestEvent);
  #if defined(DEBUG) 
  Serial.begin(9600);
  delay(10);
  #endif

 for (int i=2;i<=pins;i++){
    pinMode(i,INPUT_PULLUP);
    }
  
  }

void loop() {

  // put your main code here, to run repeatedly:

  for (int i=2;i<=pins;i++){
    bool pin=!digitalRead(i);

  if(pin==1)
  { 
    b |=(1<<i-2);
  }
  else{
    b &= ~(1<<i-2);
  }

}
  coll=analogRead(collPin);
  t1=analogRead(throttlePin1);
  t2=analogRead(throttlePin2);
  t3=analogRead(throttlePin3);
 coll = map(coll,0,1023,1023,0);

  t1 = map(t1,0,1023,1023,0);
  t2 = map(t2,0,1023,1023,0);
  t3 = map(t3,0,1023,1023,0);
  #if defined(DEBUG)

    Serial.print(coll);
    Serial.print(" ");
    Serial.print(t1);
    Serial.print(" ");
    Serial.println(t2);
    printBits(b);
    Serial.print(" ");

    #endif

  }

void requestEvent() {

  data[0] = b;
  data[1] = (coll >> 8) & 0xFF;
  data[2] = coll & 0xFF;
  data[3] = (t1 >> 8) & 0xFF;
  data[4] = t1 & 0xFF;
  data[5] = (t2 >> 8) & 0xFF;
  data[6] = t2 & 0xFF;
  data[7] = (t3 >> 8) & 0xFF;
  data[8] = t3 & 0xFF;
  Wire.write(data,9);
}

void printBits(byte myByte){

  for(byte mask = 0x80; mask; mask >>= 1){

   if(mask  & myByte)
       Serial.print('1');
   else
      Serial.print('0');

  }

}
// 222_Throttle_Master

#define I2C_ADDRESS 10
#include <Wire.h>
#define DEBUG

byte sw ;
uint16_t coll,throttle1,throttle2;

void setup() {
 // put your setup code here, to run once:
  Serial.begin(9600);
  delay(50);
  Serial.println("initialize");
  delay(10);
}

void poll_222_throttle(){

  byte sw;
  uint16_t coll;
  uint16_t throttle1;
  uint16_t throttle2;

   Wire.requestFrom(I2C_ADDRESS,9);

   while (Wire.available()){
    
    delay(100);
    byte b1 = Wire.read();  
    byte b2 = Wire.read();  
    byte b3 = Wire.read();  //receive byte as character
    byte b4 = Wire.read();  
    byte b5 = Wire.read();  
    byte b6 = Wire.read();  
    byte b7 = Wire.read();  
    byte b8 = Wire.read();
    byte b9 = Wire.read();
    sw= b1;
    coll = b2;
    coll = (coll << 8) | b3;
    if (coll > 60000){
      coll = 0;
    }
    throttle1 = b4;
    throttle1 = (throttle1 << 8) | b5;
       if (throttle1 > 60000){
        throttle1 = 0;
    }
    throttle2 = b6;
    throttle2 = (throttle2 << 8) | b7;  
        if (throttle2 > 60000){
        throttle2 = 0;

    }

   }

   Serial.print(sw);
   Serial.print(" ");
   Serial.print(coll);
   Serial.print(" ");
   Serial.print(throttle1);
   Serial.print(" ");
   Serial.println(throttle2);
  delay(1); 

  }
  void loop() {

  // put your main code here, to run repeatedly:

  poll_222_throttle();
  delay(100);
}