Show Posts
Pages: [1]
1  Using Arduino / Sensors / MaxBotics HRXL-MaxSonar-WR 7380 working code, mm-resolution ultrasonic ranging on: November 05, 2012, 12:27:12 pm
The output is clean digital data, no analog calibration necessary.  Handy for my research group, thought it might help others as well.

Code:
/* 
    HRXL MaxSonar WR TTY serial communication example sketch
    Ultrasonic rangefinding

    Original bits by Logan Park, Ph.D., in honor of his astonishingly beautiful wife.
   
    Pretty much everything else is...
    based on: http://www.maxbotix.com/documents/HRXL-MaxSonar-WR_Datasheet.pdf
    and on the Arduino Mega 2560 ADK: http://arduino.cc/en/Main/ArduinoBoardADK
    and on this handy ASCII chart: http://www.csgnetwork.com/asciiset.html
    and a bunch of posts on the Arduino forums.

    1. Connect pin 5 (tty/serial) of the ranging unit to pin 19 (Serial1 RX) on the Mega 2560.
    2. Connect pin 6 of the ranging unit to any 5V supply on the Mega 2560.
    3. Connect pin 7 of the ranging unit to any GND on the Mega 2560.
 */


int current_range_reading = -99;

void setup()
{
  Serial.begin(115200); // Set your computer's serial terminal baud rate to this.
  Serial1.begin(9600); // This is what the MaxBotics TTY sonar output needs.
}

void loop()
{
  if (Serial1.available() > 5)  // Then at least one complete range, 6 characters long, is stored in the RX buffer.
  {
    int inByte = Serial1.read(); // Examine the first stored character and decide what to do.

    if( inByte == 82 ) // "R" character
    {
      int thousands = (Serial1.read() - '0') * 1000; // Take and convert each range digit to human-readable integer format.
      int hundreds = (Serial1.read() - '0') * 100;
      int tens = (Serial1.read() - '0') * 10;
      int units = (Serial1.read() - '0') * 1;
      int cr = Serial1.read(); // Don't do anything with this, just clear it out of the buffer with the rest.
     
      // Assemble the digits into the range integer.
      current_range_reading = thousands + hundreds + tens + units;
      if(current_range_reading == 300) //This is the minimum reading for the HRXL MaxSonar WR 7380, not the actual distance
      {
        Serial.println("too close!");
      }
      else if(current_range_reading == 5000) //This is the max reading for the HRXL MaxSonar WR 7380, not the actual distance
      {
        Serial.println("too far!");
      }
      else
      {
        Serial.print("Range (mm): ");
        Serial.println(String(current_range_reading));
      }
    }
    else if( inByte == 13 ) // Carriage Return  character, oops!
    {
      //Serial.println();
    }
    else if( inByte == -1 ) // Just in case!  This shouldn't happen if Serial1.available() returns true.
    {
      Serial.println("RX buffer empty, wth?");
      return;
    }
  }
  else
  {
    //Serial.print("RX buffer not ready");  // This is very spammy, uncomment at your own risk.
  }
}
2  Using Arduino / Programming Questions / Re: Howto redirect (convert from hex to dec/Serial.print) fcn output into a var? on: November 04, 2012, 09:08:41 pm
Success!

I googled around for a BCD --> DEC conversion utility function and found

Code:
uint8_t bcdToDec(uint8_t val)
{
  return ( (val / 16 * 10) + (val % 16));
}

And the output appears to be correct.  Thanks again.
3  Using Arduino / Programming Questions / Re: Howto redirect (convert from hex to dec/Serial.print) fcn output into a var? on: November 04, 2012, 11:58:51 am
Excellent!  I appreciate your guidance.  Here's the output:

Code:
sprintf datetime is: 18-17-04_17:81:09, Sun
,
which should be:
Code:
sprintf datetime is: 12-11-04_11:51:09, Sun
.

So, I think the sprintf codeblock is correctly recognizing input from the r[] array.  The code is getting close; I think I need to bitshift or some similar operation.  I notice that when a byte is reported incorrectly, it is off by six, typically.  So that makes me wonder if I'm failing to convert to/from hex/dec. 

Here's the codeblock based on everyone's input and the man page:

Code:

const char *SD_datetime_mask =
  {
    PSTR("sprintf datetime is: %02d-%2d-%.2d_%.2d:%.2d:%.2d, %s ")
  };

  sprintf_P(SD_datetime, SD_datetime_mask, r[6], r[5], r[4], r[2], r[1], r[0], Ddd[r[3]]);
  Serial.print(SD_datetime);

Elsewhere, the functional code that goes straight to Serial.print uses:
Code:
 Serial.print(v >> 4, HEX);
  Serial.print(v & 0XF, HEX);

