Moving servos with LDR except each waiting for other to stop

Hi guys finally registered for the forum having tinkered with arduino and built a really cool project with it over at www.lunainteractive.co.uk

Scratching my head around a rpbolem and hopefully you guys can help

We are building an art installation whereby old tv monitors have their brightness controlled by a servo attached to an arduino. An LDR with an LED acts as a beam and when someone stand in the beam this tells the servo to turn and then stop.

There are 8 monitors and servos off one arudino mega 2560 - the servos are unfortunately continuos sm34303r which means im having to send speed in the write command and then use a delay to then send a stop speed (value 90)

2 problems but one has turned into quite a cool effect:

Problem 1. At the moment we have it that it turns when the beam is broken, stops (so the brightness knob doesnt break on the tv) and then after a delay goes back again - it repeats this effectively glitching the tv until you walk away. Its cool but id like to have a software gate on the led input so if triggered it turns the servo and then stops until the beam is broken again. I had a 180 servo mototr and because i could access the angle position it was easier to do.

Problem2. With 2 servos wired up it seems because of the delay in my code one has to finish being read before the other can begin. Id like the 2 ldr inputs to work reading in and affecting both but it seems this isnt possible.

Code is below and any help appreciated

ajb

// ludic rooms tv controller
 
 #include <Servo.h> 
 
Servo myservo1,myservo2,myservo3,myservo4,myservo5,myservo6,myservo7,myservo8;
//init all 8 servos

int pos1 = 0; //position of servo1
int pos2 = 0; //position of servo2
int pos3= 0; //position of servo3
int pos4 = 0; //position of servo4
int pos5 = 0; //position of servo5
int pos6 = 0; //position of servo6
int pos7 = 0; //position of servo7
int pos8 = 0; //position of servo8
 
 int sensorPin1 = A1; //input from ldr
 int sensorPin2 = A2; //input from ldr
 int sensorPin3 = A3; //input from ldr
 int sensorPin4 = A4; //input from ldr
 int sensorPin5 = A5; //input from ldr
 int sensorPin6 = A6; //input from ldr
 int sensorPin7 = A7; //input from ldr
 int sensorPin8 = A8; //input from ldr
 
 int sensorValue1 = 0; //used to send an initial state
 int sensorValue2 = 0; //used to send an initial state
 int sensorValue3 = 0; //used to send an initial state
 int sensorValue4 = 0; //used to send an initial state
 int sensorValue5 = 0; //used to send an initial state
 int sensorValue6 = 0; //used to send an initial state
 int sensorValue7 = 0; //used to send an initial state
 int sensorValue8 = 0; //used to send an initial state
 
 


 int y1;
 int y2;
 int y3;
 int y4;
 int y5;
 int y6;
 int y7;
 int y8;
 
 
 boolean servoON;

// main arduino setup

void setup() {                
  
  pinMode(13, OUTPUT); //led internal for testing purposes
  //led
  
  //code per servo
  pinMode(9, OUTPUT);    //output to the single servo
  myservo1.attach(9); //attach servo to putput pin
  //
  pinMode(11, OUTPUT);    //output to the single servo
  myservo2.attach(11); //attach servo to putput pin
  //
 
 
  Serial.begin(4800); //transmit
  //init to stop all servos when bootup 
  servoALLStop();
  
}



//maina rudino loop
//make our 2 voids

void loop() {
  
  sensorValue1 = analogRead(sensorPin1); //read in the input
  y1 = map(sensorValue1, 300, 600, 10, 0); //read ldr and map it
  Serial.println(y1);
  
  sensorValue2 = analogRead(sensorPin2); //read in the input
  y2 = map(sensorValue2, 300, 600, 10, 0); //read ldr and map it
  Serial.println(y2);
  
  
 
 
// each servo  
//  servo1Move();
if (y2<10) {
  
    servo2MoveON();
    servo2MoveOFF();
    }  
else
{
 servo2Stop(); 
}


//

 if (y1<10) {
  servoON =true;
}
if (y1>9) {
 servoON =false;
} 

if (servoON ==true){
  
  servo1MoveON();
  servo1MoveOFF();
  servo1Stop();
  servoON =false;
}
else
{
 servo1Stop(); 
}



 
 
}





void servoALLStop() {
 //all servos turn to stop position
  myservo1.write(90);
  myservo2.write(90);
  myservo3.write(90);
  myservo4.write(90);
  myservo5.write(90);
  myservo6.write(90);
  myservo7.write(90);
  myservo8.write(90); 
}


void servo1Stop() {
  myservo1.write(90);
}

void servo2Stop() {
  myservo2.write(90);
}



void servo1MoveON(){
  
 myservo1.write(0);
 delay(800);
 myservo1.write(90);
 delay(200);

 
}

void servo1MoveOFF(){
  
 myservo1.write(180);
 delay(800);
 myservo1.write(90);
 delay(200);

 
}


void servo2MoveON(){
  
 myservo2.write(0);
 delay(800);
 myservo2.write(90);
 delay(200);

 
}

