A library is available at https://github.com/Diaoul/arduino-Maxbotix
It features:
I recommend looking at the examples to get started with it.
This is a writeup on the MaxSonar ultrasonic range finder. I felt there was a lack of information out there on this product so I thought this might help out people who are learning.
First of all, I used the LV-MaxSonar EZ1 but I imagine the fundamentals will be the same and can be applied to all the MaxSonar products.
Please feel free to update the information here if you find different results for different products.
There are 3 ways to interface the MaxSonar.
//Feel free to use this code.
//Please be respectful by acknowledging the author in the code if you use or modify it.
//Author: Bruce Allen
//Date: 23/07/09
//Analog pin 1 for reading in the analog voltage from the MaxSonar device.
//This variable is a constant because the pin will not change throughout execution of this code.
const int anPin = 1;
//variables needed to store values
long anVolt, inches, cm;
int sum = 0; //Create sum variable so it can be averaged
int avgrange = 60; //Quantity of values to average (sample size)
void setup()
{
//This opens up a serial connection to shoot the results back to the PC console
Serial.begin(9600);
}
void loop()
{
//MaxSonar Analog reads are known to be very sensitive. See the Arduino forum for more information.
//A simple fix is to average out a sample of n readings to get a more consistent reading.
//Even with averaging I still find it to be less accurate than the PW method.
//This loop gets 60 reads and averages them
for (int i = 0; i < avgrange ; i++)
{
//Used to read in the analog voltage output that is being sent by the MaxSonar device.
//Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
//Arduino analog pin goes from 0 to 1024, so the value has to be divided by 2 to get the actual inches
anVolt = analogRead(anPin) / 2;
sum += anVolt;
delay(10);
}
inches = sum / avgrange;
cm = inches * 2.54;
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
//reset sample total
sum = 0;
delay(500);
}
I found this to be more accurate than the analog method and just as easy to implement.
//Feel free to use this code.
//Please be respectful by acknowledging the author in the code if you use or modify it.
//Author: Bruce Allen
//Date: 23/07/09
//Digital pin 7 for reading in the pulse width from the MaxSonar device.
//This variable is a constant because the pin will not change throughout execution of this code.
const int pwPin = 7;
//variables needed to store values
long pulse, inches, cm;
void setup()
{
//This opens up a serial connection to shoot the results back to the PC console
Serial.begin(9600);
}
void loop()
{
pinMode(pwPin, INPUT);
//Used to read in the pulse that is being sent by the MaxSonar device.
//Pulse Width representation with a scale factor of 147 uS per Inch.
pulse = pulseIn(pwPin, HIGH);
//147uS per inch
inches = pulse / 147;
//change inches to centimetres
cm = inches * 2.54;
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(500);
}
Based on the above examples and the median filter provided below, I made a mode filter for too be used with the sonar. I used this in conjunction with pulse width, but I'm sure it would work with the analog readings just as well.
/*
This script is designed to take several readings from the MaxBotix sonar and generate a mode/median.
Author: Jason Lessels
Date created: 2011/June/06
License: GPL (=>2)
This work has been compiled using many sources mainly posts/wiki posts from;
Allen, Bruce (2009/July/23) and Gentles, Bill (2010/Nov/12)
*/
//Set the pin to receive the signal.
const int pwPin = 7;
//variables needed to store values
int arraysize = 9; //quantity of values to find the median (sample size). Needs to be an odd number
//declare an array to store the samples. not necessary to zero the array values here, it just makes the code clearer
int rangevalue[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0};
long pulse;
int modE;
void setup()
{
//Open up a serial connection
Serial.begin(9600);
//Wait for the serial connection
delay(500);
}
//Main loop where the action takes place
void loop()
{
pinMode(pwPin, INPUT);
for (int i = 0; i < arraysize; i++)
{
pulse = pulseIn(pwPin, HIGH);
rangevalue[i] = pulse / 58;
delay(10);
}
Serial.print("Unsorted: ");
printArray(rangevalue, arraysize);
isort(rangevalue, arraysize);
Serial.print("Sorted: ");
printArray(rangevalue, arraysize);
modE = mode(rangevalue, arraysize);
Serial.print("The mode/median is: ");
Serial.print(modE);
Serial.println();
delay(1000);
}
/*-----------Functions------------*/
//Function to print the arrays.
void printArray(int *a, int n)
{
for (int i = 0; i < n; i++)
{
Serial.print(a[i], DEC);
Serial.print(' ');
}
Serial.println();
}
//Sorting function
// sort function (Author: Bill Gentles, Nov. 12, 2010)
void isort(int *a, int n) {
// *a is an array pointer function
for (int i = 1; i < n; ++i)
{
int j = a[i];
int k;
for (k = i - 1; (k >= 0) && (j < a[k]); k--)
{
a[k + 1] = a[k];
}
a[k + 1] = j;
}
}
//Mode function, returning the mode or median.
int mode(int *x, int n) {
int i = 0;
int count = 0;
int maxCount = 0;
int mode = 0;
int bimodal;
int prevCount = 0;
while (i < (n - 1)) {
prevCount = count;
count = 0;
while (x[i] == x[i + 1]) {
count++;
i++;
}
if (count > prevCount & count > maxCount) {
mode = x[i];
maxCount = count;
bimodal = 0;
}
if (count == 0) {
i++;
}
if (count == maxCount) { //If the dataset has 2 or more modes.
bimodal = 1;
}
if (mode == 0 || bimodal == 1) { //Return the median if there is no mode.
mode = x[(n / 2)];
}
return mode;
}
}
After using the above examples, I felt the need to contribute to this page. Please feel free to use this sketch for serial communication between your Ardunio and LV-MaxSonar Note: the LV-MaxSonar's Rx and Tx pins (RS232 interface) are directly connected to the Arduino's digital inputs (no inversion used i.e RS232 logic).
/*
MaxSonar Serial
When uploaded to an Arduino, this sketch allows an Arduino to read multiple readings
from a MaxSonar and print these reading to the Arduino IDE serial monitor.
The Arduino powers the MaxSonar and reads data from MaxSonar's Tx pin (simplex); the
interface between the sensor and Arduino is RS232 at TTL voltage levels
The protocol uses one start bit and one end bit for every data-byte(no
error detection). The Maxsonar's rx is used for software flow control.
The data-bytes are coded using ASCII format where each reading is precedded by the 'R'
character and ended by the return carriage.
The arduino prints the each reading to the serial monitor.
Author: Daniel Matthews
Date: January 2018
*/
//the pin connected to MaxSonar's tx pin
#define rx 6
//the pin connected to MaxSonar's rx pin
#define tx 7
//the bit duration and the bit half duration at 9600bits/second
#define bit9600Delay 104
#define halfBit9600Delay 52
//the number of bytes in a data packet
#define numberOfBytes 5
/* function declarations*/
//function to read a packet(reading) from the sensor
boolean readSonar(char []);
//function to read a byte from the sensor
void readSonarByte(char *);
//function to print reading to the serial monitor
void printSonarMessage(char []);
//function to print data from sensor to the serial monitor (to troubleshoot)
void printSonarData(char []);
void setup()
{
// initalise the serial communication (USB) at 9600bits per second
Serial.begin(9600);
// define the rx pin to be an input in and the tx line pin to be an output pin
pinMode(rx, INPUT);
pinMode(tx, OUTPUT);
//start ranging by pulling the tx line high
digitalWrite(tx, HIGH);
}
void loop()
{
// put your main code here, to run repeatedly:
// packet(string) from the sensor
char range[numberOfBytes];
// boolean to check if the data is complete (i.e first byte is 'R')
boolean invalidReading;
//read data from the sensor
invalidReading = readSonar(range);
//if the data is complete, print reading to the serial monitor
if(!invalidReading)
{
//comment out the below line to see data from sensor in different formats!
//printSonarData(range);
//print data to the serial monitor
printSonarMessage(range);
}
//delay between taking readings from the sensor
delay(100);
}
boolean readSonar(char range[])
{
//counting variable (for character index)
int i = 0;
//boolean to store
boolean invalid = false;
//read a byte of data from the rx line
readSonarByte(&range[0]);
//if this byte is the first, keep reading bytes from the rx line
if (range[0] == 'R')
{
//keep reading until the last byte (in the message) is read
while(i < numberOfBytes)
{
readSonarByte(&range[++i]);
}
}
else
{
//message is incomplete as start has not been read
invalid = true;
}
return invalid;
}
void readSonarByte(char *value)
{
//wait until the end of the start bit
*value = 0;
while(digitalRead(rx) == 0);
//wait until the end of the start bit
if(digitalRead(rx) == HIGH)
{
//wait half a bit to improve sampling
delayMicroseconds(halfBit9600Delay);
for (int bitShift = 0; bitShift < 7; bitShift++)
{
//wait for next bit
delayMicroseconds(bit9600Delay);
//read bit of data and store in the character
//by reading rx line, inverting that signal,
//binary shifting the signal to correct position
//and bit-wise 'oring' that mask with the current character
*value |= ((!digitalRead(rx)) << bitShift);
}
//wait for end bit
delayMicroseconds(bit9600Delay);
}
}
void printSonarMessage(char range[])
{
//replace the return carriage with null
//so that character array is a printable string
range[numberOfBytes-1] = 0;
//print string (reading) to the serial monitor
Serial.println(range);
}
void printSonarData(char range[])
{
//print the data in differnt formats
for(int i = 0; i < numberOfBytes; i++)
{
//print the byte (element) number in the character array
Serial.print(i);
Serial.print("\t");
//print the byte in ASCII format
Serial.print(range[i]);
Serial.print("\t");
//print the byte in hexidecimal
Serial.print(range[i], HEX);
Serial.print("\t");
//print the byte in decimal
Serial.print(range[i], DEC);
Serial.print("\t");
//print the byte in binary
Serial.println(range[i], BIN);
}
}
Please check this page before using LV-MaxSonar:
http://forum.arduino.cc/index.php/topic,20920.html
You can find a very useful post by Scott from MaxBotix Inc.
Take care with:
enjoy!
karduino:D