Go Down

Topic: I2C Communication / debounce / interrupt errors (Read 3756 times) previous topic - next topic

gnusso

Hi all good morning to every body,
SCENARIO:

- 2 arduino's uno connected via i2c on analog 4 (SDA) and analog 5(SCL)
- On the Master I've connected a button digital pin 2
- On the slave there is connected led on digital pin 12
Every thing is working, when I press the button send via bus the HIGH state and the led is turned on. When I press the button again send the LOW and the led is turned off.
Well the problem is that when I've pressed the button and sent data over i2c on the slave I do a serial out in this way (correct me if wrong) i see the state in that moment and i can see a lot's of value sent from the button and not only one.  So, I've looked for that internet and I've put in place a adjust my code with a bounce library it's a little bit better but not optimal ... Also I've seen that is possible use interrupt but there I don't understand if after the interrupt is switch off or if necessary detach it ... and also I've seen that is possible install this CMOS mc14490  for fix the debounce issues ...

I did a try with the interrupt configuring it but didn't work ... ;-(

My intentions if is possible is doing everything from software and I think that maybe the better solution is use the interrupt ...

please if there is someone that already encountered this kind of issues please let me know ;-)

Thx for the help
Andrea

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

PaulS

Quote
My intentions if is possible is doing everything from software and I think that maybe the better solution is use the interrupt ...

I disagree. Interrupts are complex to use and understand. If you can't get simple I2C communications to work when polling the switch state, the chances of getting it to work when using an interrupt are even lower.

Get the I2C part working with polling before you even consider interrupts.

And ditto the request to post your code.
The art of getting good answers lies in asking good questions.

robtillaart


For the debounce check - http://arduino.cc/playground/Code/Bounce -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

gnusso

Hi Guys,
I will post the exact code this evening when i will come back to work :-)

Thanks for the support,

Andrea

gnusso

MASTER CODE:

#include <Bounce.h>
#include <Wire.h>

#define buttonPin 2     // the number of the pushbutton pin
const int ledPin =  13;  // the number of the LED pin
int buttonState = LOW;   // variable for reading the pushbutton status
 
Bounce bouncer = Bounce( buttonPin,5 );

void setup()
{
  // initialize the LED pin as an output:
 pinMode(ledPin, OUTPUT);      
 // initialize the pushbutton pin as an input:
 pinMode(buttonPin, INPUT);  
 Wire.begin(); // join i2c bus (address optional for master)
 
}


void loop()
{
 
 // Update the debouncer
 bouncer.update ( );
  int in = bouncer.read();

    if (in == HIGH)
        {
           if (buttonState ==LOW)
             {    
               buttonState = HIGH;
             }
           else  
             {
               buttonState = LOW;
             }
        }    
   // turn LED on:    
     digitalWrite(ledPin,buttonState);  
     Wire.beginTransmission(4); // transmit to device #4
     Wire.send(buttonState);          
     Wire.endTransmission();
     
}

SLAVE CODE :

#include <Wire.h>

const int ledPin =  12;      // the number of the LED pin

void setup()
{
 Wire.begin(4);                // join i2c bus with address #4
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(9600);           // start serial for output
 pinMode(ledPin, OUTPUT);
}

void loop()
{
 
 delay(3000); //Wait 2 Second before re-excute
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
//while(1 < Wire.available()) // loop through all but the last
//{
 int x = Wire.receive();    // receive byte come un integer
    if (x == HIGH) {    
   // turn LED on:    
     digitalWrite(ledPin, HIGH);
     Serial.println(x);
   
 }
    else {
    // turn LED off:
     digitalWrite(ledPin, LOW);
     Serial.println(x);
  }
//}
}

thx for the support Andrea

PaulS

Code: [Select]
if (buttonState ==LOW)
              {   
                buttonState = HIGH;
              }
            else 
              {
                buttonState = LOW;
              }

could be written as
Code: [Select]
buttonState = !buttonState;

