Sigo tu hilo, si quieres hacerlo en CCS con pic seria lo suyo para poderte ayudar-
Que bien Gera, yo también me animaría a montarlo, pero no sé donde se puede cortar el acrílico a buen precio.
Un saludo
Algec yo lo programaria en CCS si no me convencen de lo contrario.
Que bien Gera, yo también me animaría a montarlo, pero no sé donde se puede cortar el acrílico a buen precio.
Un saludo
Yo aca tampoco, es mas no creo que lo hagan, entonces como podriamos hacer los acrilicos?, taladro tengo.
Hola compañeros
que bueno que se esta poniendo este hilo,
Gera esos perfiles a que escala estan,
yo tengo unos micromicro servos de tower pro SG9G
http://img.alibaba.com/photo/245829146/RC_SERVO_TowerPro_SG_90_Micro_Servo.jpg
me aseguraron que el torque es de 2 kilos y solo pensan 9 gramos.
¿que micro micro llevais pensado usar?
se necesitaria usar pwm por cada servo verdad..?
Un Saludo
Hola Gera
mira encontre algo de teoria:
http://imarrero.webs.ull.es/sctm05/modulo2lp/1/msigut.pdf
Nocturno, como era la pagina que tu has recomendado alguna vez en la cual
el icono es un integrado con ojos, el fondo es verde o verde azulado,
en la cual se habla del potenciometro digital, 555 y de la cinematica, y hay otros circuitos
muy bien explicados.
ahi venia explicado..lo del calculo de formulas para moverse aun punto desde otro dado.
no logro recordar la web ni dar con la pagina.
tu la recuerdas?
Un Saludo.
Hola Gera
mira encontre algo de teoria:
http://imarrero.webs.ull.es/sctm05/modulo2lp/1/msigut.pdf
Nocturno, como era la pagina que tu has recomendado alguna vez en la cual
el icono es un integrado con ojos, el fondo es verde o verde azulado,
en la cual se habla del potenciometro digital, 555 y de la cinematica, y hay otros circuitos
muy bien explicados.
ahi venia explicado..lo del calculo de formulas para moverse aun punto desde otro dado.
no logro recordar la web ni dar con la pagina.
tu la recuerdas?
Un Saludo.
Akena, me estas diciendo que los servos los alimente con los 7.2V de la Lipo directamente, y que las señales PWM sean de 5V?
Porque lei que los microservos se alimentan de 3V a 6V, me da miedo romperlos.
Saludos!
Yo los he alimentado con 7.2v sin ningún problema con baterias nickel.cadmio,que bien cardas dan alrededor de 8v xD
Esto en competencias :mrgreen:¿ Que servos vas a ocupar ?(http://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=9549) ya vi que modelo,parece ser de los pequeños.
Viendo el tipo de servo mejor usa un regulador switching de 5vcd@3A,así te evitas tantas perdidas y calentones con el regulador lineal.
LM2576
LM2596
LM22678
LM22679
Saludos!
Hola compañeros
Yo tambien llevo idea de hacerlo con un uC y control por emisora,
lo malo es el 18f2550 que tiene pocas patas, llevo pensado hacerle un modulo
que cuelgue de un bus por ejemplo ... i2c, y programado con ccs.
Un saludo.
De todas formas si tienes un diagrama de bloques me gustaria ver como pretendes organizar el codigo, yo es lo primero que voy a hacer antes de nada,.
Las rutinas de cinematica inversa y de bezier ya las tengo medio preparadas en base.
Una cuestion mas. necsitas un pic para 18PWM, supongo que el que elejiste es capaz, o seran pwm por software a base de interrupciones?
I checked the current draws on 5v: idle, about 10ma, freely moving full swing or with a little resistance, about 100-200ma, and stalled, 600ma.
Gracias Suky! No lo había visto.Ahí esta la clave, el consumo lo puedes limitar con la cantidad de servos que mueves en simultaneo.
200mA x 18 servos = 3.6A
Es mucho más de lo que pensaba. Tal vez pueda ponerle un transistor externo para llegar a los 3A, total es raro que se muevan los 18 servos simultáneamente.
Hola Gera, tanto entusiasmo que le pones me han dado ganas de hacer algo parecido :-/
Supongo que como vas por el lado del montaje superficial ya te has inclinado por el 18f4550 ;-)
No tanto por el tema de memoria para programa, sino por las I/O que al momento de mas adelante agregar sensores quizas el 18f2550 te resulte escaso.
[\quote]
Exacto! Es el pic que estaba pensando utilizar. El formato TQFP es muy pequeño y te permite ahorrar mucho espacio en la placa. Asique me viene de 10!CitarEstuve pensando en eso de la cinemática inversa y se me ocurrió algo para prescindir un poco, aunque no se que es lo mejor.
Pensaba en algo así como definir algunos movimientos pre establecido para cada pata, que en realidad es el mismo para cualquier pata.
Para esto se necesitaria armar una pata pero en ves de poner los servos habría que poner potenciometros y grabar los movimientos en una etapa previa, algo así como una etapa de aprendizaje.
[\quote]
Yo tambien pensaba en un principio utilizar movimientos predefinidos. Pero eso limitaria mucho las capacidades del robot, ya que solo podria realizar esos movimientos y nada mas. Si quisieras que haga movimientos nuevos, tendrias que programarlos. En cambio, con la cinematica inversa, tenes control total de la posicion de cada pata, pudiendo crear movimientos muy complejos sin la necesidad de mucha programacion.
Ademas podes hacer que el robot "adapte" sus movimientos. Por ejemplo, hay unos que tienen sensores de presion en las patas para detectar el contacto con el suelo. Esto les permite caminar por superficies irregulares.CitarOtro detalle que me surgió de ver el video del PhantomX es el tipo de servos a utilizar, mas que nada por el rango de giro, los que pusiste en el primer mensaje creo son de 60 grados y los veo un poco limitado.
Aunque no se si quieres darle la misma versatilidad que el PhantomX.
Operating speed: 0.10sec/60 degree
Eso es lo que esta especificado, pero no se si 60 grados es el rango o solo se refiere a la velocidad.
No estoy muy canchero con los servos pero poner el tiempo que tarda en hacer 60° parece que es lo habitual.
Esa es la velocidad del servo. Te dice que recorre 60º en 0.1 segundos. Sin embargo no requiero gran amplitud de movimiento, ya que pienso hacer un robot relativamente simple. Digamos que es un prototipo para ir familiarizandome con estos bichitos. Si todo sale bien, podria hacer una version mas robusta del robot ;)
Agradezco mucho tu interes en el proyecto! Por el momento estoy un poco demorado porq cuento con poco tiempo, pero voy a ir compartiendo todos mis avances!
Saludos!!!
Cuando intentes hacer una comunicación inalambrica pensaras en bluetooth o similar.
Yo voy por HID porque mi idea es montar una netbook sobre el robot y luego comunicarme con otra PC por wi fi.
A medida que valla encontrando tiempo y avance con el tema de los servos voy colgando los avances.
Con respecto a lo de Processing no tengo mucha idea, igual creo que sigo con C para no perder lo avanzado.
Ahh ok. Lei muy rapido los ejemplos que me enviaste, y si no me equivoco, es el mismo metodo para generar ondas de PWM que nos muestra Manolo aqui:
http://www.micropic.es/mpblog/2007/09/generacion-de-3-pwm-probamos-led-rgb/
No me resulta complicado el proceso, pero lo que alcancé a entender que con el direccionamiento indirecto se logra bajar la cantidad de instrucciones de la rutina de servicio de la interrupción, que puede ser critico si se trabajara con un uC con limitaciones en la frecuencia de trabajo, aunque no creo que sea un problema con nuestro 18f4550.
Lo otro que pensaba es que nuestro PIC de comando de servos tiene que ser medio "bobo", o sea, recibe datos y mueve servos, no creo que se le pueda pedir mucho mas.
#pragma config PLLDIV = 5 // (20MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HSLuego calculo bien el TCY, aunque si alguien lo calculara o me diera una ayudita no me ofendo ;-)
Recuerda que si bien el periodo del PWM es de 20mseg, los 256 pasos no son en esos 20mseg, sino que en los primeros 2,5mseg.
[\quote]
Tenes razon! Me habia olvidado de eso jeje.CitarLo del tiempo de instrucción y los calculos del timer voy a tener que repasar la hoja de datos como decis, son cosas que se me olvidan muy facil :lol:
Mi configuracion es asíCódigo: [Seleccionar]#pragma config PLLDIV = 5 // (20MHz crystal)Luego calculo bien el TCY, aunque si alguien lo calculara o me diera una ayudita no me ofendo ;-)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS
Veo que programas en C18. Yo pienso hacerlo en CCS. La configuración de los fuses se ve bien, es la misma que uso yo en mis proyectos con USB ;)
Igual todavía no me quiero meter con el código hasta que tenga el hardware listo. Estoy pensando que me puedo estar olvidando, para luego no arrepentirme cuando tenga la placa ya hecha (pasa mas seguido de lo q parece). Hasta ahora tengo los pines para los servos, un puerto para la programacion en circuito, USB, un par de leds de estado, y no se si poner un pulsador, o entradas para sensores ultrasonicos... Para el modulo bluetooth tengo q hacer una adaptacion de niveles de tension, eso esta pendiente.
Que creen que se me puede estar olvidando??
Saludos!
Hasta ahora tengo los pines para los servos, un puerto para la programacion en circuito, USB, un par de leds de estado, y no se si poner un pulsador, o entradas para sensores ultrasonicos... Para el modulo bluetooth tengo q hacer una adaptacion de niveles de tension, eso esta pendiente.
Que creen que se me puede estar olvidando??
Un apunte gera, estoy viendo que alimentas el micro con la misma alimentacion de los servos, yo siempre habia leido que era conveniente alimentarse por separado por problemas de interferencias, y como comenta willynovi tienes el GND del USB sin conectar.Miguel, estuve siguiendo tus hilos por el tema del movimiento del servo, ya lo tenes andando bien?
Te dejo el esquema de una controladora que hice:
http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=39455.0;attach=19764
http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=39455.0;attach=19765
http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=39455.0;attach=19766
Saludos!
El modulo central tiene un PIC18F4550, con todos los pines para conectar los servos, un conector ICSP, puerto USB, y aún me falta ver como voy a hacer con el modulo bluetooth, ya que tengo que hacer una adaptacion de tensiones de 5V a 3.3V.
Yo uso un integrado de Texas para adaptar de 5 a 3.3V (despues te cuento como va) es el TPS73033DBVRG4.
Una consulta muy básica quizá, es mucho más trabajo usar PaP (por ejemplo los miniaturas de las disqueteras) que unos servos?
Miquel, ahí estuve viendo tu diseño y me diste un par de ideas ;) esta piola eso de poner el micro a 45º jeje. Cómo haces para alimentar el circuito y los servos? Tenes una fuente externa?Hola gera, en principio si estoy usando una fuente externa para ir haciendo pruebas. Mi idea es hacer una pcb dedicada solo a la alimentacion, pero primero debo calcular el consumo de los servos y todavia no tengo claro si lo hare con transistores.
Hola gera, en principio si estoy usando una fuente externa para ir haciendo pruebas. Mi idea es hacer una pcb dedicada solo a la alimentacion, pero primero debo calcular el consumo de los servos y todavia no tengo claro si lo hare con transistores.
Saludos!
Se ve muy bien tu pcb.
Te recomiendo colocarle unos orificios para el montaje de la pcb.
Saludos!
Hola gera, la idea de los transistores seria para poder aumentar la intensidad, yo estuve mirando unos servos de la marca hitec y casi llego a los 7Amp.Volvi del retiro Navideño 8)
LVD (low voltage detect) gracias por el dato no sabia de esto.
Saludos!
Hola gera, la idea de los transistores seria para poder aumentar la intensidad, yo estuve mirando unos servos de la marca hitec y casi llego a los 7Amp.Volvi del retiro Navideño 8)
LVD (low voltage detect) gracias por el dato no sabia de esto.
Saludos!
Estuve avanzando con el programa pero como estaba fuera de casa no hice pruebas con servos, en estos días les cuento ;-)
Miguel, lo que te dice Gera es que la linea de señal al servo desde el PIC no lleva corriente o muy poco, entonces no es necesario el transistor o similar, no vas a tener problema si conectas directo PIC -> Servo.
Gera, estoy viendo de adquirir un módulo Bluetooth, vos ya tenes uno, o estas pensando adquirir ese del link?
En cualquiera de los dos casos, cual viene mejor? Se que algunos son mas funcionales que otros.
Gera, estoy viendo de adquirir un módulo Bluetooth, vos ya tenes uno, o estas pensando adquirir ese del link?
En cualquiera de los dos casos, cual viene mejor? Se que algunos son mas funcionales que otros.
Hola gera.
Una consulta.¿ El LVD lo haces con la entrada V_sens ?
Saludos
Hola willynovi, lo de los transistores no es para el control de los servos, ahí no tengo problemas, seria en la fuente de alimentación a la salida del integrado para aumentar la corriente para alimentar dichos servos.
Saludos!
/** CONSTANTS ******************************************************/
#define left 65160 // TMR0 Value for 0,5 msec
#define right 52410 // TMR0 Value for 17,5 msec
#define middle 65505 // TMR0 Value for 40 usec (0,04 msec)void YourHighPriorityISRCode()
{
//Check which interrupt flag caused the interrupt.
//Service the interrupt
//Clear the interrupt flag
//Etc.
if(INTCONbits.TMR0IF)
{
// Rutine to serve all servos
// it has to last 2 msec, if first 0,5 msec are driven by TMR0 interrupt, else 2,5 msec
if(Fase == 52)
{
WriteTimer0(left); // Timer for 0,5 msec
mSERVO_All_On(); // At 0,0 msec all servo pin must go ON
Fase = 0;
INTCONbits.TMR0IF = 0; // Clear interrupt flag
}
if((Fase >= 0) && (Fase < 51))
{
WriteTimer0(middle); // Timer for 20 usec
if (Servo[0] == Fase){mSERVO_0_Off();} // If servo pos < Fase then servo pin OFF
if (Servo[1] == Fase){mSERVO_1_Off();}
if (Servo[2] == Fase){mSERVO_2_Off();}
if (Servo[3] == Fase){mSERVO_3_Off();}
if (Servo[4] == Fase){mSERVO_4_Off();}
if (Servo[5] == Fase){mSERVO_5_Off();}
if (Servo[6] == Fase){mSERVO_6_Off();}
if (Servo[7] == Fase){mSERVO_7_Off();}
if (Servo[8] == Fase){mSERVO_8_Off();}
if (Servo[9] == Fase){mSERVO_9_Off();}
if (Servo[10] == Fase){mSERVO_10_Off();}
if (Servo[11] == Fase){mSERVO_11_Off();}
if (Servo[12] == Fase){mSERVO_12_Off();}
if (Servo[13] == Fase){mSERVO_13_Off();}
if (Servo[14] == Fase){mSERVO_14_Off();}
if (Servo[15] == Fase){mSERVO_15_Off();}
if (Servo[16] == Fase){mSERVO_16_Off();}
if (Servo[17] == Fase){mSERVO_17_Off();}
Fase++;
INTCONbits.TMR0IF = 0; // Clear interrupt flag
}
if(Fase == 51)
{
WriteTimer0(right); // Timer for 17,5 msec
Fase++;
INTCONbits.TMR0IF = 0; // Clear interrupt flag
}
}
#if defined(USB_INTERRUPT)
USBDeviceTasks();
#endif
} //This return will be a "retfie fast", since this is in a #pragma interrupt section OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_16);
INTCON2bits.TMR0IP = 1; // High priority for Timer0
RCONbits.IPEN = 1; // Enable priority levels
INTCONbits.GIEH = 1; // Enable interrupts
WriteTimer0(1785); // Timer for 85 msec -> only for first interrupt
Si desconectas todos los servos (de esa manera no se genera ruido) funciona la comunicación? Porque puede ser falta de atención a la comunicación debido al corto periodo que existe entre interrupciones.
Usas polling o interrupt?
Saludos!
Mi transmicion es serial >> Adaptador USB.Si eso sospecho, como te pasó a vos, lo mas probable es que tenga ruido que afecte y se reinicie el programa, mas que nada por la prueba que hice con el LED.
Para lo que te daba el ejemplo es para decirte que el USB no alimenta mas de 120 mA por el puerto, y que es muy afectado por los ruidos eléctricos y otros temas que lo perturban.
Mi transmicion es serial >> Adaptador USB.Si eso sospecho, como te pasó a vos, lo mas probable es que tenga ruido que afecte y se reinicie el programa, mas que nada por la prueba que hice con el LED.
Para lo que te daba el ejemplo es para decirte que el USB no alimenta mas de 120 mA por el puerto, y que es muy afectado por los ruidos eléctricos y otros temas que lo perturban.
Por el tema de que se pase de corriente, creo que todavía no me ha pasado porque creo que la PC me hubiera avisado, al menos una vez me avisó cuando tuve un corto en otra placa y si mal no recuerdo se reinició la compu.
Cuando tenga el soft que envia datos seguro que lo voy a confirmar.
Hablando de eso, del soft que envia datos, no soy un programador muy experimentado, lo que mas he hecho es muy simple.
La pregunta concreta es, es necesario que al enviar una trama de datos, primer byte para un código y luego 20 bytes mas para la posición de cada servo, el dispositivo con el que me estoy comunicando retorne algún byte?
Entiendo que si tengo algún sensor, por ejemplo un switch, es necesario saber el estado, pero si no tuviera, es buena práctica usar un retorno desde el dispositivo? por ejemplo un código "estoy vivo" o "recibí los datos bien"
Gera, como te fué con la compra de los servos?
Y el módulo bluetooth, lo compras en DX?
Estoy viendo de hacer una inversión en servos :mrgreen: y ahí en Hobby King tienen muy buen precio, el tema es saber de alguna experiencia previa, por el plazo de entrega no me preocupo, pero si por el tema del pago y como me lo despachan.
Si no te molesta comentar, te lo voy a agradecer ;-)
Gracias por tus comentarios Gera.
Por la calidad de los servos o del módulo no me preocupo tanto, mas que nada me preocupa el tema del pago y el envio, por un tema de desconocimiento.
Ambos, HK y DX son pago con tarjeta de crédito, no?
Voy a ver si me registro en ambas páginas y me animo a realizar la compra, por ahora quizas con micro servos de poco valor para probar el sistema de compra y luego veo si encaro algunos servos mas grandes ya que mi idea es hacer un robot que pueda llevar la netbook a hombros.
Espero que en algun momento esa informacion les sea util.
¿En que lenguaje o entorno estas programando ?He pasado por varios, hace mucho hice mis primeros pinos con el Basic y despues ya me incliné por el C.
Gracias por las felicitaciones Gera ;-)
Me ha llegado un mail de HK que en 45 días tendré los servos en casa, así que por ahora voy a ir armando una sola pata con los servos que ya tengo, así para cuando me lleguen tengo todo cocinado.
Estoy averiguando el tema de la cinematica inversa a ver como es esto y como seria para programarlo.
Por ahora todo el cálculo del movimiento lo voy a hacer en la PC y enviar solo al pic la actualización de la posición de cada servo.
Sin embargo, me surge una duda: Como sincronizar el movimiento de las patas? O sea, para generar una caminata debemos mover las patas sincronizadamente. Cada pata describe un movimiento que esta desfasado respecto al de las demas (esa fase depende de cuantas patas movamos a la vez). Como se les ocurre que podemos implementar esto?
Un contador sirve como referencia de sincronismo, un "clock universal" para las patas. Cada pata recibe como parametro el movimiento que tiene q describir (mediante una funcion matematica, probablemente curvas bezier) y una fase. Entonces la posicion de cada pata en un instante dado se calcula como la funcion correspondiente al valor del contador mas el desfasaje.
Cada pata recibe como parametro el movimiento que tiene q describir (mediante una funcion matematica, probablemente curvas bezier)
/*Código para generar una curva cúbica de Bézier*/
typedef struct
{
float x;
float y;
}
Point2D;
/*
cp es una matriz de 4 elementos donde:
cp[0] es el primer punto, o P0 en el diagrama de abajo
cp[1] es el primer punto de control, o P1 en el diagrama de abajo
cp[2] es el segundo punto de control, o P2 en el diagrama de abajo
cp[3] es el punto final, o P3 en el diagrama de abajo
t es el valor del parámetro, 0 <= t <= 1
*/
Point2D PointOnCubicBezier( Point2D* cp, float t )
{
float ax, bx, cx;
float ay, by, cy;
float tSquared, tCubed;
Point2D result;
/* cálculo de los coeficientes polinomiales */
cx = 3.0 * (cp[1].x - cp[0].x);
bx = 3.0 * (cp[2].x - cp[1].x) - cx;
ax = cp[3].x - cp[0].x - cx - bx;
cy = 3.0 * (cp[1].y - cp[0].y);
by = 3.0 * (cp[2].y - cp[1].y) - cy;
ay = cp[3].y - cp[0].y - cy - by;
/* cálculo del punto de la curva en el valor del parámetro t */
tSquared = t * t;
tCubed = tSquared * t;
result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
return result;
}
/*
ComputeBezier llena un array de Point2D con los puntos de la curva
generados de los puntos de control cp.
Esta llamada debe ubicar suficiente lugar de memoria para el resultado
la cual es del tamaño <sizeof(Point2D) numberOfPoints>
*/
void ComputeBezier( Point2D* cp, int numberOfPoints, Point2D* curve ) {
float dt;
int i;
dt = 1.0 / ( numberOfPoints - 1 );
for( i = 0; i < numberOfPoints; i++)
curve[i] = PointOnCubicBezier( cp, i*dt );
}bezier(0, 2, 0,t);Corresponde a una curva bezier cuadratica compuesta por los puntos (0,0) (0.5,2) (1,0)output_high(servo_pin[3]);
Creo que tienes un error en los cálculos de la resolución, porque el pulso alto del servo es 2ms, entonces -> 2ms/50us=40, por lo que si tienes servos de 60° te da una resolución de 1,5°. Mucho mas aceptable de lo que pensabas :mrgreen:Si no me equivoco, es 1ms, porque el pulso minimo es de 1ms y el maximo de 2ms, o sea que la informacion util se encuentra en ese intervalo de 1ms.
Creo que ese valor 20 que calculas lo usas en el programa, quizas debas cambiarlo.
Lo que no veo son los 0,5ms iniciales, o eso ya lo tienes incorporado en el valor del duty de cada servo?Tenes razon! Inicializo todos los servos en 0, cuando debería ser 30 (30 interrupciones por 50us cada una = 1.5ms)
El otro punto que le veo a diferencia de mi programa es que tu siempre mantienes el tiempo de la interrupción en 50us incluso posterior a que terminó el pulso de 2,5ms. Es decir, de 2,5ms hasta 20ms tienes 17,5ms que no es necesario tener interrupciones por el timer.Es una buena idea, asi el timer no esta interrumpiendo a lo tonto ;) Es mas, tambien hay 1ms inicial que siempre se mantiene en alto. O sea que podemos hacer lo siguiente:
Lo que yo hago es modificar el valor del timer para que desborde a 17,5ms y así cae la interrupción cuando deben ponerse nuevamente los pines de los servos en alto.
Similar con el 0,5ms iniciales donde no es necesario modificar el estado de los pines.
Veo que tu comunicacion la atiendes por interrupción, lo has probado ya? tener la interrupcion cada 50us afecta en algo?
Willy, estas queriendo controlar los servos directamente con temporizaciones desde el programa en PC ???
Es bastante dificil lograrlo, ya que las tareas en multitareas siempre tendran mayor prioridad de procesador que cualquier programa del usuario, por lo tanto veo bastante dificil que puedas lograr tiempos con precision del milisegundo...
Yo había entendido que el pc xD :D
No necesitan una tasa de envío rápida porque los servos toman su tiempo en llegar a la posición deseada.
Para tener una idea de la velocidad viene un valor de tiempo en recorrer X angulo.Podrían probar con ese tiempo para establecer velocidad de transferencia..
Saludos!
Huuuu, que garrón che, y podes recuperar el PIC?
Estos temas son los que me desalientan a hacer algo con montaje superficial :oops:
hasta tiro humito
En fin, dentro de poco voy a estar en carrera de nuevo jeje.
/* Este código sirve para controlar por medio de PWM el encendido de hasta
8 LEDs, y la posición de hasta 8 servos, por medio de comandos seriales
propios del puerto de comunicaciones seriales del PIC16F887, aunque
fácilmente se puede migrar a otros dispositivos.
En una pantalla LCD de 16x2 caracteres, se puede ver el menú de la aplicación
el cuál consta de un menú principal, al mandar el comando ASCII "ENTER" que
corresponde con el valor decimal 13, se pasa a la siguiente pantalla, para
volver al menu principal, es con ESCAPE, en el segundo menú es donde
da a escoger entre controlar los LEDs o los servos, con los números 1 y 2
respectivamente, posteriormente se muestra el número actual del LED o servo
que se esté controlando, pudiendo cambiar de número solo con presionar el
correspondiente dígito, si se presiona un número que no es, manda un mensaje
de error, al presionar "-" o "=" (lo deje con el signo igual, por que mi lap
no tiene signo más sin presionar shift) decremente o incrementa el pwm del
dispositivo en cuetión, con la barra espacioadora se va a ambos extremos, 0 o
180 grados en los servos, o prendido o apagado en los LEDs, toda la info que
se imprimie en el LCD también se manda serialmente a la computadora.
*/
#include <16F887.h>
#fuses HS, MCLR, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP, NODEBUG
#use delay(clock=20Mhz)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7,bits=8,parity=N) // Definición del RS232
#include <total_lcd.h>
#define LED1 PIN_B5
#define LED2 PIN_B4
#define LED3 PIN_B3
#define LED4 PIN_B2
#define LED5 PIN_B1
#define LED6 PIN_B0
#define LED7 PIN_C5
#define LED8 PIN_C4
#define SERVO1 PIN_A0
#define SERVO2 PIN_A1
#define SERVO3 PIN_A2
#define SERVO4 PIN_A3
#define SERVO5 PIN_A4
#define SERVO6 PIN_A5
#define SERVO7 PIN_E0
#define SERVO8 PIN_E1
#define SERVO9 PIN_E2
#define MIN_SERVO 9
#define MAX_SERVO 34
#define DEGREE 6.923
#define ENTER 13
#define ESCAPE 27
#define REGRESO 8
int8 duty_cycle=0,n=0;
int8 LED[8] = {0,0,0,0,0,0,0,0};
int8 SERVO[8] = {0,0,0,0,0,0,0,0};
int8 directory=0;
//int16 t=1000;
int1 flag_data=1;
char data=ESCAPE,last_data;
float degress[8] = {0,0,0,0,0,0,0,0};
void configure()
{
set_tris_A(0x00);
set_tris_B(0x00);
set_tris_C(0x00);
set_tris_D(0x00);
set_tris_E(0x00);
output_A(0x00);
output_B(0x00);
output_C(0x00);
output_D(0x00);
output_E(0x00);
setup_timer_0(T0_INTERNAL|T0_DIV_1);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
lcd_init();
}
void print_LED()
{
flag_data=0;
printf(lcd_putc,"\fPulsa + - SPACE\n LED %d: %U %%" ,(n+1),LED[n]);
printf("Pulsa + - SPACE\rLED %d: %U %%\r\r" ,(n+1),LED[n]);
}
void print_servo()
{
flag_data=0;
printf(lcd_putc,"\fPulsa + - SPACE\nSERVO%d: %.2f¡"(n+1),degress[n]);
printf("Pulsa + - SPACE\rSERVO%d: %.2f¡\r\r"(n+1),degress[n]);
}
void print_error()
{
lcd_putc("\f ERROR! \nOpcion invalida");
lcd_putc("ERROR! Opcion invalida\r\r");
delay_ms(500);
data=last_data;
flag_data=1;
}
//==========================
void main()
{
configure();
lcd_putc("LCD OK!!!");
delay_ms(500);
while(TRUE)
{
if(flag_data==1&&directory==0)
{
flag_data=0;
switch(data)
{
case ESCAPE:
lcd_putc("\f--- M E N U ---\n PRESS ENTER");
printf("--- M E N U ---\r PRESS ENTER\r\r");
while(data!=ENTER) {}
directory=0;
break;
case ENTER:
lcd_putc("\f 1 = LEDs\n 2 = SERVOS ");
printf("1 = LEDs\r 2 = SERVOS \r");
directory=1;
break;
default: print_error(); break;
}
}
if(flag_data==1&&directory==1)
{
flag_data=0;
switch(data)
{
case '1':
lcd_putc("\fSelecciona led:\n 1 -- 8");
printf("Selecciona led: 1 -- 8\r");
directory=2;
break;
case '2':
lcd_putc("\fSelecciona servo\n 1 -- 8");
lcd_putc("Selecciona servo: 1 -- 8\r");
directory=3;
break;
case ESCAPE:
directory=0;
flag_data=1;
break;
default: print_error(); break;
}
}
if(flag_data==1&&directory==2)
{
flag_data=0;
switch(data)
{
case '1': n=0; print_LED(); directory=4; break;
case '2': n=1; print_LED(); directory=4; break;
case '3': n=2; print_LED(); directory=4; break;
case '4': n=3; print_LED(); directory=4; break;
case '5': n=4; print_LED(); directory=4; break;
case '6': n=5; print_LED(); directory=4; break;
case '7': n=6; print_LED(); directory=4; break;
case '8': n=7; print_LED(); directory=4; break;
case ESCAPE:
directory=0;
flag_data=1;
break;
default: print_error(); break;
}
}
if(flag_data==1&&directory==3)
{
flag_data=0;
switch(data)
{
case '1': n=0; print_servo(); directory=5; break;
case '2': n=1; print_servo(); directory=5; break;
case '3': n=2; print_servo(); directory=5; break;
case '4': n=3; print_servo(); directory=5; break;
case '5': n=4; print_servo(); directory=5; break;
case '6': n=5; print_servo(); directory=5; break;
case '7': n=6; print_servo(); directory=5; break;
case '8': n=7; print_servo(); directory=5; break;
case ESCAPE:
directory=0;
flag_data=1;
break;
default: print_error(); break;
}
}
if(flag_data==1&&directory==4)
{
flag_data=0;
switch(data)
{
case '=':
{
if(LED[n]<100) LED[n]+=10;
print_LED();
}
break;
case '-':
{
if(LED[n]>0) LED[n]-=10;
print_LED();
}
break;
case ' ':
{
if(LED[n]<50) LED[n]=100;
else LED[n]=0;
print_LED();
}
break;
case '1': n=0; print_LED(); directory=4; break;
case '2': n=1; print_LED(); directory=4; break;
case '3': n=2; print_LED(); directory=4; break;
case '4': n=3; print_LED(); directory=4; break;
case '5': n=4; print_LED(); directory=4; break;
case '6': n=5; print_LED(); directory=4; break;
case '7': n=6; print_LED(); directory=4; break;
case '8': n=7; print_LED(); directory=4; break;
case ESCAPE:
directory=0;
flag_data=1;
break;
default: print_error(); break;
}
}
if(flag_data==1&&directory==5)
{
flag_data=0;
switch(data)
{
case '=':
{
if(SERVO[n]>MIN_SERVO)
{
SERVO[n]--;
degress[n]-=DEGREE;
print_servo();
}
}
break;
case '-':
{
if(SERVO[n]<MAX_SERVO)
{
SERVO[n]++;
degress[n]+=DEGREE;
print_servo();
}
}
break;
case ' ':
{
if(SERVO[n]<23)
{
SERVO[n]=MAX_SERVO;
degress[n]=179.998;
}
else
{
SERVO[n]=MIN_SERVO;
degress[n]=0;
}
print_servo();
}
break;
case '1': n=0; print_servo(); directory=5; break;
case '2': n=1; print_servo(); directory=5; break;
case '3': n=2; print_servo(); directory=5; break;
case '4': n=3; print_servo(); directory=5; break;
case '5': n=4; print_servo(); directory=5; break;
case '6': n=5; print_servo(); directory=5; break;
case '7': n=6; print_servo(); directory=5; break;
case '8': n=7; print_servo(); directory=5; break;
case ESCAPE:
directory=0;
flag_data=1;
break;
default: print_error(); break;
}
}
}
}
#INT_TIMER0
void timer0()
{
if(duty_cycle==0)
{
if(LED[0]) output_high(LED1);
if(LED[1]) output_high(LED2);
if(LED[2]) output_high(LED3);
if(LED[3]) output_high(LED4);
if(LED[4]) output_high(LED5);
if(LED[5]) output_high(LED6);
if(LED[6]) output_high(LED7);
if(LED[7]) output_high(LED8);
if(SERVO[0]) output_high(SERVO1);
if(SERVO[1]) output_high(SERVO2);
if(SERVO[2]) output_high(SERVO3);
if(SERVO[3]) output_high(SERVO4);
if(SERVO[4]) output_high(SERVO5);
if(SERVO[5]) output_high(SERVO6);
if(SERVO[6]) output_high(SERVO7);
if(SERVO[7]) output_high(SERVO8);
}
if(LED[0]==duty_cycle) output_low(LED1);
if(LED[1]==duty_cycle) output_low(LED2);
if(LED[2]==duty_cycle) output_low(LED3);
if(LED[3]==duty_cycle) output_low(LED4);
if(LED[4]==duty_cycle) output_low(LED5);
if(LED[5]==duty_cycle) output_low(LED6);
if(LED[6]==duty_cycle) output_low(LED7);
if(LED[7]==duty_cycle) output_low(LED8);
if(SERVO[0]==duty_cycle) output_low(SERVO1);
if(SERVO[1]==duty_cycle) output_low(SERVO2);
if(SERVO[2]==duty_cycle) output_low(SERVO3);
if(SERVO[3]==duty_cycle) output_low(SERVO4);
if(SERVO[4]==duty_cycle) output_low(SERVO5);
if(SERVO[5]==duty_cycle) output_low(SERVO6);
if(SERVO[6]==duty_cycle) output_low(SERVO7);
if(SERVO[7]==duty_cycle) output_low(SERVO8);
duty_cycle++;
if(duty_cycle==101) duty_cycle=0;
SET_TIMER0(0);
}
#int_rda
void serial_isr()
{
if (kbhit())
{
last_data=data;
data=getch();
printf(data);
flag_data=1;
}
}
Hola Gera, me alegro porque haya salido todo bien la operación....
Te quedó con muy buena pinta el hexapodo ((:-))
Con esa idea yo cambiaría tu programa y que el contador solo incremente hasta 50, que es cuando todos los servos ya estan en nivel bajo.Es muy buena, así voy a tener tiempo para dejar que el procesador atienda otras cosas (como la trama serial). Leí por ahí un método muy bueno que utiliza dos timers. Uno que modula los anchos de pulsos dentro de los primeros 2,5ms, y otro que temporiza el periodo total de 20ms. Vamos a probar con ese método a ver qué resultados obtengo.
Luego antes de salir de la rutina de la interrupción cargas el valor del tmr1 para que vuelva a interrumpir dentro de 17,5 ms.
Sin dudas iría por la placa esa para los 32 servos, pero no me le animo a DX, tengo mis ciertas dudas con el tema de la aduana...
Has comprado hace poco algo por DX?
Que resultado has tenido?
Estuve mirando y hay unos kit de robotica que estaria bueno para mi cuñadito que quiere iniciarse en la robotica.
Yo hasta ahora siempre compre a DX, soy de argentina y ni siquiera de cordoba o buenos aires, lo unico que si tengo que pagar 40$ al correo por paquete.
pero siempre compre por menos de 25U$S, a veces me tarda 1 mes en llegar y el otro dia me sorprendio por que me llego a las 2 semanas u algo asi.
Hasta ahora no tuve nunca problemas con eso.
Pedi por ebay una vez y nunca llego.
Todavia me faltan por probar todas las demas.