Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Wixel and PWM


#25

Hello, sheepcounter.

What Wixel pin is the signal line for your servo connected to?

The header file stdio.h is part of the compiler, not the Wixel SDK. If Eclipse is complaining that it can’t find it, there is a way to tell Eclipse what your “include directories” are so it can find it.

–David


#26

The servo control line is connected to P1_2.


#27

I still can’t get stdio.h to work in Eclipse. I manually copied the “stdio.h” file and it’s dependencies “_mingw.h”, “stddef.h”, and “stdarg.h” into the “include” folder in the eclipse workspace.
I get this error:

libraries/include/stdarg.h:40: syntax error: token -> ‘__gnuc_va_list’ ; column
40
sdcpp.exe: fatal error: when writing output to : Invalid argument
make: *** [apps/receive_servo2/receive_servo2.rel] Error 1

I also tried putting “C:\MinGW” in the Makefile Include Directories, but that didn’t do anything. Do you know what could be wrong?


#28

If you look at test_servo.c, you can see that pin P1_2 (a.k.a. channel 3) just alternates between a target of 0 (no pulses) and a target of 1700 us. This means that you servo won’t actually move, it will stay in one place unless you are trying to turn it with your hand. I suggest connecting the servo to P1_1 instead.


#29

The compiler used for the Wixel is SDCC, not MinGW. You shouldn’t need to copy any files into the Wixel SDK’s include directory.

What do you mean by “Makefile Include Directories”? You shouldn’t modify the Makefile, you should add SDCC’s include directory in Eclipse under Project -> Properties -> C/C++ General -> Paths and Symbols.

–David


#30

Thanks, I get it now! I was confused because Eclipse Help shows MinGW. I was able to add SDCC’s include directory, and it was compiling successfully with stdio.h, but then compile suddenly stopped working. All along, the “#include stdio.h” was highlighted in Eclipse as an unresolved inclusion, so I didn’t understand why it even worked before. I’m getting this error:

make: *** No rule to make target `x86)/SDCC/bin/../include/asm/mcs51/features.h)
', needed by `apps/receive_servo2/receive_servo2.rel'.  Stop.

#31

I tried “make clean” and build, and It is behaving erractically and it sometimes compiles and sometimes gives that error. When it does compile, it doesn’t work correctly because not all of the functions that contain printf statements actually print as they’re supposed to. The “#include stdio.h” is still highlighted as not being found…


#32

It sounds like you still haven’t configured Eclipse correctly to know where stdio.h is. But that doesn’t matter for now. Eclipse is not in charge of the compilation and its knowledge of the header files should not affect the compilation.

The more serious problem is that you are sometimes unable to compile. We’ve been through this before. The next time you have the problem with building, could you please send me a zip file with a complete copy of your entire wixel-sdk so I can try compiling it here with exactly the same files you have on your computer? You can email it to david AT pololu.com. Feel free to remove any code you don’t want to give away, as long as the error still happens after that code has been removed. In fact, the more you can simplify the SDK, the better, because it will help locate the problem. After sending the SDK to me, try building (or running make) about five times to see if the problem fixes itself.

–David


#33

Hello.

Thanks for emailing me a copy of your Wixel SDK. I was able to compile it just fine using make 3.82-pololu1. Here is the output:

[quote]C:\Users\David\Desktop\wixel-sdk>make
Linking apps/example_blink_led/example_blink_led.hex
Packaging apps/example_blink_led/example_blink_led.wxl
packihx: read 446 lines, wrote 253: OK.
Compiling apps/receive_servo2/receive_servo2.rel
Linking apps/receive_servo2/receive_servo2.hex
Packaging apps/receive_servo2/receive_servo2.wxl
packihx: read 795 lines, wrote 442: OK.
Linking apps/shiftbrite/shiftbrite.hex
Packaging apps/shiftbrite/shiftbrite.wxl
packihx: read 783 lines, wrote 436: OK.
Linking apps/transmit_test/transmit_test.hex
Packaging apps/transmit_test/transmit_test.wxl
packihx: read 654 lines, wrote 383: OK.