That leaves loop() on the master:
Code: [Select]
void loop()
{
 
  // Update the debouncer
  bouncer.update ( );
   int in = bouncer.read();

     if (in == HIGH)
         {
            buttonState = !buttonState;
         }   
    // turn LED on:   
      digitalWrite(ledPin,buttonState); 
      Wire.beginTransmission(4); // transmit to device #4
      Wire.send(buttonState);         
      Wire.endTransmission();
}

which makes it obvious that you are sending data on every pass through loop, not just when the button is pressed. I think it is obvious what you need to do.
The art of getting good answers lies in asking good questions.

gnusso

I've did the code improvement that you have suggest to me ...
But now How i can do for the send only one data when I've press the button one time so mainly time the is not switch off.  My problems is not the loop but the when I press the button I send out a lot of date and only 1 when is pressed one time and 0 when is pressed again ... maybe it's that you define "obvious" ;-) ... put a condesator ?or something like that ?

thx Andrea
sorry but I'm very new devoloper with arduino ;-)

PaulS

Quote
How i can do for the send only one data when I've press the button one time

If you want to send data only once for each button press, the Bounce library is not the right library to be using. The Button library would be a better choice. It has a method, uniquePress() that returns true only one time per button press.

Each time uniquePress() returns true, send the message:
Code: [Select]
Button sw(pin, PULLUP);

void loop()
{
   if(sw.uniquePress())
   {
      // Turn on the LED and send the message
   }
}


If you want to send different messages when the switch is pressed and when it is released, you can use the isPressed() and wasPressed() methods to determine if the switch is pressed and was not (send the pressed message) or was pressed and is not pressed (send the released message).
The art of getting good answers lies in asking good questions.

gnusso

Thank ;-) for your quick reply ;-) I've change the code like a your indication and now seems better thanks :-)
but is not perfect some times still to lose the pressed ... :-( and I've to click a button several time for switch on or off the led ... do you think that is only a master issues or I can Improve also the Slave ?  REgards Andrea

PaulS

Quote
but is not perfect some times still to lose the pressed

We need to see your current code.

Quote
or I can Improve also the Slave ?

Code: [Select]
void loop()
{
 
  delay(3000); //Wait 2 Second before re-excute
}

3000 milliseconds is not 2 seconds, and the delay is completely unnecessary.
The art of getting good answers lies in asking good questions.

gnusso

hi i've putted 50ms like llike delay and now it's perfect
thx

Andrea

PaulS

Quote
hi i've putted 50ms like llike delay and now it's perfect

Put the 50ms delay where?

Adding delay() is likely NOT the best solution.
The art of getting good answers lies in asking good questions.

bibre

Thank you PaulS,

Sorry to bounce-up (pun intended) this thread but this Button library you mentioned was very useful for me. I already had some working code using Bounce with .fallingEdge but liked yor suggestion better, with 16 PULLDOWN Buttons monitoring pins 2-13 & A0-A3. Much more elegant and saves some memory space.   8)

Quote
If you want to send data only once for each button press, the Bounce library is not the right library to be using. The Button library would be a better choice. It has a method, uniquePress() that returns true only one time per button press.


I built a 16 sensor input module for the tracks in my model railroad using an Arduino UNO with a ScrewShield from Adafruit.

Code: [Select]
Button sensor[16] =
  {
    Button(2, PULLDOWN), Button(3, PULLDOWN), Button(4, PULLDOWN), Button(5, PULLDOWN),
    Button(6, PULLDOWN), Button(7, PULLDOWN), Button(8, PULLDOWN), Button(9, PULLDOWN),
    Button(10, PULLDOWN), Button(11, PULLDOWN), Button(12, PULLDOWN), Button(13, PULLDOWN),
    Button(14, PULLDOWN), Button(15, PULLDOWN), Button(16, PULLDOWN), Button(17, PULLDOWN)
  };

...

      //detect sensor triggering only once
      value = sensor[pin-2].uniquePress();      // arrays start at 0 index so, use pin - 2

      abkonInputStates = abkonInputStates | ( value << (pin - 2) );  // set corresponding input pin bit



I have an "¡Hola amigos!" thread on the General Discussion forum, introducing me, in case you want to take alook at it:
http://arduino.cc/forum/index.php/topic,75690.0.html

Thank you for telling us about the Button library.   :)

Go Up