Skip to main content

Utilisation de Digilent PmodMAXSonar avec Arduino Due

awong
0

Le PmodMAXSonar est un télémètre à ultrasons. Il est actionné par MaxBotix® LV-MaxSonar®-EZ1™ (134-6439)  et peut mesurer des distances dans la gamme de 6 à 255 pouces (15 à 648 cm) avec une précision de 1 pouce (2,54 cm) pour chaque 50 millisecondes.

Interface avec PmodMAXSonar

Le Pmod MAXSONAR communique avec l'Arduino via le protocole UART, la sortie analogique et la synchronisation PWM. Le protocole UART est configuré avec un débit en bauds de 9 600, 8 bits, sans parité, et un seul bit d'arrêt. Le module peut être alimenté par 3,3 V ou 5 V. Voici le tableau de brochage.

Broche

Signal

1

Sortie analogique (AN)

2

Reception de données (RX)

3

Transmission de données (TX)

4

Modulation de largeur d'impulsion (PWM)

5

Masse (GND)

6

Alimentation électrique 3,3 V/5 V (Vcc)

Description temporelle

PmodMAXSonar a besoin de 250 millisecondes pour se mettre sous tension et effectue ensuite un auto-étalonnage si la broche (RX) est laissée à haute tension flottante ou au niveau logique. L'étalonnage prendra 49 ms, et après un temps d'attente supplémentaire de 100 ms, le module sera capable de prendre des mesures toutes les 49 millisecondes.

Au début de chaque période de 49 millisecondes, la RX est en position élevée ou ouverte, après quoi le PmodMAXSonar envoie la rafale d'émission, puis la broche de largeur d'impulsion (PW) est placée en position élevée. Lorsqu'un objet est détecté, la broche de largeur d'impulsion est placée en position basse. Si aucun objet n'est détecté, la broche PW est élevée pendant 37,5 millisecondes. Le reste du temps de 49 millisecondes (moins 4,7 millisecondes) est consacré à ajuster la tension analogique au niveau correct. Lorsqu'une longue distance est mesurée immédiatement après une courte distance, la tension analogique peut ne pas atteindre le niveau exact dans un cycle de lecture. Au cours des 4,7 dernières millisecondes, les données en série sont envoyées.

Distance de capture par les broches TX, AN ou PW

Lorsque la broche RX est laissée flottante ou maintenue à un niveau logique haute tension, 5 octets sont envoyés sur la broche TX en commençant par le caractère ASCII majuscule « R », trois chiffres ASCII représentant la distance détectée et un caractère de retour de chariot (caractère ASCII 13).

Un signal analogique représentatif de la distance mesurée de l'objet devant le Pmod MAXSONAR peut également être lu. La sortie a une résolution de neuf bits. Avec une alimentation à 3,3 V, chaque pouce équivaut à ~6,4 mV. Les utilisateurs qui mesurent le signal analogique entrant avec un ADC de 10 bits classique devront diviser leur valeur mesurée par 2 avant de calculer la distance rapportée.

Le Pmod MAXSONAR fournit également des données de distance par le biais d'un signal à modulation de largeur d'impulsion. Chaque période de mesure de la broche de 147 uS à un état de haute tension de niveau logique équivaut à une distance de 1 pouce. Si le signal est mesuré comme étant élevé pendant 2,205 millisecondes, alors l'objet détecté se trouve à 15 pouces de l'avant du Pmod MAXSONAR. Le temps d'impulsion maximum mesuré de 37,5 millisecondes indique qu'il n'y a aucun objet à moins de 255 pouces du Pmod.

