PDA

View Full Version : Help to finish off program



nolimit44
02-03-2011, 08:42 PM
i am in process of completing my robotic eyes program and ran into a lil issue. I have one of the mini push buttons and am trying to use as both an on and off switch to power an led and servo. basically what i want is when u press it once they turn on, press it again they turn off. right now i have it to where both the led and servo power on when holding down the button.. can someone please help me make the change to the code to correct this issue im having, here is my code.. thanks

#include <Servo.h> //include the servo libary - a bunch of code for a host of servo instructions y9ou can use and don't have to develop yourself
Servo myservo; // create servo object to control a servo
const int buttonPin = A0; // the number of the pushbutton pin
int pos = 0; // variable to store the servo position
int delay1 = 0; // variable to store the delay between servo arm's movement info
int ledPin = 13; // LED connected to digital pin 13
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time
int buttonState = 0; // variable for reading the pushbutton status
void setup()
{
myservo.attach(9); // attaches pin 9 of the micro controller to the servo object - the servo's "control wire"
randomSeed (analogRead (0)); // randomize
pinMode(ledPin, OUTPUT); // sets the digital pin as output
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop()
{

// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {

pos=random(65,115); // ramdomly set the servo arm postion between 65 & 115 degrees. "90" is "straight ahead"
delay1=random(50, 500); // randomly set delay between servo movement between 50 and 500 milliseconds
myservo.write(pos); // tell servo to go to position specified by variable ‘pos’ value
delay(delay1); // waits randomly between 50ms and 500 ms between servo movements
randOn = random (100, 1200); // generate ON time between 0.1 and 1.2 seconds
randOff = random (200, 900); // generate OFF time between 0.2 and 0.9 seconds
digitalWrite(ledPin, HIGH); // sets the LED on
delay(randOn); // waits for a random time while ON
digitalWrite(ledPin, LOW); // sets the LED off
delay(randOff); // waits for a random time while OFF
}

else {

}
}

Slugman
02-03-2011, 09:02 PM
Without looking at the program (I am not a good programmer), but just looking at how you describe the actual switch, it could be that you have a "Momentary on" switch instead of one that 'clicks on' with one press then 'clicks off' with a second press.
The program will not be able to sense high or low unless there is something to detect, so check with a multi-meter that you have continuity between your two button presses.
I.E. Before the first button press = no continuity, then after the first press you should have continuity, then the second press breaks the circuit again. :happy:

Xevel
02-03-2011, 09:09 PM
Hi,

Just so you know, there is a CODE beacon you can use to present your code in the original formating, makes it easier to read.

Concerning your question, if I understand it correctly the first thing you will need to have is another variable that hold the current state information (is it ON of OFF right now?), and each time a push on the button is detected, it toggles to the opposite state.
It won't be enough to solve the full problem, but it's a first step.

If you have indeed a momentary switch, as the button is checked only once per loop right now, pressing it while the servo is moving or while the led is blinking will do nothing... to go further, I think you will need to describe more precisely the behavior you want to achieve and the type of switch you have.

nolimit44
02-03-2011, 09:31 PM
hope this makes reading the code easier. basically i made a set of robotic eyes with leds that blink randomly and a servo which controls the motion from left to right at random speeds and times. i am installing this in my vehicle for a car show because i am using the transformer theme. basically i want to press the mini button to turn the devices on and off when i am showing the vehicle. this is the mini button i currently am using, http://www.trossenrobotics.com/store/p/6359-Electronic-Brick-Mini-Push-Button.aspx



#include <Servo.h> //include the servo libary - a bunch of code for a host of servo instructions y9ou can use and don't have to develop yourself
Servo myservo; // create servo object to control a servo
const int buttonPin = A0; // the number of the pushbutton pin
int pos = 0; // variable to store the servo position
int delay1 = 0; // variable to store the delay between servo arm's movement info
int ledPin = 13; // LED connected to digital pin 13
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time
int buttonState = 0; // variable for reading the pushbutton status
void setup()
{
myservo.attach(9); // attaches pin 9 of the micro controller to the servo object - the servo's "control wire"
randomSeed (analogRead (0)); // randomize
pinMode(ledPin, OUTPUT); // sets the digital pin as output
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop()
{

// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {

pos=random(65,115); // ramdomly set the servo arm postion between 65 & 115 degrees. "90" is "straight ahead"
delay1=random(50, 500); // randomly set delay between servo movement between 50 and 500 milliseconds
myservo.write(pos); // tell servo to go to position specified by variable ‘pos’ value
delay(delay1); // waits randomly between 50ms and 500 ms between servo movements
randOn = random (100, 1200); // generate ON time between 0.1 and 1.2 seconds
randOff = random (200, 900); // generate OFF time between 0.2 and 0.9 seconds
digitalWrite(ledPin, HIGH); // sets the LED on
delay(randOn); // waits for a random time while ON
digitalWrite(ledPin, LOW); // sets the LED off
delay(randOff); // waits for a random time while OFF
}

else {

}
}

