Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Development
  3. Barometric Pressure Sensor Using MS5637

Barometric Pressure Sensor Using MS5637

Scheduled Pinned Locked Moved Development
23 Posts 4 Posters 9.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Myles L
    wrote on last edited by
    #1

    Hello

    Very new to Arduino and MySensors so please excuse any novice mistakes. I am trying to get the Pressure Sensor sketch to work with a different pressure sensor http://www.freetronics.com.au/collections/modules/products/barometric-pressure-sensor-module#.VLSnlNH9mUk

    I have modified the code (included below) but when I try to add it to Vera (VeraLite, UI7, Ethernet Gateway, and yes it does work with other sensors surprisingly!) no new device is included and when I open a serial monitor no response is available. I have confirmed the pressure sensor itself is working using a different sketch. Any suggestions would be appreciated.

    #include <SPI.h>
    #include <MySensor.h>
    #include <Wire.h>
    #include <BaroSensor.h>

    #define BARO_CHILD 0
    #define TEMP_CHILD 1

    unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in seconds)

    BaroSensorClass bmp = BaroSensorClass(); // Digital Pressure Sensor
    MySensor gw;

    float lastPressure = -1;
    float lastTemp = -1;
    int lastForecast = -1;
    char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"};
    int minutes;
    float pressureSamples[180];
    int minuteCount = 0;
    bool firstRound = true;
    float pressureAvg[7];
    float dP_dt;
    boolean metric;
    MyMessage tempMsg(TEMP_CHILD, V_TEMP);
    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
    MyMessage forecastMsg(BARO_CHILD, V_FORECAST);

    void setup() {
    gw.begin();

    // Send the sketch version information to the gateway and Controller
    gw.sendSketchInfo("Pressure Sensor", "1.0");

    bmp.begin();
    // Serial.println("Could not find a valid sensor, check wiring!");
    //while (1) { }
    //}

    // Register sensors to gw (they will be created as child devices)
    gw.present(BARO_CHILD, S_BARO);
    gw.present(TEMP_CHILD, S_TEMP);
    metric = gw.getConfig().isMetric;
    }

    void loop() {
    float pressure = bmp.getPressure(); //(205)/100; // 205 meters above sealevel
    float temperature = bmp.getTemperature();

    if (!metric) {
    // Convert to fahrenheit
    temperature = temperature * 9.0 / 5.0 + 32.0;
    }

    int forecast = sample(pressure);

    Serial.print("Temperature = ");
    Serial.print(temperature);
    Serial.println(metric?" *C":" *F");
    Serial.print("Pressure = ");
    Serial.print(pressure);
    Serial.println(" Pa");
    Serial.println(weather[forecast]);

    if (temperature != lastTemp) {
    gw.send(tempMsg.set(temperature,1));
    lastTemp = temperature;
    }

    if (pressure != lastPressure) {
    gw.send(pressureMsg.set(pressure, 0));
    lastPressure = pressure;
    }

    if (forecast != lastForecast) {
    gw.send(forecastMsg.set(weather[forecast]));
    lastForecast = forecast;
    }

    /*
    DP/Dt explanation

    0 = "Stable Weather Pattern"
    1 = "Slowly rising Good Weather", "Clear/Sunny "
    2 = "Slowly falling L-Pressure ", "Cloudy/Rain "
    3 = "Quickly rising H-Press", "Not Stable"
    4 = "Quickly falling L-Press", "Thunderstorm"
    5 = "Unknown (More Time needed)
    */

    gw.sleep(SLEEP_TIME);
    }

    int sample(float pressure) {
    // Algorithm found here
    // http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
    if (minuteCount == 180)
    minuteCount = 5;

    pressureSamples[minuteCount] = pressure;
    minuteCount++;
    
    if (minuteCount == 5) {
    	// Avg pressure in first 5 min, value averaged from 0 to 5 min.
    	pressureAvg[0] = ((pressureSamples[0] + pressureSamples[1]
    			+ pressureSamples[2] + pressureSamples[3] + pressureSamples[4])
    			/ 5);
    } else if (minuteCount == 35) {
    	// Avg pressure in 30 min, value averaged from 0 to 5 min.
    	pressureAvg[1] = ((pressureSamples[30] + pressureSamples[31]
    			+ pressureSamples[32] + pressureSamples[33]
    			+ pressureSamples[34]) / 5);
    	float change = (pressureAvg[1] - pressureAvg[0]);
    	if (firstRound) // first time initial 3 hour
    		dP_dt = ((65.0 / 1023.0) * 2 * change); // note this is for t = 0.5hour
    	else
    		dP_dt = (((65.0 / 1023.0) * change) / 1.5); // divide by 1.5 as this is the difference in time from 0 value.
    } else if (minuteCount == 60) {
    	// Avg pressure at end of the hour, value averaged from 0 to 5 min.
    	pressureAvg[2] = ((pressureSamples[55] + pressureSamples[56]
    			+ pressureSamples[57] + pressureSamples[58]
    			+ pressureSamples[59]) / 5);
    	float change = (pressureAvg[2] - pressureAvg[0]);
    	if (firstRound) //first time initial 3 hour
    		dP_dt = ((65.0 / 1023.0) * change); //note this is for t = 1 hour
    	else
    		dP_dt = (((65.0 / 1023.0) * change) / 2); //divide by 2 as this is the difference in time from 0 value
    } else if (minuteCount == 95) {
    	// Avg pressure at end of the hour, value averaged from 0 to 5 min.
    	pressureAvg[3] = ((pressureSamples[90] + pressureSamples[91]
    			+ pressureSamples[92] + pressureSamples[93]
    			+ pressureSamples[94]) / 5);
    	float change = (pressureAvg[3] - pressureAvg[0]);
    	if (firstRound) // first time initial 3 hour
    		dP_dt = (((65.0 / 1023.0) * change) / 1.5); // note this is for t = 1.5 hour
    	else
    		dP_dt = (((65.0 / 1023.0) * change) / 2.5); // divide by 2.5 as this is the difference in time from 0 value
    } else if (minuteCount == 120) {
    	// Avg pressure at end of the hour, value averaged from 0 to 5 min.
    	pressureAvg[4] = ((pressureSamples[115] + pressureSamples[116]
    			+ pressureSamples[117] + pressureSamples[118]
    			+ pressureSamples[119]) / 5);
    	float change = (pressureAvg[4] - pressureAvg[0]);
    	if (firstRound) // first time initial 3 hour
    		dP_dt = (((65.0 / 1023.0) * change) / 2); // note this is for t = 2 hour
    	else
    		dP_dt = (((65.0 / 1023.0) * change) / 3); // divide by 3 as this is the difference in time from 0 value
    } else if (minuteCount == 155) {
    	// Avg pressure at end of the hour, value averaged from 0 to 5 min.
    	pressureAvg[5] = ((pressureSamples[150] + pressureSamples[151]
    			+ pressureSamples[152] + pressureSamples[153]
    			+ pressureSamples[154]) / 5);
    	float change = (pressureAvg[5] - pressureAvg[0]);
    	if (firstRound) // first time initial 3 hour
    		dP_dt = (((65.0 / 1023.0) * change) / 2.5); // note this is for t = 2.5 hour
    	else
    		dP_dt = (((65.0 / 1023.0) * change) / 3.5); // divide by 3.5 as this is the difference in time from 0 value
    } else if (minuteCount == 180) {
    	// Avg pressure at end of the hour, value averaged from 0 to 5 min.
    	pressureAvg[6] = ((pressureSamples[175] + pressureSamples[176]
    			+ pressureSamples[177] + pressureSamples[178]
    			+ pressureSamples[179]) / 5);
    	float change = (pressureAvg[6] - pressureAvg[0]);
    	if (firstRound) // first time initial 3 hour
    		dP_dt = (((65.0 / 1023.0) * change) / 3); // note this is for t = 3 hour
    	else
    		dP_dt = (((65.0 / 1023.0) * change) / 4); // divide by 4 as this is the difference in time from 0 value
    	pressureAvg[0] = pressureAvg[5]; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
    	firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop.
    }
    
    if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval.
    	return 5; // Unknown, more time needed
    else if (dP_dt < (-0.25))
    	return 4; // Quickly falling LP, Thunderstorm, not stable
    else if (dP_dt > 0.25)
    	return 3; // Quickly rising HP, not stable weather
    else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05)))
    	return 2; // Slowly falling Low Pressure System, stable rainy weather
    else if ((dP_dt > 0.05) && (dP_dt < 0.25))
    	return 1; // Slowly rising HP stable good weather
    else if ((dP_dt > (-0.05)) && (dP_dt < 0.05))
    	return 0; // Stable weather
    else
    	return 5; // Unknown
    

    }

    1 Reply Last reply
    0
    • hekH Offline
      hekH Offline
      hek
      Admin
      wrote on last edited by
      #2

      Sorry, we aren't machines that easily do diffs in our heads... :)

      What exactly did you change and why?

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Myles L
        wrote on last edited by
        #3

        Sorry about that, I changed

        #include <Adafruit_BMP085.h> changed to #include <BaroSensor.h> (Alternate library files for different baro sensor)
        Adafruit_BMP085 bmp = Adafruit_BMP085(); changed to BaroSensorClass bmp = BaroSensorClass(); (BaroSensorClass is referenced in the library files)
        float pressure = bmp.readSealevelPressure(205)/100; **changed to ** float pressure = bmp.getPressure(); (also referenced in the library)
        float temperature = bmp.readTemperature(); changed to float temperature = bmp.getTemperature(); (same reason)
        if (!bmp.begin()) {
        Serial.println("Could not find a valid BMP085 sensor, check wiring!");
        while (1) { } **changed to ** bmp.begin(); (Could not get the sketch to compile using the original so changed to just start the baro sensor)

        Thanks again.

        1 Reply Last reply
        0
        • hekH Offline
          hekH Offline
          hek
          Admin
          wrote on last edited by
          #4

          If you get no output in the Serial Monitor there could be a out of (stack) memory situation.

          Try adding debug prints to see where it fails.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            Myles L
            wrote on last edited by
            #5

            Thanks, I added debug prints after each line but still get nothing on the serial monitor. Does that mean I can assume that the problem is in the initial setup section (the code before void setup(){)?

            I couldn't find a way to add debug prints to that section but any suggestions on how to are welcome.

            1 Reply Last reply
            0
            • korttomaK Offline
              korttomaK Offline
              korttoma
              Hero Member
              wrote on last edited by korttoma
              #6

              Did you try something like this:

              void setup()
              {
              Serial.begin(115200);
              delay(1000);
              Serial.println("Serial begin ");
              
              gw.begin
              

              Edit: newermind, I don't think you can get anything from the section before setup()

              • Tomas
              1 Reply Last reply
              0
              • BulldogLowellB Offline
                BulldogLowellB Offline
                BulldogLowell
                Contest Winner
                wrote on last edited by
                #7

                maybe i missed it, but did you have a sketch that worked (with the appropriate libraries) at least outputting the sensor data to the serial monitor?

                If you have that, post it. It will be easy to add to that the 'stuff' you need for MySensors, I believe.

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  Myles L
                  wrote on last edited by
                  #8

                  Yes, I have that. It is just a really a really basic sketch that prints the sensor data to a serial output. I am also very interested in the weather forecast part of the MySensors sketch which is why I was trying to mod it.

                  #include <Wire.h>
                  #include <BaroSensor.h>

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

                  void loop()
                  {
                  if(!BaroSensor.isOK()) {
                  Serial.print("Sensor not Found/OK. Error: ");
                  Serial.println(BaroSensor.getError());
                  BaroSensor.begin(); // Try to reinitialise the sensor if we can
                  }
                  else {
                  Serial.print("Temperature: ");
                  Serial.println(BaroSensor.getTemperature());
                  Serial.print("Pressure: ");
                  Serial.println(BaroSensor.getPressure());
                  }
                  delay(1000);
                  }

                  BulldogLowellB 1 Reply Last reply
                  0
                  • M Myles L

                    Yes, I have that. It is just a really a really basic sketch that prints the sensor data to a serial output. I am also very interested in the weather forecast part of the MySensors sketch which is why I was trying to mod it.

                    #include <Wire.h>
                    #include <BaroSensor.h>

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

                    void loop()
                    {
                    if(!BaroSensor.isOK()) {
                    Serial.print("Sensor not Found/OK. Error: ");
                    Serial.println(BaroSensor.getError());
                    BaroSensor.begin(); // Try to reinitialise the sensor if we can
                    }
                    else {
                    Serial.print("Temperature: ");
                    Serial.println(BaroSensor.getTemperature());
                    Serial.print("Pressure: ");
                    Serial.println(BaroSensor.getPressure());
                    }
                    delay(1000);
                    }

                    BulldogLowellB Offline
                    BulldogLowellB Offline
                    BulldogLowell
                    Contest Winner
                    wrote on last edited by BulldogLowell
                    #9

                    @Myles-L

                    this compiles, but I could not test it:

                    #include <SPI.h>
                    #include <MySensor.h>  
                    #include <Wire.h>
                    #include <BaroSensor.h>
                    
                    #define BARO_CHILD 0
                    #define TEMP_CHILD 1
                    
                    unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in seconds)
                    
                    MySensor gw;
                    
                    float lastPressure = -1;
                    float lastTemp = -1;
                    int lastForecast = -1;
                    const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"};
                    int minutes;
                    float pressureSamples[180];
                    int minuteCount = 0;
                    bool firstRound = true;
                    float pressureAvg[7];
                    float dP_dt;
                    boolean metric; 
                    MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                    MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                    
                    void setup() {
                      gw.begin();
                    
                      // Send the sketch version information to the gateway and Controller
                      gw.sendSketchInfo("Pressure Sensor", "1.0");
                    
                      BaroSensor.begin();
                    
                      // Register sensors to gw (they will be created as child devices)
                      gw.present(BARO_CHILD, S_BARO);
                      gw.present(TEMP_CHILD, S_TEMP);
                      metric =  gw.getConfig().isMetric;
                    }
                    
                    void loop() 
                    {
                      if(!BaroSensor.isOK()) 
                      {
                        Serial.print("Sensor not Found/OK. Error: "); 
                        Serial.println(BaroSensor.getError());
                        BaroSensor.begin(); // Try to reinitialise the sensor if we can
                      }
                      
                      float pressure = BaroSensor.getPressure()/100;
                      float temperature = BaroSensor.getTemperature();
                      if (!metric) 
                      {
                        // Convert to fahrenheit
                        temperature = temperature * 9.0 / 5.0 + 32.0;
                      }
                      
                      int forecast = sample(pressure);
                    
                      Serial.print("Temperature = ");
                      Serial.print(temperature);
                      Serial.println(metric?" *C":" *F");
                      Serial.print("Pressure = ");
                      Serial.print(pressure);
                      Serial.println(" Pa");
                      Serial.println(weather[forecast]);
                    
                    
                      if (temperature != lastTemp) {
                        gw.send(tempMsg.set(temperature,1));
                        lastTemp = temperature;
                      }
                    
                      if (pressure != lastPressure) {
                        gw.send(pressureMsg.set(pressure, 0));
                        lastPressure = pressure;
                      }
                    
                      if (forecast != lastForecast) 
                      {
                        gw.send(forecastMsg.set(weather[forecast]));
                        lastForecast = forecast;
                      }
                      
                      /*
                       DP/Dt explanation
                    
                       0 = "Stable Weather Pattern"
                       1 = "Slowly rising Good Weather", "Clear/Sunny "
                       2 = "Slowly falling L-Pressure ", "Cloudy/Rain "
                       3 = "Quickly rising H-Press",     "Not Stable"
                       4 = "Quickly falling L-Press",    "Thunderstorm"
                       5 = "Unknown (More Time needed) 
                      */
                    
                      gw.sleep(SLEEP_TIME);
                    }
                    
                    int sample(float pressure) {
                    	// Algorithm found here
                    	// http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
                    	if (minuteCount > 180)
                    		minuteCount = 6;
                    
                    	pressureSamples[minuteCount] = pressure;
                    	minuteCount++;
                    
                    	if (minuteCount == 5) {
                    		// Avg pressure in first 5 min, value averaged from 0 to 5 min.
                    		pressureAvg[0] = ((pressureSamples[1] + pressureSamples[2]
                    				+ pressureSamples[3] + pressureSamples[4] + pressureSamples[5])
                    				/ 5);
                    	} else if (minuteCount == 35) {
                    		// Avg pressure in 30 min, value averaged from 0 to 5 min.
                    		pressureAvg[1] = ((pressureSamples[30] + pressureSamples[31]
                    				+ pressureSamples[32] + pressureSamples[33]
                    				+ pressureSamples[34]) / 5);
                    		float change = (pressureAvg[1] - pressureAvg[0]);
                    		if (firstRound) // first time initial 3 hour
                    			dP_dt = ((65.0 / 1023.0) * 2 * change); // note this is for t = 0.5hour
                    		else
                    			dP_dt = (((65.0 / 1023.0) * change) / 1.5); // divide by 1.5 as this is the difference in time from 0 value.
                    	} else if (minuteCount == 60) {
                    		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                    		pressureAvg[2] = ((pressureSamples[55] + pressureSamples[56]
                    				+ pressureSamples[57] + pressureSamples[58]
                    				+ pressureSamples[59]) / 5);
                    		float change = (pressureAvg[2] - pressureAvg[0]);
                    		if (firstRound) //first time initial 3 hour
                    			dP_dt = ((65.0 / 1023.0) * change); //note this is for t = 1 hour
                    		else
                    			dP_dt = (((65.0 / 1023.0) * change) / 2); //divide by 2 as this is the difference in time from 0 value
                    	} else if (minuteCount == 95) {
                    		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                    		pressureAvg[3] = ((pressureSamples[90] + pressureSamples[91]
                    				+ pressureSamples[92] + pressureSamples[93]
                    				+ pressureSamples[94]) / 5);
                    		float change = (pressureAvg[3] - pressureAvg[0]);
                    		if (firstRound) // first time initial 3 hour
                    			dP_dt = (((65.0 / 1023.0) * change) / 1.5); // note this is for t = 1.5 hour
                    		else
                    			dP_dt = (((65.0 / 1023.0) * change) / 2.5); // divide by 2.5 as this is the difference in time from 0 value
                    	} else if (minuteCount == 120) {
                    		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                    		pressureAvg[4] = ((pressureSamples[115] + pressureSamples[116]
                    				+ pressureSamples[117] + pressureSamples[118]
                    				+ pressureSamples[119]) / 5);
                    		float change = (pressureAvg[4] - pressureAvg[0]);
                    		if (firstRound) // first time initial 3 hour
                    			dP_dt = (((65.0 / 1023.0) * change) / 2); // note this is for t = 2 hour
                    		else
                    			dP_dt = (((65.0 / 1023.0) * change) / 3); // divide by 3 as this is the difference in time from 0 value
                    	} else if (minuteCount == 155) {
                    		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                    		pressureAvg[5] = ((pressureSamples[150] + pressureSamples[151]
                    				+ pressureSamples[152] + pressureSamples[153]
                    				+ pressureSamples[154]) / 5);
                    		float change = (pressureAvg[5] - pressureAvg[0]);
                    		if (firstRound) // first time initial 3 hour
                    			dP_dt = (((65.0 / 1023.0) * change) / 2.5); // note this is for t = 2.5 hour
                    		else
                    			dP_dt = (((65.0 / 1023.0) * change) / 3.5); // divide by 3.5 as this is the difference in time from 0 value
                    	} else if (minuteCount == 180) {
                    		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                    		pressureAvg[6] = ((pressureSamples[175] + pressureSamples[176]
                    				+ pressureSamples[177] + pressureSamples[178]
                    				+ pressureSamples[179]) / 5);
                    		float change = (pressureAvg[6] - pressureAvg[0]);
                    		if (firstRound) // first time initial 3 hour
                    			dP_dt = (((65.0 / 1023.0) * change) / 3); // note this is for t = 3 hour
                    		else
                    			dP_dt = (((65.0 / 1023.0) * change) / 4); // divide by 4 as this is the difference in time from 0 value
                    		pressureAvg[0] = pressureAvg[5]; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
                    		firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop.
                    	}
                    
                    	if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval.
                    		return 5; // Unknown, more time needed
                    	else if (dP_dt < (-0.25))
                    		return 4; // Quickly falling LP, Thunderstorm, not stable
                    	else if (dP_dt > 0.25)
                    		return 3; // Quickly rising HP, not stable weather
                    	else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05)))
                    		return 2; // Slowly falling Low Pressure System, stable rainy weather
                    	else if ((dP_dt > 0.05) && (dP_dt < 0.25))
                    		return 1; // Slowly rising HP stable good weather
                    	else if ((dP_dt > (-0.05)) && (dP_dt < 0.05))
                    		return 0; // Stable weather
                    	else
                    		return 5; // Unknown
                    }
                    
                    M 1 Reply Last reply
                    0
                    • BulldogLowellB BulldogLowell

                      @Myles-L

                      this compiles, but I could not test it:

                      #include <SPI.h>
                      #include <MySensor.h>  
                      #include <Wire.h>
                      #include <BaroSensor.h>
                      
                      #define BARO_CHILD 0
                      #define TEMP_CHILD 1
                      
                      unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in seconds)
                      
                      MySensor gw;
                      
                      float lastPressure = -1;
                      float lastTemp = -1;
                      int lastForecast = -1;
                      const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"};
                      int minutes;
                      float pressureSamples[180];
                      int minuteCount = 0;
                      bool firstRound = true;
                      float pressureAvg[7];
                      float dP_dt;
                      boolean metric; 
                      MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                      MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                      MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                      
                      void setup() {
                        gw.begin();
                      
                        // Send the sketch version information to the gateway and Controller
                        gw.sendSketchInfo("Pressure Sensor", "1.0");
                      
                        BaroSensor.begin();
                      
                        // Register sensors to gw (they will be created as child devices)
                        gw.present(BARO_CHILD, S_BARO);
                        gw.present(TEMP_CHILD, S_TEMP);
                        metric =  gw.getConfig().isMetric;
                      }
                      
                      void loop() 
                      {
                        if(!BaroSensor.isOK()) 
                        {
                          Serial.print("Sensor not Found/OK. Error: "); 
                          Serial.println(BaroSensor.getError());
                          BaroSensor.begin(); // Try to reinitialise the sensor if we can
                        }
                        
                        float pressure = BaroSensor.getPressure()/100;
                        float temperature = BaroSensor.getTemperature();
                        if (!metric) 
                        {
                          // Convert to fahrenheit
                          temperature = temperature * 9.0 / 5.0 + 32.0;
                        }
                        
                        int forecast = sample(pressure);
                      
                        Serial.print("Temperature = ");
                        Serial.print(temperature);
                        Serial.println(metric?" *C":" *F");
                        Serial.print("Pressure = ");
                        Serial.print(pressure);
                        Serial.println(" Pa");
                        Serial.println(weather[forecast]);
                      
                      
                        if (temperature != lastTemp) {
                          gw.send(tempMsg.set(temperature,1));
                          lastTemp = temperature;
                        }
                      
                        if (pressure != lastPressure) {
                          gw.send(pressureMsg.set(pressure, 0));
                          lastPressure = pressure;
                        }
                      
                        if (forecast != lastForecast) 
                        {
                          gw.send(forecastMsg.set(weather[forecast]));
                          lastForecast = forecast;
                        }
                        
                        /*
                         DP/Dt explanation
                      
                         0 = "Stable Weather Pattern"
                         1 = "Slowly rising Good Weather", "Clear/Sunny "
                         2 = "Slowly falling L-Pressure ", "Cloudy/Rain "
                         3 = "Quickly rising H-Press",     "Not Stable"
                         4 = "Quickly falling L-Press",    "Thunderstorm"
                         5 = "Unknown (More Time needed) 
                        */
                      
                        gw.sleep(SLEEP_TIME);
                      }
                      
                      int sample(float pressure) {
                      	// Algorithm found here
                      	// http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
                      	if (minuteCount > 180)
                      		minuteCount = 6;
                      
                      	pressureSamples[minuteCount] = pressure;
                      	minuteCount++;
                      
                      	if (minuteCount == 5) {
                      		// Avg pressure in first 5 min, value averaged from 0 to 5 min.
                      		pressureAvg[0] = ((pressureSamples[1] + pressureSamples[2]
                      				+ pressureSamples[3] + pressureSamples[4] + pressureSamples[5])
                      				/ 5);
                      	} else if (minuteCount == 35) {
                      		// Avg pressure in 30 min, value averaged from 0 to 5 min.
                      		pressureAvg[1] = ((pressureSamples[30] + pressureSamples[31]
                      				+ pressureSamples[32] + pressureSamples[33]
                      				+ pressureSamples[34]) / 5);
                      		float change = (pressureAvg[1] - pressureAvg[0]);
                      		if (firstRound) // first time initial 3 hour
                      			dP_dt = ((65.0 / 1023.0) * 2 * change); // note this is for t = 0.5hour
                      		else
                      			dP_dt = (((65.0 / 1023.0) * change) / 1.5); // divide by 1.5 as this is the difference in time from 0 value.
                      	} else if (minuteCount == 60) {
                      		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                      		pressureAvg[2] = ((pressureSamples[55] + pressureSamples[56]
                      				+ pressureSamples[57] + pressureSamples[58]
                      				+ pressureSamples[59]) / 5);
                      		float change = (pressureAvg[2] - pressureAvg[0]);
                      		if (firstRound) //first time initial 3 hour
                      			dP_dt = ((65.0 / 1023.0) * change); //note this is for t = 1 hour
                      		else
                      			dP_dt = (((65.0 / 1023.0) * change) / 2); //divide by 2 as this is the difference in time from 0 value
                      	} else if (minuteCount == 95) {
                      		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                      		pressureAvg[3] = ((pressureSamples[90] + pressureSamples[91]
                      				+ pressureSamples[92] + pressureSamples[93]
                      				+ pressureSamples[94]) / 5);
                      		float change = (pressureAvg[3] - pressureAvg[0]);
                      		if (firstRound) // first time initial 3 hour
                      			dP_dt = (((65.0 / 1023.0) * change) / 1.5); // note this is for t = 1.5 hour
                      		else
                      			dP_dt = (((65.0 / 1023.0) * change) / 2.5); // divide by 2.5 as this is the difference in time from 0 value
                      	} else if (minuteCount == 120) {
                      		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                      		pressureAvg[4] = ((pressureSamples[115] + pressureSamples[116]
                      				+ pressureSamples[117] + pressureSamples[118]
                      				+ pressureSamples[119]) / 5);
                      		float change = (pressureAvg[4] - pressureAvg[0]);
                      		if (firstRound) // first time initial 3 hour
                      			dP_dt = (((65.0 / 1023.0) * change) / 2); // note this is for t = 2 hour
                      		else
                      			dP_dt = (((65.0 / 1023.0) * change) / 3); // divide by 3 as this is the difference in time from 0 value
                      	} else if (minuteCount == 155) {
                      		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                      		pressureAvg[5] = ((pressureSamples[150] + pressureSamples[151]
                      				+ pressureSamples[152] + pressureSamples[153]
                      				+ pressureSamples[154]) / 5);
                      		float change = (pressureAvg[5] - pressureAvg[0]);
                      		if (firstRound) // first time initial 3 hour
                      			dP_dt = (((65.0 / 1023.0) * change) / 2.5); // note this is for t = 2.5 hour
                      		else
                      			dP_dt = (((65.0 / 1023.0) * change) / 3.5); // divide by 3.5 as this is the difference in time from 0 value
                      	} else if (minuteCount == 180) {
                      		// Avg pressure at end of the hour, value averaged from 0 to 5 min.
                      		pressureAvg[6] = ((pressureSamples[175] + pressureSamples[176]
                      				+ pressureSamples[177] + pressureSamples[178]
                      				+ pressureSamples[179]) / 5);
                      		float change = (pressureAvg[6] - pressureAvg[0]);
                      		if (firstRound) // first time initial 3 hour
                      			dP_dt = (((65.0 / 1023.0) * change) / 3); // note this is for t = 3 hour
                      		else
                      			dP_dt = (((65.0 / 1023.0) * change) / 4); // divide by 4 as this is the difference in time from 0 value
                      		pressureAvg[0] = pressureAvg[5]; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
                      		firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop.
                      	}
                      
                      	if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval.
                      		return 5; // Unknown, more time needed
                      	else if (dP_dt < (-0.25))
                      		return 4; // Quickly falling LP, Thunderstorm, not stable
                      	else if (dP_dt > 0.25)
                      		return 3; // Quickly rising HP, not stable weather
                      	else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05)))
                      		return 2; // Slowly falling Low Pressure System, stable rainy weather
                      	else if ((dP_dt > 0.05) && (dP_dt < 0.25))
                      		return 1; // Slowly rising HP stable good weather
                      	else if ((dP_dt > (-0.05)) && (dP_dt < 0.05))
                      		return 0; // Stable weather
                      	else
                      		return 5; // Unknown
                      }
                      
                      M Offline
                      M Offline
                      Myles L
                      wrote on last edited by
                      #10

                      Thank you so much, it is so close. Code compiles, uploads and there is output from the serial monitor but when adding the device to Vera only a repeater node gets added and not the actual pressure sensor.

                      The additional pressure sensor files have been uploaded to Vera.

                      BulldogLowellB 1 Reply Last reply
                      0
                      • M Myles L

                        Thank you so much, it is so close. Code compiles, uploads and there is output from the serial monitor but when adding the device to Vera only a repeater node gets added and not the actual pressure sensor.

                        The additional pressure sensor files have been uploaded to Vera.

                        BulldogLowellB Offline
                        BulldogLowellB Offline
                        BulldogLowell
                        Contest Winner
                        wrote on last edited by
                        #11

                        put some delays in here... especially if you do not have the caps on the radio!!!

                        BaroSensor.begin();
                        // Register sensors to gw (they will be created as child devices)
                        gw.sendSketchInfo("Pressure Sensor", "1.0");
                        delay(250);
                        gw.present(BARO_CHILD, S_BARO);
                        delay(250);
                        gw.present(TEMP_CHILD, S_TEMP);
                        delay(250);
                        metric =  gw.getConfig().isMetric;
                        

                        if that isn't enough, you can try to add a little more time to the delays....

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          Myles L
                          wrote on last edited by
                          #12

                          Tried delays right up to 5000 and also added a few others but unfortunately it still only presents the repeater node to Vera

                          BulldogLowellB 1 Reply Last reply
                          0
                          • M Myles L

                            Tried delays right up to 5000 and also added a few others but unfortunately it still only presents the repeater node to Vera

                            BulldogLowellB Offline
                            BulldogLowellB Offline
                            BulldogLowell
                            Contest Winner
                            wrote on last edited by
                            #13

                            @Myles-L

                            Try deleting the devices it created and starting over. Give it a new device number and try it without it being a repeating node:

                            change:

                            gw.begin();
                            

                            to:

                            gw.begin(NULL, DEVICE_ID, false);
                            

                            where you defined (added) in the header of the sketch:

                            #define DEVICE_ID 10 
                            

                            or some other number that is non-zero and not greater than 254

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              Myles L
                              wrote on last edited by
                              #14

                              By adding those changes it went back to not outputting to the serial interface. I was able to get it to output again by removing the DEFINE DEVICE ID and the DEVICE ID section (not sure why that made a difference) but then it goes back to only adding a node to Vera.

                              Really appreciate your determination to solve this and I am learning lots along the way!

                              BulldogLowellB 1 Reply Last reply
                              0
                              • M Myles L

                                By adding those changes it went back to not outputting to the serial interface. I was able to get it to output again by removing the DEFINE DEVICE ID and the DEVICE ID section (not sure why that made a difference) but then it goes back to only adding a node to Vera.

                                Really appreciate your determination to solve this and I am learning lots along the way!

                                BulldogLowellB Offline
                                BulldogLowellB Offline
                                BulldogLowell
                                Contest Winner
                                wrote on last edited by
                                #15

                                @Myles-L

                                you mind posting the code you tried last?

                                Can you confirm that you have deleted the Vera devices that were created (I believe you said it was a relay)

                                1 Reply Last reply
                                0
                                • M Offline
                                  M Offline
                                  Myles L
                                  wrote on last edited by
                                  #16

                                  I have deleted the Vera devices and I have also tried removing and re-adding the MySensors plugin in Vera. When I add the pressure sensor now it still adds as a node. Code is below:

                                  #include <SPI.h>
                                  #include <MySensor.h>
                                  #include <Wire.h>
                                  #include <BaroSensor.h>

                                  #define BARO_CHILD 0
                                  #define TEMP_CHILD 1

                                  unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in seconds)

                                  MySensor gw;

                                  float lastPressure = -1;
                                  float lastTemp = -1;
                                  int lastForecast = -1;
                                  const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"};
                                  int minutes;
                                  float pressureSamples[180];
                                  int minuteCount = 0;
                                  bool firstRound = true;
                                  float pressureAvg[7];
                                  float dP_dt;
                                  boolean metric;
                                  MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                  MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                  MyMessage forecastMsg(BARO_CHILD, V_FORECAST);

                                  void setup() {
                                  gw.begin(NULL, false);

                                  // Send the sketch version information to the gateway and Controller
                                  gw.sendSketchInfo("Pressure Sensor", "1.0");
                                  delay(1000);
                                  BaroSensor.begin();
                                  delay(1000);
                                  // Register sensors to gw (they will be created as child devices)
                                  gw.present(BARO_CHILD, S_BARO);
                                  delay(1000);
                                  gw.present(TEMP_CHILD, S_TEMP);
                                  delay(1000);
                                  metric = gw.getConfig().isMetric;
                                  }

                                  void loop()
                                  {
                                  if(!BaroSensor.isOK())
                                  {
                                  Serial.print("Sensor not Found/OK. Error: ");
                                  Serial.println(BaroSensor.getError());
                                  BaroSensor.begin(); // Try to reinitialise the sensor if we can
                                  }

                                  float pressure = BaroSensor.getPressure()/100;
                                  float temperature = BaroSensor.getTemperature();
                                  if (!metric)
                                  {
                                  // Convert to fahrenheit
                                  temperature = temperature * 9.0 / 5.0 + 32.0;
                                  }

                                  int forecast = sample(pressure);

                                  Serial.print("Temperature = ");
                                  Serial.print(temperature);
                                  Serial.println(metric?" *C":" *F");
                                  Serial.print("Pressure = ");
                                  Serial.print(pressure);
                                  Serial.println(" Pa");
                                  Serial.println(weather[forecast]);

                                  if (temperature != lastTemp) {
                                  gw.send(tempMsg.set(temperature,1));
                                  lastTemp = temperature;
                                  }

                                  if (pressure != lastPressure) {
                                  gw.send(pressureMsg.set(pressure, 0));
                                  lastPressure = pressure;
                                  }

                                  if (forecast != lastForecast)
                                  {
                                  gw.send(forecastMsg.set(weather[forecast]));
                                  lastForecast = forecast;
                                  }

                                  /*
                                  DP/Dt explanation

                                  0 = "Stable Weather Pattern"
                                  1 = "Slowly rising Good Weather", "Clear/Sunny "
                                  2 = "Slowly falling L-Pressure ", "Cloudy/Rain "
                                  3 = "Quickly rising H-Press", "Not Stable"
                                  4 = "Quickly falling L-Press", "Thunderstorm"
                                  5 = "Unknown (More Time needed)
                                  */

                                  gw.sleep(SLEEP_TIME);
                                  }

                                  int sample(float pressure) {
                                  // Algorithm found here
                                  // http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
                                  if (minuteCount > 180)
                                  minuteCount = 6;

                                  pressureSamples[minuteCount] = pressure;
                                  minuteCount++;
                                  
                                  if (minuteCount == 5) {
                                      // Avg pressure in first 5 min, value averaged from 0 to 5 min.
                                      pressureAvg[0] = ((pressureSamples[1] + pressureSamples[2]
                                              + pressureSamples[3] + pressureSamples[4] + pressureSamples[5])
                                              / 5);
                                  } else if (minuteCount == 35) {
                                      // Avg pressure in 30 min, value averaged from 0 to 5 min.
                                      pressureAvg[1] = ((pressureSamples[30] + pressureSamples[31]
                                              + pressureSamples[32] + pressureSamples[33]
                                              + pressureSamples[34]) / 5);
                                      float change = (pressureAvg[1] - pressureAvg[0]);
                                      if (firstRound) // first time initial 3 hour
                                          dP_dt = ((65.0 / 1023.0) * 2 * change); // note this is for t = 0.5hour
                                      else
                                          dP_dt = (((65.0 / 1023.0) * change) / 1.5); // divide by 1.5 as this is the difference in time from 0 value.
                                  } else if (minuteCount == 60) {
                                      // Avg pressure at end of the hour, value averaged from 0 to 5 min.
                                      pressureAvg[2] = ((pressureSamples[55] + pressureSamples[56]
                                              + pressureSamples[57] + pressureSamples[58]
                                              + pressureSamples[59]) / 5);
                                      float change = (pressureAvg[2] - pressureAvg[0]);
                                      if (firstRound) //first time initial 3 hour
                                          dP_dt = ((65.0 / 1023.0) * change); //note this is for t = 1 hour
                                      else
                                          dP_dt = (((65.0 / 1023.0) * change) / 2); //divide by 2 as this is the difference in time from 0 value
                                  } else if (minuteCount == 95) {
                                      // Avg pressure at end of the hour, value averaged from 0 to 5 min.
                                      pressureAvg[3] = ((pressureSamples[90] + pressureSamples[91]
                                              + pressureSamples[92] + pressureSamples[93]
                                              + pressureSamples[94]) / 5);
                                      float change = (pressureAvg[3] - pressureAvg[0]);
                                      if (firstRound) // first time initial 3 hour
                                          dP_dt = (((65.0 / 1023.0) * change) / 1.5); // note this is for t = 1.5 hour
                                      else
                                          dP_dt = (((65.0 / 1023.0) * change) / 2.5); // divide by 2.5 as this is the difference in time from 0 value
                                  } else if (minuteCount == 120) {
                                      // Avg pressure at end of the hour, value averaged from 0 to 5 min.
                                      pressureAvg[4] = ((pressureSamples[115] + pressureSamples[116]
                                              + pressureSamples[117] + pressureSamples[118]
                                              + pressureSamples[119]) / 5);
                                      float change = (pressureAvg[4] - pressureAvg[0]);
                                      if (firstRound) // first time initial 3 hour
                                          dP_dt = (((65.0 / 1023.0) * change) / 2); // note this is for t = 2 hour
                                      else
                                          dP_dt = (((65.0 / 1023.0) * change) / 3); // divide by 3 as this is the difference in time from 0 value
                                  } else if (minuteCount == 155) {
                                      // Avg pressure at end of the hour, value averaged from 0 to 5 min.
                                      pressureAvg[5] = ((pressureSamples[150] + pressureSamples[151]
                                              + pressureSamples[152] + pressureSamples[153]
                                              + pressureSamples[154]) / 5);
                                      float change = (pressureAvg[5] - pressureAvg[0]);
                                      if (firstRound) // first time initial 3 hour
                                          dP_dt = (((65.0 / 1023.0) * change) / 2.5); // note this is for t = 2.5 hour
                                      else
                                          dP_dt = (((65.0 / 1023.0) * change) / 3.5); // divide by 3.5 as this is the difference in time from 0 value
                                  } else if (minuteCount == 180) {
                                      // Avg pressure at end of the hour, value averaged from 0 to 5 min.
                                      pressureAvg[6] = ((pressureSamples[175] + pressureSamples[176]
                                              + pressureSamples[177] + pressureSamples[178]
                                              + pressureSamples[179]) / 5);
                                      float change = (pressureAvg[6] - pressureAvg[0]);
                                      if (firstRound) // first time initial 3 hour
                                          dP_dt = (((65.0 / 1023.0) * change) / 3); // note this is for t = 3 hour
                                      else
                                          dP_dt = (((65.0 / 1023.0) * change) / 4); // divide by 4 as this is the difference in time from 0 value
                                      pressureAvg[0] = pressureAvg[5]; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
                                      firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop.
                                  }
                                  
                                  if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval.
                                      return 5; // Unknown, more time needed
                                  else if (dP_dt < (-0.25))
                                      return 4; // Quickly falling LP, Thunderstorm, not stable
                                  else if (dP_dt > 0.25)
                                      return 3; // Quickly rising HP, not stable weather
                                  else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05)))
                                      return 2; // Slowly falling Low Pressure System, stable rainy weather
                                  else if ((dP_dt > 0.05) && (dP_dt < 0.25))
                                      return 1; // Slowly rising HP stable good weather
                                  else if ((dP_dt > (-0.05)) && (dP_dt < 0.05))
                                      return 0; // Stable weather
                                  else
                                      return 5; // Unknown
                                  

                                  }

                                  1 Reply Last reply
                                  0
                                  • BulldogLowellB Offline
                                    BulldogLowellB Offline
                                    BulldogLowell
                                    Contest Winner
                                    wrote on last edited by
                                    #17

                                    @BulldogLowell said:

                                    Try this, and tell me what the serial output looks like.

                                    Have you added a capacitor to the radio? It could be electronic...

                                    #include <SPI.h>
                                    #include <MySensor.h>  
                                    #include <Wire.h>
                                    #include <BaroSensor.h>
                                    
                                    #define BARO_CHILD 0
                                    #define TEMP_CHILD 1
                                    #define DEVICE_ID 99
                                    
                                    unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in seconds)
                                    
                                    MySensor gw;
                                    
                                    float lastPressure = -1;
                                    float lastTemp = -1;
                                    int lastForecast = -1;
                                    const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"};
                                    int minutes;
                                    float pressureSamples[180];
                                    int minuteCount = 0;
                                    bool firstRound = true;
                                    float pressureAvg[7];
                                    float dP_dt;
                                    boolean metric; 
                                    MyMessage tempMsg(TEMP_CHILD, V_TEMP);
                                    MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
                                    MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
                                    
                                    void setup() {
                                      gw.begin(NULL, DEVICE_ID, false);
                                      delay(1000);
                                      Serial.println("Got to GW.Begin");
                                      // Send the sketch version information to the gateway and Controller
                                      gw.sendSketchInfo("Pressure Sensor", "1.0");
                                      Serial.println("Sketch data Presented");
                                      delay(1000);
                                      BaroSensor.begin();
                                      Serial.println("Brometer Sensor started...");
                                      delay(1000);
                                      // Register sensors to gw (they will be created as child devices)
                                      gw.present(BARO_CHILD, S_BARO);
                                      Serial.println("presenting Barometer");
                                      delay(1000);
                                      gw.present(TEMP_CHILD, S_TEMP);
                                      Serial.println("presenting Thermometer");
                                      delay(1000);
                                      metric =  gw.getConfig().isMetric;
                                      Serial.println("requesting Metric");
                                      delay(1000);
                                      Serial.println("Setup Complete");
                                    }
                                    
                                    void loop() 
                                    {
                                    }
                                    
                                    1 Reply Last reply
                                    0
                                    • M Offline
                                      M Offline
                                      Myles L
                                      wrote on last edited by
                                      #18

                                      The Sensor and Ethernet gateway both have 4.7uf electrolytic capacitors across the power input of the radio's (I cant get much distance out of them, maybe <10 metres, but they do work for the relay sensor).

                                      The serial output looks like this: ��Ah���Y5����������i��`q!���J�����

                                      1 Reply Last reply
                                      0
                                      • M Offline
                                        M Offline
                                        Myles L
                                        wrote on last edited by
                                        #19

                                        Using that sketch I was able to add it to Vera, it just does not report pressure or forecast (obviously as there is no data being presented to it)

                                        1 Reply Last reply
                                        0
                                        • BulldogLowellB Offline
                                          BulldogLowellB Offline
                                          BulldogLowell
                                          Contest Winner
                                          wrote on last edited by
                                          #20

                                          Great, now just plug the loop() back into the sketch, flash your arduino, and you should be good to go

                                          oh... and add a Serial.begin(yourDesiredBaudRate) to setup() ;)

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          15

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular