{"id":3730,"date":"2023-06-18T17:20:26","date_gmt":"2023-06-18T15:20:26","guid":{"rendered":"https:\/\/miniprojets.net\/?p=3730"},"modified":"2023-07-20T13:29:50","modified_gmt":"2023-07-20T11:29:50","slug":"transfert-de-donnees-via-lora-vers-jeedom-dans-le-cadre-dune-ruche-connectee","status":"publish","type":"post","link":"https:\/\/miniprojets.net\/index.php\/2023\/06\/18\/transfert-de-donnees-via-lora-vers-jeedom-dans-le-cadre-dune-ruche-connectee\/","title":{"rendered":"Transfert de donn\u00e9es via Lora vers JEEDOM dans le cadre d&#8217;une ruche connect\u00e9e"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME-1024x768.jpg\" alt=\"\" class=\"wp-image-3731\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME-1024x768.jpg 1024w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME-300x225.jpg 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME-768x576.jpg 768w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME-1536x1152.jpg 1536w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME-160x120.jpg 160w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/SYST7ME.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Nous sommes une \u00e9quipe d&#8217;\u00e9tudiants en deuxi\u00e8me ann\u00e9e d&#8217;\u00e9cole d&#8217;ing\u00e9nieur \u00e0 Grenoble-INP Ense3, nous avons comme projet de cr\u00e9er une ruche connect\u00e9. Notre syst\u00e8me nous renvoie l&#8217;humidit\u00e9, la temp\u00e9rature ainsi que la masse de la ruche. <\/p>\n\n\n\n<p>Afin de pouvoir transmettre ces donn\u00e9es \u00e0 l&#8217;apiculteur, nous avons choisit d&#8217;utiliser le r\u00e9seau LoRa qui consomme tr\u00e8s peu et qui est open source. Dans notre syst\u00e8me nous avons une carte pycom Lopy4 qui permet de traiter les donn\u00e9es et de les envoyer en LoRa vers The Things Network puis JEEDOM.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fonctionnement Carte Lopy4<\/h2>\n\n\n\n<p>Pour utiliser la carte, il faut au pr\u00e9alable installer le logiciel <em>ATOM<\/em>, pour cela il faut aller sur <a href=\"https:\/\/atom.io\/\">https:\/\/atom.io\/<\/a>, et ensuite une fois <em>ATOM<\/em> install\u00e9, cliquer sur &#8220;Install a Package&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-36.png\" alt=\"\" class=\"wp-image-3733\" width=\"410\" height=\"232\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-36.png 721w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-36-300x170.png 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-36-720x405.png 720w\" sizes=\"auto, (max-width: 410px) 100vw, 410px\" \/><\/figure>\n\n\n\n<p>Puis il faut cliquer dans Open Installer et installer le package &#8220;pymakr&#8221;, une fois fait on peut utiliser Atom (de Savoie).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-37.png\" alt=\"\" class=\"wp-image-3734\" width=\"376\" height=\"250\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-37.png 614w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-37-300x200.png 300w\" sizes=\"auto, (max-width: 376px) 100vw, 376px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-39.png\" alt=\"\" class=\"wp-image-3736\" width=\"673\" height=\"268\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-39.png 673w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-39-300x119.png 300w\" sizes=\"auto, (max-width: 673px) 100vw, 673px\" \/><\/figure>\n\n\n\n<p>Vous pouvez vous cr\u00e9er un folder o\u00f9 vous mettrez les codes de votre projet. A noter qu&#8217;<em>ATOM <\/em>et la carte lopy 4 se codent en langage python.<\/p>\n\n\n\n<p>Vous devez vous connecter \u00e0 votre carte par le r\u00e9seau, normalement une fois aliment\u00e9 vous allez voir dans vos r\u00e9seau wifi disponible sur votre ordinateur, le r\u00e9seau de votre carte pycom (lopy-wlan-xxxx). Vous vous connectez avec le mot de passe www.pycom.io . Sur <em>Atom<\/em> vous allez dans l&#8217;onglet connect et s\u00e9lectionnez votre carte.<\/p>\n\n\n\n<p><strong>Vous voil\u00e0 connect\u00e9 \u00e0 votre carte ! <\/strong>(Attention une fois connect\u00e9 vous n&#8217;avez plus acc\u00e8s \u00e0 internet)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Capteur de Temp\u00e9rature et d&#8217;Humidit\u00e9<\/h2>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/MCFVHb_mXg9EuEgU9Jb0URp4juf2pL-ck-8ltHjTjct8J0QnBkEMGjR9pvksgYRV_40uc2ZuRuJbuHPRr2ciLYwVViVUS6UmERLzn7EyCoAxYszrJpWVWMqI_Yan6amh_rJerMQwu3wp8YGLOfenPdE\" width=\"215\" height=\"300.9497290636669\"><\/p>\n\n\n\n<p>Le capteur DHT22 est un capteur pouvant renvoyer l&#8217;humidit\u00e9 et la temp\u00e9rature, nous avons donc utiliser celui l\u00e0. Si vous voulez vous informer dessus et conna\u00eetre ses caract\u00e9ristiques (<a href=\"https:\/\/passionelectronique.fr\/tutorial-dht22\/\">https:\/\/passionelectronique.fr\/tutorial-dht22\/<\/a>).<\/p>\n\n\n\n<p>Afin de le faire fonctionner sur <em>Atom<\/em>, voici notre code : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import pycom\nimport time\nfrom machine import Pin\nfrom machine import enable_irq, disable_irq\n\n#################### Define DHT22 ####################\n\ndef getval(pin):\n    ms = [1]*700        # needs long sample size to grab all the bits from the DHT\n    time.sleep(1)\n    pin(0)\n    time.sleep_us(10000)\n    pin(1)\n    irqf = disable_irq()\n    for i in range(len(ms)):\n        ms[i] = pin()      ## sample input and store value\n    enable_irq(irqf)\n    # for i in range(len(ms)):\t\t#print debug for checking raw data\n\t#     print (ms[i])\n    return ms\n\ndef decode(inp):\n    res= [0]*5\n    bits=[]\n    ix = 0\n    try:\n        #if inp[0] == 1 : ix = inp.index(0, ix) ## skip to first 0\t# ignore first '1' as probably sample of start signal.  *But* code seems to be missing the start signal, so jump this line to ensure response signal is identified in next two lines.\n        ix = inp.index(1,ix) ## skip first 0's to next 1\t#  ignore first '10' bits as probably the response signal.\n        ix = inp.index(0,ix) ## skip first 1's to next 0\n        while len(bits) &lt; len(res)*8 : ##need 5 * 8 bits :\n            ix = inp.index(1,ix) ## index of next 1\n            ie = inp.index(0,ix) ## nr of 1's = ie-ix\n            # print ('ie-ix:',ie-ix)\n            bits.append(ie-ix)\n            ix = ie\n    except:\n        print('6: decode error')\n        print('length:')\n        print(len(inp), len(bits))\n        return([0xff,0xff,0xff,0xff])\n\n    # print('bits:', bits)\n    for i in range(len(res)):\n        for v in bits[i*8:(i+1)*8]:   #process next 8 bit\n            res[i] = res[i]&lt;&lt;1  ##shift byte one place to left\n            if v &gt; 5:                   #  less than 5 '1's is a zero, more than 5 1's in the sequence is a one\n                res[i] = res[i]+1  ##and add 1 if lsb is 1\n            # print ('res',  i,  res[i])\n\n    if (res[0]+res[1]+res[2]+res[3])&amp;0xff != res[4] :   ##parity error!\n        print(\"Checksum Error\")\n        print (res[0:4])\n        # res= [0xff,0xff,0xff,0xff]\n\n    #print ('res:', res[0:4])\n    return(res[0:4])\n\ndef DHT22(pin):\n    res = decode(getval(pin))\n    hum = res[0]*256+res[1]\n    temp = res[2]*256 + res[3]\n    if (temp &gt; 0x7fff):\n        temp = 0x8000 - temp\n    return temp, hum\n\n###########################Affichage_des_donn\u00e9es#############################\n\ndef go_DHT():\n    dht_pin=Pin('PXX', Pin.OPEN_DRAIN)\t# connect DHT22 sensor data line to pin \n    dht_pin(1)\n\nwhile True:\n\n        temp, hum = DHT22(dht_pin)\n        print(temp\/\/10,'\u00b0C')\n        print(hum\/\/10,'%')\n\npycom.heartbeat(False)\n\ngo_DHT()<\/code><\/pre>\n\n\n\n<p>Normalement <em>Atom <\/em>vous renvoie bien l&#8217;humidit\u00e9 et la temp\u00e9rature de la pi\u00e8ce.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Capteur de masse<\/h2>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/xgjsPBAyV9yYYyqoX6NSG-98GSw_N5T8-AS8wxWvJB2FLSlfa7buWQPvpMt7ENfI1Tn9Q7E6T-hpWDJp_XNwpGZTLr1-GGzU-nnTyaKVufZA7blI4V5xJW9FozLKuqkZGBv8Yb92bOZiN_fVwY7TNG0\" width=\"369\" height=\"350.42221756176775\"><\/p>\n\n\n\n<p>Pour notre balance nous avons utilis\u00e9 des capteurs de forces en s\u00e9rie avec des amplificateurs HX711, on s&#8217;est inspir\u00e9 de ce projet (<a href=\"https:\/\/www.robotique.tech\/tutoriel\/balance-de-pesee-utilisant-hx711-et-arduino-pour-la-surveillance-du-poids-a-distance-par-bluetooth\/\">https:\/\/www.robotique.tech\/tutoriel\/balance-de-pesee-utilisant-hx711-et-arduino-pour-la-surveillance-du-poids-a-distance-par-bluetooth\/<\/a>). Cependant \u00e9tant sur Python nous n&#8217;avons pas pu utiliser leurs codes nous avons r\u00e9cup\u00e9r\u00e9 des codes sur (<a href=\"https:\/\/github.com\/geda\/hx711-lopy\/commit\/a1a71a015b7edf530266025ec40d3714e9631fb5\">https:\/\/github.com\/geda\/hx711-lopy\/commit\/a1a71a015b7edf530266025ec40d3714e9631fb5<\/a>). <\/p>\n\n\n\n<p>Sur <em>ATOM <\/em>en faisant tourner : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">from machine import Pin\n\nclass HX711:\n    def __init__(self, dout, pd_sck, gain=128):\n\n        self.pSCK = Pin(pd_sck , mode=Pin.OUT)\n        self.pOUT = Pin(dout, mode=Pin.IN, pull=Pin.PULL_DOWN)\n\n        self.GAIN = 0\n        self.OFFSET = 0\n        self.SCALE = 1\n        self.lastVal = 0\n        self.allTrue = False\n\n        self.set_gain(gain);\n\n\n    def createBoolList(size=8):\n        ret = []\n        for i in range(8):\n            ret.append(False)\n        return ret\n\n    def is_ready(self):\n        return self.pOUT() == 0\n\n    def set_gain(self, gain):\n        if gain is 128:\n            self.GAIN = 1\n        elif gain is 64:\n            self.GAIN = 3\n        elif gain is 32:\n            self.GAIN = 2\n\n        self.pSCK.value(False)\n        self.read()\n        print('Gain setted')\n\n    def read(self):\n\n        dataBits = [self.createBoolList(), self.createBoolList(), self.createBoolList()]\n        while not self.is_ready():\n            pass\n\n        for j in range(2, -1, -1):\n            for i in range(7, -1, -1):\n                self.pSCK.value(True)\n                dataBits[j][i] = self.pOUT()\n                self.pSCK.value(False)\n\n\n        #set channel and gain factor for next reading\n        for i in range(self.GAIN):\n            self.pSCK.value(True)\n            self.pSCK.value(False)\n\n\n        #check for all 1\n        if all(item == True for item in dataBits[0]):\n            print('all true')\n            self.allTrue=True\n            return self.lastVal\n\n        self.allTrue=False\n\n\n        readbits = \"\"\n        for j in range(2, -1, -1):\n            for i in range(7, -1, -1):\n                if dataBits[j][i] == True:\n                    readbits= readbits +'1'\n                else:\n                    readbits= readbits+'0'\n\n        self.lastVal = int(readbits, 2)\n\n        return self.lastVal\n\n\n\n    def read_average(self, times=3):\n        sum = 0\n        effectiveTimes = 0\n        readed = 0\n        for i in range(times):\n            readed = self.read()\n            if self.allTrue == False:\n                sum += readed\n                effectiveTimes+=1\n\n        if effectiveTimes == 0:\n            return 0\n        return sum \/ effectiveTimes\n\n    def get_value(self, times=3):\n        return self.read_average(times) - self.OFFSET\n\n    def get_units(self, times=3):\n        return self.get_value(times) \/ self.SCALE\n\n    def tare(self, times=15):\n        sum = self.read_average(times)\n        self.set_offset(sum)\n\n    def set_scale(self, scale):\n        self.SCALE = scale\n\n    def set_offset(self, offset):\n        self.OFFSET = offset\n\n    def power_down(self):\n        self.pSCK.value(False)\n        self.pSCK.value(True)\n\n\n    def power_up(self):\n        self.pSCK.value(False)\n\n################################## Main Program ############################\nscale1 = HX711('PX1','PX2',128) #Attention bien connecter les 2 bons pins\ncalibration_factor = -7340\nscale1.set_scale(calibration_factor)\nscale1.tare()\n\nwhile True:\n        masse = round(scale1.get_units(3))\n        print (masse,'kg')<\/code><\/pre>\n\n\n\n<p>A noter qu&#8217;il faut faire plusieurs essais et jouer sur le calibration factor pour avoir la bonne \u00e9chelle de masse.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Connection Atom\/The Things Network<\/h2>\n\n\n\n<p>Maintenant que l&#8217;on arrive \u00e0 avoir des donn\u00e9es de masse, humidit\u00e9 et temp\u00e9rature, on souhaite les envoyer via le r\u00e9seau Lora pour l&#8217;apiculteur. Pour cela, on utilise le r\u00e9seau LoRa, pour cela on doit aller sur le site <a rel=\"noreferrer noopener\" href=\"https:\/\/www.thethingsnetwork.org\/\" data-type=\"URL\" data-id=\"https:\/\/www.thethingsnetwork.org\/\" target=\"_blank\">The Things Network<\/a>, (TTN). Tout d&#8217;abord, il faut se cr\u00e9er un compte, ensuite aller dans l&#8217;onglet console. Puis s\u00e9lectionner le cluster <a rel=\"noreferrer noopener\" href=\"https:\/\/www.europe1.fr\/direct-audio\" data-type=\"URL\" data-id=\"https:\/\/www.europe1.fr\/direct-audio\" target=\"_blank\">Europe 1<\/a>(si vous \u00eates en Europe \u00e9videmment).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"186\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-41-1024x186.png\" alt=\"\" class=\"wp-image-3740\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-41-1024x186.png 1024w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-41-300x54.png 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-41-768x139.png 768w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-41.png 1295w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"418\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-42-1024x418.png\" alt=\"\" class=\"wp-image-3741\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-42-1024x418.png 1024w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-42-300x123.png 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-42-768x314.png 768w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-42.png 1053w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Ensuite il faut cr\u00e9er une application, en remplissant une application ID (par exemple <em>&#8220;myLoraSensorXX<\/em>&#8220;), et cliquer sur &#8220;+ Add end Device&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"124\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-43-1024x124.png\" alt=\"\" class=\"wp-image-3742\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-43-1024x124.png 1024w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-43-300x36.png 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-43-768x93.png 768w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-43-1140x139.png 1140w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-43.png 1152w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Ensuite on arrive \u00e0 cette page l\u00e0 :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-46.png\" alt=\"\" class=\"wp-image-3745\" width=\"805\" height=\"429\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-46.png 805w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-46-300x160.png 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-46-768x409.png 768w\" sizes=\"auto, (max-width: 805px) 100vw, 805px\" \/><\/figure>\n\n\n\n<p>On clique sur <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"176\" height=\"49\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-44.png\" alt=\"\" class=\"wp-image-3743\"\/><\/figure>\n\n\n\n<p>S\u00e9lectionnez le mode manuel, et remplissez les trois premi\u00e8res cases comme ceci :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"609\" height=\"297\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-47.png\" alt=\"\" class=\"wp-image-3746\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-47.png 609w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-47-300x146.png 300w\" sizes=\"auto, (max-width: 609px) 100vw, 609px\" \/><\/figure>\n\n\n\n<p>Ensuite on clique ces 3 cases on clique sur Generate, fill with zeros et Generate : <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"711\" height=\"329\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-48.png\" alt=\"\" class=\"wp-image-3747\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-48.png 711w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-48-300x139.png 300w\" sizes=\"auto, (max-width: 711px) 100vw, 711px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"382\" height=\"110\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-49.png\" alt=\"\" class=\"wp-image-3748\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-49.png 382w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-49-300x86.png 300w\" sizes=\"auto, (max-width: 382px) 100vw, 382px\" \/><\/figure>\n\n\n\n<p>Maintenant, on clique sur :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"184\" height=\"47\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-50.png\" alt=\"\" class=\"wp-image-3749\"\/><\/figure>\n\n\n\n<p>On obtient quelque chose comme \u00e7a :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"509\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-51.png\" alt=\"\" class=\"wp-image-3750\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-51.png 800w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-51-300x191.png 300w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-51-768x489.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p>Maintenant on garde notre page internet ouverte et on retourne sur <em>Atom<\/em>, en amont du code, recopie ceci<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">from network import LoRa\nimport socket\nimport binascii\nimport struct\nimport pycom\nimport time\nfrom machine import Pin\nfrom machine import enable_irq, disable_irq\n\n#################### Define LoraWan ########################\n# for EU868\nLORA_FREQUENCY = 868100000\nLORA_GW_DR = \"SF7BW125\" #DR_5\nLORA_NODE_DR = 5\n\n# initialize LoRa in LORAWAN mode.\n# Please pick the region that matches where you are using the device:\n# Asia = LoRa.AS923\n# Australia = LoRa.AU915\n# Europe = LoRa.EU868\n# United States = LoRa.US915\nlora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)\n# create an OTA authentication params\ndev_eui = binascii.unhexlify('XXXXXXXXXXXXX')\napp_eui = binascii.unhexlify('0000000000000000')\napp_key = binascii.unhexlify('XXXXXXXXXXXXXXXXXXXXX')\n# set the 3 default channels to the same frequency (must be before sending the OTAA join request)\nlora.add_channel(0, frequency=LORA_FREQUENCY, dr_min=0, dr_max=5)\nlora.add_channel(1, frequency=LORA_FREQUENCY, dr_min=0, dr_max=5)\nlora.add_channel(2, frequency=LORA_FREQUENCY, dr_min=0, dr_max=5)\n# join a network using OTAA\nlora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0,\ndr=LORA_NODE_DR)\n# wait until the module has joined the network\nwhile not lora.has_joined():\n    time.sleep(5)\n    print('Not joined yet...')\nprint(\"Joined\")\n# remove all the non-default channels\nfor i in range(3, 16):\n    lora.remove_channel(i)\n# create a LoRa socket\ns = socket.socket(socket.AF_LORA, socket.SOCK_RAW)\n# set the LoRaWAN data rate\ns.setsockopt(socket.SOL_LORA, socket.SO_DR, LORA_NODE_DR)\n# make the socket blocking\ns.setblocking(True)\ntime.sleep(5.0)\n\n\n#################### End of define LoraWan ###########<\/code><\/pre>\n\n\n\n<p>Attention, il faut bien rentrer son DevEui,son AppEui et son AppKey que l&#8217;on peut copier via TTN.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Encodage des donn\u00e9es<\/h2>\n\n\n\n<p>Maintenant qu&#8217;<em>Atom<\/em> est reli\u00e9 \u00e0 TTN, il faut faire passer nos donn\u00e9es de l&#8217;un vers l&#8217;autre, cependant les nombres d\u00e9cimaux sont trop &#8220;gros&#8221; \u00e0 faire passer donc on va convertir toutes nos donn\u00e9es comme une grosse cha\u00eene de caract\u00e8re.<\/p>\n\n\n\n<p>Comme on ne pourra pas avoir de valeurs n\u00e9gatives ni de nombre d\u00e9cimaux on d\u00e9cide de convertir nos valeurs en entiers naturels via additions et multiplications tel quel :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">while True:\n        temp, hum = DHT22(dht_pin)\n        temp = round(temp\/\/10) +40\n        hum=round(hum\/\/10)\n        masse = round(scale1.get_units(3)*10)\n\n        str_temp=str(temp)\n        str_hum=str(hum)\n        str_masse=str(masse)\n\n        encoded=(2-len(str_temp)*'0'+str_temp\n        encoded+=(2-len(str_hum)*'0'+str_hum\n        encoded+=(3-len(str_masse))*'0'+str_masse\n\n        print(encoded)\n        s.send(encoded.encode())<\/code><\/pre>\n\n\n\n<p>Afin de d\u00e9coder les donn\u00e9es que l&#8217;on envoie, on saisie un code \u00e9galement sur TTN dans uplink :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-52.png\" alt=\"\" class=\"wp-image-3753\" width=\"267\" height=\"528\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-52.png 267w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-52-152x300.png 152w\" sizes=\"auto, (max-width: 267px) 100vw, 267px\" \/><\/figure>\n\n\n\n<p>Bien se mettre dans le bon &#8220;Formatter type&#8221;<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"502\" height=\"79\" src=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-53.png\" alt=\"\" class=\"wp-image-3756\" srcset=\"https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-53.png 502w, https:\/\/miniprojets.net\/wp-content\/uploads\/2023\/06\/image-53-300x47.png 300w\" sizes=\"auto, (max-width: 502px) 100vw, 502px\" \/><\/figure>\n\n\n\n<p>et saisir ce code :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">function Decoder(bytes, port) {\n var decoded = {};\n var counter = 0;\n decoded.temperature = 0;\n for(i=0; i&lt;2; i++){\n decoded.temperature += Math.pow(10,1-i)*(parseInt(bytes[i])%16);\n }\n decoded.temperature = decoded.temperature-40;\n counter +=1;\n decoded.humidite = 0;\n for(i=0; i&lt;2; i++){\n decoded.humidite += Math.pow(10,1-i)*(parseInt(bytes[2*counter+i])%16);\n }\n decoded.humidite = decoded.humidite;\n counter +=1;\n decoded.masse=0;\n for (i=0; i&lt;3; i++){\n   decoded.masse += Math.pow(10,2-i)*(parseInt(bytes[2*counter+i])%16);\n }\n decoded.masse=decoded.masse\/10\n return decoded;\n }<\/code><\/pre>\n\n\n\n<p>Dans <em>Atom<\/em> on saisie le code final :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">from network import LoRa\nimport socket\nimport binascii\nimport struct\nimport pycom\nimport time\nfrom machine import Pin\nfrom machine import enable_irq, disable_irq\n\n#################### Define LoraWan ########################\n# for EU868\nLORA_FREQUENCY = 868100000\nLORA_GW_DR = \"SF7BW125\" #DR_5\nLORA_NODE_DR = 5\n\n# initialize LoRa in LORAWAN mode.\n# Please pick the region that matches where you are using the device:\n# Asia = LoRa.AS923\n# Australia = LoRa.AU915\n# Europe = LoRa.EU868\n# United States = LoRa.US915\nlora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)\n# create an OTA authentication params\ndev_eui = binascii.unhexlify('XXXXXXXXXXXXX')\napp_eui = binascii.unhexlify('0000000000000000')\napp_key = binascii.unhexlify('XXXXXXXXXXXXXXXXXXXX')\n# set the 3 default channels to the same frequency (must be before sending the OTAA join request)\nlora.add_channel(0, frequency=LORA_FREQUENCY, dr_min=0, dr_max=5)\nlora.add_channel(1, frequency=LORA_FREQUENCY, dr_min=0, dr_max=5)\nlora.add_channel(2, frequency=LORA_FREQUENCY, dr_min=0, dr_max=5)\n# join a network using OTAA\nlora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0,\ndr=LORA_NODE_DR)\n# wait until the module has joined the network\nwhile not lora.has_joined():\n    time.sleep(5)\n    print('Not joined yet...')\nprint(\"Joined\")\n# remove all the non-default channels\nfor i in range(3, 16):\n    lora.remove_channel(i)\n# create a LoRa socket\ns = socket.socket(socket.AF_LORA, socket.SOCK_RAW)\n# set the LoRaWAN data rate\ns.setsockopt(socket.SOL_LORA, socket.SO_DR, LORA_NODE_DR)\n# make the socket blocking\ns.setblocking(True)\ntime.sleep(5.0)\n\n\n#################### End of define LoraWan ###########\n\n#################### Cr\u00e9ation de la clas HX711 ######\n\nclass HX711:\n    def __init__(self, dout, pd_sck, gain=128):\n\n        self.pSCK = Pin(pd_sck , mode=Pin.OUT)\n        self.pOUT = Pin(dout, mode=Pin.IN, pull=Pin.PULL_DOWN)\n\n        self.GAIN = 0\n        self.OFFSET = 0\n        self.SCALE = 1\n        self.lastVal = 0\n        self.allTrue = False\n\n        self.set_gain(gain);\n\n\n    def createBoolList(size=8):\n        ret = []\n        for i in range(8):\n            ret.append(False)\n        return ret\n\n    def is_ready(self):\n        return self.pOUT() == 0\n\n    def set_gain(self, gain):\n        if gain is 128:\n            self.GAIN = 1\n        elif gain is 64:\n            self.GAIN = 3\n        elif gain is 32:\n            self.GAIN = 2\n\n        self.pSCK.value(False)\n        self.read()\n        print('Gain setted')\n\n    def read(self):\n\n        dataBits = [self.createBoolList(), self.createBoolList(), self.createBoolList()]\n        while not self.is_ready():\n            pass\n\n        for j in range(2, -1, -1):\n            for i in range(7, -1, -1):\n                self.pSCK.value(True)\n                dataBits[j][i] = self.pOUT()\n                self.pSCK.value(False)\n\n\n        #set channel and gain factor for next reading\n        for i in range(self.GAIN):\n            self.pSCK.value(True)\n            self.pSCK.value(False)\n\n\n        #check for all 1\n        if all(item == True for item in dataBits[0]):\n            print('all true')\n            self.allTrue=True\n            return self.lastVal\n\n        self.allTrue=False\n\n\n        readbits = \"\"\n        for j in range(2, -1, -1):\n            for i in range(7, -1, -1):\n                if dataBits[j][i] == True:\n                    readbits= readbits +'1'\n                else:\n                    readbits= readbits+'0'\n\n        self.lastVal = int(readbits, 2)\n\n        return self.lastVal\n\n\n\n    def read_average(self, times=3):\n        sum = 0\n        effectiveTimes = 0\n        readed = 0\n        for i in range(times):\n            readed = self.read()\n            if self.allTrue == False:\n                sum += readed\n                effectiveTimes+=1\n\n        if effectiveTimes == 0:\n            return 0\n        return sum \/ effectiveTimes\n\n    def get_value(self, times=3):\n        return self.read_average(times) - self.OFFSET\n\n    def get_units(self, times=3):\n        return self.get_value(times) \/ self.SCALE\n\n    def tare(self, times=15):\n        sum = self.read_average(times)\n        self.set_offset(sum)\n\n    def set_scale(self, scale):\n        self.SCALE = scale\n\n    def set_offset(self, offset):\n        self.OFFSET = offset\n\n    def power_down(self):\n        self.pSCK.value(False)\n        self.pSCK.value(True)\n\n\n    def power_up(self):\n        self.pSCK.value(False)\n\n#################### Main program #################\nimport pycom\nimport time\nfrom machine import Pin\nfrom machine import enable_irq, disable_irq\n\n#################### Define DHT22 ####################\n\ndef getval(pin):\n    ms = [1]*700        # needs long sample size to grab all the bits from the DHT\n    time.sleep(1)\n    pin(0)\n    time.sleep_us(10000)\n    pin(1)\n    irqf = disable_irq()\n    for i in range(len(ms)):\n        ms[i] = pin()      ## sample input and store value\n    enable_irq(irqf)\n    # for i in range(len(ms)):\t\t#print debug for checking raw data\n\t#     print (ms[i])\n    return ms\n\ndef decode(inp):\n    res= [0]*5\n    bits=[]\n    ix = 0\n    try:\n        #if inp[0] == 1 : ix = inp.index(0, ix) ## skip to first 0\t# ignore first '1' as probably sample of start signal.  *But* code seems to be missing the start signal, so jump this line to ensure response signal is identified in next two lines.\n        ix = inp.index(1,ix) ## skip first 0's to next 1\t#  ignore first '10' bits as probably the response signal.\n        ix = inp.index(0,ix) ## skip first 1's to next 0\n        while len(bits) &lt; len(res)*8 : ##need 5 * 8 bits :\n            ix = inp.index(1,ix) ## index of next 1\n            ie = inp.index(0,ix) ## nr of 1's = ie-ix\n            # print ('ie-ix:',ie-ix)\n            bits.append(ie-ix)\n            ix = ie\n    except:\n        print('6: decode error')\n        print('length:')\n        print(len(inp), len(bits))\n        return([0xff,0xff,0xff,0xff])\n\n    # print('bits:', bits)\n    for i in range(len(res)):\n        for v in bits[i*8:(i+1)*8]:   #process next 8 bit\n            res[i] = res[i]&lt;&lt;1  ##shift byte one place to left\n            if v &gt; 5:                   #  less than 5 '1's is a zero, more than 5 1's in the sequence is a one\n                res[i] = res[i]+1  ##and add 1 if lsb is 1\n            # print ('res',  i,  res[i])\n\n    if (res[0]+res[1]+res[2]+res[3])&amp;0xff != res[4] :   ##parity error!\n        print(\"Checksum Error\")\n        print (res[0:4])\n        # res= [0xff,0xff,0xff,0xff]\n\n    #print ('res:', res[0:4])\n    return(res[0:4])\n\nscale1 = HX711('P3','P2',128)\ncalibration_factor = -7340\nscale1.set_scale(calibration_factor)\nscale1.tare()\n\ndef DHT22(pin):\n    res = decode(getval(pin))\n    hum = res[0]*256+res[1]\n    temp = res[2]*256 + res[3]\n    if (temp &gt; 0x7fff):\n        temp = 0x8000 - temp\n    return temp, hum\n\n#################### End of define DHT22 ###########\n\n#################### Main program #################\n\ndef go_DHT():\n    dht_pin=Pin('P23', Pin.OPEN_DRAIN)\t# connect DHT22 sensor data line to pin P9\/G16 on the expansion board\n    dht_pin(1)\t\t\t\t\t\t\t# drive pin high to initiate data conversion on DHT sensor\n\n\n    while True:\n        pycom.rgbled(0x7f0000) # red\n        temp, hum = DHT22(dht_pin)\n        temp = round(temp\/\/10) +40\n        hum=round(hum\/\/10)\n        masse = round(scale1.get_units(3)*10)\n        pycom.rgbled(0)\n        #res=str(temp)+'\/'+str(hum)+'\/'+str(scale1.get_units(3))\n        #pkt = str(res).encode() # Encode the data\n        # pkt=bin(temp)\n        # print(temp)\n        # # print(pkt)\n        # hex_temp=hex(temp)\n        # hex_hum=hex(hum)\n        # hex_masse=hex(masse)\n\n        str_temp=str(temp)\n        print(str_temp)\n        str_hum=str(hum)\n        print(str_hum)\n        str_masse=str(masse)\n        #str_masse='526'\n        encoded=(2-len(str_temp)*'0'+str_temp\n        encoded+=(2-len(str_hum)*'0'str_hum\n        encoded+=(3-len(str_masse))*'0'+str_masse\n\n        print(encoded)\n        s.send(encoded.encode())\n\npycom.heartbeat(False)\n\ngo_DHT()\n#################### End of Main program #################\n\n#################### End of Main program #################\n<\/code><\/pre>\n\n\n\n<p>Normalement s&#8217;affiche sur TTN dans l&#8217;onglet live data les valeurs ici, de masse, temp\u00e9rature et d&#8217;humidit\u00e9 ! <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nous sommes une \u00e9quipe d&#8217;\u00e9tudiants en deuxi\u00e8me ann\u00e9e d&#8217;\u00e9cole d&#8217;ing\u00e9nieur \u00e0 Grenoble-INP Ense3, nous avons comme projet de cr\u00e9er une&hellip;<\/p>\n","protected":false},"author":13,"featured_media":3732,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[80,82,96],"class_list":["post-3730","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-en-cours","tag-bureaux-detude","tag-capteurs","tag-lora"],"_links":{"self":[{"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/posts\/3730","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/comments?post=3730"}],"version-history":[{"count":12,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/posts\/3730\/revisions"}],"predecessor-version":[{"id":3766,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/posts\/3730\/revisions\/3766"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/media\/3732"}],"wp:attachment":[{"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/media?parent=3730"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/categories?post=3730"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/miniprojets.net\/index.php\/wp-json\/wp\/v2\/tags?post=3730"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}