Generation of PWM signals on GPIO pins of the PIC microcontroller: Control of the servo motor

Herbert Wichmann's picture

Offline

Joined: Mar 02, 2019

Replies: 8
Generation of PWM signals on GPIO pins of the PIC microcontroller: Control of the servo motor
March 3, 2019 - 12:12am

Hello Mr. Aswinth Raj,
As a total beginner I tried to compile the source code to your above mentioned PIC project, in MPLAB X vers.5.10 and the compiler Free XC 8 vers 2.00, which I did not succeed. I did not change anything about the code. I have attached a screenshot of the errors here. What am I doing wrong.
Yours sincerely
Herbert Wichmann

download.jpg

download-(1).jpg

Herbert Wichmann's picture

Offline

Joined: Mar 02, 2019

Replies: 8
Generation of PWM signals on GPIO pins of the PIC microcontrolle
March 7, 2019 - 1:45am

Hello Mr. Aswinth Raj, to my post from the 4th of March 2019 here is the text that the compiler issues. Would be glad if someone could help me.
Greeting Herbert Wichmann

 

make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf

make[1]: Entering directory 'C:/Users/Pauline/MPLABXProjects/PWM Servo Aswinth mit 16F877A  das im Brief.X'

make  -f nbproject/Makefile-default.mk dist/default/production/PWM_Servo_Aswinth_mit_16F877A__das_im_Brief.X.production.hex

make[2]: Entering directory 'C:/Users/Pauline/MPLABXProjects/PWM Servo Aswinth mit 16F877A  das im Brief.X'

"C:\Program Files\Microchip\xc8\v2.00\bin\xc8-cc.exe"  -mcpu=16F877A -c  -fno-short-double -fno-short-float -O0 -fasmfile -maddrqual=ignore -xassembler-with-cpp -Wa,-a -DXPRJ_default=default  -msummary=-psect,-class,+mem,-hex,-file  -ginhx032 -Wl,--data-init -mno-keep-startup -mno-osccal -mno-resetbits -mno-save-resetbits -mno-download -mno-stackcall   -std=c99 -gdwarf-3 -mstack=compiled:auto:auto     -o build/default/production/main.p1 main.c

::: advisory: (2049) C99 compliant libraries are currently not available for baseline or mid-range devices, or for enhanced mid-range devices using a reentrant stack; using C90 libraries

main.c:50:6: error: variable has incomplete type 'void'

make[2]: *** [build/default/production/main.p1] Error 1

void interrupt timer_isr()

make[1]: *** [.build-conf] Error 2

make: *** [.build-impl] Error 2

     ^

main.c:50:15: error: expected ';' after top level declarator

void interrupt timer_isr()

              ^

              ;

2 errors generated.

(908) exit status = 1

nbproject/Makefile-default.mk:106: recipe for target 'build/default/production/main.p1' failed

make[2]: Leaving directory 'C:/Users/Pauline/MPLABXProjects/PWM Servo Aswinth mit 16F877A  das im Brief.X'

nbproject/Makefile-default.mk:90: recipe for target '.build-conf' failed

make[1]: Leaving directory 'C:/Users/Pauline/MPLABXProjects/PWM Servo Aswinth mit 16F877A  das im Brief.X'

nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed

 

BUILD FAILED (exit value 2, total time: 1s)

 

 

Aswinth Raj's picture

Offline

Joined: Aug 16, 2016

Replies: 855
The error message is 
March 14, 2019 - 11:33am

The error message is 

main.c:50:6: error: variable has incomplete type 'void'

 

did you make any changes to the code?

Herbert Wichmann's picture

Offline

Joined: Mar 02, 2019

Replies: 8
Generation of PWM signals on GPIO pins of the PIC microcontrolle
March 14, 2019 - 4:17pm

Hello Mr. Aswinh,
Thank you for your feedback and help.

No, I have not changed the code, I lack the experience. I have marked the main.c and lcd.h code on your page and copied both in Nodpat + and then the two code in MPLAB X. I have here both code as I have inserted them in MPLAB X Inserted.
I would be glad to receive further help from you.
Yours sincerely
Herbert Wichmann

 

 

/*
 * 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 <xc.h>
#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');
        
        }
        
       }
        
         
    }
}

 

 

 

 

/*
 * File: Header file to interface LCD with PIC16F877A
 * Author: B.Aswinth Raj
 * More details on: https://circuitdigest.com/microcontroller-projects/16x2-lcd-interfacing-...
 * Created on 5 May, 2018, 6:43 PM
 */

/*SAMPLE CODE
        Lcd_Clear();
        Lcd_Set_Cursor(1,1);
        Lcd_Print_String("Circuit Digest");
        Lcd_Set_Cursor(2,1);
        Lcd_Print_Char(temp+'0');
/END OF SAMPL*/

void Lcd_SetBit(char data_bit) //Based on the Hex value Set the Bits of the Data Lines
{
    if(data_bit& 1)
        D4 = 1;
    else
        D4 = 0;

    if(data_bit& 2)
        D5 = 1;
    else
        D5 = 0;

    if(data_bit& 4)
        D6 = 1;
    else
        D6 = 0;

    if(data_bit& 8)
        D7 = 1;
    else
        D7 = 0;
}

