Notices

Overclockers Forums > Software > Programming Tips and Tricks
Programming Tips and Tricks
Forum Jump

Arduino Programming Help

Post Reply New Thread Subscribe Search this Thread
 
 
Thread Tools
Old 07-10-11, 10:38 PM Thread Starter   #1
Cant.Touch.This
Member

 
Cant.Touch.This's Avatar 

Join Date: May 2007
Location: New York

 
Arduino Programming Help


Hopefully someone that knows Arduino really well will stumble upon this.

Code:
#include <Servo.h> // include servo library files

Servo servo1; // initiate servo 1
Servo servo2; // initiate servo 2
Servo servo3; // initiate servo 3
Servo servo4; // initiate servo 4
int analogPin0 = 0; // initiate analog pin 0
int analogPin1 = 1; // initiate analog pin 1

int value0 = 0;
int value1 = 0;

void setup()
{
  Serial.begin(9600);
  servo1.attach(8);
  servo2.attach(9);
  servo3.attach(10);
  servo4.attach(11);
}

void loop()
{
  value0 = analogRead(analogPin0);
  value1 = analogRead(analogPin1);
  Serial.print(value0);
  Serial.print(" LEFT/RIGHT, ");
  Serial.print(value1);
  Serial.print(" UP/DOWN");
  Serial.println();
  delay(10);
  
  // UP AND DOWN MOVEMENT

  if(value1 > 500)
  {
    servo1.write(180);
    servo2.write(0);
    servo3.write(180);
    servo4.write(0);
  }
  else if(value1 < 200)
  {
    servo1.write(0);
    servo2.write(180);
    servo3.write(0);
    servo4.write(180);
  }
  else if(value1 < 400 || value1 > 300)
  {
    servo1.write(90);
    servo2.write(90);
    servo3.write(90);
    servo4.write(90);
  }
  
  // LEFT AND RIGHT MOVEMENT
  
  else if(value0 > 500)
  {
    servo1.write(180);
    servo2.write(180);
    servo3.write(180);
    servo4.write(180);
  }
  else if(value0 < 200)
  {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
  }
  else if(value0 < 400 || value0 > 300)
  {
    servo1.write(90);
    servo2.write(90);
    servo3.write(90);
    servo4.write(90);
  }
}
I'm having trouble running the the if/else statements that I've labeled "Up/Down Movement" and "Left/Right Movement".

1. If I leave the code as is, the "Left/Right" section is the only one that seems to be in effect.

2. If I comment out the "Up/Down" section, only the "Left/Right" works (obviously). Vice-versa when I comment out "Left/Right".

3. All 4 motors run off the 5V fine surprisingly, I tried it again with a separate 5V power supply for the motors but the problem persists.

I don't really have an extensive knowledge in C/C++, just a basic one really.. so I can't really see what my mistake is at all. Should I be using a switch...case statements instead (which I'm not really sure how to write out either but I'm trying it now as I write this)?

If it helps in any way, I'm using these components so you can get an idea of what my analog input is:

http://www.adafruit.com/products/245

And the Motors that I'm using:

http://www.adafruit.com/products/154

Thanks for any help offered on this, really appreciate your time on this!

__________________
LIAN LI PC-A05NB
ASUS P5Q Pro
INTEL Core 2 Duo E7400 R0 (stock) @ 1.024 VCore | Scythe MUGEN-2
G.SKILL DDR2 1066 4GB (2 x 2GB) 5-5-5-15 2T @ 1.96 V
EVGA GeForce 8800 GTS 640MB rev. A3
CREATIVE X-Fi XtremeGamer | M-AUDIO AV 40
OCZ ModXStream Pro 600W
Cant.Touch.This is offline   QUOTE Thanks
Old 07-10-11, 11:22 PM   #2
Bobnova
Senior Member



 
Bobnova's Avatar 

Join Date: May 2009
Location: Humboldt

 
Aha!

First off, congrats on moving into the Arduino world. I love it here.

Secondly, your problem is fairly simple. Rather than post fixed code I'm going to tell you what is wrong with the code and let you fix it. It's more annoying for you but also forces you to learn. People did that to me and it worked well, so I'm doing the same to you


What you have is one big If / else statement, your problem is that only one (1) portion of an if / else statement can be true.

A quick example:

if (value > 5){ blah }
else if (value > 7) { blahblah}
else if (value < 5) { no blah! }