nolimit44
02-05-2011, 04:45 PM
i have gotten this code to work with the push button, however it will only shut off now when i press the button in between blinks right as the leds turn off, is there a modification in the code i can change this so that i just press it and it shuts off


#include <Servo.h> //include the servo libary - a bunch of code for a host of servo instructions you can use and don't have to develop yourself
Servo myservo; // create servo object to control a servo
boolean active = false;
boolean lastState = LOW;
boolean currentState = LOW;
byte buttonPin = A0;
int pos = 0; // variable to store the servo position
int delay1 = 0; // variable to store the delay between servo arm's movement info
int ledPin = 13; // LED connected to digital pin 13
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time

void setup(){

myservo.attach(9); // attaches pin 9 of the micro controller to the servo object - the servo's "control wire"
randomSeed (analogRead (0)); // randomize
pinMode(ledPin, OUTPUT); // sets the digital pin as output

}
void loop(){

currentState = digitalRead(buttonPin);

//When lastState is LOW and currentState is HIGH, we have detected a rising edge transition
//ie the input has just gone high. This is when we toggle are active boolean
if(lastState == LOW && currentState == HIGH){
//toggle active state
active = !active;
}

lastState = currentState;

if(active){
//Perform actions when active = true;
pos=random(30,160); // ramdomly set the servo arm postion between 30 & 165 degrees. "90" is "straight ahead"
delay1=random(200, 550); // randomly set delay between servo movement between 200 and 550 milliseconds
myservo.write(pos); // tell servo to go to position specified by variable ‘pos’ value
delay(delay1); // waits randomly between 200ms and 550 ms between servo movements
randOn = random (100, 10000); // generate ON time between .1 and 10 seconds
randOff = random (200, 400); // generate OFF time between 0.2 and 0.4 seconds
digitalWrite(ledPin, HIGH); // sets the LED on
delay(randOn); // waits for a random time while ON
digitalWrite(ledPin, LOW); // sets the LED off
delay(randOff); // waits for a random time while OFF


}
else{
//Perform actions when active = false;

}



}

Xevel
02-05-2011, 06:38 PM
Ok, so now you have a bit of a concurrency problem: you want the controller to do stuff *and* check for the button press at the same time.

There are different ways to solve this. You can have a look at external interrupts (for doing stuff when the button is pressed), or timer interrupts (for doing stuff at regular intervals)... or maybe the simplest way to kind of fake the behavior you want would be to create a modified delay function.

This function would basically start by having a look at the timestamp (using millis() ), then loop until enough milliseconds have passed while checking in this loop if the button is pressed, and updating the "active" variable accordingly.

Not the prettyest way to do it, but considering the controller currently spends most of its time in delay(), it should do the trick.

nolimit44
02-06-2011, 06:25 AM
can you help me with this function code, im not a coder and this is my first time doing this kinda stuff so i have no clue how to do it, im just trying to finish this thing for an upcoming car show lol.

id highly be greatful if you could help me with this

Xevel
02-06-2011, 08:28 AM
Try something like this:


void my_delay(int delay_ms){
unsigned long end_time = millis() + delay_ms; // time at which to stop = now + delay
while(millis() < end_time){ // wait until enough time has past
currentState = digitalRead(buttonPin); // check the button

if(lastState == LOW && currentState == HIGH){ // check for rising edge
active = !active; //toggle active state
}
lastState = currentState; // remember last state
delayMicroseconds(200); // wait a little, not really usefull...
}
}
and replace all the calls to delay(...) by calls to my_delay(...).
Also, remove the lines checking for the button state in the loop function (everything before "if(active)").

(not tested, even for compilation, so watch out for typos!)

nolimit44
02-06-2011, 12:09 PM
like this ? it errored out during compiling saying undefined reference to loop



#include <Servo.h> //include the servo libary - a bunch of code for a host of servo instructions you can use and don't have to develop yourself
Servo myservo; // create servo object to control a servo
boolean active = false;
boolean lastState = LOW;
boolean currentState = LOW;
byte buttonPin = A0;
int pos = 0; // variable to store the servo position
int delay1 = 0; // variable to store the delay between servo arm's movement info
int ledPin = 13; // LED connected to digital pin 13
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time