Connexion à Arduino Due (769-7412)

  1. PmodVcc  à Arduino Due 3V3
  2. Pmod GND à Arduino Due  GND.
  3. Pmod AN à Arduino Due A0 (pour le mode analogique)
  4. Pmod PW à Arduino Due D2 (pour la détermination de la largeur d'impulsion)
  5. Broches Pmod RX et TX à Serial3 (broches 14 et 15) pour la communication UART.

Les résultats des mesures sont affichés dans le moniteur série.

/************************************************************************

  Distance measurement using Pmod MAXSonar and Arduino Due

*************************************************************************

  Description: Pmod_MAXSonar, Arduino_Due
  The mode of the communication is selectable, as well as the unit.
  Measurement results are displayed on the serial monitor (use the programming USB port for serial communication - near the DC plug)

  Material
  1. Arduino Due
  2. Pmod MAXSonar

  Wiring
  Pmod <----------> Arduino
  VCC       to        3V3
  GND       to        GND
  PW        to        2     *
  TX        to        15    *
  RX        to        14    *
  AN        to        A0    *

   You can choose to connect PW and RX, TX and RX, or AN and RX, for pulse width, UART, or analog measurements

************************************************************************/

//define connections
#define PW 2  //PWM output
#define TX 15 //UART send
#define RX 14 //UART recieve
#define AN A0 //analog output

//define measurement mode (uncomment the chosen mode - default: none)
#define ANALOG     //output: analog voltage
#define PULSEWIDTH //output: PWM signal
#define UART       //output: UART

//define measurement unit (uncomment the chosen unit - default: INCH)
#define CM //output in cm
//#define MM      //output in mm
//#define INCH    //output in inch

//define UART timeout
#define timeout 50 //timeout for UART communication in ms

/*------------------------------------------------------------------------*/

//function prototypes
int MAXSonar_begin(int RX_pin);                   //initializes the sensor in the chosen mode
float MAXSonar_getDistance(int pin, String mode); //returns the measured distance in the chosen unit
void MAXSonar_end(int RX_pin);                    //terminates the communication with the pmod
void display_unit(void);                          //display the measurement unit on the serial monitor

/*------------------------------------------------------------------------*/

//define serial
#ifdef UART //if uart is used
#if (RX == 14)
#define Ser Serial3 //serial 3 is used
#elif (RX == 16)
#define Ser Serial2 //serial 2 is used
#elif (RX == 18)
#define Ser Serial1 //serial 1 is used
#else
#define Ser Serial //serial monitor is used
#endif
#endif

/*------------------------------------------------------------------------*/

void setup()
{
  Serial.begin(9600);            //initialize serial communication
  Serial.println("Starting..."); //display a message

  pinMode(RX, OUTPUT);   //set pin as output
  digitalWrite(RX, LOW); //disable the pmod

#ifdef PULSEWIDTH //check if PWM mode is used or not
  pinMode(PW, INPUT); //configure pin only if required
#endif

#ifdef UART        //if uart is used
  Ser.begin(9600); //start hardware serial if necessary
#endif

  delay(1000); //wait one second (make the message readable and allow power up)
}

/*------------------------------------------------------------------------*/

void loop()
{
  //analog aquisition
  Serial.println("Analog aquisition mode: "); //display aquisition mode
  Serial.print("\tdistane: ");
  MAXSonar_begin(RX);                               //initialize the pmod
  Serial.print(MAXSonar_getDistance(AN, "analog")); //display measurement result
  MAXSonar_end(RX);                                 //end communication
  display_unit();                                   //display measurement unit

  //pwm aquisition
  Serial.println("PWM aquisition mode: "); //display aquisition mode
  Serial.print("\tdistane: ");
  MAXSonar_begin(RX);                            //initialize the pmod
  Serial.print(MAXSonar_getDistance(PW, "pwm")); //display measurement result
  MAXSonar_end(RX);                              //end communication
  display_unit();                                //display measurement unit

  //UART aquisition
  Serial.println("UART aquisition mode: "); //display aquisition mode
  Serial.print("\tdistane: ");
  MAXSonar_begin(RX);                             //initialize the pmod
  Serial.print(MAXSonar_getDistance(RX, "uart")); //display measurement result
  MAXSonar_end(RX);                               //end communication
  display_unit();                                 //display measurement unit

  Serial.println(); //leave a line out
  delay(3000);      //wait 3 seconds between measurements
}

/*------------------------------------------------------------------------*/

/*
  initializes the sensor and starts the conversion sequence
  arguments: RX pin, PW pin (optional, if PWM mode is used)
  returns: 0 = success, else there is an error
*/
int MAXSonar_begin(int RX_pin)
{
  digitalWrite(RX_pin, HIGH); //enable the pmod
  return 0;                   //no error
}

/*------------------------------------------------------------------------*/

/*
  returns the measured distance in the chosen unit
  arguments: RX/PW/AN pin (dependent of the mode), mode ("analog"/"pwm"/"uart")
  returns: the measured distance, or -1 if there is an error
*/
float MAXSonar_getDistance(int pin, String mode)
{
  float distance;

  //analog mode
  if (mode.equals("analog"))
  {
#ifdef ANALOG                         //if the mode is enabled
    distance = analogRead(pin) / 2.0; //read voltage and convert to inch
#else
    return -1;             //return -1 if the analog mode is disabled
#endif
  }

  /*---------------------------------*/

  //pwm mode
  else if (mode.equals("pwm"))
  {
#ifdef PULSEWIDTH //if the mode is enabled
    int index = 0;
    while (digitalRead(pin) != HIGH && (index < timeout)) //wait for result/timeout
    {
      delay(1); //if data is not available, wait 1ms
      index++;  //count iterations
    }
    if (index == timeout) //check for timeout
    {
      return -1; //no data available
    }

    index = 0;   //loop iteration index
    while (true) //repeat
    {
      delayMicroseconds(147);                         //wait: 147us = 1 inch (acording to datasheet)
      index++;                                        //step index
      if ((digitalRead(pin) == LOW) || (index > 255)) //check if the pulse finished or is out of range
      {
        if (index > 255) //check for out of range error
        {
          return -1; //out of range error
        }
        else
        {
          distance = index * 1.0; //save pulse width = distance in inch
          break;                  //exit loop
        }
      }
    }
#endif
  }

  /*---------------------------------*/

  //uart mode
  else if (mode.equals("uart"))
  {
#ifdef UART //if the mode is enabled

    //wait for data/timeout
    int index = 0; //loop iteration counter
    while (!Ser.available() && (index < timeout))
    {
      delay(1); //if data is not available, wait 1ms
      index++;  //count iterations
    }
    if (index == timeout) //check for timeout
    {
      return -1; //no data available
    }

    /*--------------*/

    //read measurement
    char raw_data[3];    //array for data bytes
    if (Ser.available()) //if data is available
    {
      Ser.read();            //discard the first byte
      if (Ser.read() == 234) //data start
      {
        for (int i = 0; i < 3; i++) //read 3 data bytes
        {
          while (!Ser.available()) //wait for the byte
            ;
          raw_data[i] = Ser.read(); //and save it
        }
        while (!Ser.available()) //wait for endline to signal data end
          ;
        if (Ser.read() == 13) //check for return character
        {
          distance = String(raw_data).toInt() * 1.0; //convert bytes to inch
        }
        else
        {
          return -1; //packet error
        }
      }
      else
      {
        return -1;  //packet error
      }
    }
#endif
  }

  /*---------------------------------*/

  if (distance != -1) //don't convert erronouos results
  {
    //convert the result if required
#if defined(CM)
    distance *= 2.54; //convert to cm
#elif defined(MM)
    distance *= 2.54 * 10; //convert to mm
#endif
  }

  return distance; //return the result
}

/*------------------------------------------------------------------------*/

/*
  terminates the communication with the pmod
  arguments: RX pin
  returns: none
*/
void MAXSonar_end(int RX_pin)
{
  //disable the pmod
  digitalWrite(RX_pin, LOW);
}

/*------------------------------------------------------------------------*/

/*
  displays the measurement unit on the serial monitor
  arguments: none
  returns: none
*/
void display_unit(void)
{
  //inch
#ifdef INCH
  Serial.println(" inch"); //dispay message
  return;
#endif

  //cm
#ifdef CM
  Serial.println(" cm"); //dispay message
  return;
#endif

  //mm
#ifdef MM
  Serial.println(" mm"); //dispay message
  return;
#endif
}
Love learn engineering in hands-on approach. Interested in new technology. Work in Digilent as International Sales and Distribution Manager.

Contenu Connexe

Commentaires

DesignSpark Electrical Logolinkedin