void Lcd_Cmd(char a)
{
    RS = 0;           
    Lcd_SetBit(a); //Incoming Hex value
    EN  = 1;         
        __delay_ms(4);
        EN  = 0;         
}

Lcd_Clear()
{
    Lcd_Cmd(0); //Clear the LCD
    Lcd_Cmd(1); //Move the curser to first position
}

void Lcd_Set_Cursor(char a, char b)
{
    char temp,z,y;
    if(a== 1)
    {
      temp = 0x80 + b - 1; //80H is used to move the curser
        z = temp>>4; //Lower 8-bits
        y = temp & 0x0F; //Upper 8-bits
        Lcd_Cmd(z); //Set Row
        Lcd_Cmd(y); //Set Column
    }
    else if(a== 2)
    {
        temp = 0xC0 + b - 1;
        z = temp>>4; //Lower 8-bits
        y = temp & 0x0F; //Upper 8-bits
        Lcd_Cmd(z); //Set Row
        Lcd_Cmd(y); //Set Column
    }
}

void Lcd_Start()
{
  Lcd_SetBit(0x00);
  for(int i=1065244; i<=0; i--)  NOP();  
  Lcd_Cmd(0x03);
    __delay_ms(5);
  Lcd_Cmd(0x03);
    __delay_ms(11);
  Lcd_Cmd(0x03);
  Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
  Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
  Lcd_Cmd(0x08); //Select Row 1
  Lcd_Cmd(0x00); //Clear Row 1 Display
  Lcd_Cmd(0x0C); //Select Row 2
  Lcd_Cmd(0x00); //Clear Row 2 Display
  Lcd_Cmd(0x06);
}

void Lcd_Print_Char(char data)  //Send 8-bits through 4-bit mode
{
   char Lower_Nibble,Upper_Nibble;
   Lower_Nibble = data&0x0F;
   Upper_Nibble = data&0xF0;
   RS = 1;             // => RS = 1
   Lcd_SetBit(Upper_Nibble>>4);             //Send upper half by shifting by 4
   EN = 1;
   __delay_us(40);//for(int i=2130483; i<=0; i--)  NOP();
   EN = 0;
   Lcd_SetBit(Lower_Nibble); //Send Lower half
   EN = 1;
   __delay_us(40);//for(int i=2130483; i<=0; i--)  NOP();
   EN = 0;
}

void Lcd_Print_String(char *a)
{
    int i;
    for(i=0;a[i]!='\0';i++)
       Lcd_Print_Char(a[i]);  //Split the string using pointers and call the Char function
}

 

 

Herbert Wichmann's picture

Offline

Joined: Mar 02, 2019

Replies: 8
Generation of PWM signals on GPIO pins of the PIC microcontrolle
March 14, 2019 - 4:42pm

Hello Mr. Aswinth,
sorry I have the wrong code Beigegestellt, here is the code main.c to the problem.

Many Thanks
Herbert Wichmann

/*
 * File:   PIC_GPIO_PWM.c
 * Author: Aswinth
 *
 * Created on 17 October, 2018, 11:59 AM
 */

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#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)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#define _XTAL_FREQ 20000000
#define PWM_Frequency 0.05 // in KHz (50Hz)

//TIMER0    8-bit  with 64-bit Prescalar
//$$RegValue = 256-((Delay * Fosc)/(Prescalar*4))  delay in sec and Fosc in hz  ->Substitute value of Delay for calculating RegValue

int POT_val; //variable to store value from ADC
int count; //timer variable
int T_TOTAL = (1/PWM_Frequency)/10; //calculate Total Time from frequency (in milli sec)) //2msec
int T_ON=0; //value of on time
int Duty_cycle; //Duty cycle value

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.1ms
    {
        TMR0 = 248;     //Load the timer Value
        TMR0IF=0;       // Clear timer interrupt flag
        count++; //Count increments for every 0.1ms -> count/10 will give value of count in ms
    }
    
    if (count <= (T_ON) )
        RD1=1;
    else
        RD1=0;
    
    if (count >= (T_TOTAL*10) )
        count=0;
}

void main()
{    
/*****Port Configuration for Timer ******/
    OPTION_REG = 0b00000101;  // Timer0 with external freq and 64 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 ******/
    TRISD = 0x00; //Instruct the MCU that all pins on PORT D are output
    PORTD=0x00; //Initialize all pins to 0
    /***********______***********/   
    
    ADC_Initialize();

    while(1)
    {
       POT_val = (ADC_Read(0)); //Read the value of POT using ADC
       
       Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100
       
       T_ON = ((Duty_cycle * T_TOTAL)*10 / 100); //Calculate On Time using formulae unit in milli seconds

       __delay_ms(100);     
       
    }
    
}

 
 

 

Jamessex's picture

Offline

Joined: Mar 15, 2019

Replies: 1
hello from Mike
March 15, 2019 - 12:18am

I am new at this forum. What are you talking about?

Herbert Wichmann's picture

Offline

Joined: Mar 02, 2019

Replies: 8
Generation of PWM signals on GPIO pins of the PIC microcontrolle
March 15, 2019 - 4:15am

Hi Mike,
it's about the main code of Mr. Aswinth Raj
which can not be compiled as previously described by me.
 

Greeting Herbert Wichmann