If the value is 6, obviously the first "if" fires. At this point the else if's are not tested.
If the value is 7, same answer, the first if fires, none of the others are tested.
If the value is 8, the second if could fire if it got tested, but it never does, as the first if is true (8 being greater than 5, after all).
If the value is 4, the first is not true, the second if is not true, and the third is, so it fires.

You should be able to find the issue in your code now, just remember that only one (1) if in an if / if else tree can return true.

If not let me know and I'll point it out to you, I'm not aiming to be mean and cause frustration here!

__________________
"Two things are infinite: the universe and human stupidity; and I'm not sure about the the universe." -- Einstein (maybe)

Thinking about an Asus motherboard? Think again.

How to check your PSU with a multimeter.

17bXw5t51rEBXGavJFMJsC8g7HQgThUGc7
Bobnova is offline Author Profile Benching Profile Folding Profile Heatware Profile Rosetta Profile   QUOTE Thanks
Old 07-10-11, 11:44 PM Thread Starter   #3
Cant.Touch.This
Member

 
Cant.Touch.This's Avatar 

Join Date: May 2007
Location: New York

 
Hi there, thanks for the quick reply! Read your repsonse and working on it now, if anything I'll post back tomorrow with news .

__________________
LIAN LI PC-A05NB
ASUS P5Q Pro
INTEL Core 2 Duo E7400 R0 (stock) @ 1.024 VCore | Scythe MUGEN-2
G.SKILL DDR2 1066 4GB (2 x 2GB) 5-5-5-15 2T @ 1.96 V
EVGA GeForce 8800 GTS 640MB rev. A3
CREATIVE X-Fi XtremeGamer | M-AUDIO AV 40
OCZ ModXStream Pro 600W
Cant.Touch.This is offline   QUOTE Thanks
Old 07-11-11, 12:00 AM   #4
Bobnova
Senior Member



 
Bobnova's Avatar 

Join Date: May 2009
Location: Humboldt

 
You bet! I'm glad Arduino was in the title, I don't usually venture in here.
Feel free to send me a PM if/when you post in here again (or other arduino posts, or for help, or whatever), I'm always happy to help if I can.

__________________
"Two things are infinite: the universe and human stupidity; and I'm not sure about the the universe." -- Einstein (maybe)

Thinking about an Asus motherboard? Think again.

How to check your PSU with a multimeter.

17bXw5t51rEBXGavJFMJsC8g7HQgThUGc7
Bobnova is offline Author Profile Benching Profile Folding Profile Heatware Profile Rosetta Profile   QUOTE Thanks
Old 07-11-11, 12:27 AM Thread Starter   #5
Cant.Touch.This
Member

 
Cant.Touch.This's Avatar 

Join Date: May 2007
Location: New York

 
Code:
#include <Servo.h> // include servo library files

Servo servo1; // initiate servo 1
Servo servo2; // initiate servo 2
Servo servo3; // initiate servo 3
Servo servo4; // initiate servo 4
int analogPin0 = 0; // initiate analog pin 0
int analogPin1 = 1; // initiate analog pin 1

int value0 = 0;
int value1 = 0;

void setup()
{
  Serial.begin(9600);
  servo1.attach(8);
  servo2.attach(9);
  servo3.attach(10);
  servo4.attach(11);
}

void loop()
{
  value0 = analogRead(analogPin0);
  value1 = analogRead(analogPin1);
  Serial.print(value0);
  Serial.print(" LEFT/RIGHT, ");
  Serial.print(value1);
  Serial.print(" UP/DOWN");
  Serial.println();
  delay(10);
  
  // UP AND DOWN MOVEMENT
  
  if(value1 > 500)
  {
    servo1.write(180);
    servo2.write(0);
    servo3.write(180);
    servo4.write(0);
  }
  else if(value1 < 200)
  {
    servo1.write(0);
    servo2.write(180);
    servo3.write(0);
    servo4.write(180);
  }
  else
  {
    servo1.write(90);
    servo2.write(90);
    servo3.write(90);
    servo4.write(90);
  }
  
  // LEFT AND RIGHT MOVEMENT
  
  if(value0 > 500)
  {
    servo1.write(180);
    servo2.write(180);
    servo3.write(180);
    servo4.write(180);
  }
  else if(value0 < 200)
  {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
  }
  else
  {
    servo1.write(90);
    servo2.write(90);
    servo3.write(90);
    servo4.write(90);
  }
}
Okay, apparently it isn't as obvious to me as I thought it was when I read your post, lol.

