I2C ; Arduino Uno Slave Takes Only One Character

Hi All,
I am new to arduino. I am trying to make a simple circuit where two arduinos communicate using I2C. This is how I've done it.

  • Master takes input from serial monitor
  • If character is 'H' or 'L' character will be sent to slave
  • if character is 'H' slave will turn on LED(in the code pin 12)
  • if character is 'L' slave will turn off LED

I have connected two arduinos like this

additionally D12 pin in slave uno is connected to an LED. pull up resistors are connected to 5v pin on master arduino uno.

My problem is that slave responds(turn on/off LED) for only first character. If I entered 'H' as first character LED will turn on. then if I entered 'L' it won't turn off. but it has to be turned off when 'L' is entered. and no any response for subsequent characters('L' and 'H').

This is the Master Code

#include <Wire.h>
void setup() {

  • Serial.begin(9600);*

  • Wire.begin();*
    }
    void loop() {

  • char c ;*

  • if(Serial.available()){*

  • c = (char)Serial.read();*

  • if(true){*

  • Wire.beginTransmission(0x05);*

  • Wire.write(c);*

  • Wire.endTransmission();*

  • }*

  • }*
    }

This is the slave code

#include <Wire.h>
void setup()
{

  • Wire.begin(0x05); *
  • Wire.onReceive(receiveEvent);*
  • pinMode(12,OUTPUT);*
    }
    void loop()
    {
  • delay(100);*
    }
    void receiveEvent(int howMany)
    {
  • if(Wire.available()){*
  • char c;*
  • c = (char)Wire.read();*
  • if(c=='H'){*
  • digitalWrite(12,HIGH);*
  • }*
  • else if(c=='L'){*
  • digitalWrite(12,LOW);*
  • }*
  • }*
    }

What is the wrong with this??

AIIsuranga:
Hi All,
I am new to arduino. I am trying to make a simple circuit where two arduinos communicate using I2C. This is how I've done it.

  • Master takes input from serial monitor
  • If character is 'H' or 'L' character will be sent to slave
  • if character is 'H' slave will turn on LED(in the code pin 12)
  • if character is 'L' slave will turn off LED

What is the wrong with this??

Two problems.

First: Did you add an LED to pin 12? The internal LED is on pin 13.

Second: I changed your Slave to this code:

char buff[64];
volatile uint8_t head=0;
volatile uint8_t tail=0;

#include <Wire.h>
void setup()
{
  Wire.begin(0x05);               
  Wire.onReceive(receiveEvent);
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}
void loop()
{
  delay(50);
  if(head != tail){
    processEvent();
  }
}

void processEvent(){
noInterrupts();
char c = buff[tail];
tail = (tail+1) % 64;
interrupts();
if(c=='H'){
  digitalWrite(13,HIGH);
  }
else if(c=='L'){
  digitalWrite(13,LOW);
  }
}

void receiveEvent(int howMany)
{
  while(Wire.available()){
    char c;
    c = (char)Wire.read();
    buff[head]=c; // if buffer is full(head+1)=tail this code
                  // will overwrite last character in buffer
    uint8_t test=head;
    test++;
    test %= 64;
    if (test!=tail) head = test;
    //else buffer is full, don't increment head
  }
}

The receiveEvent function needs to be brutally fast. It is triggered by each I2C transaction, and I wanted to see each character event. I wanted a delay between characters, but delay CANNOT/MUST NOT be used in an interrupt. So I changed the Receive event to stuff a buffer that is played out in the Loop().

There might be a problem with your slave code in receiveEvent, you only allow for one character at a time if(Wire.available()). I like while(Wire.available()). so if there is more than one charater in the packet I process it to.

I wired up your circuit, using internal LED's. I can send a string of LHLHLHLHLLLLHLHHLHLH from the master and the slave flickers just fine.

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

Thanks for your reply. Actually I want to send a one character at a time. First I send character 'H' then the LED is turned on. Then if I send 'L' LED should be turned off. But it doesn't work like that.

AIIsuranga:
Thanks for your reply. Actually I want to send a one character at a time. First I send character 'H' then the LED is turned on. Then if I send 'L' LED should be turned off. But it doesn't work like that.

Looks like I cannot help you, I have 2 Uno's connected as in your diagram, and I enter 'H', click Send in the serial monitor of the Master. And the Slave turns on the LED marked L. Conversely by sending 'L' the LED go out.

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

p.s. I have attached my current master and slave sketches, they are a little more complex than the first example. I got bored, excuse me.

I2CMaster.ino (2.02 KB)

I2CSlave.ino (2.16 KB)