Hey! Sie scheinen aus United States zu kommen, möchten Sie auf die Englisch Webseite wechseln?
Switch to Englisch site
Skip to main content

Verwendung des Digilent Pmod MAXSonar mit Arduino Due

Das Pmod MAXSonar ist ein Ultraschall-Entfernungsmesser. Es wird von  MaxBotix® LV-MaxSonar®-EZ1™ (134-6439) angetrieben und kann alle 50 Millisekunden Entfernungen Messungen in einem Bereich von 15 bis 648 cm (6 bis 255 Zoll) mit einer Genauigkeit von 2,54 cm (1 Zoll) anstellen.

Schnittstelle mit Pmod MAXSonar

Der Pmod MAXSONAR kommuniziert via dem UART-Protokoll mit dem Arduino, dem Analogausgang und dem PWM-Timing. Das UART-Protokoll ist mit einer Baudrate von 9600, 8 Bit, keiner Parität und einem einzelnen Stoppbit konfiguriert. Das Modul kann mit 3,3 V oder 5 V betrieben werden. Die Pinbelegungstabelle sieht wie folgt aus:

Pin

Signal

1

Analogausgang (AN)

2

Daten empfangen (RX)

3

Daten übertragen (TX)

4

Pulsweitenmodulation (PWM)

5

Boden (GND)

6

3,3 V / 5 V Stromversorgung (Vcc)

Beschreibung der Zeiteinteilung

Das Pmod MAXSonar benötigt 250 Millisekunden zum Einschalten und führt danach eine Selbstkalibrierung durch, wenn der (RX)-Pin auf einem hohem Schwebeladungslevel oder einem hohen Logikspannungslevel belassen wird. Die Kalibrierung dauert 49 ms. Nach weiteren 100 ms Wartezeit kann das Modul alle 49 ms Messwerte erfassen.

Jede 49-Millisekunden-Periode beginnt damit, dass der RX hoch oder offen ist. Danach sendet der Pmod MAXSonar den Sendeburst, wonach der Pulsbreiten-Pin (PW) auf hoch gesetzt wird. Wenn ein Objekt erkannt wird, wird der PW-Pin nach unten gezogen. Wenn kein Objekt erkannt wird, ist der PW-Pin für bis zu 37,5 Millisekunden hoch. Der Rest der 49-Millisekunden-Periode (weniger als 4,7 Millisekunden) wird mit der Einstellung der analogen Spannung auf das korrekte Level verbracht. Wenn unmittelbar nach einer kurzen Entfernungsmessung eine weite Entfernung gemessen wird, erreicht die analoge Spannung den exakten Pegel möglicherweise nicht innerhalb eines Lesezyklus. Während der letzten 4,7 Millisekunden werden die seriellen Daten gesendet.

pmodmaxsonar_timingdiagram11_63871777054a811cc74c3038a840b7a57bd741df.png

Erfassung der Entfernung über den TX-, AN- oder PW-Pin

Wenn der RX-Pin schwebend bleibt oder auf einem hohen Logikspannungslevel gehalten wird, werden über den TX-Pin 5 Bytes gesendet. Diese bestehen beginnend aus dem ASCII-Großbuchstaben ‚R‘, darauffolgend drei ASCII-Ziffern, die die erkannte Entfernung darstellen, und am Schluss einem Return-Steuerzeichen (ASCII-Zeichen 13).

Ein analoges Signal kann ebenfalls gesendet werden, das die gemessene Entfernung des Objekts vor dem Pmod MAXSONAR repräsentiert. Der Ausgang hat eine Auflösung von neun Bit. Bei einer Stromversorgung von 3,3 V entspricht jeder Zoll ~6,4 mV. Nutzer, die das eingehende analoge Signal mit einem gängigen 10-Bit-ADC messen, müssen vor der Berechnung der gemeldeten Distanz ihren Messwert durch 2 dividieren.

Das Pmod MAXSONAR liefert auch  über ein Pulsweitenmodulationssignal Entfernungsdaten. Alle 147 μs, die der Pin auf einem hohen Logikspannungslevel gemessen wird, entsprechen einem Abstand von 1 Zoll. Wenn das Signal 2,205 Millisekunden lang als hoch gemessen wird, befindet sich das erkannte Objekt also 15 Zoll von der Vorderseite des Pmod MAXSONAR entfernt. Die maximal messbare Pulszeit von 37,5 Millisekunden zeigt an, dass sich innerhalb von 255 Zoll vom Pmod entfernt kein Objekt befindet.

Mit dem Arduino Due (769-7412) verbinden

  • Pmod Vcc zu Arduino Due 3V3 
  • Pmod GND zu Arduino Due GND.
  • Pmod AN zu Arduino Due A0 (für den analogen Modus)
  • Pmod PW zu Arduino Due D2 (zur Pulsweitenmessung)
  • Pmod RX- und TX-Pins zu Serial3 (Pins 14 und 15) für die UART-Kommunikation

Messergebnisse werden im seriellen Monitor angezeigt.

result1_647a999e87619668404be30ca63f729e2c98babe.png

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

  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
}
awong hat noch keine Biografie verfasst...
DesignSpark Electrical Logolinkedin