ciclos anidados? saltos??... ayuda

hola, espero q puedan ayudarme con esta duda q me ha surgido

estoy trtabajando con un servomotor y una fotoresistencia, a traves de esta se efectuara el paro del servo, y bueno he entendido q tengo q poner un par de ciclos anidados, algo mas o menos asi:

for (pos=0; pos<=180;pos+=1)//pos es una variable int en la q se guarda la posicion del motor
{
while (val<= 1000)//donde val es una variable donde se va guardando el valor de la fotoresistencia
{
//codigo del servo y del sensado de la fotoresistencvia
}
}

bueno algo asi, pero tengo mis dudas, puesto q el servo con el q estoy trabajando fue modificado para q girara 360° en lugar de 180°, por lo q me dicen q trabajara, de ahora en adelante como si siempre estuviera en 90° (se cambio su potenciometro por un par de resistencias), entonces segun entiendo se ciclaria el for a q nunca va a alcanzar la posicion de 180°...aun tengo dudas de esa parte, ppr favor diganme si me equivoco.

en fin, me gustaria saber si es buena idea el poner una especie de salto al finaldel while, con la misma condicion que este para q al terminar de ejecutarse, se saltara a la siguiente parte del codigo (no se nada acerca de saltos, me gustaria q me dieran un ejemplo o una explicacion), o q deberia de hacer? cualquier sugerencia, informacion y ejemplo son bienvenidos. gracias y saludos

Hola sustirijiyo. Tienes razón en lo del servo, al haberlo trucado, ya sea incorporando las resistencias o ajustando el propio potenciometro, el servo motor siempre hará un giro continuo de 360º ya sea en sentido horario o antihorario, por lo que el código que has insertado en el comentario no es válido, ya que nunca se cumplirá la condición "for" como tu bien has dicho.
Por otro lado, no acabo de entender bien la duda que tienes sobre las estructuras condicionales o ciclos anidados, como dices tú... si lo expones mejor quizás te pueda ayudar...

Un saludo!

Creo que haría falta una descripción mucho más detallada tanto del código como del hardware.

En principio, un servo puede estar en su estado original o "trucado" de dos formas diferentes.

Un servo normal de fábrica está formado por un motor que mueve el mecanismo y un sensor que mide la posición del mecanismo. El sensor que mide la posición viene a ser un potenciómetro y la posición se mide midiendo la resistencia. Este potenciómetro suele tener una carrera mecánica (el ángulo de giro que abarca) de unos 240º grados y una carreta eléctrica de unos 220º. Así que el mecanismo puede moverse hasta 240º antes de dar en el tope mecánico pero la resistencia solo cambia y la posición solo puede medirse en los 220º centrales.

El control del servo suele estar ajustado para que cuando la señal de control va de extremo a extremo el servo se mueva unos 90º.

Si se truca este potenciómetro la amplitud del movimiento se puede ampliar hasta 200 o 220º.

Otro "truco" consiste en suprimir y los topes mecánicos y entonces el servo se convierte en un "servo de rotación continua", que puede dar, por ejemplo, 12 vueltas en un sentido y luego 16 en el otro. El problema es que con este "truco" deja de ser posible conocer la posición en que está el servo y el servo, en realidad, deja de ser un servomotor.

El código típico para una cosa de estas podría tener esta pinta general:

Vamos a suponer que la posición del servo (pos) puede moverse desde 0 (extremo izquierda) hasta 255 (derecha), que y que el valor medido en la fotoresistencia (val) crece cuando el servo se mueve hacia la derecha y que queremos pararnos el el valor de fotoresistencia TARGET.

Necesitamos una función, o unas líneas de código que ordenen al servo una nueva posición, lo llamaremos servo_pos() y otra función o lineas de código que miden el valor de la resistencia, lo llamaremos mide_val()

#define MIN_SERVO    0
#define MAX_SERVO   255