void setup(){

myservo.attach(9); // attaches pin 9 of the micro controller to the servo object - the servo's "control wire"
randomSeed (analogRead (0)); // randomize
pinMode(ledPin, OUTPUT); // sets the digital pin as output

}
void my_delay(int delay_ms){
unsigned long end_time = millis() + delay_ms; // time at which to stop = now + delay
while(millis() < end_time){ // wait until enough time has past
currentState = digitalRead(buttonPin); // check the button

if(lastState == LOW && currentState == HIGH){ // check for rising edge
active = !active; //toggle active state
}
lastState = currentState; // remember last state
delayMicroseconds(200); // wait a little, not really usefull...
}
if(active){
//Perform actions when active = true;
pos=random(30,160); // ramdomly set the servo arm postion between 30 & 165 degrees. "90" is "straight ahead"
delay1=random(200, 550); // randomly set delay between servo movement between 200 and 550 milliseconds
myservo.write(pos); // tell servo to go to position specified by variable ‘pos’ value
my_delay(delay1); // waits randomly between 200ms and 550 ms between servo movements
randOn = random (100, 10000); // generate ON time between .1 and 10 seconds
randOff = random (200, 400); // generate OFF time between 0.2 and 0.4 seconds
digitalWrite(ledPin, HIGH); // sets the LED on
my_delay(randOn); // waits for a random time while ON
digitalWrite(ledPin, LOW); // sets the LED off
my_delay(randOff); // waits for a random time while OFF


}
else{
//Perform actions when active = false;

}



}

Xevel
02-06-2011, 05:08 PM
nope, *in the loop function*, remove stuff before if(active), does not mean removing the loop function itself.



#include <Servo.h> //include the servo libary - a bunch of code for a host of servo instructions you can use and don't have to develop yourself
Servo myservo; // create servo object to control a servo
boolean active = false;
boolean lastState = LOW;
boolean currentState = LOW;
byte buttonPin = A0;
int pos = 0; // variable to store the servo position
int delay1 = 0; // variable to store the delay between servo arm's movement info
int ledPin = 13; // LED connected to digital pin 13
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time

void setup(){
myservo.attach(9); // attaches pin 9 of the micro controller to the servo object - the servo's "control wire"
randomSeed (analogRead (0)); // randomize
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}

void my_delay(int delay_ms){
unsigned long end_time = millis() + delay_ms; // time at which to stop = now + delay
while(millis() < end_time){ // wait until enough time has past
currentState = digitalRead(buttonPin); // check the button

if(lastState == LOW && currentState == HIGH){ // check for rising edge
active = !active; //toggle active state
}
lastState = currentState; // remember last state
delayMicroseconds(200); // wait a little, not really usefull...
}
}

void loop(){
if(active){
//Perform actions when active = true;
pos=random(30,160); // ramdomly set the servo arm postion between 30 & 165 degrees. "90" is "straight ahead"
delay1=random(200, 550); // randomly set delay between servo movement between 200 and 550 milliseconds
myservo.write(pos); // tell servo to go to position specified by variable ‘pos’ value
my_delay(delay1); // waits randomly between 200ms and 550 ms between servo movements
randOn = random (100, 10000); // generate ON time between .1 and 10 seconds
randOff = random (200, 400); // generate OFF time between 0.2 and 0.4 seconds
digitalWrite(ledPin, HIGH); // sets the LED on
my_delay(randOn); // waits for a random time while ON
digitalWrite(ledPin, LOW); // sets the LED off
my_delay(randOff); // waits for a random time while OFF
}
else{
//Perform actions when active = false;
}
}


Hope this helps.

nolimit44
02-06-2011, 07:32 PM
ok i compiled the code and uploaded it , however the unit wont even power on at the push of the button anymore

Xevel
02-06-2011, 07:48 PM
Oops, my bad.
Now the code only checks the state of the button when waiting using my_delay(), and it only calls my_delay() when active is true...

Add a my_delay(10) in the "else" branch of the "if(active)" conditional...

nolimit44
02-06-2011, 08:02 PM
thank you very much for taking the time to help me, everything worked great. if i have any other questions ill post again

nolimit44
02-09-2011, 05:32 PM
ok after testing the robot eyes for a few days, i noticed that the led will not blink or be on on during servo movement.

basically the led stays on, blinks, the servo moves to new location, and then led comes back on after the servo shift.

how can i make the led seperate from the servo movement so that it doesnt matter if the servo is moving or not to be on or blink?

Xevel
02-10-2011, 08:40 PM
What you are asking now is a little more complex, and you will need some sort of (faked) concurrency.
Again, their is multiple ways to get to the behavior you want, some simpler than others.