C:\Users\David\Desktop\wixel-sdk>make -v
GNU Make 3.82-pololu1
Built for Windows32
Copyright © 2010 Free Software Foundation, Inc.
Modified by Pololu https://www.pololu.com
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[/quote]

However, when I tried to do “make clean” I got this error:

It looks like you’ve added so many apps that the number of arguments Make tries to pass to rm is way too large, so “make clean” probably wasn’t actually doing anything for you. I’ve pushed a change up to the official Wixel SDK that fixes this problem (at least for now).

I also saw some very weird behavior from make (Interrupt/Exception caught at 0x416638) which seemed to be triggered by me running a command such as “make clean >error.txt” and seemed to be fixed sometimes by various odd actions such as closing the Command Prompt and reopening it. There is probably a bug in make and I will look into it.

In the meantime, as a workaround to the error you are having, I think you should comment out the “-include $(Ds)” line at the bottom of the Makefile. One side effect is that whenever you edit a header (.h) file you will have to run “make clean” afterwards to ensure that all the affected .c files get recompiled.

Here is the Makefile from your copy of the Wixel SDK, modified to have both of those changes in it (fixing make clean, commenting out the include line):

Makefile.txt (6.47 KB)

I recommend renaming this file to Makefile, replacing your existing Makefile with it, then running “make clean”, then running “make”. You should run those two commands at a Command Prompt instead of from within Eclipse so you can see any errors that might happen.

–David


#34

Thanks for your help! There’s no more errors in the command prompt, but there’s still a problem with printf because the servo runs as programmed, but the terminal window will only sometimes display the printf statements.


#35

You’re probably calling printf without checking that there is space available in the buffer, or making some other error in your code. Could you try to simplify your code to the simplest thing that demonstrates the problem and post it here?

–David


#36

Here’s the code:

[code]#include <cc2511_types.h>
#include <wixel.h>
#include <usb.h>
#include <usb_com.h>
#include <radio_queue.h>
#include <stdio.h>

PDATA uint16 a_value;
uint16 done;

void PwmInit(){
/* PWM freq = 24M / 32 / 511 = 198.75 Hz, SETS THE LOW TIME*/
T1CC0L = 0xFF;
T1CC0H = 0x1F;

// PWM duty cycle about 1/8, SETS THE HIGH TIME
T1CC1L = 0xFF;
T1CC1H = 0xFF;

/* Timer 1 channel 0 set compare mode 4 */
T1CCTL0 = 0x24;

/* Timer 1 CFG set to Alt 2 location */
PERCFG = 0x40;

/* P1_1 set peripheral func which associated with Timer 1 Channel 0 output */
P1SEL = 0x04;

/* set modulo mode Prescaler set to Tick Freq / 32*/
T1CTL = 0x0E;

}

void analogInputsInit() {
//Disable pull-ups and pull-downs for all pins on Port 0.
P0INP = 0x3F;

}

typedef struct adcReport
{
uint8 length;
uint8 serialNumber[4];
uint16 readings[6];
} adcReport;

void updateLeds()
{
usbShowStatusWithGreenLed();
LED_YELLOW(0);
LED_RED(0);
}

void putchar(char c)
{
usbComTxSendByte©;
}

void servoControl()
{

if (a_value <= 1600){
	printf("LOW");
	T1CTL = 0x0E;
	 // SETS THE HIGH TIME
	    T1CC1L = 0x00;
	    T1CC1H = 0x00;
	done = 1;
}
else{
	printf("HIGH");
	T1CTL = 0x0A;
	 T1CC1L = 0x40;
	 T1CC1H = 0x00;
	 /*  SETS THE LOW TIME*/
	     T1CC0L = 0xFF;
	     T1CC0H = 0x00;

}

}

void radioToUsbService() {
adcReport XDATA * rxPacket;

//Check if there is a radio packet to report and space in the USB TX buffers to report it.
if ((rxPacket = (adcReport XDATA *) radioQueueRxCurrentPacket())) {
	//We received a packet from a Wixel

	a_value = rxPacket->readings[5];

	printf(" %5u", a_value);

	putchar('\r');
	putchar('\n');

	radioQueueRxDoneWithPacket();
                                                                                                   }

                           }

