/* * Program to Control Robotic Arm through POT * 5 Servo controlled with Timer Register PWM * Dated: 15-1-2019 * Web: www.circuitdigest.com * Author: B.Asiwnth Raj */ #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #define _XTAL_FREQ 20000000 //Crystak Freq is 20MHz #define PWM_Frequency 0.05 // in KHz (50Hz) //Define LCD pins #define RS RB1 #define EN RB2 #define D4 RB3 #define D5 RB4 #define D6 RB5 #define D7 RB6 #include #include "lcd.h" //Header for using LCD module int POT_val; //variable to store value from ADC int count; //timer variable //int T_TOTAL = (1/PWM_Frequency); //calculate Total Time from frequency (in milli sec)) //20msec int Duty_cycle; //Duty cycle value int T_ON[4]; char servo; void ADC_Initialize() //Prepare the ADC module { ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected ADCON1 = 0b11000000; // Internal reference voltage is selected } unsigned int ADC_Read(unsigned char channel) //Read from ADC { ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits ADCON0 |= channel<<3; //Setting the required Bits __delay_ms(2); //Acquisition time to charge hold capacitor GO_nDONE = 1; //Initializes A/D Conversion while(GO_nDONE); //Wait for A/D Conversion to complete return ((ADRESH<<8)+ADRESL); //Returns Result } void interrupt timer_isr() { if(TMR0IF==1) // Timer flag has been triggered due to timer overflow -> set to overflow for every 0.05ms { TMR0 = 248; //Load the timer Value TMR0IF=0; // Clear timer interrupt flag count++; //Count increments by 1 for every 0.05ms } int servo_code[] = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100 }; if (count >= 20*20) count=0; if (count <= (T_ON[servo]) ) PORTD = PORTD | servo_code[servo]; else PORTD = PORTD & ~(servo_code[servo]); } void main() { /*****Port Configuration for Timer ******/ OPTION_REG = 0b00000100; // Timer0 with external freq and 32 as prescalar // Also Enables PULL UPs TMR0=248; // Load the time value for 0.0001s; delayValue can be between 0-256 only TMR0IE=1; //Enable timer interrupt bit in PIE1 register GIE=1; //Enable Global Interrupt PEIE=1; //Enable the Peripheral Interrupt /***********______***********/ /*****Port Configuration for I/O ******/ TRISB = 0x00; //PORT B is output since LCd is connected PORTB=0x00; //Initialize all pins to 0 TRISD = 0x00; //PORT D is output since servo is connected PORTD=0x00; //Initialize all pins to 0 /***********______***********/ Lcd_Start(); //Initialize LCD module ADC_Initialize(); //Initialize ADC module // Lcd_Clear(); // Lcd_Set_Cursor(1,1); //Lcd_Print_String("Circuit Digest"); //Lcd_Set_Cursor(2,1); //Lcd_Print_String("WORKING!!"); //__delay_ms(500); while(1) { for (int pot_num=0; pot_num<=3; pot_num++) { int Pev_val = T_ON[pot_num]; POT_val = (ADC_Read(pot_num)); //Read the value of POT using ADC Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100 T_ON[pot_num] = Duty_cycle* 0.4;//((Duty_cycle * T_TOTAL) / 1000)*10; //Calculate On Time from 0ms to 2ms for 0-100 Duty Cycle //*10 is multiplication factor if (T_ON[pot_num] != Pev_val) { Lcd_Clear(); servo = pot_num; Lcd_Set_Cursor(2,11); Lcd_Print_String("S:");Lcd_Print_Char(servo+'0'); if (pot_num==0) {Lcd_Set_Cursor(1,1); Lcd_Print_String("A:");} else if (pot_num==1) {Lcd_Set_Cursor(1,6); Lcd_Print_String("B:");} else if (pot_num==2) {Lcd_Set_Cursor(1,11); Lcd_Print_String("C:");} else if (pot_num==3) {Lcd_Set_Cursor(2,1); Lcd_Print_String("D:");} else if (pot_num==4) {Lcd_Set_Cursor(2,6); Lcd_Print_String("E:");} char d2 = (Duty_cycle) %10; char d1 = (Duty_cycle/10) %10; Lcd_Print_Char(d1+'0');Lcd_Print_Char(d2+'0'); } } } }