I thought I had figured it out by breaking it into if, elseif, else statements but to no avail. I have two variables (value0, value1) but it doesn't see it as two separate if statements? Am I to 'merge' the two statements for each value (value0 and value1)? Slightly bummed at this...

Can you toss me another hint before I ultimately surrender?

__________________
LIAN LI PC-A05NB
ASUS P5Q Pro
INTEL Core 2 Duo E7400 R0 (stock) @ 1.024 VCore | Scythe MUGEN-2
G.SKILL DDR2 1066 4GB (2 x 2GB) 5-5-5-15 2T @ 1.96 V
EVGA GeForce 8800 GTS 640MB rev. A3
CREATIVE X-Fi XtremeGamer | M-AUDIO AV 40
OCZ ModXStream Pro 600W
Cant.Touch.This is offline   QUOTE Thanks
Old 07-11-11, 12:52 AM   #6
Bobnova
Senior Member



 
Bobnova's Avatar 

Join Date: May 2009
Location: Humboldt

 
You fixed the issue I saw with the ifs (and improved things with an else to finish instead of another if else), there must be a second issue. Never surrender! Anything is doable.

My basic debugging plan says:
Next thing I would do would be to put a serial.print line in each of the if/if else checks to tell you whether it's firing or not.
The first thing I would do would be to comment out the servo commands (just in case something really weird is happening. Admittedly I've only used woefully noisy servos that made a mess of things) and just put "Serial.println("Up/down section one just fired!"); in each section (though obviously say what section it's in).
I put debugging stuff eeeeevvveeeerrrryyywheeeeere. If it all goes off making sense out of it in the serial monitor is a headache :P


Further brainstorming finds....
I looks like both the up/down and left/right sections use all four servos, just in different combinations, this makes for somewhat of an awkward setup, as you're stuck with either the first if that returns true being the only one (previous way), or the second if tree overwriting your servo movement right after the first sets it.

Example: Lets say value0 is 150 and value1 is 400.

First If tree (up/down) happens:
Value0 gets checked, it's 150 which is less than 200, so servo1 gets set to 180 and servo2 gets set to 0.

Second if (left/right) tree happens a microsecond later:
Value1 gets checked, it's 400 which is neither >500 nor <200, so the else takes over and sets servo1 to 90 and servo2 to 90.

The up/down tree never gets a chance to see it's choices for servo1/2 happen, as left/right plows right over them.
I don't know how the servos are hooked up physically so I have no clue what is moving up/down or left/right, but I can't come up with something in my head that moves left/right if half servos go in opposite directions and up/down if they all go in the same direction.

Do both the up/down functions and the left/right functions really use all four servos? One for each or two for each is more common.

Anyway, a simple fix might be to put a delay between the up/down and the left/right to allow whatever it is to get into position. 200ms ought to do it.



EDIT: On delay, there is the easy way and the elegant way, the easy way is of course delay(200);, it's very easy indeed, and for this application should be just fine. At some point you should experiment with the millis() method found in BlinkNoDelay, it's more resource intensive but you can make multitasking (sort of) programs with it.




Seriously though, never give up.
I've found that the vast majority of problems I run into in Arduinoland are due to me missing something really simple, plugging something into the wrong pins (bye bye D3/D4, whoops), or making a minor error in programming. The most common for me is to use a single = in an if check. if (value = 53){ will always return true, as well as setting "value" to 53. if (value ==53){ checks value to see if it's 53.
That one cost me hours.

2.EDIT:
Aha! I think I figured out what the four servo thing is, heh. One servo per wheel for a car thingie? Slightly embarrassing that it took that long, but whatever. I'm going to write assuming that.

Here's how I would go about it:

Step1: two new values, we'll call them "leftRight" and "upDown", for clarities sake. You could use bytes, but ints will work fine (and bytes and I hate each other for some reason).

Step2:
In the first if/else tree, rather than activating the servos it simply sets the value in upDown, to 1(up), 2(down), or 0(nothing).
In the second if/else tree the same thing happens for leftRight, it gets set to 1 (left), or 2(right), or 0 (neither).

Step3:
New if/else tree! This one runs the servos.
syntax might be slightly screwed up here, it's an example after all and I don't have servos to test it with anyway.
[code]
if (leftRight == 0 && upDown = 1){
servo1.write(180);
servo2.write(0);
servo3.write(180);
servo4.write(0);
}

