Bueno aqui en este programita controlo un motor dc mediante el pwm hardware del pic y un servo por software. Para ello se accede a una interrupcion cada 100us y dependiendo del valor del dutty me genera el pulso deseado para posicionar el servo. Probado fisicamente y funciona pèrfectamente, la unica pega, que para el caso de un pulso de 600 us me lo genera de 1200. Ya lo mirare.
Otra cosa, mediante i2c se envia un byte que recibe el esclavo. Los 4 primeros bits me marcan la velocidad del motor dc, los 3 siguientes la posicion del servo y el ultimo para hacer que el cacharro vaya hacia alante o hacia atras.
Pocher, al fianl miramos eso de que porque no recibia correctamente el i2c cuando metiamos la interrupcion del servo y ya funciona. En la directiva de use i2c, en vez de fast pusimos slow, y el puerto c no esta configurado, creo que lo configuraba como salida y creemos que por eso no recibia nada (que va a ser que si).
Bueno este es el programita del esclavo:
#include <16F876A.H>
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD//, WRT
#use Delay(Clock=4000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=0X08, SLOW , NOFORCE_SW)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#byte port_a = 5 // Identificador asociado al registro de dirección 5
#byte port_b = 6 // Identificador asociado al registro de dirección 6
#byte port_c = 7 // Identificador asociado al registro de dirección 7
int periodo, dutty;
#INT_TIMER1 //Rutina de atención a la interrupcion
void interrupcion()
{
set_timer1(65472); //Recarga el timer a 100us (-36us) Base de tiempo
periodo=periodo+1; // cada vez que se entre incrementamso periodo
if(periodo<dutty) //Duracion de estado alto PWM segun
posicion servo
{
output_high(pin_a0);
}
else
{
output_low(pin_a0);
}
if(periodo==200) // Acaba el periodo
{
periodo=0;
}
}
void main()
{
int dato, servo, xx, dutycalculado;
set_tris_a(0x00);
set_tris_b(0x00);
enable_interrupts(GLOBAL); // Activamos interrupciones
globales
enable_interrupts(INT_TIMER1); // ... y la interrupcion por TMR1
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_1); //Configuracion TMR1 y preescaler
setup_timer_2(T2_DIV_BY_16,249,1) ; // Div=16 ; PR2=249 ; Postscale=1
setup_CCP1 (CCP_PWM);
set_timer1(65472);
delay_ms(50);
while(1)
{
if(i2c_poll())
{
dato=0;
dato=i2c_read();
i2c_stop();
}
port_b=dato;
servo= 0b01110000 & dato;
xx= 0b00001111 & dato; //velocidad (1=10%, 2=20%......10=100%)
if(xx>10) //
{
xx=0;
set_pwm1_duty(0); //Si es mayor a 10 duty=0
}
else
{
dutycalculado= 25 * xx ; // Valor a cargar en duty
set_pwm1_duty(dutycalculado);
}
switch (servo)
{
case 0:
dutty=12;
break;
case 16:
dutty=15;
break;
case 48:
dutty=18;
break;
case 64:
dutty=9;
break;
case 114:
dutty=6;
break;
}
while (!(i2c_poll()))
{
port_b=dato;
}
}
}
Bueno y el maestro es sencillo, simplemente enviar con las funciones de ccs i2c write()..... etc. Y eso funciona fisicamente sin problemas.
Una cosa que no tiene nada que ver, queremos enviar un byte de un robot a otro mediante infrarrojos y no sabemos muy bien como hacerlo. Hemos encontrado un enlace parece ser que bueno
www.jdlope.tripod.com/infra.html y tal te explica como hacerlo. Si le pegais un vistazo y tal me comentais. Nos gustaria si es posible evitar modular la señal. Si alguien ha hecho algo de esto porfi que comente algo por aqui o que abra un post de comunicacion infrarroja en el subforo de robotica.
Un saludo desde valencia.