Continue to Site

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.

  • 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.

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

Status
Not open for further replies.
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:
#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:
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?
 
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.

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

Wrong

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

Right
 
I don't understand why you have wrapped the __delay_ms(); and __delay_us(); functions inside your custom functions.
 
I don't understand why you have wrapped the __delay_ms(); and __delay_us(); functions inside your custom functions.

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..
 
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:
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..
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.

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).
 
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:

C:
void msdelay(unsigned char b) {
    do {
        b--;
        __delay_ms(1);
    } while(b);
}

Just make sure you don't pass zero as parameter..
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top