I2c Multiple Input and Output

Hello,
My name is Yi-Chun and i’m making a project for my school.
I’m fairly new to arduino and dont understand that much of the language.
I want to make i2c communication but with multiple inputs and outputs so i can save wire’s in my project because the second arduino is going to be placed on a risky part.

Can someone help me with this? i already made it work with 1 input and 1 output but i dont know where to start with multiple in and outputs.

Thanks !

 #include <Wire.h>


#define BUTTON 10
#define ADDRESS 42

void setup() {
  Serial.begin(112500);           // start serial for output
  pinMode(BUTTON, INPUT);
  digitalWrite(BUTTON, HIGH);
  Wire.begin();
}

boolean last_state = HIGH;

void loop() {
  if (digitalRead(BUTTON) != last_state){
    last_state = digitalRead(BUTTON);
    Serial.println("Start");
    Wire.beginTransmission(ADDRESS);
    Serial.println("Beginning transmission");
    Wire.write(last_state);
    Serial.println("Sent Data");
    Wire.endTransmission();
    Serial.println("Ended transmission");
  }
} 
For master arduino
#include <Wire.h>

#define LED_OUT 7
#define ADDRESS 42

void setup() {
  pinMode(LED_OUT, OUTPUT);
  digitalWrite(LED_OUT, LOW);
  Serial.begin(112500);
  Wire.begin(ADDRESS);
  Wire.onReceive(receiveEvent);
}


void loop() {

}

void receiveEvent(int howMany){
  while (Wire.available() > 0){
    boolean b = Wire.read();
    Serial.print(b, DEC);
    digitalWrite(LED_OUT, !b);
  }
  Serial.println(); 
}

Project_ropbot_slave.ino (409 Bytes)

master_project_robot.ino (582 Bytes)

Maybe show your current code (between code tags) so we can see what you have done and how multiple inputs outputs can be incorporated.

[code] your code here [/code] will result in

your code here

Here you go , i just dont know how to add multiple inputs here :c

The usual way for multiple buttons is to declare an array of pins. You also need an array to keep the laststate of each button.

// array with pin numbers for buttons
const byte[] buttons = { 4, 5, 6, 7, 8 };
// array to hold laststate for each button
byte[] lastStates[sizeof(buttons)];

Now your loop can loop through the buttons, read them, check if they changed etc.

void loop()
{
  // for all buttons, read and send
  for (int cnt = 0; cnt < sizeof(buttons); cnt++)
  {
    if (digitalRead(buttons[cnt]) != lastStates[cnt])
    {
      lastStates[cnt] = digitalRead(buttons[cnt]);
      Serial.println("Start");
      Wire.beginTransmission(ADDRESS);
      Serial.println("Beginning transmission");
      Wire.write(lastStates[cnt]);
      Serial.println("Sent Data");
      Wire.endTransmission();
      Serial.println("Ended transmission");
    }
  }
}

Now the problem with the above is that you will never know which button is pressed. The below solves that; it will send the state of all buttons if one button changed.

void loop()
{
  // flag to indicate that a button changed state
  bool fChanged = false;
  // values of buttons
  byte buttonValues = 0;

  // read all buttons and check for change
  for (int cnt = 0; cnt < sizeof(buttons); cnt++)
  {
    byte buttonState = digitalRead(buttons[cnt]);
    if (buttonState != lastStates[cnt])
    {
      // update last state
      lastStates[cnt] = buttonState;
      // indicate that a button changed
      fChanged = true;
      // set flags in button values
      buttonValues |= (1 << cnt);
    }
  }

  // if a button changed, send the data
  if (fChanged == true)
  {
    Serial.println("Start");
    Wire.beginTransmission(ADDRESS);
    Serial.println("Beginning transmission");
    Wire.write(buttonValues);
    Serial.println("Sent Data");
    Wire.endTransmission();
    Serial.println("Ended transmission");
  }
}

The above will be the sending side and will work for up to eight buttons;you need to change buttonValues to an appropriate type if you need more buttons. I’m not familiar with the Wire library, so I’m not sure how I would send e.g. an integer; somebody else might chime in.

For the receiving side, you can declare a similar array of pins and initialize it.

#include <Wire.h>

#define ADDRESS 42

// array with pin numbers for LEDs
const byte leds[] = { 4, 5, 6, 7, 8 };


void setup()
{
  // make all LED pins output and switch all LEDs off
  for (int cnt = 0; cnt < sizeof(leds); cnt++)
  {
    pinMode(leds[cnt], OUTPUT);
    digitalWrite(leds[cnt], LOW);
  }

  Serial.begin(9600);
  Wire.begin();

}

To parse the ‘received’ byte, you can modify the receiveEvent

void receiveEvent(int howMany)
{
  while (Wire.available() > 0)
  {
    byte b = Wire.read();
    Serial.print(b, DEC);
    // loop through the bits in the received byte for every defined LED
    for (int cnt = 0; cnt < sizeof(leds); cnt++)
    {
      digitalWrite(leds[cnt], b & (1 << cnt));
    }
  }
  Serial.println();
}

Note that the code reads a byte, not a bool.

The above code examples are fully based on yours. As said, if you need more than 8 buttons/leds, somebody else must chime in.

I’ve changed the baudrates; you seem to have used a very odd one :wink:

I keep getting this error exit status 1 expected unqualified-id before '[' token at the last state of button line

I think I mixed my languages a bit ;)

// array with pin numbers for buttons
const byte buttons[] = { 4, 5, 6, 7, 8 };
// array to hold laststate for each button
byte lastStates[sizeof(buttons)];

