Pages: [1] 2 3   Go Down
Author Topic: Arduino, Processing and 2 HC-SR04 Ultrasonic Sensor problems. Please help....  (Read 3601 times)
0 Members and 1 Guest are viewing this topic.
London
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi there,

I am in desperate need of help. I am doing a school project using processing, Arduino with 2 ultrasonic sensors and what I am trying to do is change between 7 images by using the sensors (left or right) unfortunately I haven’t been able to achieve this as I am really new to Arduino and processing and I don’t understand where I am going wrong.

The two sensors will be set apart so that when the user approaches the left or right sensor the image changes either going back to the previous image or go to the next image. I want to trigger the change when the distance is between 50 and 60 cm so that the images don’t get triggered when you are too close or too far.

The codes that I am using are bellow. Please take a look and help solve this. I only have 4 days to do it plus evaluate it.

Thank you so so much I am very grateful to you all.


Arduino code:
#include <NewPing.h>

int generalDist = 50;

int TRIGGER_PIN1 = 2 ; // Arduino pin tied to trigger pin on the ultrasonic sensor.
int ECHO_PIN1    = 4 ; // Arduino pin tied to echo pin on the ultrasonic sensor.
int TRIGGER_PIN2 = 7 ; // Arduino pin tied to trigger pin on the ultrasonic sensor.
int ECHO_PIN2    = 8 ; // Arduino pin tied to echo pin on the ultrasonic sensor.
//#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
//#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.

int MAX_DISTANCE1 = 200 ;// Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

int MAX_DISTANCE2 = 200 ;// Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
//#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
int dist1=0;
int dist2=0;


unsigned int uS;
int val= 0;

//int Delay_Ms = 300;  //delay value for setting tempo
// int range = 0;

NewPing sonar1(TRIGGER_PIN1, ECHO_PIN1, MAX_DISTANCE1); // NewPing setup of pins and maximum distance.
NewPing sonar2(TRIGGER_PIN2, ECHO_PIN2, MAX_DISTANCE2); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(9600); // Open serial monitor at 115200 baud to see ping results.
  delay(500);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  uS = sonar1.ping(); // Send ping, get ping time in microseconds (uS).

  MAX_DISTANCE1 = ((uS / US_ROUNDTRIP_CM)); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  delay(100);   

  uS = sonar2.ping(); // Send ping, get ping time in microseconds (uS).
  MAX_DISTANCE2 = ((uS / US_ROUNDTRIP_CM)); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  delay(500);   
}


