nerdegutta.no
PIC16F628A - Move a servo motor 45 degrees
29.12.24
Embedded
These lines of code moves a servomotor 45 degrees and back. We're not using any timers, but make the PWM signal manual with a for-loop.
// INCLUDE LIBRARIES
#include < xc.h >
// CONFIGURATION BITS
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// DEFINITIONS
#define _XTAL_FREQ 4000000
#define servo PORTBbits.RB0
// VARIABLES
// PROTOTYPES
// FUNCTIONS
// Servo Initialization function
void Servo_Init(void) {
servo = 0; // Ensure the pin starts low
}
// Function to create a precise delay in microseconds
void Delay_us(unsigned int us) {
while (us--) {
__delay_us(1);
}
}
// Function to set servo angle
void Set_Servo_Angle(unsigned char angle) {
unsigned int pulse_width;
// Calculate pulse width (1ms to 2ms for 0 to 180 degrees)
pulse_width = (unsigned int)((angle * 20 / 180) + 5);
// Generate PWM signal manually
for (unsigned char i = 0; i < 50; i++) { // 50 cycles for 20ms period
servo = 1; // Set pin high
Delay_us(pulse_width * 10); // Delay for high period
servo = 0; // Set pin low
Delay_us((20 - pulse_width) * 100); // Delay for low period
}
}
void main() {
TRISBbits.TRISB0 = 0; // Configure PORTB.RB0 as output
Servo_Init(); // Initialize Servo control
while (1) {
Set_Servo_Angle(0); // Set servo to 0 degrees
__delay_ms(500); // Wait for 0.5 second
Set_Servo_Angle(45); // Set servo to 45 degrees
__delay_ms(500); // Wait for 0.5 second
}
}