-->
Page 1 of 1

Help with looping mqtt data from a sensor

PostPosted: Fri Mar 17, 2017 11:22 pm
by jhaury
Hello, I have cobbled together a semi working sketch of an ESP-01 and two MPU6050 sensors. The code was frankensteined from a few sketches on the web. Right now the module boots up, connects to wifi and waits for a "1" on a MQTT topic it subscribes to. Once a "1" is received it then sends the sensor data to a MQTT topic. This works. The problem is that it only sends the sensor data when a "1" is detected once. It will send the data each time a "1" is sent, but I want it to send the sensor data until a "0" is detected on the subscribed topic. I cant figure out how to loop it until that happens. I am not very experienced with coding ESPs or Arduinos, but I can cobble something together most of the time. Can you guys help me out? Where am I going wrong? Code below.

Code: Select all#include <Wire.h>
//#include <SPI.h>
#include <PubSubClient.h>
//#include <string.h>
//#include <stdio.h>
#include <ESP8266WiFi.h>

// Settings
const char* ssid = "Tomato Express";      // SSID
const char* password = "notyournetwork";  // Wifi PWD
const char* server = "10.0.0.10";         // IP address of your MQTT server
//const char* outTopic = "test/";         // Topic to publish to
const char* inTopic = "inTopic";          // Topic to subscribe to

// Wifi MAC address
byte mac[]= {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };

// I2C address of the MPU-6050 & 0x68 or 0x69 if AD0 is pulled HIGH
const int MPU = 0x68;                                     // MPU6050 #1
const int MPU2 = 0x69;                                    // MPU6050 #2
int16_t AcX, AcY, AcZ, GyX, GyY, GyZ;                     // MPU6050 #1
int16_t AcX2, AcY2, AcZ2, GyX2, GyY2, GyZ2;               // MPU6050 #2
float gForceX, gForceY, gForceZ, rotX, rotY, rotZ;        // MPU6050 #1
float gForceX2, gForceY2, gForceZ2, rotX2, rotY2, rotZ2;  // MPU6050 #2

WiFiClient espClient;
IPAddress ip;
PubSubClient mqttClient(espClient);


void setup(){
  Serial.begin(9600);

  // MPU6050 #1
  Wire.begin(0,2);              // GPIO0, GPIO2
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);             // PWR_MGMT_1 register
  Wire.write(0);                // Sset to zero (wakes up the MPU6050)
  Wire.endTransmission(true);

  // MPU6050 #2
//  Wire.begin(0,2);
  Wire.beginTransmission(MPU2);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // Set to zero (wakes up the MPU6050)
  Wire.endTransmission(true);
 
  mqttClient.setServer(server, 1883); // Set MQTT server
  mqttClient.setCallback(callback);   // Set subscribe
 
  Serial.println(ip);                 // Print the IP?
  Serial.println(server);             // Print the server?
  //delay(10);
}


void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  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) {
  // Subscribe functions, print the incoming message
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
    // digitalWrite(led, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // do stuff
 
    dataAcc();
    dataGy();
 
  } else {
    // digitalWrite(led, HIGH);  // Turn the LED off by making the voltage HIGH
    // do more stuff
   
    Serial.print("Not initiated");
  }
}


void dataReceiver(){
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);                  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,14,true);     // request a total of 14 registers
  AcX = Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY = Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  GyX = Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY = Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ = Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
//  processData();

  Wire.beginTransmission(MPU2);
  Wire.write(0x3B);                   // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU2,14,true);     // request a total of 14 registers
  AcX2 = Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY2 = Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ2 = Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  GyX2 = Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY2 = Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ2 = Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  processData();
}


void processData(){
  gForceX = AcX / 16384.0;
  gForceY = AcY / 16384.0;
  gForceZ = AcZ / 16384.0;
 
  rotX = GyX / 131.0;
  rotY = GyY / 131.0;
  rotZ = GyZ / 131.0;

  gForceX2 = AcX2 / 16384.0;
  gForceY2 = AcY2 / 16384.0;
  gForceZ2 = AcZ2 / 16384.0;
 
  rotX2 = GyX2 / 131.0;
  rotY2 = GyY2 / 131.0;
  rotZ2 = GyZ2 / 131.0;
}


void debugFunction(int16_t AcX, int16_t AcY, int16_t AcZ, int16_t GyX, int16_t GyY, int16_t GyZ){
  // Print the MPU values to the serial monitor
  Serial.print("Accelerometer: ");
  Serial.print("X="); Serial.print(gForceX);
  Serial.print("|Y="); Serial.print(gForceY);
  Serial.print("|Z="); Serial.println(gForceZ); 
  Serial.print("Gyroscope:");
  Serial.print("X="); Serial.print(rotX);
  Serial.print("|Y="); Serial.print(rotY);
  Serial.print("|Z="); Serial.println(rotZ);
}


void debugFunction2(int16_t AcX2, int16_t AcY2, int16_t AcZ2, int16_t GyX2, int16_t GyY2, int16_t GyZ2){
  // Print the MPU2 values to the serial monitor
  Serial.print("Accelerometer2: ");
  Serial.print("X2="); Serial.print(gForceX2);
  Serial.print("|Y2="); Serial.print(gForceY2);
  Serial.print("|Z2="); Serial.println(gForceZ2); 
  Serial.print("Gyroscope2:");
  Serial.print("X2="); Serial.print(rotX2);
  Serial.print("|Y2="); Serial.print(rotY2);
  Serial.print("|Z2="); Serial.println(rotZ2);
}