void servo2MoveOFF(){
  
 myservo2.write(180);
 delay(800);
 myservo2.write(90);
 delay(200);

 
}

I know its messy without arrays but its helping my friend learn and see Arduino as its his first foray into Arduino.

Also in my loop ive tried 2 different methods with an if to call the servos. the servo move voids are there to control the servo to switch it on, then back off.

And yes we did glue pot controls to the servo. mad i know.

Problem 1. At the moment we have it that it turns when the beam is broken, stops (so the brightness knob doesnt break on the tv) and then after a delay goes back again - it repeats this effectively glitching the tv until you walk away. Its cool but id like to have a software gate on the led input so if triggered it turns the servo and then stops until the beam is broken again. I had a 180 servo mototr and because i could access the angle position it was easier to do.

So, you want to move the servo one way when the beam is broken (the sensor goes LOW) and the other way when the beam is restored (the sensor goes HIGH). Simple enough. What is the problem?

Problem2. With 2 servos wired up it seems because of the delay in my code one has to finish being read before the other can begin. Id like the 2 ldr inputs to work reading in and affecting both but it seems this isnt possible.

So, get rid if the delay. Implement a state machine. Define the states that you want to be in (servo1 at n degrees, servo1 at m degrees, servo2 at x degrees, servo2 at Y degrees, etc.), what happens when a state change occurs (move servo1 to ?, etc.), and what should trigger that transition (beam 1 broken, n milliseconds have elapsed after the beam was broken, etc.).

Then, write code to implement the state machine.

I know its messy without arrays but its helping my friend learn and see Arduino as its his first foray into Arduino.

Use arrays where they are appropriate. Get the functionality right, first, though.

the servo move voids

void is a return type, like int or char. You wouldn't say "the servo move ints..." would you? "The servo move functions are there...".

So, you want to move the servo one way when the beam is broken (the sensor goes LOW) and the other way when the beam is restored (the sensor goes HIGH). Simple enough. What is the problem?

This works already. I didnt know i could get a high and low from an analog read in ? But i actually i wanted that break the beam turn the servo on and then off and stay that way - it currently loops that function.

So, get rid if the delay. Implement a state machine. Define the states that you want to be in (servo1 at n degrees, servo1 at m degrees, servo2 at x degrees, servo2 at Y degrees, etc.), what happens when a state change occurs (move servo1 to ?, etc.), and what should trigger that transition (beam 1 broken, n milliseconds have elapsed after the beam was broken, etc.).

You missed where i said continuos servo - i assumed you need the delay otherwise it doesnt move. I can only write the speed to turn it with value 0-90 turning one way and 91-1780 turning the other. I use delay to calculate the time its taken to turn and pass a speed and a stop eitehr side Can you please suggest how i could use milliseconds to keep track. Im presuming you mean read current system time and store, add a value noto that and then turn the servos and keep checking every millis to see if its reached that value ?

void is a return type, like int or char. You wouldn't say "the servo move ints..." would you? "The servo move functions are there...".

ive been working for the last 12 hours and im tired so apologies - i know they are functions - i code in java and processing. my friend is sat next to me and its tricky coding around a problem and explaining at the same time.

cheers for your input :-)

int pos1 = 0; //position of servo1 int pos2 = 0; //position of servo2 int pos3= 0; //position of servo3 int pos4 = 0; //position of servo4 int pos5 = 0; //position of servo5 int pos6 = 0; //position of servo6 int pos7 = 0; //position of servo7 int pos8 = 0; //position of servo8

Doesn't Java/Processing have arrays?

To operate multiple servos simultaneously, turn the problem around and get rid of the "delay" calls. Have a look at the blink without delay example to see how to do this.

You missed where i said continuos servo

I didn't miss it. I don't see what it has to do with the problem, or why you are using the wrong kind of servo. If you can move the servo to where you want it, or in the direction you want it to go, it doesn't matter what kind of servo it is.

I didnt know i could get a high and low from an analog read in ?

You can't, exactly. You can detect when the beam is present/broken, right? That is the important part. Exact values are less important.

AWOL:

int pos1 = 0; //position of servo1 int pos2 = 0; //position of servo2 int pos3= 0; //position of servo3 int pos4 = 0; //position of servo4 int pos5 = 0; //position of servo5 int pos6 = 0; //position of servo6 int pos7 = 0; //position of servo7 int pos8 = 0; //position of servo8

Doesn't Java/Processing have arrays?

To operate multiple servos simultaneously, turn the problem around and get rid of the "delay" calls. Have a look at the blink without delay example to see how to do this.

yes didnt you see where i posted i know im not using arrays but im getting things to work first and im at the same time teaching a friend basics of using an arduino - theres no need to be patronising.

but thank you ill examine again and see if that can help with my problem. maybe im just not explaining it correctly enough

PaulS:

You missed where i said continuos servo

I didn't miss it. I don't see what it has to do with the problem, or why you are using the wrong kind of servo. If you can move the servo to where you want it, or in the direction you want it to go, it doesn't matter what kind of servo it is.

I didnt know i could get a high and low from an analog read in ?