#define T_INICIAL     1500
#define T_PASO         15

#define TARGET         1000

servo_pos(MIN_SERVO);
delay(T_INICIAL);              // Damos tiempo al servo a llegar al extremo izquierdo

for(n = MIN_SERVO; n<= MAX_SERVO; n++){
       if(mide_val()>TARGET) break;
       servo_pos(n);
       delay(T_PASO);
       }

if(TARGET<mide_val()) Serial.printnl(Error: El target no ha sido alcanzado);

La instrucción break; hace que la ejecución "salte fuera" del bucle y continúe, el problema es que no sabemos si hemos salido del bucle porque val ha alcanzado el target o porque se ha alcanzado el extremo izquierdo de las posiciones del servo.

Con "while" se puede emplear break; o hacer falsa la condición del while

#define MIN_SERVO    0
#define MAX_SERVO   255

#define T_INICIAL     1500
#define T_PASO         15

#define TARGET         1000

servo_pos(MIN_SERVO);
delay(T_INICIAL);              // Damos tiempo al servo a llegar al extremo izquierdo

int continua = 1;
int posicion = MIN_SERVO;

while(continua==1){
       if(mide_val()>TARGET)        continua=2;

       servo_pos(posicion); 
       posicion++;
       if(posicion>MAX_SERVO)      continua=3;

       delay(T_PASO);
       }

if(continua==2) Serial.printnl(Target alcanzado); 
if(continua==3) Serial.printnl(Error: Target no alcanzado);

bueno primero q nada gracias por responder tan pronto a ambos :slight_smile:

bueno pues la modificacion q se le hizo al servo fue ponerle 2 resistencias de valores iguales, en lugar del potenciometro q traen de fabrica, (no se como insertar imagenes aqui para ser un poco mas explicito, pero la adjuntare al menos al final), se coloco el extremo de una de las resistencias en el extremo q deberia estar una de las patas del potenciometro, y del otro extremo la para de la segunda resistencia, despues las patas q no estaban conectadas se juntaron y se soldaron en el lugar q deberia estar la pata intermedia del potenciometro, con esto me han dicho q el servo se comportaria aun como un servomotor normal pero q seria como si siempre estuviera a 90°.

0xDA_bit mi pregunta respecto a las estructuras condicionales, mi pregunta es, q tipo de instruccion puedo usar para salir de un ciclo, aunq las condiciones del mismo no se hayan cumplido aun, como en el caso del for, ya q este no se cumpliria nunca, cual seria un tipo de "salto" para q al cumplirse la condicion del while, parara el for y se saltara hacia la siguiente instruccion, como dice Mitxel, un break, aunq no se si exista otra instruccion q sirva para lo mismo.

Mitxel espero q lo poco q supe explicar la modificacion te sirva un poco mas, tu codigo me parece miuy bueno, y con lo poco q se de programacion apenas y puedo entenderlo, podrias explicarme un poco mas?? te explico un poco mas de q se trata mi programa:

tenemos un servomotor (trucado) y este tiene q girar indefinidamente (olvide mencionar q junto con los ciclos estoy usando la llibreria q viene para servos) hasta q una fotoresistencia q esta en otro lado nos de un valor mayor a digamos 700 (ya q esta conectada a un pin analogico y se supone q nos da un valor entre 0 y 1023, corrijanme si me equivoco), esta fotoresistencia se activara con un led, y la luz esta practicamente controlada. ahora, despues de este proceso tengo otros cuantos procesos, movimientos de motores a pasos y encendido de leds, es por eso q pido ayuda para saltar del ciclo hacia la siguiente linea.

bueno espero q eso sea suficiente, y si no, pueden preguntarme cuanto quieran, muchas gracias