char* init(float val){
  char buff[100];

  for (int i = 0; i < 100; i++) {
      dtostrf(val, 4, 2, buff);  //4 is mininum width, 6 is precision
  }
   return buff;
}


void dataAcc(){
  char mpu6050X[100]= "";   
  strcat(mpu6050X,init(gForceX));

  char mpu6050Y[100]= "";   
  strcat(mpu6050Y,init(gForceY));

  char mpu6050Z[100]= "";   
  strcat(mpu6050Z,init(gForceZ));

  // accelerometer - "topic, mpu6050"
  mqttClient.publish("AcX/", mpu6050X);
  mqttClient.publish("AcY/", mpu6050Y);
  mqttClient.publish("AcZ/", mpu6050Z);

  char mpu6050X2[100]= "";   
  strcat(mpu6050X2,init(gForceX2));

  char mpu6050Y2[100]= "";   
  strcat(mpu6050Y2,init(gForceY2));

  char mpu6050Z2[100]= "";   
  strcat(mpu6050Z2,init(gForceZ2));

  // accelerometer - "topic, mpu6050"
  mqttClient.publish("AcX2/", mpu6050X2);
  mqttClient.publish("AcY2/", mpu6050Y2);
  mqttClient.publish("AcZ2/", mpu6050Z2);
//  mqttClient.publish(outTopic, "text to send via mqtt");
}


void dataGy(){
  char mpu6050X[100]= "";
  strcat(mpu6050X,init(rotX));

  char mpu6050Y[100]= "";
  strcat(mpu6050Y,init(rotY));

  char mpu6050Z[100]= "";
  strcat(mpu6050Z,init(rotZ));
 
  // gyroscope - "topic, mpu6050"
  mqttClient.publish("GyX/", mpu6050X);
  mqttClient.publish("GyY/", mpu6050Y);
  mqttClient.publish("GyZ/", mpu6050Z);

  char mpu6050X2[100]= "";
  strcat(mpu6050X2,init(rotX2));

  char mpu6050Y2[100]= "";
  strcat(mpu6050Y2,init(rotY2));

  char mpu6050Z2[100]= "";
  strcat(mpu6050Z2,init(rotZ2));
 
  // gyroscope - "topic, mpu6050"
  mqttClient.publish("GyX2/", mpu6050X2);
  mqttClient.publish("GyY2/", mpu6050Y2);
  mqttClient.publish("GyZ2/", mpu6050Z2);
//  mqttClient.publish(outTopic, "text to send via mqtt");
}


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");
      // subscribe to topic
      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(1000);
    }
  }
}


void loop(){
  dataReceiver();
  debugFunction(AcX,AcY,AcZ,GyX,GyY,GyZ);
  debugFunction2(AcX2,AcY2,AcZ2,GyX2,GyY2,GyZ2);

  if (!mqttClient.connected()) {
    reconnect();
  }

  mqttClient.loop();

//  dataAcc();
//  dataGy();


  delay(3000);
}

Re: Help with looping mqtt data from a sensor

PostPosted: Sat Mar 18, 2017 4:51 pm
by picstart
I don't see where you subscribed to your topic
//espclient.subscribe(topic); //// your specific topic
espclient.subscribe("#"); ////// we will receive all messages

Re: Help with looping mqtt data from a sensor

PostPosted: Sat Mar 18, 2017 5:36 pm
by jhaury
I thought thats what mqttClient.subscribe(inTopic) did in "void reconnect"? If I try to stick espclient.subscribe(inTopic) anywhere it wont compile and says espclient was not declared in this scope. The esp appears to be listening on inTopic, and only inTopic. That seems to work. There may be pieces of code left in there that don't do anything. I have already edited/commented out what I thought was safe. But it still matches the code I copied for turning an LED off and on via gpio2 on an esp. Thats where I am confused, and I admit I don't know much and I am still learning. In the sketch I copied the LED stays on until a 0 is received, why is my sketch not looping too? Or am I misunderstanding something?

Re: Help with looping mqtt data from a sensor

PostPosted: Sun Mar 19, 2017 4:23 pm
by picstart
I didn't look deeply at your code but here is a conceptual template if it helps
///const char* user_name = "";
///const char* password = "";
///const char* clientID = ""; // client ID
String topic="IoT";
////WiFiClient wclient; /// instantiate the wifi
////PubSubClient client(wclient, serverURI, port); /// instantiate the MQTT pubsub

void callback(const MQTT::Publish& pub)
{ // handle incoming message
///// Pub.payload_string() // has received data from broker
//// client.publish(topic, String( message goes here)); //// send response to message from broker if you want to
}
void setup()
{
///// client.set_callback(callback); ///sets up callback
//// WiFi.begin(ssid, pass); //// sets up wifi connection
////client.connect(MQTT::Connect(String("who we are to the broker")).set_auth(user_name, password)
If (client.connected())
{
/////client.publish(topic, String(message string)); //// send message to broker if needed at set up
}
void loop()
{
////// client.loop(); ///// keep in contact with the broker
}