Hey, Im trying to make a thermostat using Arduino Mega2560, rotary encoder KY40 and temperature sensor ds18b20 and ethernet module ENC28J60. Everything work just fine until I try to publish temperature in a loop. Here is my code:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <UIPEthernet.h>
#include <PubSubClient.h>
#include "config.h"
void setup() {
pinMode(pinA, INPUT_PULLUP); // enabling pullups
pinMode(pinB, INPUT_PULLUP);
pinMode(pinSW, INPUT_PULLUP);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
Serial.begin(9600);
sensors.begin();
sensors.setResolution(thermometer, 9);
mqttClient.setServer("test.mosquitto.org", 1883);
mqttClient.setCallback(callback);
connectToEthernet();
delay(1500);
}
// main loop, work is done by interrupt service routines, this one only prints stuff
void loop() {
if (!mqttClient.connected()) {
reconnect();
}
rotating = true; // reset the debouncer
//to protect from going over min & max values
if (encoderPos <= MIN_POS - 1 ) {
encoderPos = MIN_POS;
lastReportedPos = MIN_POS + 1;
} else if (encoderPos >= MAX_POS + 1) {
encoderPos = MAX_POS;
lastReportedPos = MAX_POS - 1;
} else {
if (lastReportedPos != encoderPos) { // Serial print
setTemp = encoderPos * 0.5;
Serial.print("Set temperature: ");
Serial.println(setTemp);
lastReportedPos = encoderPos;
}
}
if (digitalRead(pinSW) == LOW ) { // push to restart to 0
encoderPos = 0;
lastReportedPos = 1;
delay (10);
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
//request temperature from sensors
sensors.requestTemperatures();
//print temperature out with my function
printTemperature(thermometer);
}
mqttClient.loop();
}
// Interrupt on A changing state
void doEncoderA() {
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if ( digitalRead(pinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set ) encoderPos += 1;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state, same as A above
void doEncoderB() {
if ( rotating ) delay (1);
if ( digitalRead(pinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if ( B_set && !A_set ) encoderPos -= 1;
rotating = false;
}
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress) {
float temperature = sensors.getTempC(deviceAddress);
Serial.print("Got temperature: ");
//Serial.println(temperature);
char tempBuff[10];
dtostrf(temperature, 3, 2, tempBuff);
Serial.println(tempBuff);
mqttClient.publish("temperature", tempBuff);
Serial.println("published");
}
void connectToEthernet() {
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
for (;;)
;
}
// print your local IP address:
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void reconnect() {
// Loop until we're reconnected
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (mqttClient.connect("arduinoClient")) {
Serial.println("connected");
// Once connected, publish an announcement...
mqttClient.publish("outTopic", "hello world");
// ... and resubscribe
mqttClient.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
and a config.h:
/*KY-40 INIT*/
#define MAX_POS 60
#define MIN_POS 30
enum PinAssignments {
pinA = 2, // DT pin
pinB = 3, // CLK pin
pinSW = 4 // SW pin
};
volatile int encoderPos = MIN_POS; // a counter for the dial
int lastReportedPos = MIN_POS-1; // change management
static boolean rotating = false; // debounce management
// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;
/*TEMP setup*/
float setTemp = MIN_POS*0.5;
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 5
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device address
DeviceAddress thermometer = { 0x28, 0xFF, 0xE3, 0xD4, 0x67, 0x14, 0x03, 0x39 };
/*DELAYS*/
unsigned long previousMillis = 0;
const long interval = 3000;
/*Ethernet*/
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
EthernetClient ethClient;
/* MQTT */
PubSubClient mqttClient(ethClient);
char* tempC;
unsigned long time;
char message_buffer[100];[/quote]
The serial monitor shows this:
[quote]My IP address: 192.168.0.29.
Attempting MQTT connection...connected
Set temperature: 15.00
Got temperature: 25.00
published
and it stops... If I rotate encoder, nothing happens,it just publishes first value and then the loop stops. If I disable the line
mqttClient.publish("temperature", tempBuff);
it works againg, but of course it doesnt publish anything...
Any suggestions? Thanks in advance
P.S.: Dont mind some of the comments, I havent cleaned the sketch yet.