void loop() {
  delay(100);   
  int uS = sonar1.ping(); // Send ping, get ping time in microseconds (uS).

  dist1 = (uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)

  delay (200);
  uS = sonar2.ping(); // Send ping, get ping time in microseconds (uS).
  dist2 = (uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)

  //range = map(dist, 0, 50, 15, 0);



  // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  //int uS = sonar1.ping(); // Send ping, get ping time in microseconds (uS).
  // Serial.print(" ");
  delay (500);
  Serial.write(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
 //Serial.print("L");
 Serial.write(dist1);
 
 if (dist1<generalDist){
 Serial.println(1);
}
else{
Serial.println(0);
 }

  //Serial.println ("");
  //int uS = sonar2.ping(); // Send ping, get ping time in microseconds (uS).
  //Serial.print(dist);
  delay (100);
  Serial.write(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
 //Serial.print("R");
  Serial.write(dist2);
 

if (dist2<generalDist){
Serial.println(2);
 }
else{
Serial.println(0);
}
 Serial.println(dist2);


}


Processing Code:
import processing.serial.*;

// curent state
int currentState=0;

// images and text to display
ArrayList<PImage> displayImage= new ArrayList<PImage>();

int sensorValue=0;
int sensorMin=1023;
int sensorMax=0;

int leftSensorPin=4; // the left sensor pin

int rightSensorPin=8; // the right sensor pin

boolean leftSensorTriggered=false;
boolean rightSensorTriggered=false;

Serial myPort;  // Create object from Serial class
int val=0;      // Data received from the serial port

void setup()
{
  size(900, 700);


 displayImage.add( loadImage("1.jpg"));
 displayImage.add(loadImage("2.jpg"));
 displayImage.add(loadImage("3.jpg"));
 displayImage.add(loadImage("4.jpg"));
 displayImage.add(loadImage("5.jpg"));
 displayImage.add(loadImage("6.jpg"));
 displayImage.add(loadImage("7.jpg"));
 

 // etc for other images
 
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  String portName = Serial.list()[0];
 
  println(portName);
  myPort = new Serial(this, portName, 9600);
 
}

void draw()
{
 
   byte[] inBuffer = new byte[2];
  while (myPort.available()> 0) {
    inBuffer = myPort.readBytes();
    myPort.readBytes(inBuffer);
    if (inBuffer != null) {
      String myString = new String(inBuffer);
      println(myString);

    }
  }
 
  delay (500);
  if ( myPort.available() > 0)

 
  {  // If data is available,
    val = myPort.read();         // read it and store it in val
  }
 
 if  (currentState<displayImage.size()) {
   image(displayImage.get(currentState), 0, 0);
 }


 int dist = 20;
 
  println(val);
  //--------------------------------- Left Sensor Triggered ---------------------------------------
  if (!leftSensorTriggered &&  val < dist) {
   // not previously triggered - but triggered this time
   // i.e. *just* triggered

   leftSensorTriggered = true ;
   currentState= currentState +1;
   // need to check if we're at the end:
   
   if (currentState>= displayImage.size()) {
     currentState=0;
   }
 }
 if (leftSensorTriggered &&  val < dist) {
   // was triggered, but now isn't
   leftSensorTriggered=false;
 }
 //---------------------------------Right Sensor Triggered ---------------------------------------
   
  if (!rightSensorTriggered &&  val < dist) {
   // not previously triggered - but triggered this time
   // i.e. *just* triggered

   rightSensorTriggered = true ;
   currentState= currentState -1;
   // need to check if we're at the end:
   if (currentState>= displayImage.size()) {
     currentState=-1;
   }
 }
 if (rightSensorTriggered &&  val < dist) {
//   // was triggered, but now isn't
   leftSensorTriggered=false;
 }

}
 
 

PS only the sensor on TRIGGER_PIN2 = 7 ; ECHO_PIN2    = 8; is working properly and the other one doesnt work.

Thank you again and i am sorry for the long essay  smiley
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void setup() {
  Serial.begin(9600); // Open serial monitor at 115200 baud to see ping results.
  delay(500);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  uS = sonar1.ping(); // Send ping, get ping time in microseconds (uS).

  MAX_DISTANCE1 = ((uS / US_ROUNDTRIP_CM)); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  delay(100);   

  uS = sonar2.ping(); // Send ping, get ping time in microseconds (uS).
  MAX_DISTANCE2 = ((uS / US_ROUNDTRIP_CM)); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  delay(500);   
}
It's rather useless to ping anything in setup(). Why are you?

Code:
  Serial.write(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside
Serial.write() is for sending binary data.

You need to make up your mind what you are sending to Processing. Some delimiters between the values makes it easier to parse the data. Right now, you are sending "xx1<cr><lf>xx2<cr><lf>nnn<cr><lf>" where x is a binary value and nnn is the distance, as a string, that the second ping got, and <cr><lf> are carriage return and line feed.

In Processing, you are reading all the data available on the serial port, which may or may not be a full packet, and storing that data in a 2 element array. The first two bytes are binary data that you then convert to a String. You do nothing with this String except print it, with no indication what the String is.

Then, you may or no read anything, depending on how much of the packet had already been read.

You are doing all this in draw(), which is wrong.

Make your Arduino program send something like "1, dist1, 2, dist2<cr><lf>",

Make your Processing sketch bufferUntil() the \n arrives. Add a serialEvent() method that gets called when the complete packet has arrived. Read ALL the data, as a String. Then, split the String at the commas, to create an array. If there are 4 values in the array, set global variables, that draw() uses, to useful parts of the array.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I do want to send the distance as 1 or 2 for dist1 and dist2 and want it to be sent as bytes to processing and then trigger the changes.
If you measure the distance, why not send that value? Just sending 1 seems useless.

Why do you want the data sent as bytes, when you read as strings?

If you do this:
Code:
Serial.print(1);
Serial.print(",");
Serial.print(dist1);
Serial.print(2);
Serial.print(",");
Serial.println(dist2);
Processing could receive something like "1,45,2,34<cr><lf>".

Testing leftSensorTriggered or rightSensorTriggered is pointless, as you are getting (incorrectly now, but the above code will fix that) data from both sensors.

What you need to test is which value is smaller. That indicates which side the object being sensed (presumably a person) is closer to.

The values that you get do not distinguish between the values this time and the values last time. You need to store the current readings as the previous readings before updating the current readings. Then, the Processing side needs to compare the current reading with the previous reading to determine whether the object has moved closer, farther away, or stayed still. You need to do that for each side.

Lets work on getting the Arduino side getting, and sending, good data, correctly, only when it needs to. Then, we can work on getting Processing to collect and read that data. Then, we can work on getting Processing to use the data.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So what do I do with data now that both sensors printing out the distances?
Well, the first thing you need is another Serial.print() between dist1 and 2, to add a comma.

Then, in Processing, you need a serialEvent() function and some changes in setup():
Quote
  String portName = Serial.list()[0];
 
  println(portName);
  myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil('\n');

Code:
void serialEvent(Serial myPort)
{
  boolean validString = true;  // whether the string you got is valid

  // read the serial buffer:
  String myString = myPort.readStringUntil('\n');

  // make sure you have a valid string:
  if (myString != null)
  {
     print("Serialized data: ");
     println(myString);

     // Use the function to convert the string to an array of ints
     int[] nums = int(split(myString, '''));

     // Then, make sure that there are 4 values in nums
     // You get to figure this out

     // Then, copy nums[1] and nums[3] somewhere
     // else (global variables) so draw() can use them
  }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
unfortunately I am still having troubles with processing. The thing is when I added the "void serialEvent(Serial myPort)" bit it stopped working and I keep getting "Unexpected token: void" highlighting the serialEvent bit and I dont know what is going on really.
I'd guess that you are trying to put serialEvent() inside draw(), rather than after it. Of course, sans your code, it's only a guess.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You have so many problems in that code that it is hard to know where to start. NO SERIAL DATA should be handled in draw(). GET RID OF ANYTHING THAT DEALS WITH SERIAL DATA in draw().

Code:
String myString = myPort.readStringUntil('\n');
if (myString != null)
{
print("Serialized data: ");
println(myString);
// Use the function to convert the string to an array of ints
String numbers = "10 50 15 60";
int char [] nums = int(split(myString, ''));
}
Let's get some data from the serial port, and print it out. Then, lets create another String instance that we don't use. Then, lets ignore any advice about the TYPE of variable to be created. Finally, let's ignore any advice about the character to use to split the String. Where does that leave us. Thoroughly frustrated, I'm guessing.

Oh, wait. I see the problem. My last post isn't there. Ignore that.

Your serialEvent method needs to be:
Code:
void serialEvent(Serial myPort)
{
  // read the serial buffer:
  String myString = myPort.readStringUntil('\n');
  if (myString != null)
  {
    print("Serialized data: ");
    println(myString);
    // Use the function to convert the string to an array of ints
    int [] nums = int(split(myString, ','));
  }

   d1 = nums[1];
   d2 = nums[3];
}
where d1 and d2 are global variables that then get used in draw() as the distances from the Arduino sensors.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Thanks for that, So this is how processing is printing the data from the arduino
It shouldn't be. But it is because your are reading data all over the place.

Uncomment this:
Code:
  //myPort.bufferUntil('\n');
That is essential code.

Get rid of this, from draw():
Code:
  byte[] inBuffer = new byte[2];
  while (myPort.available ()> 0) {
   inBuffer = myPort.readBytes();
    myPort.readBytes(inBuffer);
    if (inBuffer != null) {
      String myString = new String(inBuffer);
      println(myString);
    }
  }

And this:
Code:
if ( myPort.available() > 0)
   
  {  // If data is available,
   //myPort = myPort.read();         // read it and store it in myPort
  }

Remove the whole sensorTriggered() method, for now. Until you get good data into Processing, there is no need to have any code that tries to use that data.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In serialEvent(), nums is a local array. It goes out of scope before d1 and d2 are assigned values. Move those two assignments up before the closing } after the int nums[] statement.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So now I am getting this, what's next?
Verify that the values in d1 and d2 are correct.

Then, use them in draw(). It don't understand what you are trying to do with them, but, now you have them, so you can do whatever it is you are trying to do with them.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So does this code seem right to you?
Not entirely. There is too much white space. There is a delay() call. The code is not properly formatted.

There are no sensors that are triggered. There are distances that are known. I think that you need to get rid of rightSensorTriggered and leftSensorTriggered. Create two new variables that hold the previous values of d1 and d2.

Compare d1 to prevD1 to decide if one action is needed. Compare d2 to prevD2 to see if another action is needed.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How would do this by removing the booleans and replacing with something like int left, right
Yes.

Quote
When I remove the delays flicker through quickly as soon as the distance is 20 and above
Then, you need to change the frame rate. Unlike loop() on the Arduino, draw() is not called as fast as possible. You can set the frame rate, which defines how often the draw() function is called. The artificial delay is not the solution.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
int left = d1;
int right = d2;
So, what values do left and right have?

Do they ever change?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46029
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I think that the value of left and right should be 10 and if d1 or d2 are greater than or equal to the left or right the image should change.
No. d1 and d2 are global variables. Therefore, they are initialized to 0. Then, left and right are also initialized to 0. You never assign new values to left and right, and you never use d1 and d2 (that you do assign values to).
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24321
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have tried different methods of doing it
the experience works better if you show us your attempts.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24321
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
if (right(d2>= dist)){
"right" is a non-void function taking a boolean parameter?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Pages: [1] 2 3   Go Up
Jump to: