Program Download:
Main C and Hex File
animatronic_eyes.c
animatronic_eyes.hex
eyes_and_eyebrows.c
eyes_and_eyebrows.hex
Main C and Hex File
animatronic_eyes.c
animatronic_eyes.hex
eyes_and_eyebrows.c
eyes_and_eyebrows.hex
The software used in this tutorial came from the previous Robotic Eyebrows tutorial and then was modified for controlling 6 servos instead of 2. 4 servos control how the eyes move and 2 servos control how the eyebrows move.
The PIC's Timer0 is used to refresh the system every 20 miliseconds or at 50 Hz. Timer1 is used to cycle through and create a pulse for each servo that we are using. This system only has 2 servos so there are only two unique states that the system can switch between to send servo PWM pulses.
Servo Pulse Control - Interrupt Routine
------------« Begin Code »------------
void InterruptHandlerHigh() // Declaration of InterruptHandler { //Run When Timer overflows from FFFF->0000 if(INTCONbits.TMR0IF) //If TMR0 interrupt flag set { WriteTimer0( 0x3CAF ); //Reset Timer0 for 20mS Delay WriteTimer1( 0xFC77 ); //Reset Timer1 for 1mS Delay count = 0; //Reset Timer1 Interrupt Counter INTCONbits.TMR0IF = 0; //Clear TMR0 Flag } if(PIR1bits.TMR1IF == 1 && PIE1bits.TMR1IE == 1) { //If Timer1 interrupts, do your thing... count++; //Increment Timer1 Interrupt Counter switch(count){ //Choose which servo to modify: case 1: PORTD = 0x01; WriteTimer1( servo0 ); //Right Eyebrow break; case 2: PORTD = 0x02; WriteTimer1( servo1 ); //Left Eyebrow break; case 3: PORTD = 0x04; WriteTimer1( servo2 ); //Left Eye Left/Right break; case 4: PORTD = 0x08; WriteTimer1( servo3 ); //Left Eye Up/Down break; case 5: PORTD = 0x10; WriteTimer1( servo4 ); //Right Eye Left/Right break; case 6: PORTD = 0x20; WriteTimer1( servo5 ); //Right Eye Up/Down break; case 7: PORTD = 0x00; WriteTimer1( 0 ); break; } PIR1bits.TMR1IF = 0; //Clear Timer1 flag } .... ... ..
------------« End Code »------------
In addition to controlling the servos with timers 0 and 1, a low priority timer, timer3 was used to so that movement profiles could be built. This means that not only can the location controlled but the movement speeds. This makes it so that eye movement can be slow or quick, helping to create the illusion that they are actually eyes.
PWM Control - Interrupt Routine
------------« Begin Code »------------
.. .. ... if(PIR2bits.TMR3IF == 1){ //If Timer3 interrupts, do your thing... if(servo_0_dest < servo_0_current){ servo_0_current--; servo0 = servo_0_current; } else if(servo_0_dest > servo_0_current){ servo_0_current++; servo0 = servo_0_current; } if(servo_1_dest < servo_1_current){ servo_1_current--; servo1 = servo_1_current; } else if(servo_1_dest > servo_1_current){ servo_1_current++; servo1 = servo_1_current; } ... .. ... WriteTimer3( speed ); // Reset Instruction Speed Until Interrupt PIR2bits.TMR3IF = 0; //Clear Timer3 flag } INTCONbits.GIE = 1; //Re-enable all interrupts }
There's naturally a lot of other things going on in the software, but I felt these two parts were the key points. Please download the software above and load it onto your PIC. Then you can move to the next phase, testing the system out!