void main(void)
{
systemInit();
usbInit();
radioQueueInit();
PwmInit();
analogInputsInit();
done = 0;
while(1)
{
updateLeds();
boardService();
usbComService();
radioToUsbService();

	if (done == 0){

	printf("hi");
	servoControl();
			 }

}

}

[/code]

Another observation that I don’t understand is that the if statement in Main is never entered, and I had to comment out the if (done == 0){ for the servoControl function to work.


#37

I didn’t look carefully at all of your code, but indeed you are doing the printing wrong. Your putchar function calls usbComTxSendByte. The documentation of usbComTxSendByte explains that you have to make sure there is enough space in the buffer before calling it. There could be all kinds of things going wrong since you don’t perform this basic check.

I recommend changing your printing code to be like this:

if (usbComTxAvailable() >= 20)
{
  printf(" %5u\r\n", a_value);
}

This way, it will just not send the data unless there is space. You’ll need to make changes like this to every place where you call printf or putchar. You used to do this.

If you want to guarantee that the data is sent you’ll need to do something more complicated.

–David


#38

oh I forgot about that…after adding the buffer check, printf works but I still have the problem I mentioned about the if statement not being executed.


#39

Back to the topic of PWM, :mrgreen:

I’m using Timer 1 Channel 0, with these register settings:

[code]// Timer 1 channel 0 set compare mode 4
T1CCTL0 = 0x24;

// Timer 1 Channel 0 set to Alt 2 location
PERCFG = 0x40;

// P1_1 set peripheral func which associated with Timer 1 Channel 0 output 
P1SEL = 0x04;

//set prescaler to divide tick frequency by 128, modulo mode
T1CTL = 0x0E;

	 // set the pulse width
	 T1CC1L = 0x77;
	 T1CC1H = 0x0A;

	 //  set the frequency
	     T1CC0L = 0xFF;
	     T1CC0H = 0x00;

[/code]

I’m finding that the T1CC0 register is affecting the servo’s speed rather than the T1CC1 register and I don’t understand why. Setting the T1CC1 register to two different extreme values (with T1CC0 being constant) has no effect on the servo speed.


#40

You’re setting “done” to 1 in servoControl but never setting it to 0 so at some point it will just be stuck at 1. You’re reading a_value before it’s guaranteed to be initialized. --David


#41

I looked at your PWM code for Timer 1.

Why do you think T1CC1 will have any effect?

It looks like you configured your timer badly because you set it up so that T1CC0 controls the high time of the pulse (because you configured it to be in output compare mode) but it also controls the frequency (because that’s how modulo mode works). This doesn’t make sense and I think it will just result in your line being high or low all the time. You need to instead configure channel 1 to be your PWM output so that T1CC0 sets the frequency and T1CC1 sets the pulse width. If this doesn’t make sense, read the datasheet carefully.

–David


#42

I was looking at Figure 33: Output Compare Modes, Timer Modulo Mode and the Output Compare Mode 4 signal. If I’m setting T1CCTL0 for output compare mode 4, why does this diagram not apply to it? It looks like T1CC0 is setting the frequency and T1CCn (T1CC1 or T1CC2?) is setting the pulse width…


#43

In your code you never configured Timer 1 Channel 1 to be in output compare mode, so T1CC1 doesn’t control anything.

Figure 33 explains what happens when you set a channel to be in output compare mode while the timer itself is in modulo mode (frequency controlled by T1CC0). The channel that is in output compare mode is then named “n” for the purpose of the diagram. Since you incorrectly set channel 0 to be in output compare mode, n is 0, so T1CCn is the same as T1CC0. The diagram might still apply, but not in the way you think it does.

Section 12.6.5 is helpful.

–David


#44

wow, thank you for clarifying that! One more question: does this mean it isn’t possible to output a PWM signal on P1_2 because it is Timer 1 Channel 0? If I set T1CC1 to modify the duty cycle, does that mean the whole PWM signal is being output on Timer 1 Channel 1?