Wixel and PWM

another problem: I can’t find the header file stdio.h in the latest SDK, and it’s not in the list of include files on the Wixel github. I can’t find the header file I was using before…

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

The servo control line is connected to P1_2.

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?

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.

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

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.

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…

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

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:

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 (C) 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.

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

...
 libraries/src/wixel/fixed.sym libraries/src/wixel/time.adb libraries/src/wixel/
time.asm libraries/src/wixel/time.d libraries/src/wixel/time.lst libraries/src/w
ixel/time.rel libraries/src/wixel/time.rst libraries/src/wixel/time.sym, ...) fa
iled.
make (e=87): The parameter is incorrect.
make: [clean] Error 87 (ignored)

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

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.

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

Here’s the 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(c);
}

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();
				 }

	}
}

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.

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

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.

Back to the topic of PWM, :mrgreen:

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

// 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;

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.

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

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

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…

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