Si lo entiendo bien, quieres decir que tu servo lee que está siempre a 90, por lo que si le envías la instrucción para que se ponga a un grado menor que 90, sea el que sea, se va a mover indefinidamente en un sentido, si es mayor que 90 viceversa y si es 90 se para.
De todas formas en respuesta a tu pregunta, este sería un while dentro de un for genérico que cuando se cumple una condición sale del while y del for (el for sí que termina en tu primer ejemplo, cuando pos llega a valer más de 180).

for (i = 0; i < 180, i++) //Un for cualquiera (como el de tu ejemplo)
{
while (val <= 1000 && i != 180) //El while se realiza mientras y solo mientras el valor sea menor o igual que "val" e i distinta de 180
{
//Tu código para el control del servo
if (condicion) //Si se da la condición en la cual quieres que salga del while y del for i pasa a valer 180, saliendo del while y del for.
{
i = 180;
}
}
}

De todas formas, dime justo lo que quieres hacer y si es cierto lo que he estimado del servo, y hacemos un código en condiciones.

Saludos :slight_smile:

Max_Maker gracias por responder tan pronto

la verdad no se si en realidad el servo lea como q esta a 90° solo se q se comporta como si lo estuviera.
mira lo q intento hacer es es algo asi:
tengo una serie de leds, y tengo el servo, montado en el servo tengo la fotoresistencia, elservo se mueve a traves de unas guias a lo largo de la serie de leds, al haber un led encendido, la fotoresistencia lo sensa como un valor arriba de 700(ya cuando estacerca del led), en ese momento necesito q el servo se detenga, es en el momento en el q ha llegado a su "Target" como decia Mitxel

espero aclarar algo, ustedes si me han aclarado varias cosas, gracias

saludos :slight_smile:

Ahh guay... Pues este sería el código:

#include <Servo.h>

int LDR = 3;
Servo servo1;

void setup ()
{
servo1.attach(23);
pinMode(LDR,INPUT);
}

void loop()
{
if (analogRead(LDR) >= 700)
{
servo1.write(90); //Para que se detenga al encontrar el LED encendido
}
else if (analogRead(LDR) < 700)
{
servo1.write(91); //Para que gire indefinidamente o vuelva a girar si se apaga el LED
}
}

El programa está basado en el supuesto de mi anterior comentario (el servo piensa que siempre está en 90º y si le mandas 91º nunca llega y por lo tanto no para, con 89º igual en sentido opuesto).

Fácil, sencillo y para toda la familia.

ok, muchas gracias ahora lo pruebo y les aviso si me funciono

saludos

Max_Maker con la novedad de q no esta sirviendo el programa, lo intente asi tal cual lo dejaste y no ha funcionado,

la cosa es q con el programa original q viene de ejemplo para servos si funciona(con lo q yo llegue a la conclusion de q en realidad no lee al servo como si estubiera exactamente a 90°), el unico problema sigue siendo el paro, no se como hacerlo parar, pero bueno este es mas o menos el programa q use y funciono, el servo da vuelta a un lado indefinidamente y despues al otro, el problema sigue siendo el como lo detengo :S jaja aqui use el serial para comunicarme en lugar de la fotoresistencia ya q por el momento no la tengo.

cualquier idea es bienvenida, gracias y saludos

#include <Servo.h>
Servo myservo;
int val=0;
int pos = 0;
void setup()
{
myservo.attach(9);
Serial.begin(9600);
}
void loop()
{
val = Serial.read()-48;

switch (val)
{
case 1:
{
for(pos = 0; pos < 180; pos += 1)
{
myservo.write(pos);
delay(15);
}
break;
}
case 2:
{
for(pos = 180; pos>=1; pos-=1)
{
myservo.write(pos);
delay(15);
}//for
break;
}//case 2
}//switch
}

A ver, dime en qué condiciones se mueve el servo y en cuáles se para, y entonces te podré adaptar el programa.
A las malas, si resulta que no hay ninguna instrucción que lo haga pararse, se incorpora un optoacoplador (como un relé) entre el positivo del servo y alimentación, de manera que lo desconectas cuando llega a la posición.
Pero lo más importante, lo primero que nos tienes que decir es como se comporta tu servo, sino no te podemos ayudar.

PD: Si no quieres que se mueva circularmente, ¿porque has modificado el servo?

hola, perdon por la demora, he estado un poco ocupado

bueno como ya te comente antes Max_Maker el servo se mueve despues de q algun led se enciende, ese no es problema en realidad, utilizo un switch case para encender los leds, sepues de eso se pone en marcha el servo, sobre este esta montada una fotoresistencia (esta va conectada a ua entrada analogica del arduino) y cuando esta sensa la luz de uno de los leds (cuando sensa un poco mas de 700, para ser un poco mas precisos) es cuando el servo debe recibir la señal de paro, o no se si se pueda solo salir del ciclo en el q esta el servo y despues continuar con la seccion del programa q sigue.

la razon por la cual se decidio modificar el servo es por q la serie de leds es algo larga, y con la carrera q nos ofrecia el servo de fabrica no alcanzaba toda esta longitud, es por eso q se decidio modificarlo.

espero con esto me explique mejor, gracias por tu ayuda y saludos.

Te había entendido ya. Lo que te he preguntado es "en qué condiciones se mueve el servo", no cuando se tiene que mover, eso ya se dio por entendido. La pregunta era que con que instrucción se empezaba a mover.
Respecto a tu solución de hardware, yo hubiera optado por dos servos, uno anclado al otro y con ángulos de giro opuestos.
Volviendo a lo de antes, lo que quiero saber es qué escribes en el programa para que el servo se mueva (o se pare). Sin saber eso no puedo hacer un programa acorde.

hola, disculpa la demora, he estado bastante ocupado, mira aqui esta mas o menos el programa o al menos la parte a la q me refiero

#include <Servo.h>
Servo myservo;
int val=0;
int pos = 0;
//para los leds:
int ledPin1 =8;
int ledPin2 =9;
int ledPin3 =11;
int SlB = 3; // SlB :SENSOR DE LUZ
void setup()
{
pinMode (ledPin1, OUTPUT);
pinMode (ledPin2, OUTPUT);
pinMode (ledPin3, OUTPUT);
myservo.attach(12);
Serial.begin(9600);
pinMode(SlB, INPUT);
}
void loop()
{
int val = Serial.read()-48;
switch (val)//encendido de leds a traves de un integrado
{
case 1:
{
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
break;
}
case 2:
{
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
digitalWrite(ledPin3, LOW);
break;
}
case 3:
{
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, HIGH);
digitalWrite(ledPin3, LOW);
break;
}
case 4:
{
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, HIGH);
break;
}
case 5:
{
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, HIGH);
break;
}
}//fin de switch

//inicio de servo
for(pos = 0; pos < 180; pos += 1)
{
if (analogRead(SlB)>= 700) break;
else
{
myservo.write(pos);
delay(15);
}
} //fin de for
delay(5000);
}

en cuanto a lo de el acoplamiento de los 2 servos, es buena idea, pero la verdad es q en mi ciudad no se consiguen y no hay dinero para mandarlos traer, lamentablemente, bueno gracias por el apoyo y por la paciencia sobre todo jeje saludos

emm bueno, al fin he probado este ultimo programa y en teoria trabaja bien, lo estuve checando observando con el serial como se comportaba, imprimiendo en pantalla lo q hay en la variable pos y lo q la fotoresistencia sensa, pues, ha funcionado bien, al acercar una fuente de luz se rompe el ciclo y pasa a la siguiente instruccion, lo malo es q el servo no se detiene :S intente agregando una instruccion directa para el servo, algo como "myservo.write(180);" afuera del for, esto ha detenido el movimiento del servo, pero tambien se detiene el programa con mensajes de error de tipo serial Event, si alguien me pudiera indicar q estoy haciendo mal se los agradeceria

saludos