{"id":235,"date":"2019-07-29T07:24:40","date_gmt":"2019-07-29T06:24:40","guid":{"rendered":"http:\/\/daniel974.fr\/wordpress\/?p=235"},"modified":"2021-06-19T10:20:14","modified_gmt":"2021-06-19T09:20:14","slug":"pluviometre-wh0531-a-finir","status":"publish","type":"post","link":"http:\/\/daniel974.fr\/wordpress1\/2019\/07\/29\/pluviometre-wh0531-a-finir\/","title":{"rendered":"Pluviom\u00e8tre WH0531 (\u00e0 finir&#8230;)"},"content":{"rendered":"<p>Apr\u00e8s avoir bien jou\u00e9 avec le <a href=\"http:\/\/daniel974.fr\/wordpress\/2019\/07\/29\/pluviometre-1-a-finir\/\">pluviom\u00e9tre1&#8230;<\/a> , j&rsquo;ai achet\u00e9 ce WH0531 <a href=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/wh0531.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-236\" src=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/wh0531.png\" alt=\"\" width=\"259\" height=\"194\" \/><\/a><a href=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/wh0531bis.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-237\" src=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/wh0531bis-300x225.png\" alt=\"\" width=\"253\" height=\"190\" srcset=\"http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/wh0531bis-300x225.png 300w, http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/wh0531bis.png 400w\" sizes=\"(max-width: 253px) 100vw, 253px\" \/><\/a><br \/>\net je ne le regrette pas&#8230; pour environ 20 euros il fait le boulot&#8230;<\/p>\n<p>Le probl\u00e8me est que le capteur ne communique qu&rsquo;avec l&rsquo;afficheur et moi je souhaitais r\u00e9cup\u00e9rer les donn\u00e9es pour enrichir ma BD&#8230;<br \/>\nEn fouillant un peu je suis tomb\u00e9 sur ce site:<br \/>\n<a href=\"https:\/\/lucsmall.com\/2012\/04\/27\/weather-station-hacking-part-1\/\">https:\/\/lucsmall.com\/2012\/04\/27\/weather-station-hacking-part-1\/<\/a><\/p>\n<p>et c&rsquo;\u00e9tait parti pour une passerelle RF433-Internet adapt\u00e9e \u00e0 ce pluviom\u00e8tre&#8230;<\/p>\n<p>Quelques modifications pour intercepter compl\u00e9tement les paquets envoy\u00e9s par le WH0531<\/p>\n<pre class=\"\">\/*\r\nUpdated code for receiving data from WH2 weather station\r\nThis code implements timeouts to make decoding more robust\r\nDecodes received packets and writes a summary of each packet to the Arduino's\r\nserial port\r\nCreated by Luc Small on 19 July 2013.\r\nReleased into the public domain.\r\n*\/\r\n\r\n\/\/ Read data from 433MHz receiver on digital pin 2\r\n#define RF_IN 2\r\n\/\/ For better efficiency, the port is read directly\r\n\/\/ the following two lines should be changed appropriately\r\n\/\/ if the line above is changed.\r\n#define RF_IN_RAW PIND2\r\n#define RF_IN_PIN PIND\r\n\r\n\/\/ Port that is hooked to LED to indicate a packet has been received\r\n#define LED_PACKET A2\r\n\r\n#define COUNTER_RATE 3200-1 \/\/ 16,000,000Hz \/ 3200 = 5000 interrupts per second, ie. 200us between interrupts\r\n\/\/ 1 is indicated by 500uS pulse\r\n\/\/ wh2_accept from 2 = 400us to 3 = 600us\r\n#define IS_HI_PULSE(interval) (interval &gt;= 2 &amp;&amp; interval &lt;= 3)\r\n\/\/ 0 is indicated by ~1500us pulse\r\n\/\/ wh2_accept from 7 = 1400us to 8 = 1600us\r\n#define IS_LOW_PULSE(interval) (interval &gt;= 7 &amp;&amp; interval &lt;= 8)\r\n\/\/ worst case packet length\r\n\/\/ 6 bytes x 8 bits x (1.5 + 1) = 120ms; 120ms = 200us x 600\r\n#define HAS_TIMED_OUT(interval) (interval &gt; 600)\r\n\/\/ we expect 1ms of idle time between pulses\r\n\/\/ so if our pulse hasn't arrived by 1.2ms, reset the wh2_packet_state machine\r\n\/\/ 6 x 200us = 1.2ms\r\n#define IDLE_HAS_TIMED_OUT(interval) (interval &gt; 6)\r\n\/\/ our expected pulse should arrive after 1ms\r\n\/\/ we'll wh2_accept it if it arrives after\r\n\/\/ 4 x 200us = 800us\r\n#define IDLE_PERIOD_DONE(interval) (interval &gt;= 4)\r\n\/\/ Shorthand for tests\r\n\/\/#define RF_HI (digitalRead(RF_IN) == HIGH)\r\n\/\/#define RF_LOW (digitalRead(RF_IN) == LOW)\r\n#define RF_HI (bit_is_set(RF_IN_PIN, RF_IN_RAW))\r\n#define RF_LOW (bit_is_clear(RF_IN_PIN, RF_IN_RAW))\r\n\r\n\/\/ wh2_flags\r\n#define GOT_PULSE 0x01\r\n#define LOGIC_HI 0x02\r\nvolatile byte wh2_flags = 0;\r\nvolatile byte wh2_packet_state = 0;\r\nvolatile int wh2_timeout = 0;\r\n#define nbp 7 \/\/la modification la plus importante !...\r\nbyte wh2_packet[nbp];\r\nbyte wh2_calculated_crc;\r\n\r\nISR(TIMER1_COMPA_vect)\r\n{\r\nstatic byte sampling_state = 0;\r\nstatic byte count;\r\nstatic boolean was_low = false;\r\n\r\nswitch (sampling_state) {\r\ncase 0: \/\/ waiting\r\nwh2_packet_state = 0;\r\nif (RF_HI) {\r\nif (was_low) {\r\ncount = 0;\r\nsampling_state = 1;\r\nwas_low = false;\r\n}\r\n} else {\r\nwas_low = true;\r\n}\r\nbreak;\r\ncase 1: \/\/ acquiring first pulse\r\ncount++;\r\n\/\/ end of first pulse\r\nif (RF_LOW) {\r\nif (IS_HI_PULSE(count)) {\r\nwh2_flags = GOT_PULSE | LOGIC_HI;\r\nsampling_state = 2;\r\ncount = 0;\r\n} else if (IS_LOW_PULSE(count)) {\r\nwh2_flags = GOT_PULSE; \/\/ logic low\r\nsampling_state = 2;\r\ncount = 0;\r\n} else {\r\nsampling_state = 0;\r\n}\r\n}\r\nbreak;\r\ncase 2: \/\/ observe 1ms of idle time\r\ncount++;\r\nif (RF_HI) {\r\nif (IDLE_HAS_TIMED_OUT(count)) {\r\nsampling_state = 0;\r\n} else if (IDLE_PERIOD_DONE(count)) {\r\nsampling_state = 1;\r\ncount = 0;\r\n}\r\n}\r\nbreak;\r\n}\r\n\r\nif (wh2_timeout &gt; 0) {\r\nwh2_timeout++;\r\nif (HAS_TIMED_OUT(wh2_timeout)) {\r\nwh2_packet_state = 0;\r\nwh2_timeout = 0;\r\n}\r\n}\r\n}\r\n\r\nvoid setup() {\r\nSerial.begin(9600);\r\nSerial.println(\"BetterWH2\");\r\n\r\npinMode(LED_PACKET, OUTPUT);\r\npinMode(RF_IN, INPUT);\r\n\r\nTCCR1A = 0x00;\r\nTCCR1B = 0x09;\r\nTCCR1C = 0x00;\r\nOCR1A = COUNTER_RATE;\r\nTIMSK1 = 0x02;\r\n\r\n\/\/ enable interrupts\r\nsei();\r\n}\r\n\r\nvoid loop() {\r\nstatic unsigned long old = 0, packet_count = 0, bad_count = 0, average_interval;\r\nunsigned long spacing, now;\r\nbyte i;\r\n\r\nif (wh2_flags) {\r\nif (wh2_accept()) {\r\n\/\/ calculate the CRC\r\nwh2_calculate_crc();\r\n\r\nnow = millis();\r\nspacing = now - old;\r\nold = now;\r\npacket_count++;\r\naverage_interval = now \/ packet_count;\r\nif (!wh2_valid()) {\r\nbad_count++;\r\n}\r\n\r\n\/\/ flash green led to say got packet\r\ndigitalWrite(LED_PACKET, HIGH);\r\ndelay(100);\r\ndigitalWrite(LED_PACKET, LOW);\r\n\r\nSerial.print(packet_count, DEC);\r\nSerial.print(\" | \");\r\nSerial.print(bad_count, DEC);\r\nSerial.print(\" | \");\r\n\/* Serial.print(spacing, DEC);\r\nSerial.print(\" | \");\r\nSerial.print(average_interval, DEC);\r\nSerial.print(\" | \");*\/\r\n\r\nfor (i = 0; i &lt; nbp; i++) {\r\nSerial.print(\"0x\");\r\nSerial.print(wh2_packet[i], HEX);\r\nSerial.print(\"\/\");\r\nSerial.print(wh2_packet[i], DEC);\r\nSerial.print(\" \");\r\n}\r\nfor (i = 0; i &lt; nbp; i++) {\r\n\/\/ Serial.print(wh2_packet[i], BIN);\r\nSerial.print(ByteToBin(wh2_packet[i]));\r\nif (i&lt;(nbp-1)) Serial.print(\"-\");\r\n}\r\nSerial.print(\" SensorID:0x\");\r\nSerial.print(wh2_sensor_id(), HEX);\r\nSerial.print(\" T:\");\r\nSerial.print(wh2_temperature(), DEC);\r\nSerial.print(\" R:\");\r\nSerial.print(wh2_rain(), DEC);\r\nSerial.print((wh2_valid() ? \" OK.\" : \" BAD.\"));\r\nSerial.println();\r\n}\r\nwh2_flags = 0x00;\r\n}\r\n}\r\n\r\n\r\n\/\/ processes new pulse\r\nboolean wh2_accept()\r\n{\r\nstatic byte packet_no, bit_no, history;\r\n\r\n\/\/ reset if in initial wh2_packet_state\r\nif (wh2_packet_state == 0) {\r\n\/\/ should history be 0, does it matter?\r\nhistory = 0xFF;\r\nwh2_packet_state = 1;\r\n\/\/ enable wh2_timeout\r\nwh2_timeout = 1;\r\n} \/\/ fall thru to wh2_packet_state one\r\n\r\n\/\/ acquire preamble\r\nif (wh2_packet_state == 1) {\r\n\/\/ shift history right and store new value\r\nhistory &lt;&lt;= 1;\r\n\/\/ store a 1 if required (right shift along will store a 0)\r\nif (wh2_flags &amp; LOGIC_HI) {\r\nhistory |= 0x01;\r\n}\r\n\/\/ check if we have a valid start of frame\r\n\/\/ xxxxx110\r\nif ((history &amp; B00000111) == B00000110) {\r\n\/\/ need to clear packet, and counters\r\npacket_no = 0;\r\n\/\/ start at 1 becuase only need to acquire 7 bits for first packet byte.\r\nbit_no = 1;\r\nwh2_packet[0] = wh2_packet[1] = wh2_packet[2] = wh2_packet[3] = wh2_packet[4] = 0;\r\n\/\/ we've acquired the preamble\r\nwh2_packet_state = 2;\r\n}\r\nreturn false;\r\n}\r\n\/\/ acquire packet\r\nif (wh2_packet_state == 2) {\r\n\r\nwh2_packet[packet_no] &lt;&lt;= 1;\r\nif (wh2_flags &amp; LOGIC_HI) {\r\nwh2_packet[packet_no] |= 0x01;\r\n}\r\n\r\nbit_no ++;\r\nif (bit_no &gt; 7) {\r\nbit_no = 0;\r\npacket_no ++;\r\n}\r\n\r\nif (packet_no &gt; (nbp - 1)) {\r\n\/\/ start the sampling process from scratch\r\nwh2_packet_state = 0;\r\n\/\/ clear wh2_timeout\r\nwh2_timeout = 0;\r\nreturn true;\r\n}\r\n}\r\nreturn false;\r\n}\r\n\r\n\r\nvoid wh2_calculate_crc()\r\n{\r\nwh2_calculated_crc = crc8(wh2_packet, nbp-1);\r\n}\r\n\r\nbool wh2_valid()\r\n{\r\nreturn (wh2_calculated_crc == wh2_packet[nbp-1]);\r\n}\r\n\r\nint wh2_sensor_id()\r\n{\r\nreturn (wh2_packet[0] &lt;&lt; 4) + (wh2_packet[1] &gt;&gt; 4);\r\n}\r\n\r\nint wh2_rain()\r\n{\r\nreturn wh2_packet[3] + 256 * wh2_packet[4];\r\n}\r\n\r\n\/* Temperature in deci-degrees. e.g. 251 = 25.1 *\/\r\nint wh2_temperature()\r\n{\r\nint temperature;\r\ntemperature = ((wh2_packet[1] &amp; B00000111) &lt;&lt; 8) + wh2_packet[2] - 400;\r\n\/\/ make negative\r\nif (wh2_packet[1] &amp; B00001000) {\r\ntemperature = -temperature;\r\n}\r\nreturn temperature;\r\n}\r\n\r\nuint8_t crc8( uint8_t *addr, uint8_t len)\r\n{\r\nuint8_t crc = 0;\r\n\r\n\/\/ Indicated changes are from reference CRC-8 function in OneWire library\r\nwhile (len--) {\r\nuint8_t inbyte = *addr++;\r\nfor (uint8_t i = 8; i; i--) {\r\nuint8_t mix = (crc ^ inbyte) &amp; 0x80; \/\/ changed from &amp; 0x01\r\ncrc &lt;&lt;= 1; \/\/ changed from right shift\r\nif (mix) crc ^= 0x31;\/\/ changed from 0x8C;\r\ninbyte &lt;&lt;= 1; \/\/ changed from right shift\r\n}\r\n}\r\nreturn crc;\r\n}\r\nString ByteToBin(byte b) {\r\nString r = \"\";\r\nfor (int j = 0; j &lt; 8; j++) {\r\nif (bitRead(b, j) == 1) r = \"1\" + r;\r\nelse r = \"0\" + r;\r\n}\r\nreturn r;\r\n}\r\n<\/pre>\n<p>R\u00e9sultat:<a href=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/passerelle-e1591875583785.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-239\" src=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/passerelle-e1591875583785-225x300.jpg\" alt=\"\" width=\"225\" height=\"300\" srcset=\"http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/passerelle-e1591875583785-225x300.jpg 225w, http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/passerelle-e1591875583785-768x1024.jpg 768w, http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/passerelle-e1591875583785-1152x1536.jpg 1152w, http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/passerelle-e1591875583785-1536x2048.jpg 1536w\" sizes=\"(max-width: 225px) 100vw, 225px\" \/><\/a>\u00a0 Il intercepte les paquets destin\u00e9s \u00e0 l&rsquo;afficheur <a href=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/CaptureWH0631.png\"><img decoding=\"async\" loading=\"lazy\" class=\"size-medium wp-image-300 aligncenter\" src=\"http:\/\/daniel974.fr\/wordpress\/wp-content\/uploads\/2019\/07\/CaptureWH0631-300x174.png\" alt=\"\" width=\"300\" height=\"174\" srcset=\"http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/CaptureWH0631-300x174.png 300w, http:\/\/daniel974.fr\/wordpress1\/wp-content\/uploads\/2019\/07\/CaptureWH0631.png 734w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>et\u00a0 envoie sur ma BD internet uniquement les donn\u00e9es RAIN (R:octets 4 et 5), BD consultable <a href=\"http:\/\/daniel974.fr\/pluviowh0531\/\">i\u00e7i.<\/a><\/p>\n<p>Un module similaire permet d&rsquo;asservir mon arrosage automatique&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apr\u00e8s avoir bien jou\u00e9 avec le pluviom\u00e9tre1&#8230; , j&rsquo;ai achet\u00e9 ce WH0531 et je ne le regrette pas&#8230; pour environ 20 euros il fait le boulot&#8230; Le probl\u00e8me est que le capteur ne communique qu&rsquo;avec l&rsquo;afficheur et moi je souhaitais &hellip; <a href=\"http:\/\/daniel974.fr\/wordpress1\/2019\/07\/29\/pluviometre-wh0531-a-finir\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/posts\/235"}],"collection":[{"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/comments?post=235"}],"version-history":[{"count":10,"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/posts\/235\/revisions"}],"predecessor-version":[{"id":304,"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/posts\/235\/revisions\/304"}],"wp:attachment":[{"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/media?parent=235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/categories?post=235"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/daniel974.fr\/wordpress1\/wp-json\/wp\/v2\/tags?post=235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}