4-pin Switch not working with MQTT publish in Arduino

I have done a setup where if I press 4-pin switch,the LED connected to digital pin 7 with Arduino,will glow.
This is working fine when I connect it without MQTT publish.
Its working fine for the below code,
void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
Serial.println(buttonState);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, LOW);
}
else {
// turn LED off:
digitalWrite(ledPin, HIGH);
}
But When I use MQTT publish,its sending more than 300 publish messages to MQTT clients!!!! .I want it as,when I press the switch,the led has to glow and an MQTT message has to be published.But here it is like,eventhough I press once or twice,or evenif I dont press also,the message starts getting published the moment I upload the sketch into Arduino!
Code which is not working,
#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#include <util.h>
#include <ctype.h>

#define CLIENTID "ArduinoSensor"
#define TOPICNAME "switch/signal"
#define POLLINTERVAL 120000

#define PORT 80
//Connect to MQTT server
byte server1 [] = {X,X,X,X};
byte mac[] = {X,X,X,X};

IPAddress arduinoIP(X,X,X,X);
IPAddress dnsIP(X,X,X,X);
IPAddress gatewayIP(X,X,X,X);
IPAddress subnetIP(X,X,X,X);
EthernetServer server(PORT);

EthernetClient ethClient;
PubSubClient arduinoClient(server1, 8081, callback, ethClient);

const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 7; // the number of the LED pin

// variables will change:
int buttonState=0;

void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}

void setup() {
Serial.begin(9600);
Ethernet.begin(mac, arduinoIP, dnsIP, gatewayIP, subnetIP);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
digitalWrite(ledPin, LOW);

//Connect to the MQTT server
beginConnection() ;
}

//Initialise MQTT connection
void beginConnection() {
Serial.begin(9600);
//Ethernet.begin(mac) ;
int connRC = arduinoClient.connect(CLIENTID) ;
if (!connRC) {
Serial.println(connRC) ;
Serial.println("Could not connect to MQTT Server");
Serial.println("Please reset the arduino to try again");
delay(100);
exit(-1);
}
else {
Serial.println("Connected to MQTT Server...");

}}
void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
Serial.println(buttonState);
if (buttonState == HIGH) {
digitalWrite(ledPin, LOW);
}
else {
digitalWrite(ledPin, HIGH);
arduinoClient.publish(TOPICNAME, "Button A is pressed") ;
}
}

In Serial Monitor,I can see the output as below,

1
1
1
0
0
0
0
1
1
1
0
0
0
0
0
0

When switch is not pressed,the output is with 1s and 0s.But when there is switch pressed,0s are coming continuously until switch is pressed...

Not sure how to make this work...I need this little urgently..Please help me on this...

generk4:
I have done a setup where if I press 4-pin switch,the LED connected to digital pin 7 with Arduino,will glow.
This is working fine when I connect it without MQTT publish.
Its working fine for the below code,

void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
Serial.println(buttonState);
if (buttonState == HIGH) {
digitalWrite(ledPin, LOW);
}
else {
digitalWrite(ledPin, HIGH);
arduinoClient.publish(TOPICNAME, "Button A is pressed") ;
}
}

Do you only want to send the "Button A is pressed" once for each press? Or do you want to send the message until the button is released?

If you only want to send it once per keypress try this:

boolean buttonState=false; // global variable, I like boolean because State is either True or False, 2 has no meaning.

unsigned long timeout=0;  // used to limit how many 'nothing happening' messages are send

void print_buttonState(boolean buttonState){
if(buttonState) Serial.print("Released")
else Serial.print("Pressed");
}

void setup(){
// after pinMode
buttonState= digitalRead(buttonpin); // record current state of button
// other stuff
}