If you want to stay with only arduino functions (this implies that it will work no matter what on any arduino board), you will have to do something similar to what you already have, but with more levels.

An other way would be to use interrupts, or to create a sort of scheduler...

I think you should check this library http://www.arduino.cc/playground/Code/Metro
With it, you can make a separate "Metro" for each event (led, moving servo) and eliminate all the delays in your code.

Basically the idea would be something along these lines:



Metro ledMetro = Metro(10);
Metro servoMetro = Metro(10);

char ledState = LOW;
bool servoDeployed = false;

void loop(){
//check_button and use it to set 'active'
...

if(ledMetro.check() ==1){
//change the led state and set the metro interval with a random number depending on the led state

if(ledState==HIGH){
... change led and ledState to LOW, change metro interval to a random number
}else {
... if not active, change led state and update metro interval
}
}

if(servoMetro.check() == 1){
// move the servo and set set the metro interval...
if(servoDeployed){
... return to home position
} else {
... if not active, then deploy and change metro interval
}
}
}
The "active" flag is used only in the inner conditions so that you have a code that does not allow the animation to begin when "active" is false, yet allows it to terminate once it has started.

You should not have any delay() left

Hope this helps.

nolimit44
02-11-2011, 07:41 AM
ok so am i adding this to what i already have and just getting rid of the delays or am i removing everything i have in the loop function. i ask this because i have all the motion range of servos and led blink timeframes and not sure how to combine the new code with the old

Xevel
02-11-2011, 08:11 AM
I would start from scratch, in a new sketch. You can copy all the stuff that you are sure you still need (the top, up to setup()), but check for stuff not needed anymore.

Keep the first version opened beside this one so that you have all the data available.

Servo range of motion will still be used the exact same way it was, all significant delays will translate to intervals for the Metros.

nolimit44
02-11-2011, 09:52 PM
anything like this ? lol i tried but am prob not even close


#include <Servo.h> //include the servo libary - a bunch of code for a host of servo instructions you can use and don't have to develop yourself
Servo myservo; // create servo object to control a servo
boolean active = false;
boolean lastState = LOW;
boolean currentState = LOW;
byte buttonPin = A0;
Metro ledMetro = Metro(10);
Metro servoMetro = Metro(10);
char ledState = LOW;
bool servoDeployed = false;
int pos = 0; // variable to store the servo position
int delay1 = 0; // variable to store the delay between servo arm's movement info
int ledPin = 13; // LED connected to digital pin 13
long randOn = 0; // Initialize a variable for the ON time
long randOff = 0; // Initialize a variable for the OFF time
void setup(){

myservo.attach(9); // attaches pin 9 of the micro controller to the servo object - the servo's "control wire"
randomSeed (analogRead (0)); // randomize
pinMode(ledPin, OUTPUT); // sets the digital pin as output

}
void my_delay(int delay_ms){
unsigned long end_time = millis() + delay_ms; // time at which to stop = now + delay
while(millis() < end_time){ // wait until enough time has past
currentState = digitalRead(buttonPin); // check the button

if(lastState == LOW && currentState == HIGH){ // check for rising edge
active = !active; //toggle active state
}
lastState = currentState; // remember last state
delayMicroseconds(200); // wait a little, not really usefull...
}
}
void loop(){
//check_button and use it to set 'active'
...

if(ledMetro.check() ==1){
//change the led state and set the metro interval with a random number depending on the led state

if(ledState==HIGH){

randOn = random (100, 10000); // generate ON time between .1 and 10 seconds
randOff = random (200, 400); // generate OFF time between 0.2 and 0.4 seconds
digitalWrite(ledPin, HIGH); // sets the LED on
my_delay(randOn); // waits for a random time while ON
digitalWrite(ledPin, LOW); // sets the LED off
my_delay(randOff); // waits for a random time while OFF
//... change led and ledState to LOW, change metro interval to a random number
}else {

Metro(10);
//...if not active, change led state and update metro interval
}
}
if(servoMetro.check() == 1){

pos=random(30,160); // ramdomly set the servo arm postion between 30 & 165 degrees. "90" is "straight ahead"
delay1=random(200, 550); // randomly set delay between servo movement between 200 and 550 milliseconds
myservo.write(pos); // tell servo to go to position specified by variable ‘pos’ value
my_delay(delay1); // waits randomly between 200ms and 550 ms between servo movements
// move the servo and set set the metro interval...

if(servoDeployed){
... return to home position
} else {
Metro(10);
... if not active, then deploy and change metro interval
}
}
}