Sunday, September 30, 2012

Arduino Mega + URM04 v2.0 + SPI LCD

As I noticed in previous post there is a way to connect your URM04 v2.0 ultrasonic sensor to Arduino without IO expansion shield.
Initial circuit is instable because it is extremely sensitive to any electrical interference due to the fact that it doesn't have appropriate "protection" - even if you just bring your hand too close to the wires (in case if your body is not grounded) circuit functioning will be broken and you will have to reset Arduino.
This issue may be fixed easily by adding several components: line termination resistor, decoupling (bypass) capacitor, pull-up, pull-down and load resistors - to the circuit (refer to URM04 v2.0 wiki page):
"Upgraded" circuit is stable and works great:
I have also connected  128x64 SPI LCD module to display measured distance on its screen.
Provided SPI LCD library does not work with Arduino 1.0 IDE (only with Arduino 0.23 AFAIK), so I've modified it a bit to correct this confusion - LCD12864RSPI.7z.
Coding:
// SPI LCD <--> Arduino:
// SID <-> Digital 9
// CS <-> Digital 8
// SCK <-> Digital 3
// GND <-> GND
// (?) <-->
// VCC <-> 5V
//
// URM04 v2.0 <--> RS485 board:
// + <--> VCC
// A <--> A
// B <--> B
// - <--> GND
//
// RS485 circuit <--> Arduino:
// VCC <--> 5V
// 1 <--> Digital 19 (RX1)
// 2 <--> Digital 2
// 3 <--> Digital 18 (TX1)
// GND <--> GND
//
#include <LCD12864RSPI.h>
//
//#define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )
//unsigned char wangzhi[]=" www.DFRobot.com ";//
//unsigned char en_char1[]="ST7920 LCD12864 ";//
//unsigned char en_char2[]="Test, Copyright ";//
//unsigned char en_char3[]="by DFRobot ---> ";//
char lol[] ="LOL!            ";
char temp[16];
//
// Pin number to enable XBee expansion board V5
int EN = 2;
//
// Measure distance using the URM04V2 ultrasonic sensor
void measureDistance(byte device) {
  digitalWrite(EN, HIGH);
  // Trigger distance measurement
  uint8_t DScmd[6] = {0x55, 0xaa, device, 0x00, 0x01, 0x00};   
  for(int i = 0; i < 6; i++) {
    Serial1.write(DScmd[i]);
    DScmd[5] += DScmd[i];
  }
  delay(30);
  // Send command to read measured distance 
  uint8_t STcmd[6] = {0x55, 0xaa, device, 0x00, 0x02, 0x00};
  for(int i = 0; i < 6; i++) {
    Serial1.write(STcmd[i]);
    STcmd[5] += STcmd[i];
  }
  delay(3);
}
//
// Return last measured distance by the URM04V2 ultrasonic sensor
// -1 means the last measurement is out of range or unsuccessful
int readDistance() {
  uint8_t data[8];
  digitalWrite(EN, LOW);
  boolean done = false;
  int counter = 0;
  int result = -1;
  while(!done) {
    int bytes = Serial1.available();
    if(bytes == 8) {
      for(int i = 0; i < 8; i++) {
        data[i] = Serial1.read();
      }
      result = (int)data[5] * 256 + (int)data[6];
      done = true;
    }
    else {
      delay(10);
      counter++;
      // If failed to read measured data for 5 times, give up and return -1
      if(counter == 5) {
        done = true;
      }
    }
  }
  return result;
}
//
void setup() {
  LCDA.Initialise();
  delay(100);
  LCDA.DisplayString(0, 0, (unsigned char *)lol, 16);
  delay(1000); 
  pinMode(EN, OUTPUT);
  delay(250);
  Serial.begin(19200);
  delay(250);
  Serial1.begin(19200);
  delay(250);
  digitalWrite(EN, HIGH);
  delay(1000);
}
//
void loop() {
  measureDistance(0x11);
  int distance = readDistance();
  LCDA.CLEAR();
  delay(100);
  memset(lol, ' ', 16);
  sprintf(lol, "%s cm", dtostrf(distance, 0, 0, temp));
  LCDA.DisplayString(0, 0, (unsigned char *)lol, 16);
  delay(1000);
}
Results:

Sunday, September 16, 2012

Connecting URM04 v2.0 ultrasonic sensor to Arduino

If you have bought URM04 v2.0 ultrasonic sensor but forgot to buy IO expansion shield (which is required to connect it to your Adruino), you still may use simple workaround to achieve your goal.
All you need is a few wires and RS485 chip - MAX485 or its analogue (I have used ST485):
Wire up your Arduino, RS485 and URM04 as it shown at the picture:
If ultrasonic sensor is connected properly then its LED will blink four times after powering on (also it blinks every time the data is transmitted).
Prepare sketch in Arduino IDE:
// Pin number to enable XBee expansion board V5
int EN = 2;
//
// Measure distance using the URM04V2 ultrasonic sensor
void measureDistance(byte device) {
  digitalWrite(EN, HIGH);
  // Trigger distance measurement
  uint8_t DScmd[6] = {0x55, 0xaa, device, 0x00, 0x01, 0x00};   
  for(int i = 0; i < 6; i++) {
    Serial1.write(DScmd[i]);
    DScmd[5] += DScmd[i];
  }
  delay(30);
  // Send command to read measured distance 
  uint8_t STcmd[6] = {0x55, 0xaa, device, 0x00, 0x02, 0x00};
  for(int i = 0; i < 6; i++) {
    Serial1.write(STcmd[i]);
    STcmd[5] += STcmd[i];
  }
  delay(3);
}
//
// Return last measured distance by the URM04V2 ultrasonic sensor
// -1 means the last measurement is out of range or unsuccessful
int readDistance() {
  uint8_t data[8];
  digitalWrite(EN, LOW);
  boolean done = false;
  int counter = 0;
  int result = -1;
  while(!done) {
    int bytes = Serial1.available();
    if(bytes == 8) {
      for(int i = 0; i < 8; i++) {
        data[i] = Serial1.read();
      }
      result = (int)data[5] * 256 + (int)data[6];
      done = true;
    }
    else {
      delay(10);
      counter++;
      // If failed to read measured data for 5 times, give up and return -1
      if(counter == 5) {
        done = true;
      }
    }
  }
  return result;
}
//
void setup() {
  pinMode(EN, OUTPUT);
  delay(250);
  Serial.begin(19200);
  delay(250);
  Serial1.begin(19200);
  delay(250);
  digitalWrite(EN, HIGH);
  delay(1000);
}
//
void loop() {
  measureDistance(0x11);
  int distance = readDistance();
  Serial.println(distance);
  delay(1000);
}
Upload it to your board and open Serial Monitor to see the result - distance to the closest object in centimeters.
Important Note: I have Arduino Mega, so I'm using serial port 1 (Serial1 - RX1/TX1) to connect to URM, if you have Arduino UNO or another board model which has only one serial port (Serial - RX0/TX0), then you should connect URM to RX0/TX0 appropriately and replace Serial1.-commands with Serial.-commands in the sketch. Also in that case you will have to unplug wires from RX0/TX0 before uploading your code to the board because this port is also used by Arduino to connect with PC and that's why it's okay if you will see strange "Ua" character in Serial Monitor - just ignore it.