1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

XC8, delays, and servo control. Simple code won't word.

Discussion in 'Microcontrollers' started by wannaBinventor, Jul 21, 2013.

  1. wannaBinventor

    wannaBinventor Member

    Joined:
    Jun 24, 2010
    Messages:
    214
    Likes:
    2
    Hey all, still trying to learn C and get back into this.

    I've attached a servo to the PICKIT2 devboard (the one with the 16F887).

    First, my variable delay functions are not working. I'm trying to just use the "__delay_ms(#)" and "__delay_us(#)" macros inside a function with a for loop. The idea is that I'll pass the # of us or ms that I want to the function and the for loop with the __delay macro will run that many times. Let's ignore compensating for overhead for the sake of just getting it going. Please see the code and the error that this is generating below. I don't understand the error, as "_delayms" isn't even in the code.

    Besides that problem, the main purpose of the code was just to move a servo from one position to another over and over again. It serves no real purpose, other than just establishing the concept. Note that in the below code, i substituted __delay_ms(#) for the function that I wrote since I am getting errors. Notice in my while(1) loop, I'm just sending the pulse once every 20ms five hundred times. The first for loop should move it 90 deg left, and the second for loop should move 90 deg right. It should remain in each position for 10,000ms (or 10 seconds).

    It is not behaving as expected. The servo is moving 90 left for several seconds and then just bouncing to the right quickly and then back left. It's only staying in the 90 deg right position for probably 250ms. I can't understand that because the period and the number of iterations is the same for both for loops. I even tried a different servo, but had the same results.

    Here is the code:
    Code (text):
    #include <xc.h>
    #include <stdlib.h>
    #include <stdio.h>
    #pragma config WDTE = OFF // Disable Watchdog timer
    #pragma config LVP = OFF
    #define _XTAL_FREQ 4000000

    //__CONFIG(MCLRE_ON & CP_OFF & WDT_OFF & OSC_IntRC)



    usdelay(int a);
    msdelay(int b);



    void main()

    {


    int i;
    int j;
    int adcresult;
    long int delay;
    ANSEL = 1;
    TRISD = 0;
    TRISB = 0;
    INTCON = 0;
    OPTION_REG = 128;
    INTCONbits.GIE = 0;

    ANSELH = 0b00000000;


    PORTD = 128;

    while(1){

    for (i=0;i<500;i++)
        {
        PORTBbits.RB0 = 1;
        msdelay(1);
        PORTBbits.RB0 = 0;
        msdelay(19);
        }

    PORTDbits.RD7 = ~PORTDbits.RD7;
    PORTDbits.RD0 = ~PORTDbits.RD0;

    for (i=0;i<500;i++)
        {
        PORTBbits.RB0 = 1;
        delayms(2);
        PORTBbits.RB0 = 0;
        delayms(18);
        }

    }
    }


    usdelay(int a)
    {
    int r;
    for (r=0;r<a;r++)
    __delay_us(1);
    }

    msdelay(int b)
    {
    int s;

    for (s=0;s<b;s++)
    __delay_ms(1);
    }  

    Here is the compiler output:
    Code (text):

    Warning [361] C:\Program Files (x86)\Microchip\xc8\v1.12\bin\flashy.c; 60.1 function declared implicit int
    Executing: "C:\Program Files (x86)\Microchip\xc8\v1.12\bin\xc8.exe" -otestothercode.cof -mtestothercode.map --summary=default --output=default flashy.p1 --chip=16F887 -P --runtime=default --opt=default -N-1 -D__DEBUG=1 -g --asmlist "--errformat=Error   [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s"
    Microchip MPLAB XC8 C Compiler V1.12
    Copyright (C) 2012 Microchip Technology Inc.
    License type: Node Configuration

    Warning [1273] ; . Omniscient Code Generation not available in Free mode
    Error   [499] ; 0. undefined symbol:
        _delayms(testothercode.obj)
    (908) exit status = 1

    ********** Build failed! **********
     
    Any idea what I am getting that error, and why the servo is behaving as it is?
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,145
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    You have defined a function

    msdelay();

    Then you call

    delayms();


    The compiler doesn't know the latter.. you need to call the function you made.

    Code (C):
    for (i=0;i<500;i++)
        {
        PORTBbits.RB0 = 1;
        delayms(2);
        PORTBbits.RB0 = 0;
        delayms(18);
        }
    Wrong

    Code (C):
    for (i=0;i<500;i++)
        {
        PORTBbits.RB0 = 1;
        msdelay(2);
        PORTBbits.RB0 = 0;
        msdelay(18);
        }
    Right
     
  3. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    I don't understand why you have wrapped the __delay_ms(); and __delay_us(); functions inside your custom functions.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,145
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE

    Because the HTC __delay_ms() routine has some issues with certain values.... ie.. __delay_ms(200); sometimes fouls up....

    Also there is a constant / variable issue..
     
  6. wannaBinventor

    wannaBinventor Member

    Joined:
    Jun 24, 2010
    Messages:
    214
    Likes:
    2
    Wow Ian. Thanks for showing me the obvious. That was a dumb one on my part! Is there a way to guard against those kind of dumb mistakes? IE:, when I write macros in VBA at work, I will declared variables like "totalBalance" and then I code in all in lower case. If the visual basic editor doesn't autocorrect "totalbalance" to "totalBalance", then I know I have mistyped or not declared it. Is there anyway to do such a thing in the MPLAB IDE with XC8, or do I just need to be more careful?

    And misterT, Ian is correct. For some reason XC8 doesn't come with a delay function that allows a variable to be passed to it, so this is the work around that I came up with. Maybe I just don't understand the language yet, but for the life of me I can't understand why it wouldn't come with a variable delay function right out of the box.

    EDIT:
    Servos are still acting erratically. Any idea what may be causing that?
    Servo signal list is connected to RB0, servo positive connected to 5v positive rail, servo ground connected to the ground rail.
     
    Last edited: Jul 21, 2013
  7. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    That is perfectly good explanation. I was wondering because you used the delay functions with small constants. Actually I don't remember ever using delay functions with variables. The library delay-functions are optimized at compile time for the constant values to give accurate timing. When you use the delay with variables like that, they are less accurate (they are longer than intended).
     
  8. misterT

    misterT Well-Known Member Most Helpful Member

    Joined:
    Apr 19, 2010
    Messages:
    2,697
    Likes:
    368
    Location:
    Finland
    I don't think this matters at all in your application, but if you want to optimize the delay functions, you could write them like this:

    Code (C):

    void msdelay(unsigned char b) {
        do {
            b--;
            __delay_ms(1);
        } while(b);
    }
     
    Just make sure you don't pass zero as parameter..
     
  9. lijoppans

    lijoppans New Member

    Joined:
    Jul 11, 2011
    Messages:
    5
    Likes:
    0

Share This Page