hehe i made it a bit different, maybe that’s why it doesnt work right now haha

 Master 

#include <Wire.h>

#define ADDRESS 42

void setup() {

}

// array with pin numbers for buttons
const byte buttons[] = { 10, 5, 6, 7, 8 };
// array to hold laststate for each button
byte lastStates[] = { 1, 1, 1, 1, 1 };



void loop()
{
  // for all buttons, read and send
  for (int cnt = 0; cnt < 5; cnt++)
  {
    if (digitalRead(buttons[cnt]) != lastStates[cnt])
    {
      lastStates[cnt] = digitalRead(buttons[cnt]);
      Serial.println("Start");
      Wire.beginTransmission(ADDRESS);
      Serial.println("Beginning transmission");
      Wire.write(lastStates[cnt]);
      Serial.println("Sent Data");
      Wire.endTransmission();
      Serial.println("Ended transmission");
    }
  }

  // flag to indicate that a button changed state
  bool fChanged = false;
  // values of buttons
  byte buttonValues = 0;

  // read all buttons and check for change
  for (int cnt = 0; cnt < 5; cnt++)
  {
    byte buttonState = digitalRead(buttons[cnt]);
    if (buttonState != lastStates[cnt])
    {
      // update last state
      lastStates[cnt] = buttonState;
      // indicate that a button changed
      fChanged = true;
      // set flags in button values
      buttonValues |= (1 << cnt);
    }
  }

  // if a button changed, send the data
  if (fChanged == true)
  {
    Serial.println("Start");
    Wire.beginTransmission(ADDRESS);
    Serial.println("Beginning transmission");
    Wire.write(buttonValues);
    Serial.println("Sent Data");
    Wire.endTransmission();
    Serial.println("Ended transmission");
  }
}
  Slave

#include <Wire.h>

#define ADDRESS 42

// array with pin numbers for LEDs
const byte leds[] = { 4, 5, 6, 7, 8 };


void setup()
{
  // make all LED pins output and switch all LEDs off
  for (int cnt = 0; cnt < sizeof(leds); cnt++)
  {
    pinMode(leds[cnt], OUTPUT);
    digitalWrite(leds[cnt], LOW);
  }

  Serial.begin(9600);
  Wire.begin();

}
void loop()
{ 
}

void receiveEvent(int howMany)
{
  while (Wire.available() > 0)
  {
    byte b = Wire.read();
    Serial.print(b, DEC);
    // loop through the bits in the received byte for every defined LED
    for (int cnt = 0; cnt < sizeof(leds); cnt++)
    {
      digitalWrite(leds[cnt], b & (1 << cnt));
    }
  }
  Serial.println();
}

master_project.ino (1.49 KB)

slave_project.ino (694 Bytes)

I gave you two different versions for the transmitter loop(); you were supposed to use the second one only.

It does not work does not mean too much; be clear in what it does and does not do. After the above change, do you get data in the receiver? I think that 'my' version of the receiveEvent works different from yours.

Once i loaded the 2 programs to the arduino's and pushed the button nothing happend that's what i ment haha , i will try it with exactly your code tomorro 1 question what happens if i push 2 buttons at the same time , or if something goes wrong with the data transfer because if i understand it correctly the code looks from button 1- 5 in that order

The code scans all buttons. If it detects a change on any of them, it will send the current status of all buttons.

You basically will never be able to push two buttons at exactly the same time. 'my' transmitter code will send e.g. 0x01 (first button pressed) followed by 0x03 (first and second button pressed) in that situation.

Also take into account that buttons can bounce; so when you press the first button, you might get a burst of data till the button has stabilised.

The code works at my side from the perspective that I get serial output when I push a button. You can add a print statement to see which data will be send.

  // if a button changed, send the data
  if (fChanged == true)
  {
    Serial.print("Data: "); Serial.println(buttonValues);
    ...
    ...

Okey, i tried to code it myself today but a little bit different, with code i actually understand haha. but my slave arduino isnt setting the outputs do you have any idea why?

testprogramma.ino (1.84 KB)

testprogramma_slave.ino (848 Bytes)

Do not re-declare c in the isr, it does not have scope for the entire sketch.

Use only the global byte c declared at the head of the program.

Do not use Serialprint() from within an isr. Move move it into loop.

#include <Wire.h>
#define ADDRES 42
#define UITGANG_0   2
#define UITGANG_1   3
#define UITGANG_2   4


const byte relais[] = { 2, 3, 4, 5, 6, 7, 8, 9};
int ttt = 0;
byte c = 0;
void setup() {

  Wire.begin(42);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void loop() {

  Serial.write ("test");
  if ( bitRead(c, 0) == HIGH) digitalWrite(UITGANG_0, HIGH);
  else if (bitRead(c, 0) == LOW) digitalWrite(UITGANG_0, LOW);

  if ( bitRead(c, 1) == HIGH) digitalWrite(UITGANG_1, HIGH);
  else if (bitRead(c, 1) == LOW) digitalWrite(UITGANG_1, LOW);

  if (bitRead(c, 2) == HIGH) digitalWrite(UITGANG_2, HIGH);
  else if (bitRead(c, 2) == LOW) digitalWrite(UITGANG_2, LOW);

  Serial.println(c);
}

void receiveEvent(int howMany) {
  while ( Wire.available () > 0) {
    //byte c = Wire.read();
    c = Wire.read();
    //Serial.print(c, DEC);
  }
}

i think i found the problem, i'm trying to write my button state into a byte, and send this byte: Input_ar over to my slave but when i open my slave's monitor and i try to read it out it keeps saying 0