Navigation

    • Register
    • Login
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. รอเรือ
    3. Best
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Best posts made by รอเรือ

    • My Wind Station

      I made a wind station using the two following sensors that I bought on e-bay.

      • Wind Sensor JL-FS2 Wind Direction Sensor (4-20mA, 0-5V) Signal Output
      • Wind Speed Sensor Anemometer Three Cups Aluminium Alloyed pulse signal output

      0_1533548833049_s-l500.jpg
      0_1533548847083_s-l1600.jpg

      I think they are quite nice. They are fed with 12V DC and are giving a 5V output signal. Therefore I'm using a 5V Arduino Mini Pro for the sketch.

      The following sketch is measuring the wind data once a second, storing it into an array and doing calculations to get the average wind speed, direction and gust for each minute, each other minute and each 10 minutes.

      Before getting the average the wind is split into it's vector components. Cool isn't it?

      I upload the average 10 minute wind data to Weather Underground. It looks very smooth.

      Here is the sketch:

      /**
       * WindMonitor
       * 
      
      About the windspeed sensor, have a look here:
      https://www.dfrobot.com/wiki/index.php/Wind_Speed_Sensor_Voltage_Type(0-5V)_SKU:SEN0170#Connection_Diagram
      
      */
      #define MY_NODE_ID 17
      
      #define SKETCH_NAME "Wind Station"
      #define SKETCH_VERSION "1.1.1"
      #define DWELL_TIME 1000  // this allows for radio to come back to power after a transmission, ideally 0
      
      //#define MY_DEBUG // Enable debug Serial.prints to serial monitor and arrays are smaller
      
      #if defined MY_DEBUG
      #define MY_BAUD_RATE 115200 // Sets the serial baud rate for console and serial gateway
      
      #define Sprintln(a) (Serial.println(a))
      #define Sprint(a) (Serial.print(a))
      const uint8_t num1mReadings = 2; // Use a low value to free memory for making debug possible
      const uint8_t num2mReadings = 2; // Use a low value to free memory for making debug possible
      const uint8_t num10mReadings = 2; // Use a low value to free memory for making debug possible
      const uint8_t FORCE_TRANSMIT_CYCLE = 10; // Force sending value even if hasn't changed after N cycles
      const uint16_t WAIT_TIME = 5000;
      #else 
      #define Sprintln(a)
      #define Sprint(a)
      const uint8_t num1mReadings = 60; //Defines number of reading to calculate average windspeed
      const uint8_t num2mReadings = 2;
      const uint8_t num10mReadings = 10;
      const uint8_t FORCE_TRANSMIT_CYCLE = 10; // Force sending value even if hasn't changed after N cycles
      const uint16_t WAIT_TIME = 1000;
      #endif
      
      // Enable and select radio type attached
      #define MY_RADIO_NRF24
      //#define MY_PARENT_NODE_ID 0
      //#define MY_PARENT_NODE_IS_STATIC
      #include <MySensors.h>
      
      #define LED_PIN 8
      #define ANEMOMETER_ANALOG_PIN 0
      #define WIND_VANE_ANALOG_PIN 1
      
      #define CHILD_ID_WIND 0
      #define CHILD_ID_WIND2M 1
      #define CHILD_ID_WIND10M 2
      #define CHILD_ID_GUST_DIR 3 // Specifically for wind gust direction
      #define CHILD_ID_GUST2M_DIR 4
      #define CHILD_ID_GUST10M_DIR 5
      
      
      #define FORCE_TRANSMIT_CYCLE 60 // Force sending value even if hasn't changed after N cycles
      uint8_t cycleCountWindSpeed = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindGust = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindGustDir = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindDir = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindSpeed2m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindGust2m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindGustDir2m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindDir2m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindSpeed10m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindGust10m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindGustDir10m = FORCE_TRANSMIT_CYCLE;
      uint8_t cycleCountWindDir10m = FORCE_TRANSMIT_CYCLE;
      
      float last_wspeed;
      float last_wgust;
      uint16_t last_wdirection;
      uint16_t last_wgustdirection;
      float last_wspeed2m;
      float last_wgust2m;
      uint16_t last_wdirection2m;
      uint16_t last_wgustdirection2m;
      float last_wspeed10m;
      float last_wgust10m;
      uint16_t last_wdirection10m;
      uint16_t last_wgustdirection10m;
      
      float windSpeedReadings[num1mReadings]; // the readings from the analog input
      float windSpeedReadings2m[num2mReadings]; // For 2 minute average wind speed
      float windSpeedReadings10m[num10mReadings]; // For 10 minute average wind speed
      float windDirReadings[num1mReadings]; // the readings from the analog input
      float windDirReadings2m[num2mReadings]; // For 2 minute average wind dir
      float windDirReadings10m[num10mReadings]; // For 10 minute average wind dir
      float windGustReadings2m[num2mReadings]; // For 2 minute wind gust
      float windGustDirReadings2m[num2mReadings]; // For 2 minute wind gust direction
      float windGustReadings10m[num10mReadings]; // For 10 minute wind gust
      float windGustDirReadings10m[num10mReadings]; // For 10 minute wind gust direction
      boolean got2mins = false;
      boolean got10mins = false;
      
      float windSpeed = 0.0; // Wind speed in meters per second (m/s)
      float windDir = 0; // Wind dir in degrees 0-360
      uint8_t readIndex = 0; // the index of the current reading
      uint8_t minute2Index = 0; // the index of the current reading
      uint8_t minute10Index = 0; // the index of the current reading
      uint16_t sensorValue = 0; //Variable stores the value direct from the analog pin
      const uint8_t wsMin = 22; // Mininum reading
      const uint16_t wsMax = 1023; // Maximum reading
      const uint8_t wdMin = 3; // Mininum reading
      const uint16_t wdMax = 941; // Maximum reading
      const uint8_t windSpeedMax = 30; // Wind speed in meters/sec corresponding to maximum voltage
      
      
      MyMessage msgWSpeed(CHILD_ID_WIND, V_WIND);
      MyMessage msgWGust(CHILD_ID_WIND, V_GUST);
      MyMessage msgWDirection(CHILD_ID_WIND, V_DIRECTION);
      MyMessage msgWSpeed2m(CHILD_ID_WIND2M, V_WIND);
      MyMessage msgWGust2m(CHILD_ID_WIND2M, V_GUST);
      MyMessage msgWDirection2m(CHILD_ID_WIND2M, V_DIRECTION);
      MyMessage msgWSpeed10m(CHILD_ID_WIND10M, V_WIND);
      MyMessage msgWGust10m(CHILD_ID_WIND10M, V_GUST);
      MyMessage msgWDirection10m(CHILD_ID_WIND10M, V_DIRECTION);
      MyMessage msgWGustDir(CHILD_ID_GUST_DIR, V_DIRECTION);
      MyMessage msgWGust2mDir(CHILD_ID_GUST2M_DIR, V_DIRECTION);
      MyMessage msgWGust10mDir(CHILD_ID_GUST10M_DIR, V_DIRECTION);
      
      void setup()  
      {
        Sprint(SKETCH_NAME);
        Sprint(F(" version "));
        Sprint(SKETCH_VERSION);
        Sprint(F(" (using MY_NODE_ID: "));
        Sprint(MY_NODE_ID);
        Sprintln(F(") says hello!"));
      
        // Initialize arrays
        for (readIndex = 0; readIndex < num1mReadings; readIndex++) {
          windSpeedReadings[readIndex] = 0;
          windDirReadings[readIndex] = 0;
        }
        for (minute2Index = 0; minute2Index < num2mReadings; minute2Index++) {
          windSpeedReadings2m[minute2Index] = 0;
          windDirReadings2m[minute2Index] = 0;
          windGustReadings2m[minute2Index] = 0;
          windGustDirReadings2m[minute2Index] = 0;
        }
        for (minute10Index = 0; minute10Index < num10mReadings; minute10Index++) {
          windSpeedReadings10m[minute10Index] = 0;
          windDirReadings10m[minute10Index] = 0;
          windGustReadings10m[minute10Index] = 0;
          windGustDirReadings10m[minute10Index] = 0;
        }
      }
      
      void presentation()  {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
        wait(DWELL_TIME);
        // Register all sensors to gateway (they will be created as child devices)
        present(CHILD_ID_WIND, S_WIND);
        wait(DWELL_TIME);
        present(CHILD_ID_WIND2M, S_WIND);
        wait(DWELL_TIME);
        present(CHILD_ID_WIND10M, S_WIND);
        wait(DWELL_TIME);
        present(CHILD_ID_GUST_DIR, S_WIND);
        wait(DWELL_TIME);
        present(CHILD_ID_GUST2M_DIR, S_WIND);
        wait(DWELL_TIME);
        present(CHILD_ID_GUST10M_DIR, S_WIND);
        wait(DWELL_TIME);
      }
      
      struct speedAndDir {    
       float uv;
       float Dv;
      };
      
      struct speedAndDir windvec(float speedArr[], float dirArr[], uint8_t size) {
        /*
         *
         *       Function to calculate the wind vector from time series of wind speed and direction.
         *       
         *       Parameters:
         *           - u: array of wind speeds [m s-1].
         *           - D: array of wind directions [degrees from North].
         *           
         *       Returning speedAndDir struct values:
         *           - uv: Vector wind speed [m s-1].
         *           - Dv: Vector wind direction [degrees from North].
         *
         */
        struct speedAndDir o;
        float ve = 0.0; // define east component of wind speed
        float vn = 0.0; // define north component of wind speed
      
        for (int i = 0; i < size; ++i) {
          ve += speedArr[i] * sin(dirArr[i] * PI / 180.0); // calculate sum east speed components
          vn += speedArr[i] * cos(dirArr[i] * PI / 180.0); // calculate sum north speed components
        }
        ve = - ve / size; // determine average east speed component
        vn = - vn / size; // determine average north speed component
        o.uv = sqrt(ve * ve + vn * vn); // calculate wind speed vector magnitude
        // Calculate wind speed vector direction
        float vdir = atan2(ve, vn);
        vdir = vdir * 180.0 / PI; // Convert radians to degrees
        if (vdir < 180) {
          o.Dv = vdir + 180.0;
        }
        else {
          if (vdir > 180.0) {
            o.Dv = vdir - 180;
          }
          else {
            o.Dv = vdir;
          }
        }
        o.uv = ((int) (o.uv * 10.0 + 0.5) / 10.0); // Round to one decimal
        o.Dv = (o.uv == 0.0) ? 0 : ((int) (o.Dv + 0.5)); // Round to integer
        return o;
      }
      
      void loop()
      {
        readIndex++;
        if (readIndex >= num1mReadings) {
          readIndex = 0;
        }
      
        /* 
         * Wind speed reading 
         */
        sensorValue = analogRead(ANEMOMETER_ANALOG_PIN); //Get a value between 0 and 1023 from the analog pin connected to the anemometer
        sensorValue = (sensorValue < wsMin) ? wsMin : sensorValue;
        windSpeed = (float)(sensorValue - wsMin)*windSpeedMax/(wsMax - wsMin);
        windSpeedReadings[readIndex] = windSpeed;
      
        Sprint(F("Reading: "));
        Sprint(readIndex);
        Sprint(F(", Wind speed sensor value: "));
        Sprint(sensorValue);
        Sprint(F(", wind speed: "));
        Sprint(windSpeed);
        Sprint(F(" m/s."));
      
        /* 
         * Wind vane reading 
         */
        const float dirTable[] PROGMEM = {0.0, 22.5, 45.0, 67.5, 90.0, 112.5, 135.0, 157.5, 180.0, 202.5, 225.0, 247.5, 270.0, 292.5, 315.0, 337.5};
        sensorValue = (windSpeed > 0) ? analogRead(WIND_VANE_ANALOG_PIN) : wdMin; //Get a value between 0 and 1023 from the analog pin connected to the wind vane
        sensorValue = (sensorValue < wdMin) ? wdMin : sensorValue;
      
        windDir = (sensorValue - wdMin)*337.5/(wdMax - wdMin); // This will be close but not exact.
        // Find the closest of the 16 predefined wind directions
        for (int i = 0; i < 16; ++i)
        {
          if (windDir < (dirTable[i] + 11.25)) {
            windDir = dirTable[i];
            break;
          }
        }
        windDirReadings[readIndex] = windDir;
      
        Sprint(F("\tWind direction sensor value: "));
        Sprint(sensorValue);
        Sprint(F(", wind direction: "));
        Sprint(windDir);
        Sprintln(F("°"));
      
        if (readIndex == num1mReadings - 1) {
          minute2Index++;
          minute2Index = (minute2Index >= num2mReadings) ? 0 : minute2Index;
          minute10Index++;
          minute10Index = (minute10Index >= num10mReadings) ? 0 : minute10Index;
          got2mins = (minute2Index == num2mReadings-1) ? true : got2mins; // One time switch
          got10mins = (minute10Index == num10mReadings-1) ? true : got10mins;
      
          cycleCountWindSpeed++;
          cycleCountWindGust++;
          cycleCountWindGustDir++;
          cycleCountWindDir++;
          cycleCountWindSpeed2m++;
          cycleCountWindGust2m++;
          cycleCountWindGustDir2m++;
          cycleCountWindDir2m++;
          cycleCountWindSpeed10m++;
          cycleCountWindGust10m++;
          cycleCountWindGustDir10m++;
          cycleCountWindDir10m++;
      
          struct speedAndDir o;
          o = windvec(windSpeedReadings, windDirReadings, num1mReadings);
          Sprint(F("\nWind vector calculation results: Speed: "));
          Sprint(o.uv);
          Sprint(F(" m/s"));
          Sprint(F(" \tDirection: "));
          Sprint(o.Dv);
          Sprintln(F("°\n"));
      
          float gust = 0;
          uint16_t gustDir = 0;
          for (int i = 0; i < num1mReadings; ++i)
          {
            if (windSpeedReadings[i] > gust)
              gust = windSpeedReadings[i];
              gustDir = windDirReadings[i];
          }
          gust = ((int) (gust * 10.0 + 0.5) / 10.0);
      
          windSpeedReadings10m[minute10Index] = windSpeedReadings2m[minute2Index] = o.uv;
          windDirReadings10m[minute10Index] = windDirReadings2m[minute2Index] = o.Dv;
          windGustReadings10m[minute10Index] = windGustReadings2m[minute2Index] = gust;
          windGustDirReadings10m[minute10Index] = windGustDirReadings2m[minute2Index] = gustDir;
      
          if ((o.uv != last_wspeed) or (cycleCountWindSpeed >= FORCE_TRANSMIT_CYCLE)) {
            cycleCountWindSpeed = 0;
            last_wspeed = o.uv;
            Sprint(F("Sending wind speed: "));
            Sprint(o.uv);
            Sprintln(F(" m/s"));
            send(msgWSpeed.set(o.uv, 1));
            wait(DWELL_TIME);
          }
          if ((gust != last_wgust) or (cycleCountWindGust >= FORCE_TRANSMIT_CYCLE)) {
            cycleCountWindGust = 0;
            last_wgust = gust;
            Sprint(F("Sending wind gust speed: "));
            Sprint(gust);
            Sprintln(F(" m/s"));
            send(msgWGust.set(gust, 1));
            wait(DWELL_TIME);
          }
          if ((o.Dv != last_wdirection) or (cycleCountWindDir >= FORCE_TRANSMIT_CYCLE)) {
            cycleCountWindDir = 0;
            last_wdirection = o.Dv;
            Sprint(F("Sending wind direction: "));
            Sprint(o.Dv);
            Sprintln(F("°"));
            send(msgWDirection.set(o.Dv, 0));
            wait(DWELL_TIME);
          }
          if ((gustDir != last_wgustdirection) or (cycleCountWindGustDir >= FORCE_TRANSMIT_CYCLE)) {
            cycleCountWindGustDir = 0;
            last_wgustdirection = gustDir;
            Sprint(F("Sending wind gust direction: "));
            Sprint(gustDir);
            Sprintln(F("°"));
            send(msgWGustDir.set(gustDir, 0));
            wait(DWELL_TIME);
          }
          // Do the 2 minute average but only if we have been running for 2 minutes or more.
          if (got2mins) {
            o = windvec(windSpeedReadings2m, windDirReadings2m, num2mReadings);
            Sprint(F("\n==========2 minute wind vector calculation results: Speed: "));
            Sprint(o.uv);
            Sprint(F(" m/s"));
            Sprint(F(" \tDirection: "));
            Sprint(o.Dv);
            Sprintln(F("°\n"));
      
            gust = gustDir = 0;
            for (int i = 0; i < num2mReadings; ++i)
            {
              if (windGustReadings2m[i] > gust)
                gust = windGustReadings2m[i];
                gustDir = windDirReadings2m[i];
            }
            gust = ((int) (gust * 10.0 + 0.5) / 10.0);
      
            if ((o.uv != last_wspeed2m) or (cycleCountWindSpeed2m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindSpeed2m = 0;
              last_wspeed2m = o.uv;
              Sprint(F("Sending 2 min wind speed: "));
              Sprint(o.uv);
              Sprintln(F(" m/s"));
              send(msgWSpeed2m.set(o.uv, 1));
              wait(DWELL_TIME);
            }
            if ((gust != last_wgust2m) or (cycleCountWindGust2m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindGust2m = 0;
              last_wgust2m = gust;
              Sprint(F("Sending 2 min wind gust speed: "));
              Sprint(gust);
              Sprintln(F(" m/s"));
              send(msgWGust2m.set(gust, 1));
              wait(DWELL_TIME);
            }
            if ((o.Dv != last_wdirection2m) or (cycleCountWindDir2m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindDir2m = 0;
              last_wdirection2m = o.Dv;
              Sprint(F("Sending 2 min wind direction: "));
              Sprint(o.Dv);
              Sprintln(F("°"));
              send(msgWDirection2m.set(o.Dv, 0));
              wait(DWELL_TIME);
            }
            if ((gustDir != last_wgustdirection2m) or (cycleCountWindGustDir2m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindGustDir2m = 0;
              last_wgustdirection2m = gustDir;
              Sprint(F("Sending 2 min wind gust direction: "));
              Sprint(gustDir);
              Sprintln(F("°"));
              send(msgWGust2mDir.set(gustDir, 0));
              wait(DWELL_TIME);
            }
          }
      
          // Do the 10 minute average but only if we have been running for 10 minutes or more.
          if (got10mins) {
            o = windvec(windSpeedReadings10m, windDirReadings10m, num10mReadings);
            Sprint(F("\n#############10 minute wind vector calculation results: Speed: "));
            Sprint(o.uv);
            Sprint(F(" m/s"));
            Sprint(F(" \tDirection: "));
            Sprint(o.Dv);
            Sprintln(F("°\n"));
      
            gust = gustDir = 0;
            for (int i = 0; i < num10mReadings; ++i)
            {
              if (windGustReadings10m[i] > gust)
                gust = windGustReadings10m[i];
                gustDir = windDirReadings10m[i];
            }
            gust = ((int) (gust * 10.0 + 0.5) / 10.0);
      
            if ((o.uv != last_wspeed10m) or (cycleCountWindSpeed10m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindSpeed10m = 0;
              last_wspeed10m = o.uv;
              Sprint(F("Sending 10 min wind speed: "));
              Sprint(o.uv);
              Sprintln(F(" m/s"));
              send(msgWSpeed10m.set(o.uv, 1));
              wait(DWELL_TIME);
            }
            if ((gust != last_wgust10m) or (cycleCountWindGust10m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindGust10m = 0;
              last_wgust10m = gust;
              Sprint(F("Sending 10 min wind gust speed: "));
              Sprint(gust);
              Sprintln(F(" m/s"));
              send(msgWGust10m.set(gust, 1));
              wait(DWELL_TIME);
            }
            if ((o.Dv != last_wdirection10m) or (cycleCountWindDir10m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindDir10m = 0;
              last_wdirection10m = o.Dv;
              Sprint(F("Sending 10 min wind direction: "));
              Sprint(o.Dv);
              Sprintln(F("°"));
              send(msgWDirection10m.set(o.Dv, 0));
              wait(DWELL_TIME);
            }
            if ((gustDir != last_wgustdirection10m) or (cycleCountWindGustDir10m >= FORCE_TRANSMIT_CYCLE)) {
              cycleCountWindGustDir10m = 0;
              last_wgustdirection10m = gustDir;
              Sprint(F("Sending 10 min wind gust direction: "));
              Sprint(gustDir);
              Sprintln(F("°"));
              send(msgWGust10mDir.set(gustDir, 0));
              wait(DWELL_TIME);
            }
          }
        }
        
        wait(WAIT_TIME);
      }
      

      0_1533549913325_graph.png

      Feel free to improve the code if you want. It's occupying a great deal of dynamic memory. I guess that the wind directions could be stored in a uint16_t type instead (multiplied by 10) but I haven't done that.

      0_1533550317138_ws.JPG

      The arrangement above is temporary. I just used what I had available.

      posted in My Project
      รอเรือ
      รอเรือ
    • RE: 💬 Soil Moisture Sensor

      How would you guys protect one of these capacitive soil moisture sensors from moisture in case the probe shall be buried 20 cm deep in the soil outdoors.

      The way they are made now, they may only be used in a indoor flower pot and even then there is a risk that the probes electronic components will be drowned in water while watering your flowers. Ideally, they should be water proof from the beginning, that's what I think.

      Anyway, now I have a few of them and I intend to do a solar powered a multi depth soil moisture sensor using capacitive soil moisture sensors at various depths.

      So, how to protect them?

      I have an idea but I'm not sure it's working: Put it partly inside a plastic tube and cover the electronics with 2 component expoxy glue. ...

      EDIT 1 : maybe silicone rubber would work...
      EDIT 2 : Adding a photo of an untested prototype. Plastic housing filled with construction silicone rubber!
      0_1529322106621_sensor.jpg

      EDIT 3: Prototype sensor works great. (At least for the moment. I hope it will last several years.)
      Cheers!

      posted in Announcements
      รอเรือ
      รอเรือ
    • RE: Where to buy components now if you happen to live in Sweden

      Sorry for the monologue!

      Today I found a seller on E-bay that has most of the things that I will need. The new strategy is to buy many items from a single seller in a single transaction. Kindly asking him to put everything inside one box (We'll see if GONG TAO manages to do that)

      The sellers store: https://www.ebay.com/str/modulefans

      There are many other stores too of course but I think the above mentioned is quite good.

      Cheers!

      posted in General Discussion
      รอเรือ
      รอเรือ
    • RE: 💬 Easy/Newbie PCB for MySensors

      Hello @sundberg84

      What if feeding a Pro Mini 3.3V (EasyPCB Nrf24l01+ edition rev 10) with regulated power on RAW. (I have 5 VDC). I guess I can feed the radio via the VCC terminal instead of using an external voltage regulator. Can the EasyPCB be used in such a setup?

      Edit: To answer my own question. I should RTFM 👊

      It states clearly that:

      "(If you are using regulated 3.3v, use 5v instructions but skip the voltage regulator and bypass this with a jumper between Vin and Vout"

      Thanks anyway!

      posted in OpenHardware.io
      รอเรือ
      รอเรือ
    • RE: Misol rain gauge tipping bucket rain amount

      @hek

      I let 1126-202 grams water slowly flow into the 55 cm2 gauge and it generated 475 tips.

      That gives me 0.3537 mm/tip. I'll go with that. ☺

      posted in Hardware
      รอเรือ
      รอเรือ
    • RE: !TSM:FPAR:NO REPLY

      My problem was caused by the fact that the radio was inserted into a socket. The 4.7uF stabilizing capacitor was put on the main board side of the socket. Moving the capacitor to the radio board or just soldering the radio to the main board (without using a socket) solved the problem. So, don't use a socket between the radio and the stabilizing capacitor.

      Another interesting thing is that by putting a finger onto the antenna also solved the problem. I could use that method for testing all my radios (using the socket) before permanently soldering them onto the main board.

      posted in Troubleshooting
      รอเรือ
      รอเรือ
    • RE: Node behavior after connection lost

      @hek said:

      It takes a few failed transmission before it tries to "find new parent". Not sure what happended here without seeing the node log.

      @mfalkvidd said:

      @รอเรือ which version are you using? 2.0 has a problem with nodes that go back to sleep too soon after a failed send. This is fixed in the development version. See https://github.com/mysensors/MySensors/pull/558 for details.

      Thanks guys! Well, I'm on 2.0.0. I'm not the "adventurous type" so I'm not on the development version if You get my point (ha ha).

      It's good to know that there exists some healing mechanisms in the communication. I might wait for the next stable release or I might build me a dedicated "MySensor : RepeaterNode" with an external antenna to facilitate the communication with my upcoming battery powered nodes in my garden and for the lawn mower that really must be automated soon.

      Hej tjolahopp! (Cheers!)

      posted in General Discussion
      รอเรือ
      รอเรือ
    • RE: NRF24L01+ range of only few meters

      I'm currently in the process of trying to figure out why one of my battery powered nodes isn't working very well with a newly purchased NRF24L01+PA+LNA module. I've shielded it as described in earlier posts. There is plenty of pure power in the batteries.

      Just as in the case for @pkjjneal it works well only if I'm touching the antenna with a finger.

      I decided to look inside the antenna:
      0_1533729640287_DSC_1916.JPG

      As you see above, it starts with an antenna cable that leads to a half wave dipole (where the antenna element is of about 1/4 wave length) and there is a "sleeve balun" going back over the cable . I can find no ground plane though. The problem that I can see is that the antenna length is 27 mm where it should optimally be 28.8 mm.

      Now, if I remove the antenna completely my node works quite well. At least better than if I use the original antenna unmodified.

      If I insert a wire (DIY antenna made by a paper clip) extending 121 mm out of the antenna sockets forming a full wave length antenna things work great.

      I also modified the original antenna so that the antenna element becomes 28.8 mm. It works a bit better but it's far from perfect and communication errors are shown in the log.

      As the final test, I added a nice ground plane to the original antenna and now it works really perfect!
      0_1533729823658_DSC_1917.JPG

      So what can I learn from this?

      My test rig is an EasyPCB powered with batteries. I'm quite sure that my NRF24L01+PA+LNA module used in another scenario, for example connected to a Arduino Nano fed by a FTDI connector could actually work. It's because it would create a different environment. The antenna will work in relation to what it's connected to, shielding the grounding, and surrounding objects. Capacitive and inductive reactances are involved in mysterious ways.

      Anyway. My conclusion is that the two original antennas I have are not working very good. They obviously have the wrong length just a little bit, and I'd say that the the way the antenna is constructed with the sleeve balun and no ground plane, doesn't seem to work well. At least not here.

      I'll do some more experimenting with making my own antennas. Starting with taking apart an original antenna is not so bad, I can solder anything (solderable) onto the cable.

      Cheers!

      From wikipedia:

      Sleeve balun
      At VHF frequencies, a sleeve balun can also be built to remove feeder radiation.

      Another narrow-band design is to use a λ/4 length of metal pipe. The coaxial cable is placed inside the pipe; at one end the braid is wired to the pipe while at the other end no connection is made to the pipe. The balanced end of this balun is at the end where no connection is made to the pipe. The λ/4 conductor acts as a transformer, converting the zero impedance at the short to the braid into an infinite impedance at the open end. This infinite impedance at the open end of the pipe prevents current flowing into the outer coax formed by the outside of the inner coax shield and the pipe, forcing the current to remain in the inside coax.

      posted in Hardware
      รอเรือ
      รอเรือ
    • RE: Build a reliable power supply chain

      Thanks @Mathea90 for bringing up this interesting subject.

      It's sure difficult I believe to find a power supply for various Arduino projects that's both reliable and has a low cost.

      @sundberg84 made a nice breakout PCB for the HLK-PM01, that "was considered at that time (2015-2017) the best AC to DC 5v module option (within reasonable price range)."

      I hesitate though to build them due to that they will not be certified and if I cause a fire at my home, my home insurance may not cover the damages that can arise. With that being said, I'm quite sure that the HLK-PM01-breakout-board is by far much more safer than many wall plug chargers marked with CE (China Export).

      It would be nice to have a breakout board that can turn the power from any random 5V wall plug charger into something that's clean and ripple free with a good margin to feed NRF24L01+ nodes with. With such a board I wouldn't have to be involved in working directly with 230V AC.

      Meanwhile I'll probably try to build me a couple of LC filters using prototype breadboards.

      Thanks again and keep up the good work!

      posted in Troubleshooting
      รอเรือ
      รอเรือ
    • RE: CDEBYTE's new NRF24 modules are great! (and cheap)

      @yveaux said in CDEBYTE's new NRF24 modules are great! (and cheap):

      This patch makes both regular and amplified nRF24 modules work correctly!

      Dear @Yveaux

      Thanks for all the work you've put into investigating this issue.

      I have a different brand of the Nano IO Shield but the quality is equally very low. I guess I'll need to inspect them carefully before I use them. I guess I have 10 of them and I will try to apply the HW patch you've suggested but I'm not sure I'll be able to make it, I don't have any SMD resistors and they are to small to work with for me. I'll need to give it a try anyway.

      Thanks again and merry christmas btw 🎅

      posted in General Discussion
      รอเรือ
      รอเรือ
    • RE: 💬 Building a MQTT Gateway

      I rebuilt my serial gateway to a MQTT gateway. FWIW I had to connect 5V to my WizNET (W5100) Ethernet module (3.3V did not work) I couldn't make DHCP work so I used a fixed IP. Finally I had to replace the capacitor over the radio power feed from 4.7 uF capacitor to a 100 uF capacitor (That made a big difference!). Works great now.

      posted in Announcements
      รอเรือ
      รอเรือ
    • RE: Serial Gateway w/ MQTT using nodeJS

      Anyway, I put some effort in this because I think that the Serial-to-MQTT gateway is actually the ultimate gateway for MySensors. It's very easy to build and it's versatile because it uses MQTT which in many cases will eliminate the use of more or less buggy add-ons for different home automation systems. It's my hope that the team would like to consider to add it as a new gateway type.

      I used the code from @barduino as a starting point but there has been many changes to it. Here it goes:

      /* Serial Gateway w/ MQTT using nodeJS, originally written by barduino https://forum.mysensors.org/user/barduino
       * Rewritten by รอเรือ
       *
       * Copyright: Unknown
       *
       * MySensors forum topic: https://forum.mysensors.org/topic/3042/serial-gateway-w-mqtt-using-nodejs
       *
       * Using:
       *		serialport -npm: https://www.npmjs.com/package/serialport
       *		mqtt -npm: https://www.npmjs.com/package/mqtt#client
       */
      
      // Custom settings
      var serial_port = '/dev/ttyUSBmys';
      var serial_baud_rate = 115200;
      var mqtt_host     = 'XXXXXXXX';
      var mqtt_port     =  1883;
      var mqtt_subscribe_topic = 'mysensors-in';
      var mqtt_publish_topic = 'mysensors-out';
      var mqtt_username =  '';
      var mqtt_password =  '';
      var mqtt_client_id = 'mysensors_' + Math.random().toString(16).substr(2, 8);
      const DEBUG = false;
      
      // LIBS
      const SerialPort = require('serialport');
      const Readline = require('@serialport/parser-readline')
      const mqtt = require('mqtt');
      
      // MQTT CLIENT OPTIONS
      var mqtt_Options = {
      	port: mqtt_port,
      	keepalive: 60, //seconds, set to 0 to disable
      	clientId: mqtt_client_id,
      	protocolId: 'MQTT', //'MQTT', 'mqtts', 'tcp', 'tls', 'ws', 'wss'. 
      	//protocolVersion: 4,
      	clean: true, //set to false to receive QoS 1 and 2 messages while offline
      	reconnectPeriod: 5000, // milliseconds, interval between two reconnections
      	connectTimeout: 30 * 1000, //milliseconds, time to wait before a CONNACK is received
      	//username: mqtt_username, //the username required by your broker, if any
      	//password: mqtt_password, //the password required by your broker, if any
      	will: {topic: mqtt_publish_topic, payload: mqtt_client_id +' disconnected', qos: 1, retain: false }
      }
      
      // Define the port and a parser
      const port = new SerialPort(serial_port, { baudRate: serial_baud_rate });
      const parser = port.pipe(new Readline({ delimiter: '\n' }))
      
      // START MQTT
      if (DEBUG) console.log('Starting MQTT...');
      var mqtt_client = mqtt.connect('mqtt://'+mqtt_host, mqtt_Options);
      
      mqtt_client.on('connect', function () {
      	if (DEBUG) console.log('Subscribing MQTT...');
      	mqtt_client.subscribe(mqtt_subscribe_topic+'/#');
      
      	if (DEBUG) console.log('Publish MQTT...'); 
      	mqtt_client.publish(mqtt_publish_topic, 'mqtt client '+mqtt_client_id+' started at '+ new Date());
      })
      
      parser.on('data', function (data) {
      	if (DEBUG) console.log('Data:', data);
      	mqttPublish(data);
      });
      
      // MQTT INCOMING
      mqtt_client.on('message', function (topic, message) {
      	var m = topic.toString();
      	m = m.replace(mqtt_subscribe_topic, '');
      	m = m.split('/').join(';');
      	m = m + ';' + message.toString();
      	port.write('' + m + '\n', function(err) {
      		if (err) {
      		  return console.log('Error on write: ', err.message);
      		}
      		if (DEBUG) console.log('INCOMING MQTT: ' + topic + ':' + message.toString());
      	});
      });
      
      // MQTT OUTGOING
      function mqttPublish(data){
      	var topic = mqtt_publish_topic+'/';
      	var params = data.split(';');
      	topic = topic + params[0] + '/';
      	topic = topic + params[1] + '/';
      	topic = topic + params[2] + '/';
      	topic = topic + params[3] + '/';
      	topic = topic + params[4] + '';
      	var payload = params[5];
      	mqtt_client.publish(topic,payload);
      	if (DEBUG) console.log('OUTGOING MQTT: ' + topic + ' ' + payload);
      }
      

      Use pm2 to keep it running!

      Cheers!!

      Very simple hardware:

      0_1533390263234_DSC_1915.JPG

      posted in Development
      รอเรือ
      รอเรือ
    • RE: SPI conflict: nRF24L01+ wants the same pins as my MAX7219 LED dot matrix display

      @mfalkvidd Thanks a lot!

      I just made some tests and it looks promising. 😁 😁 😁

      posted in General Discussion
      รอเรือ
      รอเรือ
    • RE: 💬 Soil Moisture Sensor

      @robkuipers

      Your code will fail compiling in Arduino 1.8.5 (mysensors 2.2.0) with the following errors:

      /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino: In function 'void before()':
      /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:112:114: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
         sensors[0] = { SENSOR1_ROD1_DIGITAL, SENSOR1_ROD1_ANALOG, SENSOR1_ROD2_DIGITAL, SENSOR1_ROD2_ANALOG, -1, false };
                                                                                                                        ^
      /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:112:14: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
         sensors[0] = { SENSOR1_ROD1_DIGITAL, SENSOR1_ROD1_ANALOG, SENSOR1_ROD2_DIGITAL, SENSOR1_ROD2_ANALOG, -1, false };
                    ^
      /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:116:114: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
         sensors[1] = { SENSOR2_ROD1_DIGITAL, SENSOR2_ROD1_ANALOG, SENSOR2_ROD2_DIGITAL, SENSOR2_ROD2_ANALOG, -1, false };
                                                                                                                        ^
      /mnt/data/Dropbox/UTV/Arduino/SoilMoisture/SoilMoisture.ino:116:14: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
         sensors[1] = { SENSOR2_ROD1_DIGITAL, SENSOR2_ROD1_ANALOG, SENSOR2_ROD2_DIGITAL, SENSOR2_ROD2_ANALOG, -1, false };
                    ^
      

      So the following code need tobe changed to something valid

      sensors[0] = { SENSOR1_ROD1_DIGITAL, SENSOR1_ROD1_ANALOG, SENSOR1_ROD2_DIGITAL, SENSOR1_ROD2_ANALOG, -1, false };
      
      	sensors[1] = { SENSOR2_ROD1_DIGITAL, SENSOR2_ROD1_ANALOG, SENSOR2_ROD2_DIGITAL, SENSOR2_ROD2_ANALOG, -1, false };
      
      

      I'm not a c++ guy so I can't tell what needs to be done. Maybe you or someone else would like to help out?

      Cheers!

      EDIT: After removing the file platform.txt for solving another problem (as suggested here) The problem above vanished. So strange. But it works now so... 😎 😎 😎

      posted in Announcements
      รอเรือ
      รอเรือ
    • RE: Serial Gateway w/ MQTT using nodeJS

      @electrik

      There are already plenty of instructions on how you install Node.js and it would be beyond the scope of this topic to do so here. There are so many variables such as operating systems and so on to take into account.

      After installing Node.js you need to install the Node serialport and Node mqtt.

      pm2 is a very nice process manager for Node.js that you can use to make sure that your node scripts always is running. It's highly recommended and will make your life easier.

      In my own installation, I created a sub directory ~/node_modules/serialgwmqtt/ where I saved the app.js script file. Then cd ~/node_modules/serialgwmqtt/ followed by node app.js to make sure that everything works fine.

      When it does (works fine) you should make it autostart. I added my script to pm2 with the following command: pm2 start app.js --name "serialgwmqtt" (while still in the same directory). check hat it's working by issuing pm2 list

      I might have been running npm installor something similar also. I'm actually not so clever with these things and I'm sure my instructions can be simplified. The script should also be uploaded so some place to make it available for installing with a simple command. Maybe someone else more node.js-talented person want's to help here.

      I hope I have't forgotten anything, it's quite straight forward.

      Things are running rock solid here.

      posted in Development
      รอเรือ
      รอเรือ
    • Moisture penetrates my outdoor enclosures...

      Hi there! I have a few moisture safe enclosures for outdoor sensor. At least, that's what I thought but inspecting one of them today due to failure (see attached image below) made me aware that they are not moisture safe at all. They even seem to suck moisture from the outside and store it inside the box.

      I guess that the plastic that the box is made of isn't moisture proof.

      If some of you guys have experience to share with me on this topic I'd appreciate it a lot. I'd like to rebuild this repeater node using an enclosure that does not allow moisture to enter it and eventually destroy the electronics. Stability of operation and an enclosure that resists the environmental challenges that it will face has a much higher priority than the cost of the enclosure.

      62caf6c3-0a95-4524-83dc-db853ac6009f-image.png

      Cheers!

      posted in General Discussion
      รอเรือ
      รอเรือ
    • RE: 💬 Soil Moisture Sensor

      @alowhum

      How are your capacitive sensors wired to the board?

      posted in Announcements
      รอเรือ
      รอเรือ