void loop(){
  // read the state of the pushbutton value:
if (buttonState != digitalRead(buttonPin)){ // button state has changed, post it, Yea!
   buttonState = !buttonState;  // set it to other State.
   Serial.print("New Button State=");
   print_buttonState(buttonState);
   Serial.println();
   timeout = millis() + 1000; // set time out to report 'old' state
   if (buttonState == HIGH) {  
      digitalWrite(ledPin, LOW);
      arduinoClient.publish(TOPICNAME, "Button A is Released") ;
      
      }
  else {
      digitalWrite(ledPin, HIGH);
      arduinoClient.publish(TOPICNAME, "Button A is Pressed") ;
      }
  }
}
else {
// Button is still in prior State, nothing has changed
 
It is really a bad Idea to send a message every time the Arduino 'loops'.  It would quickly fill the Serial Tx buffer and hang in the print statement waiting for the Serial port to send enough characters for the new message to fit in the 64byte transmit buffer.
  
so this code only sends a 'nothing happened message once a second'

   unsigned long timenow = millis();
   if (timenow>=timeout){ // one second has elapsed, or the first time thru 'loop' 
      
      Serial.print("Old Button State=");
      print_buttonState(buttonState);
      Serial.println();
      timeout = timenow + 1000; // only send old button state very second
      }
   else if((timeout-timenow)>1000){ // timer has rapped 52days running! wow!
     timeout = 0xffffffff - timeout; // rap timeout 
     }


   }
}

Do you understand what I did? this code does not care what state the button is, just that it has changed.

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.

Thats very nice of you..Thanks much for responding..I will immediately check now and update..

The program has not worked for me.
Below is the full sketch that I tried

#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#include <util.h>
#include <ctype.h>


#define CLIENTID "ArduinoSensor"
#define TOPICNAME "switch/signal"
#define POLLINTERVAL 120000

#define PORT 80
//Connect to MQTT server
byte server1 [] = {192, 168, 1, 4};
byte mac[] = {0x5e, 0xa4, 0x18, 0xf0, 0x8a, 0xf6};

IPAddress arduinoIP(192, 168, 1, 67);
IPAddress dnsIP(203, 145, 184, 32); 
IPAddress gatewayIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);
EthernetServer server(PORT);

EthernetClient ethClient;
PubSubClient arduinoClient(server1, 8081, callback, ethClient);

boolean buttonState=false; // global variable, I like boolean because State is either True or False, 2 has no meaning.

unsigned long timeout=0;  // used to limit how many 'nothing happening' messages are send

int ledPin=7,buttonPin=2;

void print_buttonState(boolean buttonState){
if(buttonState) Serial.print("Released");
else Serial.print("Pressed");
}


void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}

void setup(){
// after pinMode
Serial.begin(9600);
Ethernet.begin(mac, arduinoIP, dnsIP, gatewayIP, subnetIP);
pinMode(ledPin, OUTPUT); 
pinMode(buttonPin, INPUT);  

buttonState= digitalRead(buttonPin); // record current state of button
// other stuff
//Connect to the MQTT server 
beginConnection() ;
}
void beginConnection() {
Serial.begin(9600);
//Ethernet.begin(mac) ;
int connRC = arduinoClient.connect(CLIENTID) ;
if (!connRC) {
Serial.println(connRC) ;
Serial.println("Could not connect to MQTT Server");
Serial.println("Please reset the arduino to try again");
delay(100);
exit(-1);
}
else {
Serial.println("Connected to MQTT Server...");


}}
void loop(){
// read the state of the pushbutton value:
if (buttonState != digitalRead(buttonPin)){ // button state has changed, post it, Yea!
 buttonState = !buttonState;  // set it to other State.
 Serial.print("New Button State=");
 print_buttonState(buttonState);
 Serial.println();
 timeout = millis() + 1000; // set time out to report 'old' state
 if (buttonState == HIGH) {  
    digitalWrite(ledPin, LOW);
    arduinoClient.publish(TOPICNAME, "Button A is Released") ;
    
    }
else {
    digitalWrite(ledPin, HIGH);
    arduinoClient.publish(TOPICNAME, "Button A is Pressed") ;
    }
}
else {
// Button is still in prior State, nothing has changed

//It is really a bad Idea to send a message every time the Arduino 'loops'.  It would quickly fill the Serial Tx buffer and hang in the print statement waiting for the Serial port to send enough characters for the new message to fit in the 64byte transmit buffer.

//so this code only sends a 'nothing happened message once a second'

 unsigned long timenow = millis();
 if (timenow>=timeout){ // one second has elapsed, or the first time thru 'loop' 
    
    Serial.print("Old Button State=");
    print_buttonState(buttonState);
    Serial.println();
    timeout = timenow + 1000; // only send old button state very second
    }
 else if((timeout-timenow)>1000){ // timer has rapped 52days running! wow!
   timeout = 0xffffffff - timeout; // rap timeout 
   }


 }
}

The output in Serial monitor is,
Connected to MQTT Server
New Button State=Released
New Button State=Pressed
New Button State=Released
New Button State=Pressed
New Button State=Released
New Button State=Pressed
.
.
.

This is getting continuously repeated even when switch is not pressed.
Also,MQTT message is getting published continously at 36 msgs/sec.
Not sure where is the problem...
Could you please check this and help me..?

I have just tried by reading analog input for the switch.

#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#include <util.h>
#include <ctype.h>


#define CLIENTID "ArduinoSensor"
#define TOPICNAME "switch/signal"
#define POLLINTERVAL 120000

#define PORT 80
//Connect to MQTT server
byte server1 [] = {192, 168, 1, 4};
byte mac[] = {X};

IPAddress arduinoIP(X);
IPAddress dnsIP(X); 
IPAddress gatewayIP(X);
IPAddress subnetIP(X);
EthernetServer server(PORT);

EthernetClient ethClient;
PubSubClient arduinoClient(server1, 8081, callback, ethClient);


void callback(char* topic, byte* payload, unsigned int length) {
 // handle message arrived
}


int analogPin = 0;     // potentiometer wiper (middle terminal) connected to analog pin 3

                      // outside leads to ground and +5V

int val = 0;           // variable to store the value read



void setup()

{

 Serial.begin(9600);          //  setup serial

Ethernet.begin(mac, arduinoIP, dnsIP, gatewayIP, subnetIP);
beginConnection() ;
}

void beginConnection() {
Serial.begin(9600);
//Ethernet.begin(mac) ;
int connRC = arduinoClient.connect(CLIENTID) ;
if (!connRC) {
Serial.println(connRC) ;
Serial.println("Could not connect to MQTT Server");
Serial.println("Please reset the arduino to try again");
delay(100);
exit(-1);
}
else {
Serial.println("Connected to MQTT Server...");


}}

void loop()

{

[b]val = analogRead(analogPin);    // read the input pin

  Serial.println(val); 
delay(100);  // debug value
if(val == 1023)
{
Serial.println("Button pressed and message published");
arduinoClient.publish(TOPICNAME, "Button A is Pressed") ;[/b]
}
}

Its working better...But I see a problem with the analogRead...
The readings goes as below,
0
0
0
0
19
20
49
71
117
126
227
322
451
571
702
809
923
1023
Button pressed and message published
1023
Button pressed and message published
1023
Button pressed and message published
1022
1003
966
929
905
842
748
615
480
356
229
122
1
0
0
0
0
0
0

The readings gradually increasing till 1023 and then decreasing gradually.This should not happen as it is publishing messages when it is reaching 1023 without even pressing the switch.
But When the switch is pressed,it reaches 1023 and publishing the message.This is fine as this is required scenario..

Can you please help how to control the flow of analogRead?If this is kept under control,then my problem would be resolved...

If none of this is going to work,then please give me a solution where I need to initiate for Publishing messages through Arduino.It is not necessarily be via only switch..it can be through other mechanism also..

Hi generk4

In the program you posted in reply #3, try these changes ...

Declare buttonState like this:

int buttonState=LOW;

Change this part of your code in loop():

if (buttonState != digitalRead(buttonPin)) {
  buttonState = digitalRead(buttonPin);

Does this change how the program behaves?

EDIT

By the way, please use code tags when posting code. It makes it much easier for people to help you. The code tag button looks like this </>. You can go back and edit your earlier posts.

Regards

Ray

Hi,
Thanks for the response...I will try the code change.
And,I have edited my post with code formatting as you have mentioned.

Thanks,
Radha

Its working fine now with the below code for two switches itself...
I used Digital pin 0 and 2 for the Input

#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#include <util.h>
#include <ctype.h>


#define CLIENTID "ArduinoSensor"
#define TOPICNAME "switch/signal"
#define POLLINTERVAL 120000

#define PORT 80
//Connect to MQTT server
byte server1 [] = {192, 168, 1, 4};
byte mac[] = {0x5e, 0xa4, 0x18, 0xf0, 0x8a, 0xf6};

IPAddress arduinoIP(192, 168, 1, 67);
IPAddress dnsIP(203, 145, 184, 32); 
IPAddress gatewayIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);
EthernetServer server(PORT);

EthernetClient ethClient;
PubSubClient arduinoClient(server1, 8081, callback, ethClient);
void callback(char* topic, byte* payload, unsigned int length) {
 // handle message arrived
}
int inPin1 = 2; 
int inPin2 = 0;// the number of the input pin
int outPin = 7; // the number of the output pi

int state = HIGH; // the current state of the output pin
int reading; // the current reading from the input pin
int previous = LOW; // the previous reading from the input pin

// the follow variables are long's because the time, measured in milliseconds
// will quickly become a bigger number than can be stored in an int.
long time = 0;                   // the last time the output pin was toggled
long debounce = 200;      // the debounce time, increase if the output flickers

int state2 = HIGH; // the current state of the output pin
int reading2; // the current reading from the input pin
int previous2 = LOW; // the previous reading from the input pin

// the follow variables are long's because the time, measured in milliseconds
// will quickly become a bigger number than can be stored in an int.
long time2 = 0;                   // the last time the output pin was toggled
long debounce2 = 200;      // the debounce time, increase if the output flickers
void setup()
{
 Serial.begin(9600);
 Ethernet.begin(mac, arduinoIP, dnsIP, gatewayIP, subnetIP);
   pinMode(inPin1, INPUT);
 pinMode(inPin2, INPUT);
 pinMode(outPin, OUTPUT);
 beginConnection() ;
}

void beginConnection() {
Serial.begin(9600);
//Ethernet.begin(mac) ;
int connRC = arduinoClient.connect(CLIENTID) ;
if (!connRC) {
Serial.println(connRC) ;
Serial.println("Could not connect to MQTT Server");
Serial.println("Please reset the arduino to try again");
delay(100);
exit(-1);
}
else {
Serial.println("Connected to MQTT Server...");


}}

void loop()
{

   reading = digitalRead(inPin1);

 // if the input just went from LOW and HIGH and we've waited long enough
 // to ignore any noise on the circuit, toggle the output pin and remember
 // the time
 if (reading == HIGH && previous == LOW && millis() - time > debounce) {
   if (state == HIGH){
     state = LOW;
       arduinoClient.publish(TOPICNAME, "Button A is Pressed") ;
     Serial.println("Button A is Pressed and message published");}
   else
   {
     state = HIGH;
        arduinoClient.publish(TOPICNAME, "Button A is Pressed") ;
     Serial.println("Button A is Pressed and message published");
   }
   time = millis(); 
 }
 digitalWrite(outPin, state);
 
 previous = reading;
 
  reading2 = digitalRead(inPin2);

 // if the input just went from LOW and HIGH and we've waited long enough
 // to ignore any noise on the circuit, toggle the output pin and remember
 // the time
 if (reading2 == HIGH && previous2 == LOW && millis() - time2 > debounce2) {
   if (state2 == HIGH){
     state2 = LOW;
       arduinoClient.publish(TOPICNAME, "Button B is Pressed") ;
     Serial.println("Button B is Pressed and message published");}
   else
   {
     state2 = HIGH;
     arduinoClient.publish(TOPICNAME, "Button B is Pressed") ;
     Serial.println("Button B is Pressed and message published");
   }
   time2 = millis(); 
 }
 digitalWrite(outPin, state2);
 
 previous2 = reading2;
   
}