0

I have code which control thermometer, OLED and nanoservo via MQTT. I want to refresh temperature every 10s. It works but my servo receive command only when temperature is refreshed. How can I configure my loop so my servo can receive MQTT command anytime I send it?

Here in my code (I combined several example codes...):

 #include <ESP8266WiFi.h>
 #include <Servo.h>
 #include <PubSubClient.h>
 #include <OneWire.h>
 #include <DallasTemperature.h>
 #include <Wire.h>
 #include "SH1106.h"
 #include "thermometer.h"
 // Data wire is plugged into pin 2 on the Arduino
 #define ONE_WIRE_BUS 14 // je D5 was 2 (D4)
 // 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);
 SH1106 display(0x3c, D1, D2);
 #define DEMO_DURATION 3000
 typedef void (*Demo)(void);
 int demoMode = 0;
 int counter = 1;
 // Update these with values suitable for your network.
 const char* ssid = "******";
 const char* password = "******";
 const char* mqtt_server = "192.168.100.220"; /// MQTT Broker
 const char* topic_state = "/blinds/state";
 const char* topic_command = "/blinds/command";
 IPAddress my_ip (192, 168, 100, 224);
 IPAddress my_gateway (192,168, 100, 1);
 IPAddress my_subnet (255, 255, 255, 0);
 WiFiClient espClient;
 PubSubClient client(espClient);
 long lastMsg = 0;
 char msg[50];
 int value = 0;
 Servo myservo;
 int state = 0;
 int prevstate = 0;
 int dirc = 0;
 int spintime = 0;
 int servoPin = D4; //CHANGE TO WHATEVETR PIN YOUR USING
 void reconnect();
 void callback(char* topic, byte* payload, unsigned int length);
 void setup() { 
 Serial.begin(115200);
 setup_wifi();
 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);
 // Start up the library
 sensors.begin();
 // Initialising the UI will init the display too.
 display.init();
 display.flipScreenVertically();
 display.setFont(ArialMT_Plain_10);
 }
 void servo_move() {
 Serial.println("State Change. Rotating Servo");
 if ( dirc == 180) {
 client.publish(topic_state,"open");
 }
 else if (dirc == 0) {
 client.publish(topic_state,"close"); 
 }
 myservo.attach(servoPin);
 myservo.write(dirc);
 delay(spintime);
 myservo.detach();
 Serial.println("Returning to main loop");
 return;
 }
 void setup_wifi() {
 delay(10);
 // We start by connecting to a WiFi network
 Serial.println();
 Serial.print("Connecting to ");
 Serial.println(ssid);
 WiFi.setPhyMode(WIFI_PHY_MODE_11N);
 WiFi.config(my_ip, my_gateway, my_subnet);
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
 }
 Serial.println("");
 Serial.println("WiFi connected");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 }
 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();
 char *blindcommand = (char *) payload; // convert mqtt byte array into char array
 blindcommand[length] ='0円'; // Must delimit with 0
 Serial.print(blindcommand);
 if (strcmp(blindcommand,"open") == 0) {
 Serial.println(" 433MHZ OPEN COMMAND RECEIVED");
 dirc = 180; // direction for servo to run
 spintime = 50; // << CHANGE TO WHATEVER TIME YOU NEED TO OPEN YOUR BLINDS
 state = 1; //sets current state
 }
 else if (strcmp(blindcommand,"close") == 0) {
 Serial.println(" 433MHZ CLOSE COMMAND RECEIVED");
 dirc = 0;
 spintime = 150; // << CHANGE TO WHATEVER TIME YOU NEED TO CLOSE YOUR BLINDS
 state = 2; //sets current state
 }
 if (state != prevstate) {
 Serial.println("State change!");
 servo_move();
 }
 prevstate = state;
 }
 char temperatureVonku[15];
 String tempUnit = " °C";
 void temperature(){
 float temperatureFloat;
 sensors.requestTemperatures();
 temperatureFloat = sensors.getTempCByIndex(0);
 dtostrf(temperatureFloat, 7, 1, temperatureVonku);
 client.publish("temp/outside", temperatureVonku); /// send char
 delay(10000);
 }
 void dispTempVonku() {
 display.drawRect(1, 1, DISPLAY_WIDTH -1, DISPLAY_HEIGHT -1);
 // Font Demo1
 // create more fonts at http://oleddisplay.squix.ch/
 display.setTextAlignment(TEXT_ALIGN_LEFT);
 display.setFont(Roboto_Bold_12);
 display.drawString(5, 5, "Temp: ");
 display.drawXbm(7, 24, Img_width, Img_height, thermometer);
 display.setTextAlignment(TEXT_ALIGN_CENTER);
 display.setFont(Roboto_Bold_28);
 display.drawString(64, 22, temperatureVonku + tempUnit);
 }
 void dispTempVnutri() { 
 display.drawRect(1, 1, DISPLAY_WIDTH -1, DISPLAY_HEIGHT -1);
 display.setTextAlignment(TEXT_ALIGN_CENTER);
 display.setFont(ArialMT_Plain_16);
 display.drawString(64, 22, "Hello World");
 }
 Demo demos[] = {dispTempVonku, dispTempVnutri};
 int demoLength = (sizeof(demos) / sizeof(Demo));
 long timeSinceLastModeSwitch = 0;
 void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266Client", "******", "******")) {
 Serial.println("connected");
 client.subscribe(topic_command);
 } else {
 Serial.print("failed, rc=");
 Serial.print(client.state());
 Serial.println(" try again in 5 seconds");
 // Wait 5 seconds before retrying
 delay(5000);
 }
 }
 }
 void loop() {
 temperature(); 
 if (!client.connected()) {
 reconnect();
 }
 client.loop();
 // clear the display
 display.clear();
 // draw the current demo method
 demos[demoMode]();
 display.setTextAlignment(TEXT_ALIGN_RIGHT);
 display.drawString(10, 128, String(millis()));
 // write the buffer to the display
 display.display();
 if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
 demoMode = (demoMode + 1) % demoLength;
 timeSinceLastModeSwitch = millis();
 }
 counter++;
 //delay(10000);
 }

Thank you.

asked Jul 18, 2017 at 10:42
2
  • please follow the below links, might be useful: stackoverflow.com/questions/5452394/… stackoverflow.com/questions/14397973/… Commented Jul 19, 2017 at 12:32
  • MQTT does not guarantee delivery times. Delays between publishing and receiving can reach 2-3 seconds in a local configuration. If you are using an Internet broker, it's worse. Commented Aug 17, 2017 at 15:31

1 Answer 1

1

I assume your servo only receives data when you keep the delay(10000).

The problem is that with a delay, the Arduino does kind of nothing during that time, so it cannot control your servo.

What you want is to call every 10 s the temperature update, but keep the servo control always running.

So keep a last-time-called variable (type unsigned long) that keeps the time of the last call to update the temperature. When 10 s have passed (you can check somewhere in the loop), you call it, and update the last time to the current time.

answered Jul 18, 2017 at 13:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.