Need help with programming OX2 -> MM^ -> BLDC

I am trying to connect the OX2 to the Micro Maestro 6 outputting to two hobby brushless motor controllers. I have successfully sent data to the MM6 without errors but it does not respond. (IE the controllers don’t do anything and trying servos also don’t do anything) The servos and motor controllers will respond correctly when using Maestro Control Center to command the MM6.

I also am having trouble figuring out how to take the A/D data from a trimpot and send it to the MM6 as position information. I would like to take the voltage on channels 3 and 4 and use that as the position target on the MM6, however, I am not sure how to convert it to the upper and lower bits the MM6 needs.

Finally, I would like to call the sub only when the value changes so is the best method to store the current value in memory and then compare to the next one, calling the sub if they are changed?


void delay_sec(unsigned char sec)
{
	unsigned int cycles;

	for(cycles = 0; cycles < (sec * 40); cycles ++)
	{
		_delay_ms(12);
		_delay_ms(13);
	}
}

char send_buffer[32];

void wait_for_sending_to_finish()   
{   
    while(!serial_send_buffer_empty(UART0));   
} 

void send_servo_init()
{
	wait_for_sending_to_finish();
	send_buffer[0] = 0x84, 0x00, 0x03, 0xE0; 
	serial_send(UART0, send_buffer, 4);
	send_buffer[0] = 0;

	wait_for_sending_to_finish();
	send_buffer[0] = 0x84, 0x01, 0x03, 0xE0; 
	serial_send(UART0, send_buffer, 4); 
	send_buffer[0] = 0;	
}

void send_servo_ins()
{
	wait_for_sending_to_finish(); 
	send_buffer[0] = 0x84, 0x00, 0x07, 0xD0;
	serial_send(UART0, send_buffer, 4); 
	send_buffer[0] = 0;	

	wait_for_sending_to_finish(); 
	send_buffer[0] = 0x84, 0x01, 0x05, 0xDC; 
	serial_send(UART0, send_buffer, 4); 
	send_buffer[0] = 0;	
}

int main(void)
{
	int out1;
	int out2;
	int servo1;
	int servo2;

	serial_set_baud_rate(UART0, 9600); 
	serial_set_mode(UART0, SERIAL_AUTOMATIC);
	
	send_servo_init();

	while (1)
	{
		
	  	unsigned int RD1 = analog_read(3);
		unsigned int RD2 = analog_read(4);
		out1 = 4*RD1;
		out2 = 4*RD2;

		servo1 = 2*RD1;
		servo2 = 2*RD2;	

		send_servo_ins();
	}
}

You are not successfully sending data to the Maestro.

This line of code:

send_buffer[0] = 0x84, 0x00, 0x03, 0xE0;  // Wrong in two ways

is equivalent to this:

send_buffer[0] = 0x84;  // Only sets one byte

You should familiarize yourself with C’s comma operator, or just stop using it because it is not useful in most cases.

The other thing that’s wrong with that code is that for some reason your third data byte (0xE0) has the MSB set, so the Maestro will interpret it as a command. You should read the Maestro serial command protocols documentation to learn about data bytes vs. command bytes.

Our Maestro documentation for serial servo commands has example C code that shows how you would populate an array of bytes:

serialBytes[0] = 0x84; // Command byte: Set Target.  
serialBytes[1] = channel; // First data byte holds channel number.  
serialBytes[2] = target & 0x7F; // Second byte holds the lower 7 bits of target.  
serialBytes[3] = (target >> 7) & 0x7F;   // Third data byte holds the bits 7-13 of target.

Also, please make sure that you have configured your Maestro to use the same baud rate that you specified in your code. By default, the Maestro auto-detects the baud rate but your code isn’t sending it any 0xAA bytes so it can’t detect it.

Actually, I recommend using a higher baud rate like 115200 because both the Maestro and the X2 can handle it, but its probably better to get it working at 9600 first and then change it.

If your system still isn’t working after this advice, please simplify your code to the simplest possible thing that doesn’t work (it should only send one command), and post it again, along with all your relevant Maestro configuration settings.

–David

Thanks for the advise. I have read the manual, but I clearly have not understood it. I tried your example previously and the code would not compile.

serialBytes[0] = 0x84; // Command byte: Set Target.  
serialBytes[1] = channel; // First data byte holds channel number.
serialBytes[2] = target & 0x7F; // Second byte holds the lower 7 bits of target.  
serialBytes[3] = (target >> 7) & 0x7F;   // Third data byte holds the bits 7-13 of target.

How does this apply to sending the captured target? What method is this Pololu or the simple command? I was trying to keep to the simple command and the register shift I thought applied to pololu commands.

The code I gave will not compile on its own because it doesn’t contain “main()” and it doesn’t define any of the variables that is uses. You need to define those on your own.

I don’t understand your question. The example code mentioned generates the serial bytes that you must send to the Maestro in order to set the target of a channel.

You could have answered this question yourself by reading the manual and noting that the byte sequence generated by the example code has a 0x84 in it, followed by three data bytes, so the example code uses the Compact protocol. All Pololu protocol commands start with 0xAA, and my example code does not generate a 0xAA. There is no “simple” protocol, there is only simple ((edit: oops, I meant Compact)), Pololu, and Mini-SSC.

That is incorrect. Why did you think that? The data bytes are the same no matter what protocol you are using.

–David

By your code I mean the example code in the manual with all the required other “stuff”.

