Navigation

    OpenWindMap

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    Format messages Sigfox de Arduino vers OpenWindMap

    Arduino
    5
    11
    2169
    Loading More Posts
    • 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.
    • C
      CAMBON last edited by nicolas

      Bonjour.
      Un arduino MKRFox1200,un anémomètre Davis (ceux de nos vielles balises FFVL), un petit panneau solaire et un accu et je me suis lancé.
      Voici un début de programme qui fonctionnait avant que je me décourage et je voyais mes données arriver sur SigFox.
      Je ne suis pas très bon programmeur alors j'ai fait comme toujours avec mes Arduinos, j'ai utilisé des bouts de code déjà faits.
      Hors je ne sais pas trop comment formater mes données pour qu'elles correspondent à L'API openwindmap et surtout à mettre tout ça en lien.
      Concernant les mesures, si jamais je pouvais "coller " aux données envoyées par un pioupiou V1 ce serait super (fréquence des mesures, calcul des valeurs min, moy et max).
      Voilà je poste le code brut tel que je l'ai abandonné il y a 2 ans:

      // -------------------------------------------------------------------------
      // This project sends Davis sensor windspeed and direction through Sigfox network
      // Start: 07.12.2017
      //  Author: Cédric CAMBON
      //  With the original code from
      //  Author: Antoine de Chassey
      //  Code: https://github.com/AntoinedeChassey/MKRFOX1200_weather_station
      //  and 
      //  cactus.io
      //  http://cactus.io/hookups/weather/anemometer/davis/hookup-arduino-to-davis-anemometer
      
      //Hardware: Arduino MKRFox1200 + Davis anemometer
      // --------------------------------------------------------------------------
      
      #include "SigFox.h"
      #include "ArduinoLowPower.h"
      #include "TimerOne.h"          // Timer Interrupt set to 2 second for read sensors
      #include <math.h>
      
      
      // Connect Red Wire to ground
      // Connect Black wire to Digital input 2 with a 4k7 resistor pull up to 3,3V
      // Connect Yellow Wire to 3,3V
      // Connect Green Wire to Anbalog input 4
      
      
      #define SpeedPin        (2)                // What digital pin we're connected to
      #define DirectionPin    (A4)
      
      #define SLEEPTIME     10 * 60 * 1000   // Set the delay to 10 minutes (10 min x 60 seconds x 1000 milliseconds)
      
      #define UINT16_t_MAX  65536
      #define INT16_t_MAX   UINT16_t_MAX/2
      
      int16_t VaneValue;       // raw analog value from wind vane
      int16_t Direction;       // translated 0 - 360 direction
      int16_t LastValue;
      
      volatile bool IsSampleRequired;       // this is set true every 2.5s. Get wind speed
      volatile unsigned int  TimerCount;    // used to determine 2.5sec timer count
      volatile unsigned long Rotations;     // cup rotation counter used in interrupt routine
      volatile unsigned long ContactBounceTime;  // Timer to avoid contact bounce in interrupt routine
      
      int16_t Speed;        // speed kilometers per hour
      
      typedef struct __attribute__ ((packed)) sigfox_message {
              int16_t moduleTemperature;
              int16_t WindSpeed;
              uint16_t WindDirection;
              uint8_t lastMessageStatus;
      } SigfoxMessage;
      
      // Stub for message which will be sent
      SigfoxMessage msg;
      
      
      
      void setup() {
             
      LastValue = 0;
        
        IsSampleRequired = false;
        TimerCount = 0;
        Rotations = 0;   // Set Rotations to 0 ready for calculations
      
        pinMode(SpeedPin, INPUT);
        attachInterrupt(digitalPinToInterrupt(SpeedPin), isr_rotation, FALLING);
        
        // Setup the timer intterupt
        Timer1.initialize(500000);
        Timer1.attachInterrupt(isr_timer);
      
      
              if (!SigFox.begin()) {
                      // Something is really wrong, try rebooting
                      // Reboot is useful if we are powering the board using an unreliable power source
                      // (eg. solar panels or other energy harvesting methods)
                      reboot();
              }
      
              // Send module to standby until we need to send a message
              SigFox.end();
      }
      
      void loop() {
        float t = 0;
             
              getWindDirection();
              // Only update the display if change greater than 5 degrees. 
        if(abs(Direction - LastValue) > 5)
        { 
           LastValue = Direction;
        }
       
        msg.WindDirection = Direction;
      
       if(IsSampleRequired)
        {
           // convert to km/h using the formula V=P(2.25 *1.609/T)
           // V = P *1.4481
           Speed = Rotations * 1.4481;
           Rotations = 0;   // Reset count for next sample
           
           IsSampleRequired = false; 
        }
      
        msg.WindSpeed= Speed;
        
              // Start the module
              SigFox.begin();
              // Wait at least 30ms after first configuration (100ms before)
              delay(100);
      
              // We can only read the module temperature before SigFox.end()
              t = SigFox.internalTemperature();
              msg.moduleTemperature = convertoFloatToInt16(t, 60, -60);
      
              // Clears all pending interrupts
              SigFox.status();
              delay(1);
      
              SigFox.beginPacket();
              SigFox.write((uint8_t*)&msg, 12);
      
              msg.lastMessageStatus = SigFox.endPacket();
      
              SigFox.end();
              //Sleep for 10 minutes
              LowPower.sleep(SLEEPTIME);
      }
      
      void reboot() {
              NVIC_SystemReset();
              while (1) ;
      }
      
      
      // isr routine fr timer interrupt
      void isr_timer() {
        
        TimerCount++;
        
        if(TimerCount == 5)
        {
          IsSampleRequired = true;
          TimerCount = 0;
        }
      }
      
      // This is the function that the interrupt calls to increment the rotation count
      void isr_rotation ()   {
      
        if ((millis() - ContactBounceTime) > 15 ) {  // debounce the switch contact.
          Rotations++;
          ContactBounceTime = millis();
        }
      
      }
      
      // Get Wind Direction
      void getWindDirection() {
       
         VaneValue = analogRead(DirectionPin);
         Direction = map(VaneValue, 0, 1023, 0, 360);
         
         if(Direction > 360)
           Direction = Direction - 360;
           
         if(Direction < 0)
           Direction = Direction + 360;
        }
      
        int16_t convertoFloatToInt16(float value, long max, long min) {
              float conversionFactor = (float) (INT16_t_MAX) / (float)(max - min);
              return (int16_t)(value * conversionFactor);
      }
      
      

      Voilà. Je n'ai pas remis le nez dedans depuis 2 ans mais je m'y remets doucement. J'ai une version avec des timers mais pour optimiser la consommation j'ai préféré faire déjà faire une version de mesure continue pour regarder la conso et insérer plus tard des mises en veille...
      Si jamais quelqu'un (Nicolas par exemple...) veut bien me renseigner, je suis pas sur d'avoir le courage de fouiller dans le code de la PiouPiou pour avoir ces infos.
      A bientôt.

      luc2T 1 Reply Last reply Reply Quote 0
      • luc2T
        luc2T @CAMBON last edited by

        @CAMBON
        courage, il en faut, et tous les apports partagés sont bienvenus. on encourage ... 😉

        1 Reply Last reply Reply Quote 0
        • C
          CAMBON last edited by

          Ah je me suis trompé, j'ai mis le mauvais Code avec le timer et trop tard pour faire un edit, voici le bon:

          #include <math.h>
          #include "RunningAverage.h"
          
          
          // Connect Red Wire to ground
          // Connect Black wire to Digital input 2 
          // Connect Yellow Wire to 3,3V
          // Connect Green Wire to Anbalog input 4
          
          
          #define SpeedPin        (3)                // What digital pin we're connected to
          #define DirectionPin    (A4)
          #define Sample_qty  60                   //Sample qty expected before sending message
          #define Sample_Time 10000                  //Time for Windspeed measurement
          
          
          
          #define UINT16_t_MAX  65536
          #define INT16_t_MAX   UINT16_t_MAX/2
          
          int16_t VaneValue;       // raw analog value from wind vane
          int16_t Direction;       // translated 0 - 360 direction
          int16_t LastValue;
          int16_t Sample_count;
          
          volatile unsigned long Rotations;     // cup rotation counter used in interrupt routine
          volatile unsigned long ContactBounceTime;  // Timer to avoid contact bounce in interrupt routine
          float Speed;        // speed kilometers per hour
          
          
          typedef struct __attribute__ ((packed)) sigfox_message {
                  int16_t WindSpeed;
                  int16_t WindSpeedMax;
                  int16_t WindSpeedMin;
                  uint16_t WindDirection;
                  uint8_t lastMessageStatus;
          } SigfoxMessage;
          
          // Stub for message which will be sent
          SigfoxMessage msg;
          
          RunningAverage Spedd_Av(Sample_qty);
          RunningAverage Direction_Av(Sample_qty);
          
          void setup() {
          Sample_count = 0;       
          LastValue = 0; 
          Spedd_Av.clear(); // explicitly start clean 
          Direction_Av.clear();
          
          pinMode(SpeedPin, INPUT_PULLUP);
            attachInterrupt(digitalPinToInterrupt(SpeedPin), isr_rotation, FALLING);
           
                  if (!SigFox.begin()) {
                          // Something is really wrong, try rebooting
                          // Reboot is useful if we are powering the board using an unreliable power source
                          // (eg. solar panels or other energy harvesting methods)
                          reboot();
                  }
          
                  // Send module to standby until we need to send a message
                  SigFox.end();
          }
          
          void loop() {
            float t = 0; //???????????????????????????
            for (int i=0; i <= Sample_qty; i++)     
            {
              getSamples();
              
            }
          
            msg.WindSpeed = convertoFloatToInt16(Spedd_Av.getAverage(), 60, -60);; //
            msg.WindDirection = Direction_Avn.getAverage();
          
            
              
            
                  
                  
                  // Start the module
                  SigFox.begin();
                  // Wait at least 30ms after first configuration (100ms before)
                  delay(100);
          
                  // We can only read the module temperature before SigFox.end()
                  t = SigFox.internalTemperature();
                  msg.moduleTemperature = convertoFloatToInt16(t, 60, -60);
          
                  // Clears all pending interrupts
                  SigFox.status();
                  delay(1);
          
                  SigFox.beginPacket();
                  SigFox.write((uint8_t*)&msg, 12);
          
                  msg.lastMessageStatus = SigFox.endPacket();
          
                  SigFox.end();
                  
          }
          
          void reboot() {
                  NVIC_SystemReset();
                  while (1) ;
          }
          
          
          
          
          // This is the function that the interrupt calls to increment the rotation count
          void isr_rotation ()   {
          
            if ((millis() - ContactBounceTime) > 15 ) {  // debounce the switch contact.
              Rotations++;
              ContactBounceTime = millis();
            }
          }
          
          //Get Speed and direction values
          void getSamples () {
          
          
          //Get Wind Speed
            Rotations = 0;   // Set Rotations to 0 ready for calculations
            interrupts(); // Enables interrupts 
            delay (Sample_Time); // Wait n seconds to average 
            noInterrupts(); // Disable interrupts 
            Speed = (Rotations * 3.621015)/ Sample_Time;
            Speed_Av.addValue(Speed); //Add value to Speed array
          
          
          // Get Wind Direction 
             VaneValue = analogRead(DirectionPin);
             Direction = map(VaneValue, 0, 1023, 0, 360);
             if(Direction > 360)
               Direction = Direction - 360;
             if(Direction < 0)
               Direction = Direction + 360;
             Direction_Av.addValue(Direction); //Add value to Direction array
          
          }
          
            int16_t convertoFloatToInt16(float value, long max, long min) {
                  float conversionFactor = (float) (INT16_t_MAX) / (float)(max - min);
                  return (int16_t)(value * conversionFactor);
          }
          
          

          Je continue à travailler dessus.

          1 Reply Last reply Reply Quote 0
          • nicolas
            nicolas last edited by nicolas

            Voici le code que tu peux utiliser.
            Avec ça, je pourrai te connecter facilement à notre backend.

            //  pour transmettre 2 périodes / message :
            // message de 8 bytes
            typedef struct __attribute__ ((packed)) sigfox_wind_message {
                    int8_t speedMin[2];
                    int8_t speedAvg[2];
                    int8_t speedMax[2];
                    int8_t directionAvg[2];
            } SigfoxWindMessage;
            
            // /!\ avec ce format, il faut transmettre
            // impérativement deux périodes de 5 minutes
            // xxx[0] -> de T-10 à T-5 minutes
            // xxx[1] -> de T-5 minutes à T
            // T étant l'heure de transmission
            
            //  alternativement, pour transmettre 1 période / message :
            // à la fréquence que vous voulez
            // (maximum toute les 10 minutes)
            
            // message de 4 bytes
            typedef struct __attribute__ ((packed)) sigfox_wind_message {
                    int8_t speedMin;
                    int8_t speedAvg;
                    int8_t speedMax;
                    int8_t directionAvg;
            } SigfoxWindMessage;
            
            // pour l'encodage du vent sur 1 byte
            // (code original du Pioupiou)
            uint8_t encodeWindSpeed (float speedKmh) {
              uint8_t encodedSpeed;
              if (speedKmh < 10.) {
                // 0 to 9.75 kmh : 0.25 km/h resolution
                encodedSpeed = (uint8_t)(float)(speedKmh * 4. + 0.5);
              } else if (speedKmh < 80.) {
                // 10 to 79.5 kmh  : 0.5 km/h resolution
                encodedSpeed = (uint8_t)(float)(speedKmh * 2. + 0.5) + 20;
              } else if (speedKmh < 120.) {
                // 80 to 119 kmh  : 1 km/h resolution
                encodedSpeed = (uint8_t)(float)(speedKmh + 0.5) + 100;
              } else if (speedKmh < 190.) {
                // 120 to 188 kmh  : 2 km/h resolution
                encodedSpeed = (uint8_t)(float)(speedKmh / 2. + 0.5) + 160;
              } else {
                // 190 or + : out of range
                encodedSpeed = 0xFF;
              }
              return encodedSpeed;
            }
            
            // pour l'encodage de la direction sur 1 byte
            uint8_t encodeWindDirection (float direction) { // radians
              direction = direction / M_PI * 180.;   // radians to degrees
              if (direction < 0.) direction += 360.;  // -180-180 to 0-360+
            
              // encode with 2° precision
              // add 0.5 for rounding when converting from (float) to (int)
              return (uint8_t)(float)(direction / 2. + 0.5);
            }
            
            dam74 1 Reply Last reply Reply Quote 0
            • C
              CAMBON last edited by

              Merci Nicolas. Je vais tester ça.

              1 Reply Last reply Reply Quote 0
              • nicolas
                nicolas last edited by

                Pour ensuite connecter l'appareil au réseau OpenWindMap, faîtes une demande ici :
                https://forum.openwindmap.org/topic/221/connecter-un-arduino-mkr-fox-à-openwindmap/1

                ? 1 Reply Last reply Reply Quote 0
                • ?
                  Guest @nicolas last edited by

                  @nicolas j'ai réalisé il y a 2ans
                  Une station météo connecté
                  Avec un esp8266
                  Qui fonctionne aussi en 3.3v mais je l'alimente avec un ancien chargeur de portable micro usb
                  Il se connect au wifi tout seul et transmet les données sur thing view
                  Et j'ai connecté dessus 2 sonde température humidité une intérieur une extérieur et un anémomètre la crosse tx21 avec 4 connection par fil cuivre

                  Et ça fonctionne plutôt bien
                  Est ce le même principe mais avec une puce sigfox au lieu d'une wifi sur votre projet?

                  1 Reply Last reply Reply Quote 0
                  • T
                    toby last edited by

                    Bonjour,

                    J'essaye de comprendre les données.
                    Sigfox envoi toutes les 10 min, je vois (si je comprend bien) que dans chaque message il y 2 série de données:

                    2021-05-13_21-58-03.jpg

                    Ici c'est un peu plus clair :

                    2021-05-13_22-04-59.jpg

                    J'aimerai avoir des infos sur l'enregistrement des données.
                    Dans l'exemple à 19h18 j'ai 26.5 km/h cette valeur est une moyenne entre 19h13 et 19h18? La valeur la plus haute entre 19h13 et 19h18? La valeur a 19h18?
                    Je pense qu'il faudrait qq explications.
                    Merci

                    T 1 Reply Last reply Reply Quote 0
                    • T
                      toby @toby last edited by nicolas

                      @toby said in Format messages Sigfox de Arduino vers OpenWindMap:

                      Bonjour,

                      J'essaye de comprendre les données.
                      Sigfox envoi toutes les 10 min, je vois (si je comprend bien) que dans chaque message il y 2 série de données:

                      2021-05-13_21-58-03.jpg

                      Ici c'est un peu plus clair :

                      2021-05-13_22-04-59.jpg

                      J'aimerai avoir des infos sur l'enregistrement des données.
                      Dans l'exemple à 19h18 j'ai 26.5 km/h cette valeur est une moyenne entre 19h13 et 19h18? La valeur la plus haute entre 19h13 et 19h18? La valeur a 19h18?
                      Je pense qu'il faudrait qq explications.
                      Merci

                      Puis-je obtenir une réponse? Merci.

                      nicolas 1 Reply Last reply Reply Quote 0
                      • nicolas
                        nicolas @toby last edited by

                        @toby
                        2021-05-13_21-58-03.jpg

                        Donc, sur la période qui va de 19h13 à 19h18 (UTC) on a mesuré :
                        au minimum : 0 km/h
                        au maximum : 26.5 km/h
                        en moyenne : 3km/h
                        (échantillonnage WMO de 3 secondes sur ce modèle de balise arduino)

                        T 1 Reply Last reply Reply Quote 0
                        • T
                          toby @nicolas last edited by toby

                          @nicolas said in Format messages Sigfox de Arduino vers OpenWindMap:

                          @toby
                          2021-05-13_21-58-03.jpg

                          Donc, sur la période qui va de 19h13 à 19h18 (UTC) on a mesuré :
                          au minimum : 0 km/h
                          au maximum : 26.5 km/h
                          en moyenne : 3km/h
                          (échantillonnage WMO de 3 secondes sur ce modèle de balise arduino)

                          @nicolas

                          Bonjour,
                          Merci, c'est plus clair. J'ai de quoi argumenter le montage d'un des deux entre Sintra et Cascais, couloir très venteux que peu de personnes connaissent! Mais pas évident à convaincre.
                          PS: le 2ème je n'ai pas encore décider où le mettre. (Nazaré?)
                          Bon we

                          1 Reply Last reply Reply Quote 0
                          • 1 / 1
                          • First post
                            Last post