GY-US42V2 e Arduino, Sensore di distanza ad ultrasuoni

Ciao!

in questo post vi parlerò di un sensore di distanza ad ultrasuoni identificato come GY-US42V2.
Ho aquistato questo modulo su Amazon dal venditore HiLetgo




Questo modulo ha un range teorico di 7,65 metri, un range notevole soprattutto se comparato con quello del diffuso modulo hc-sr04.
Inoltre ha un consumo medio piuttosto basso (dichiarati 4.4mA alimentandolo a 5V)

Il modulo comunica tramite protocollo I2C, quindi il collegamento ad Arduino è piuttosto semplice,
come potete vedere qui sotto



Passiamo ora al codice,
per prima cosa è necessario scaricare ed installare la libreria SoftI2CMaster

Poi caricate ed installate il seguente codice (che ho trovato sul sito MaxBotix)

  1. /*                   Arduino I2C for a MaxSonar                         */
  2. //////////////////////////////////////////////////////////////////////////
  3. //  Arduino I2C for a MaxSonar by Carl Myhre is licensed under a        //
  4. //  Creative Commons Attribution-ShareAlike 4.0 International License.  //
  5. //  Original Author:  Carl Myhre, 10-02-2014, Revision: 1.0             //
  6. //  Modifications by:                                                   //
  7. //                                                                      //
  8. //  Revision History: 1.0 -- 10-02-2014 -- Created initial code build   //
  9. //                                                                      //
  10. //  The original I2C libraries were created by Peter Fleury             //
  11. //    http://homepage.hispeed.ch/peterfleury/avr-software.html          //
  12. //                                                                      //
  13. //  These libraries were adapted by Bernhard Nebel for use on Arduino   //
  14. //    https://github.com/felias-fogg/SoftI2CMaster                      //
  15. //                                                                      //
  16. //  Special Thanks to MaxBotix Inc. for sponsoring this project!        //
  17. //    http://www.maxbotix.com -- High Performance Ultrasonic Sensors    //
  18. //                                                                      //
  19. //  For more information on installing the I2C libraries for Arduino    //
  20. //    visit http://playground.arduino.cc/Main/SoftwareI2CLibrary        //
  21. //////////////////////////////////////////////////////////////////////////
  22. //Hints on installing this code:
  23. // 1. You will need to install the <SoftI2CMaster.h> library before using this code.
  24. //      On Windows, the files are placed in C:\Program Files (x86)\Arduino\libraries\SoftI2CMaster\
  25. // 2. As of 10-02-14 the Arduino library page (reference above) has the wrong name for the include file
  26. //      it lists <SoftI2C.h> instead of <SoftI2CMaster.h> -- use the one that matches your installation.
  27. // 3. Make sure to load the library into the Arduino compiler.
  28. //      To do this go to: SKETCH >> IMPORT LIBRARY... >> ADD LIBRARY...
  29. //      Then navigate to C:\Program Files (x86)\Arduino\libraries\SoftI2CMaster\SoftI2CMaster.h
  30. // 4. Be sure to set the SCL and SDA pins so that they match the pins you are using.
  31. // 5. I have included 3 working "code examples" which differ from the 3 "functions" I included.
  32. //      The functions are all that should be required to quickly use the I2C library to talk to a MaxSonar.
  33. //      The three code examples show how I would implement each of the common tasks you may wish to do.
  34. // 6. The included functions are as follows:
  35. //      A. start_sensor(addr)
  36. //      B. read_sensor(addr)
  37. //      C. change_address(oldaddr,newaddr)
  38. // 7. The included code examples are as follows:
  39. //      A. read_the_sensor_example()
  40. //      B. address_polling_example()
  41. //      C. default_address_change_example()
  42. // 8. You do not have to keep track of the error codes passed out by the installed functions if you do not want to.
  43. //      I inluded the error tracking so that it was easy for others to build a reliable system -- and to ease
  44. //      troubleshooting. (not using it makes for cleaner code if you trust your interface)
  45. /*
  46. Below, I define the SCL and SDA pins by their ATMEGA pins I have included links to common mappings below.
  47.     UNO:  http://arduino.cc/en/Hacking/PinMapping168
  48.     NANO: (matches UNO but has fewer pins)
  49.     MEGA 2560: http://arduino.cc/en/Hacking/PinMapping2560
  50. The current data matches the setup for the Arduino Uno -- they may need to be changed if the hardware changes.
  51. You can also switch the I2C interface
  52. to any of the tristate pins that you want (not just the SDA or SCL pins).
  53. */
  54. #define SCL_PIN 5              //Default SDA is Pin5 PORTC for the UNO -- you can set this to any tristate pin
  55. #define SCL_PORT PORTC
  56. #define SDA_PIN 4              //Default SCL is Pin4 PORTC for the UNO -- you can set this to any tristate pin
  57. #define SDA_PORT PORTC
  58. #define I2C_TIMEOUT 100        //Define a timeout of 100 ms -- do not wait for clock stretching longer than this time
  59. /*
  60. I have included a couple of extra useful settings for easy reference.
  61. //#define I2C_CPUFREQ (F_CPU/8)//Useful if you plan on doing any clock switching
  62. #define I2C_FASTMODE 1         //Run in fast mode (400 kHz)
  63. #define I2C_SLOWMODE 1         //If you do not define the mode it will run at 100kHz with this define set to 1 it will run at 25kHz
  64. */
  65. #include <SoftI2CMaster.h>     //You will need to install this library
  66. void setup(){
  67.   // Initialize both the serial and I2C bus
  68.   Serial.begin(9600);
  69.   i2c_init();
  70.   // (OPTIONAL) Check each address for a sensor
  71.   address_polling_example();
  72.   /*
  73.     Note that I placed the address change example in setup() for a good reason.
  74.     Changing the sensor address causes an EEPROM write, there should only be ~1,000,000+
  75.       of these writes to the sensor microcontroller over its product lifetime.
  76.     Changing the address is fine, but doing it every second for the next 4 years may
  77.       cause reliability issues.
  78.   */
  79.   // (OPTIONAL) Run an address change example
  80.   default_address_change_example();  
  81.   // Your code here
  82. }
  83. void loop()
  84. {
  85.   // (OPTIONAL) Read a sensor at the default address
  86.   read_the_sensor_example();
  87.   // Your code here
  88. }
  89. ///////////////////////////////////////////////////
  90. // Function: Start a range reading on the sensor //
  91. ///////////////////////////////////////////////////
  92. //Uses the I2C library to start a sensor at the given address
  93. //Collects and reports an error bit where: 1 = there was an error or 0 = there was no error.
  94. //INPUTS: byte bit8address = the address of the sensor that we want to command a range reading
  95. //OUPUTS: bit  errorlevel = reports if the function was successful in taking a range reading: 1 = the function
  96. //  had an error, 0 = the function was successful
  97. boolean start_sensor(byte bit8address){
  98.   boolean errorlevel = 0;
  99.   bit8address = bit8address & B11111110;               //Do a bitwise 'and' operation to force the last bit to be zero -- we are writing to the address.
  100.   errorlevel = !i2c_start(bit8address) | errorlevel;   //Run i2c_start(address) while doing so, collect any errors where 1 = there was an error.
  101.   errorlevel = !i2c_write(81) | errorlevel;            //Send the 'take range reading' command. (notice how the library has error = 0 so I had to use "!" (not) to invert the error)
  102.   i2c_stop();
  103.   return errorlevel;
  104. }
  105. ///////////////////////////////////////////////////////////////////////
  106. // Function: Read the range from the sensor at the specified address //
  107. ///////////////////////////////////////////////////////////////////////
  108. //Uses the I2C library to read a sensor at the given address
  109. //Collects errors and reports an invalid range of "0" if there was a problem.
  110. //INPUTS: byte  bit8address = the address of the sensor to read from
  111. //OUPUTS: int   range = the distance in cm that the sensor reported; if "0" there was a communication error
  112. int read_sensor(byte bit8address){
  113.   boolean errorlevel = 0;
  114.   int range = 0;
  115.   byte range_highbyte = 0;
  116.   byte range_lowbyte = 0;
  117.   bit8address = bit8address | B00000001;  //Do a bitwise 'or' operation to force the last bit to be 'one' -- we are reading from the address.
  118.   errorlevel = !i2c_start(bit8address) | errorlevel;
  119.   range_highbyte = i2c_read(0);           //Read a byte and send an ACK (acknowledge)
  120.   range_lowbyte  = i2c_read(1);           //Read a byte and send a NACK to terminate the transmission
  121.   i2c_stop();
  122.   range = (range_highbyte * 256) + range_lowbyte;  //compile the range integer from the two bytes received.
  123.   if(errorlevel){
  124.     return 0;
  125.   }
  126.   else{
  127.     return range;
  128.   }
  129. }
  130. /////////////////////////////////////////
  131. // Function: Change the sensor address //
  132. /////////////////////////////////////////
  133. //Uses the I2C library to change the address of a sensor at a given address
  134. //Collects and reports an error bit where: 1 = there was an error or 0 = there was no error.
  135. //INPUTS: byte oldaddress = the current address of the sensor that we want to change
  136. //INPUTS: byte newddress  = the address that we want to change the sensor to
  137. //OUPUTS: bit  errorlevel = reports if the function was successful in changing the address: 1 = the function had an
  138. //      error, 0 = the function was successful
  139. boolean change_address(byte oldaddress,byte newaddress){
  140.   //note that the new address will only work as an even number (odd numbers will round down)
  141.   boolean errorlevel = 0;
  142.   oldaddress = oldaddress & B11111110;  //Do a bitwise 'and' operation to force the last bit to be zero -- we are writing to the address.
  143.   errorlevel = !i2c_start(oldaddress) | errorlevel; //Start communication at the new address and track error codes
  144.   errorlevel = !i2c_write(170) | errorlevel;        //Send the unlock code and track the error codes
  145.   errorlevel = !i2c_write(165) | errorlevel;        //Send the unlock code and track the error codes
  146.   errorlevel = !i2c_write(newaddress) | errorlevel; //Send the new address
  147.   i2c_stop();
  148.   return errorlevel;
  149. }
  150. //////////////////////////////////////////////////////////
  151. // Code Example: Read the sensor at the default address //
  152. //////////////////////////////////////////////////////////
  153. void read_the_sensor_example(){
  154.   boolean error = 0;  //Create a bit to check for catch errors as needed.
  155.   int range;
  156.   //Take a range reading at the default address of 224
  157.   error = start_sensor(224);    //Start the sensor and collect any error codes.
  158.   if (!error){                  //If you had an error starting the sensor there is little point in reading it as you will get old data.
  159.     delay(100);
  160.     range = read_sensor(224);   //reading the sensor will return an integer value -- if this value is 0 there was an error
  161.     Serial.print("R:");Serial.println(range);
  162.   }
  163. }
  164. ////////////////////////////////////////////////////////////////
  165. // Code Example: Poll all possible addresses to find a sensor //
  166. ////////////////////////////////////////////////////////////////
  167. void address_polling_example(){
  168.   boolean error = 0;  //Create a bit to check for catch errors as needed.
  169.   int range = 0;
  170.   Serial.println("Polling addresses...");
  171.   //Walk through all possible addresses and check for a device that can receive the range command and will
  172.   //    return two bytes.
  173.   for (byte i=2; i!=0; i+=2){   //start at 2 and count up by 2 until wrapping to 0. Checks all addresses (2-254) except 0 (which cannot be used by a device)
  174.     error = 0;
  175.     error = start_sensor(i);    //Start the sensor and collect any error codes.
  176.     if (!error){                //If you had an error starting the sensor there is little point in reading it.
  177.       delay(100);
  178.       range = read_sensor(i);   //reading the sensor will return an integer value -- if this value is 0 there was an error
  179.       Serial.println(i);
  180.       if (range != 0){
  181.         Serial.print("Device found at:");Serial.print(i);Serial.print(" Reported value of:");Serial.println(range);
  182.       }  
  183.     }
  184.     else{
  185.       Serial.print("Couldn't start:");Serial.println(i);
  186.     }
  187.   }
  188.   Serial.println("Address polling complete.");
  189. }
  190. //////////////////////////////////////////////
  191. // Code Example: Change the default address //
  192. //////////////////////////////////////////////
  193. void default_address_change_example(){
  194.   boolean error = 0;  //Create a bit to check for catch errors as needed.
  195.   int range;
  196.   Serial.println("Take a reading at the default address");
  197.   //Take a range reading at the default address of 224
  198.   error = start_sensor(224);    //Start the sensor and collect any error codes.
  199.   if (!error){                  //If you had an error starting the sensor there is little point in reading it.
  200.     delay(100);
  201.     range = read_sensor(224);   //reading the sensor will return an integer value -- if this value is 0 there was an error
  202.     Serial.print("R:");Serial.println(range);
  203.   }
  204.    Serial.println("Change the sensor at the default address to 222");
  205.   //Change the address from 224 to 222
  206.   error = 0;
  207.   error = change_address(224,222);  //Change the address -- I don't do anything with the error handler at this point but you can if you want.
  208.   delay(200);    //Wait 125ms for the sensor to save the new address and reset
  209.    Serial.println("Take a reading at the new address");
  210.   //Take a range reading at the new address of 222
  211.   error = 0;
  212.   error = start_sensor(222);     //Same as above but at the new address
  213.   if (!error){
  214.     delay(100);
  215.     range = read_sensor(222);
  216.     Serial.print("N:");Serial.println(range);
  217.   }  
  218.    Serial.println("Change the sensor back to the default address");  
  219.   //Change the address from 222 to 224
  220.   error = 0;
  221.   error = change_address(222,224);
  222.   delay(200);    //Wait 125ms for the sensor to save the new address and reset
  223. }


Una volta caricato il codice sarà sufficiente aprire il serial monitor (con baud rate 9600)
per iniziare a leggere la distanza tra il sensore e ciò che è nella sua traiettoria.

Questo è tutto, vi aggiungo il link dove potete trovare il datasheet del modulo,
per qualsiasi domanda lascia pure un commento.
Seguimi sulle mie pagine per rimanere sempre aggiornato sui nuovi post!

Nessun commento:

Posta un commento

Lascia un commento qui sotto, ti risponderò il prima possibile!

Altri Post