Please, I am just trying to get clarification of how the Pololu product works in the case I am attempting to implement it. I need it broken down more than “read the manual”.

For example this statement:

serialBytes[2] = target & 0x7F;
serialBytes[3] = (target >> 7) & 0x7F;

I want to set the target to 1000 uS, so can I just define for the data byte:

int target = 1000;
serialBytes[2] = target & 0x7F;
serialBytes[3] = (target >> 7) & 0x7F;

Most of your questions make it seem like you have not read the manual. If you understood all the relevant sentences in the manual, you wouldn’t need to ask these questions. If there is a sentence in a relevant section of the the manual that you don’t understand, you should quote that sentence, explain why you are confused about it, and ask us what it means.

For example, your latest question could have been answered if you had read and understood the following sentence in the manual, which immediately precedes the example code you were asking about from the Maestro User’s Guide:

Here is some example C code that will generate the correct serial bytes, given … an integer “target” that holds the desired target (in units of quarter microseconds if this is a servo channel) and an array called serialBytes.

So your target variable should hold 4000 if you want 1000us.

–David

I readily admitted I didn’t understand. I often find myself at a loss and it can be difficult for those of us less awesome to identify where we have overlooked something in a text to point it out. For this project I am just helping out another dept and I am here for product support. In the end I did get it working.

For what it is worth: the code -

int servo1;
int servo2;
int init = 4000;

// Delay for N seconds
void delay_sec(unsigned char sec)
{
	unsigned int cycles;

	// Delay 25ms at a time (38.4ms is the most we can delay with a
	// 20MHz processor, unfortunately.  See the delay.h include file
	// for more info.)

	for(cycles = 0; cycles < (sec * 40); cycles ++)
	{
		_delay_ms(12);
		_delay_ms(13);
	}
}

// send_buffer: A buffer for sending bytes on UART.
char send_buffer[32];

void wait_for_sending_to_finish()   
{   
    while(!serial_send_buffer_empty(UART0));   
} 

void send_servo_init()
{
	wait_for_sending_to_finish();
	send_buffer[0] = 0x84; 
	send_buffer[1] = 0x00;
	send_buffer[2] = init & 0x7F; 
	send_buffer[3] = (init >> 7) & 0x7F;
	serial_send(UART0, send_buffer, 4); //send array

	wait_for_sending_to_finish();
	send_buffer[0] = 0x84;
	send_buffer[1] = 0x01;
	send_buffer[2] = init & 0x7F;
	send_buffer[3] = (init >> 7) & 0x7F;
	serial_send(UART0, send_buffer, 4); //send array
}

void send_servo_ins()
{
	wait_for_sending_to_finish(); 
	send_buffer[0] = 0x84;
	send_buffer[1] = 0x00;
	send_buffer[2] = servo1 & 0x7F;
	send_buffer[3] = (servo1 >> 7) & 0x7F;
	serial_send(UART0, send_buffer, 4); //send array

	wait_for_sending_to_finish(); 
	send_buffer[0] = 0x84;
	send_buffer[1] = 0x01;
	send_buffer[2] = servo2 & 0x7F;
	send_buffer[3] = (servo2 >> 7) & 0x7F;
	serial_send(UART0, send_buffer, 4); //send array
}

int main(void)
{
	//Declare variables for main program
	int out1 = 0;
	int out2 = 0;

	serial_set_baud_rate(UART0, 115200); //Sets up transmission rate to Micro Maestro
	serial_set_mode(UART0, SERIAL_AUTOMATIC); //sets up the serial library to use interrupts.  Alternativly serial_check() could be used.
	
	send_servo_init();

	lcd_init_printf();	// required if we want to use printf()

	clear();			// clear the LCD
	delay_ms(200);		// wait for 200 ms

	lcd_goto_xy(0, 0);
	printf("********************");
	lcd_goto_xy(0, 1);
	printf("    Initializing    ");	// print to LCD
	lcd_goto_xy(0, 2);
	printf("********************");

	delay_ms(1000);		// wait
	lcd_scroll(LCD_LEFT, 20, 200);

	clear();			// clear the LCD
	delay_ms(200);		// wait for 200 ms

	lcd_goto_xy(0,0);
	printf("*** WHEEL SPEED ***");
	lcd_goto_xy(0,1);
	printf("    -----------    ");
	lcd_goto_xy(0,2);
	printf(" Left    Right     ");

	while (1)
	{
		//Read wheel speed and display on LCD.
	  	int AD1 = analog_read(3);
		int AD2 = analog_read(4);
		
		delay_ms(50);  				//wait for some time then read channels again.

		int AD11 = analog_read(3);
		int AD22 = analog_read(4);

		if (AD1 != AD11)
		{
			servo1 = 4000+(8*AD11);
			send_servo_ins();
			out1 = 8*(AD11-511);  	//pulled up by trim pot so it never goes below 0.
		}
		else
		{
			out1 = 8*(AD11-511);
		}

		if (AD2 != AD22)
		{
			servo2 = 4000+(8*AD22);
			send_servo_ins();
			out2 = 8*(AD22-511);	//pulled up by trim pot so it never goes below 0.
		}
		else
		{
			out2 = 8*(AD22-511);
		}

		
		lcd_goto_xy(0,3);
		printf(" %4u", out1);
		lcd_goto_xy(10,3);
		printf("%4u  RPM", out2);

		delay_ms(100); 				// wait to reduce LCD flicker
	}
}