I think I need to apply those operations somehow to my data before displaying the sprintf'ed string.  Am I on the right track?
4  Using Arduino / Programming Questions / Re: Howto redirect (convert from hex to dec/Serial.print) fcn output into a var? on: November 04, 2012, 11:32:31 am
Ok, I have been poring over the linux man pages for (s)printf, and have come up with:
Code:
char SD_datetime[100];

 sprintf(SD_datetime, "%s-%s-%s-%.2d-%.2d-%.2d", r[6], r[5], r[4], r[2], r[1], r[0]);
  Serial.print("||||| sprintf version: ");
  Serial.print(SD_datetime);
  Serial.print("|||||");

where the r array is filled by
Code:
readDS1307(0, r, 8)

and readDS1307() is
Code:
uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
  // issue a start condition, send device address and write direction bit
  if (!rtc.start(DS1307ADDR | I2C_WRITE)) return false;

  // send the DS1307 address
  if (!rtc.write(address)) return false;

  // issue a repeated start condition, send device address and read direction bit
  if (!rtc.restart(DS1307ADDR | I2C_READ))return false;

  // read data from the DS1307
  for (uint8_t i = 0; i < count; i++) {

    // send Ack until last byte then send Ack
    buf[i] = rtc.read(i == (count-1));
  }

  // issue a stop condition
  rtc.stop();
  return true;
}


The output I get is... blank. 

Krupsi, I will next work on adapting your example into the code to see what happens.  Thank you for providing a detailed answer!
5  Using Arduino / Programming Questions / Re: Howto redirect (convert from hex to dec/Serial.print) fcn output into a var? on: November 04, 2012, 10:46:08 am
Where is this function:
Code:
readDS1307(0, r, 8)
defined/implemented?

Hi, PaulS,

Wow, you guys are fast!  The RTC read function is:

Code:
uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
  // issue a start condition, send device address and write direction bit
  if (!rtc.start(DS1307ADDR | I2C_WRITE)) return false;

  // send the DS1307 address
  if (!rtc.write(address)) return false;

  // issue a repeated start condition, send device address and read direction bit
  if (!rtc.restart(DS1307ADDR | I2C_READ))return false;

  // read data from the DS1307
  for (uint8_t i = 0; i < count; i++) {

    // send Ack until last byte then send Ack
    buf[i] = rtc.read(i == (count-1));
  }

  // issue a stop condition
  rtc.stop();
  return true;
}
6  Using Arduino / Programming Questions / Howto redirect (convert from hex to dec/Serial.print) fcn output into a var? on: November 04, 2012, 10:10:10 am
Hello!  Very new to Hex/Dec conversion, and I haven't been able to locate the right arduino/C++ tutorial yet.

I have the following function to retrieve datetime information from a real-time clock (RTC) chip on the Adafruit data logger shield:

Code:
void displayTime(void) {
  uint8_t r[8];
  if (!readDS1307(0, r, 8)) {
    PgmPrintln("Read Failed for display time");
    return;
  }
  PgmPrint("The current time is ");
  // month
  hexPrint(r[5]);
  Serial.write('/');
  // day
  hexPrint(r[4]);
  PgmPrint("/20");
  // year
  hexPrint(r[6]);
  Serial.write(' ');
// and so on for the time variables.
}

The hexPrint function referenced above is:
Code:
void hexPrint(uint8_t v) {
  Serial.print(v >> 4, HEX);
  Serial.print(v & 0XF, HEX);
}

And it all works great, echoing the correctly-set date through my Mega 2560's serial output.  However, I'd like to capture the output--human-readable date-- into the datalogger's line-by-line entries.  How do I modify the displayTime/hexPrint function to save the readable date into a variable, not jet it out through serial?

Thank you!
7  Development / Other Hardware Development / Re: Arduino Laser Range Finder on: October 29, 2012, 09:10:18 pm
We've been hacking around with two AL_01 kits for a few weeks now in my research group and have enjoyed them immensely.  I wrote a short post on our early experiences here: research group blog

The rangefinding works quite well enough for our purposes, esp. once we configured averaging = off by default in the EEPROM.  We're using one of the kits to scan for movement at high relative speeds (30-50mph), so we learn more about the passing object from non-averaged data.  Good times are experienced with 20+ Hz sampling rate.

We have, however, hit the memory ceiling for the UNO board (32k) and want to switch to a Mega 2560 for the extra headroom (256k), but the SPI pin mapping is different (Mega = 50-53 vs. UNO = AL_01 = 10-13).  Is there a way to change the pins the laser board is looking for?  This isn't a design problem with the AL_01 kit at all, it is primarily an Arduino programming question, so, OK to punt if you need to.

So far we have found in constants.h from the AL_01 Arduino sketch files:

Code:
// SPI Hardware
#define SPI_CHIPSELECT_PIN        10
#define DATA_READYN_PIN           9

I should note that our setup is Mega2560 --> Wireless SD shield (for datalogging) --> AL_01 board all snugly stacked on the header pins.  

I also want to note that Tracy has been OUTSTANDING on support over email over the past month.  I thought other folks on the fence about buying these AL_01 kits should know that.  It is rare to get decent support these days but Lightware has really treated us well.  I have no commercial connection to them so I can say that without bias.  smiley
Pages: [1]