You can't, exactly. You can detect when the beam is present/broken, right? That is the important part. Exact values are less important.

wrong kind of servo becuase its a budget art project (even though im 33 its part of teaching..im not a student) and soemone else bought them and we have no budget left. we had 1 servo that does 0-180 and i had better control over that but now im stuck with what i have.

yeh i can detect the beam broken - thats basically the if y value is less than becuase its read in at value 10 and the mintue you break it it goes down to 9 so thats my off/on

i just cant get every servo to read each relevant ldr at the same time and trigger it to turn and then stop - it seems to do each servo sequentially through the loop() and it waits for each one

im assuming i need to not use delay

Can you please suggest how i could use milliseconds to keep track. Im presuming you mean read current system time and store, add a value noto that and then turn the servos and keep checking every millis to see if its reached that value ?

Missed this part, earlier.

One transition would start the motor moving, and record when that happened.

unsigned long motor1Start; // global variables
unsigned long motor1RunTime = 800; // Or whatever
bool motorOneMoving = false;

Create a function, MotorOneForward(). In that function, call myServo1.write() with whatever value is needed to get it moving forward. Also set motor1Start:

motor1Start = millis();
motorOneMoving = true;

In loop(), what you need to take action based on the state you are in:

if(motorOneMoving)
{
   if(millis() - motor1Start >= motor1RunTime)
   {
      // stop motor1
      motorOneMoving = false;
      motor1Start = 0;
  }
}

PaulS:

Can you please suggest how i could use milliseconds to keep track. Im presuming you mean read current system time and store, add a value noto that and then turn the servos and keep checking every millis to see if its reached that value ?

Missed this part, earlier.

One transition would start the motor moving, and record when that happened.

unsigned long motor1Start; // global variables
unsigned long motor1RunTime = 800; // Or whatever
bool motorOneMoving = false;

Create a function, MotorOneForward(). In that function, call myServo1.write() with whatever value is needed to get it moving forward. Also set motor1Start:

motor1Start = millis();
motorOneMoving = true;

In loop(), what you need to take action based on the state you are in:

if(motorOneMoving)
{
   if(millis() - motor1Start >= motor1RunTime)
   {
      // stop motor1
      motorOneMoving = false;
      motor1Start = 0;
  }
}

ive just been scribbling something like that but thrown it away as this is much neater :-) as its 10pm ive given up for the night and will look again tomorrow but it think this is probably the direction i need to go because i can do this for each of the 8 servos and technically they should/could all operate at the same time

when i messed about with minimum delay times then i had better result so i know that this is my issue - also watching the serial monitor i saw it pause between which suggested again the delay is an issue

thanks again ill let you know

Treat that as an outline, not THE way to do things. Some functions, like motorOneForward(). would be better as motorForward(int whichOne). The time variables should be arrays, as should the booleans. Lots of stuff should be done in loops.

yes didnt you see where i posted i know im not using arrays but im getting things to work first and im at the same time teaching a friend basics of using an arduino

If you're trying to teach someone else how to program, then it is best to concentrate on how to program the problem for a single entity. After that, additional similar entities are relatively trivial by making entity references into arrays. Confusing someone with masses of unused declarations is just likely to be counter-productive.

AWOL:

yes didnt you see where i posted i know im not using arrays but im getting things to work first and im at the same time teaching a friend basics of using an arduino

If you’re trying to teach someone else how to program, then it is best to concentrate on how to program the problem for a single entity.
After that, additional similar entities are relatively trivial by making entity references into arrays.
Confusing someone with masses of unused declarations is just likely to be counter-productive.

true, but they are only unused at the moment as once we get 2 to move we can get 8. i agree its better but we have to finish it by tomorrow evening and we only started this morning!! im trying to get across the basics of arudino, and try and code around this problem that the students want to accomplish - normally you wouldnt go past very basics in 2 days of programming education so its only if i get time that i will then show how to better code it using arrays and calls

true, but they are only unused at the moment as once we get 2 to move we can get 8

Ah yes, but so much easier to explain how to get one working.

(Is your shift-key broken?)

Ah yes, but so much easier to explain how to get one working.

I think that, in this case, the idea to get two to work is smart, as all the problems are with getting two to move at the same time. Getting just one working by itself is what leads people to use delay() when they know they shouldn't, and causes major restructuring of the code to then not use delay.

In general, though, I agree with your "make it work for one, then expand to more than one" approach.

AWOL:

true, but they are only unused at the moment as once we get 2 to move we can get 8

Ah yes, but so much easier to explain how to get one working.

(Is your shift-key broken?)

nope thats my style - all lowercase

thats my style - all lowercase

ee cummings k.d. lang S'been done.

Lot of noise. If you have continous rotation servos, you will need to determine the servo control values that make the servos move as desired. You will need to look at the blink without delay setup and determine how many ms duration you need to ensure the servos travel the desired rotation to position the pot. If you glue, use hot glue. it is plenty strong for servos, and can be easily pealed off if needed. Work on getting one servo to position as desired, then add more.