else if (leftRight == 0 && upDown = 2){
servo1.write(0);
servo2.write(180);
servo3.write(0);
servo4.write(180);
}

else if (leftRight == 0 && upDown = 0){
servo1.write(90);
servo2.write(90);
servo3.write(90);
servo4.write(90);
}

// same thing for leftRight being non-zero and upDown being zero goes here.
//Now for the interesting part


else if (leftRight == 1 && upDown = 1){
servo1.write(120);
servo2.write(180);
servo3.write(120);
servo4.write(180);
}

else if (leftRight == 1 && upDown = 2){
servo1.write(180);
servo2.write(120);
servo3.write(180);
servo4.write(120);
}

You have to populate all the combinations which is sort of a pain, but you should be able to get combinations that way. It may or may not actually work, it depends on whether your servos go the same speed for large changes as for small changes or not. If they do, the above won't work and you'll have to step through combinations.

Another possibility would be to set the first if/then/else loop to disable the second if the first is doing something, but let the second run if the first hits the else. The easy way to do this would be to put the second loop in the first loop's final else section, and let the second loop's else set everything to dead center.

Now it's time for me to hit the sack, but I'll check in tomorrow morning and see how things are going

__________________
"Two things are infinite: the universe and human stupidity; and I'm not sure about the the universe." -- Einstein (maybe)

Thinking about an Asus motherboard? Think again.

How to check your PSU with a multimeter.

17bXw5t51rEBXGavJFMJsC8g7HQgThUGc7

Last edited by Bobnova; 07-11-11 at 01:24 AM.
Bobnova is offline Author Profile Benching Profile Folding Profile Heatware Profile Rosetta Profile   QUOTE Thanks
Old 07-11-11, 02:26 PM Thread Starter   #7
Cant.Touch.This
Member

 
Cant.Touch.This's Avatar 

Join Date: May 2007
Location: New York

 
Hey again! Had to pick up some battery holders for the motors today just in case.

I'll list out chronologically what I've done so far.

I added a 200ms delay between each movement to see if it would fix the problem - failed.

I've gone through the steps you've suggested by placing serial.println() for each if statement to see if it was firing off separately and I did see some problems with the left movement only. It was really weird how pressing 'left' on the joystick would result in an 'up' movement.

I was slightly confused with step 2 and 3, it does look like it could slim down my lines of code and make it more efficient.

Late into the night I slimmed down the code slightly and edited some of the values for the if statements (before passing out on my bed ):

Code:
#include <Servo.h> // include servo library files

Servo servo1; // initiate servo 1
Servo servo2; // initiate servo 2
Servo servo3; // initiate servo 3
Servo servo4; // initiate servo 4
int analogPin0 = 0; // initiate analog pin 0
int analogPin1 = 1; // initiate analog pin 1

int leftRight = 0;
int upDown = 0;

void setup()
{
  Serial.begin(9600);
  servo1.attach(8);
  servo2.attach(9);
  servo3.attach(10);
  servo4.attach(11);
}

void loop()
{
  leftRight = analogRead(analogPin0); // reads left/right analog input
  upDown = analogRead(analogPin1); // reads up/down analog input
//  Serial.print(leftRight);
//  Serial.print(" LEFT/RIGHT, ");
//  Serial.print(upDown);
//  Serial.print(" UP/DOWN");
//  Serial.println();
  delay(10);
  
  // UP AND DOWN MOVEMENT
  
  if(upDown > 600) // car moves forward
  {
//    Serial.println("UP");
    servo1.write(180);
    servo2.write(0);
    servo3.write(180);
    servo4.write(0);
  }
  else if(upDown < 200) // car moves backward
  {
//    Serial.println("DOWN");
    servo1.write(0);
    servo2.write(180);
    servo3.write(0);
    servo4.write(180);
  }
  
  // LEFT AND RIGHT MOVEMENT
  
  else if(leftRight > 600) // car moves right
  {
//    Serial.println("RIGHT");
    servo1.write(180);
    servo2.write(180);
    servo3.write(180);
    servo4.write(180);
  }
  else if(leftRight < 200) // car moves left
  {
//    Serial.println("LEFT");
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
  }
  else
  {
    servo1.write(90);
    servo2.write(90);
    servo3.write(90);
    servo4.write(90);
  }
}
Somehow this works, it doesn't look much different than my original code now that I'm looking at it but it seemed to have remedy the situation. Maybe it was the sheer act of communicating with you that fixed it? Lol .

I've attached some pictures of what the 'prototype' looks like so far, looks like a complete mess but I wanna make sure it all works before I commit to the final design. The arrows on the pictures indicate the upright position of the servo's if the logo/lettering were facing you.

So that:
servo.write(180); // full speed counter-clockwise
servo.write(0); // full speed clockwise
servo.write(90); // brings the servo to a halt
Attached Images
  

__________________
LIAN LI PC-A05NB
ASUS P5Q Pro
INTEL Core 2 Duo E7400 R0 (stock) @ 1.024 VCore | Scythe MUGEN-2
G.SKILL DDR2 1066 4GB (2 x 2GB) 5-5-5-15 2T @ 1.96 V
EVGA GeForce 8800 GTS 640MB rev. A3
CREATIVE X-Fi XtremeGamer | M-AUDIO AV 40
OCZ ModXStream Pro 600W
Cant.Touch.This is offline   QUOTE Thanks
Old 07-11-11, 02:53 PM   #8
Bobnova
Senior Member



 
Bobnova's Avatar 

Join Date: May 2009
Location: Humboldt

 
Looks good! As long as it works, right?

I see why forward has the servos going in opposite directions now, it all makes sense.

Communication helps a lot, it forces describing things which means Thinking in New Ways.

__________________
"Two things are infinite: the universe and human stupidity; and I'm not sure about the the universe." -- Einstein (maybe)

Thinking about an Asus motherboard? Think again.

How to check your PSU with a multimeter.

17bXw5t51rEBXGavJFMJsC8g7HQgThUGc7
Bobnova is offline Author Profile Benching Profile Folding Profile Heatware Profile Rosetta Profile   QUOTE Thanks
Old 07-11-11, 03:08 PM Thread Starter   #9
Cant.Touch.This
Member

 
Cant.Touch.This's Avatar 

Join Date: May 2007
Location: New York

 
Yup, thanks a lot for your help on this.

I've found that the power delivery to my project is iffy at times but grounding the power to the Arduino's ground seems to stabilize it.

I'm not sure if this is the case but sometimes when I add multiple delay() commands throughout a program, the effect seems to compound so it's almost adding up the delays. I thought it would see it separately for each case but apprently not. I think this is where I should really get to learn the millis() command.

I wonder if there's any way to slim down the code further cause I still plan to add on things like photoresistors or an ultrasonic sensor (whichever might fit the project more).

I'll definitely ask you later in the future if any problems arise again if you don't mind .

__________________
LIAN LI PC-A05NB
ASUS P5Q Pro
INTEL Core 2 Duo E7400 R0 (stock) @ 1.024 VCore | Scythe MUGEN-2
G.SKILL DDR2 1066 4GB (2 x 2GB) 5-5-5-15 2T @ 1.96 V
EVGA GeForce 8800 GTS 640MB rev. A3
CREATIVE X-Fi XtremeGamer | M-AUDIO AV 40
OCZ ModXStream Pro 600W
Cant.Touch.This is offline   QUOTE Thanks
Old 07-11-11, 03:10 PM   #10
Bobnova
Senior Member



 
Bobnova's Avatar 

Join Date: May 2009
Location: Humboldt

 
It should use each by itself, if it's doing anything else something is wrong.

Having a solid ground path between all components is crucial, without that very strange things can happen!

__________________
"Two things are infinite: the universe and human stupidity; and I'm not sure about the the universe." -- Einstein (maybe)

Thinking about an Asus motherboard? Think again.

How to check your PSU with a multimeter.

17bXw5t51rEBXGavJFMJsC8g7HQgThUGc7
Bobnova is offline Author Profile Benching Profile Folding Profile Heatware Profile Rosetta Profile   QUOTE Thanks

Post Reply New Thread Subscribe


Overclockers Forums > Software > Programming Tips and Tricks
Programming Tips and Tricks
Forum Jump

Thread Tools Search this Thread
Search this Thread:

Advanced Search


Mobile Skin
All times are GMT -5. The time now is 06:07 AM.
Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
You can add these icons by updating your profile information to include your Heatware ID, Benching Profile ID or your Folding/SETI profile ID. Edit your profile!
X

Welcome to Overclockers.com

Create your username to jump into the discussion!

New members like you have made this the best community on the Internet since 1998!


(4 digit year)

Why Join Us?

  • Share experience
  • Max out your hardware
  • Best forum members anywhere
  • Customized forum experience

Already a member?