Jump to content
43oh

Help with serial comunication and Servo controller


Recommended Posts

Hi everyone Im a noob with msp430 and Im having troubles with serial comunication with a pololu maestro servocontroller, I got serial comunnication with an arduino board an it was easy but with the msp430 has been imposible for me.

 

I dont know where is the problem and i cant get the serial comunication, please If someone can tell me whats wrong with the code I'll be so grateful, thank you.

 

 

#include "msp430g2553.h"
unsigned char TxByte=0; 
unsigned int result;
unsigned int del;

void in(); 
void main(void)
{
 WDTCTL = WDTPW + WDTHOLD;                
 P1SEL = BIT1 + BIT2 ;                     // P1.1 = RXD, P1.2=TXD               
 UCA0CTL1 |= UCSSEL_1;                     // ACLK = 32.768kHz  (PAG. 435 SLAU144) 
 UCA0BR0 = 0x03;                           // Baud rate de 9600, 32kHz/9600 = 3.41 (PAG. 435 SLAU144)
 UCA0BR1 = 0x00;							//(PAG. 435 SLAU144)
 UCA0MCTL = UCBRS1 + UCBRS0;               // Modulacion UCBRSx = 3 (PAG. 435 SLAU144)
 UCA0CTL1 &= ~UCSWRST;                     // Inicializa USCI (PAG. 451 SLAU144)

 while (1)
{ 
 in(0,1000);      //in(num servo, position)
 for (del=10000; del>0x01; del--);   

}

}

void in(unsigned int servo, unsigned int angle)
{
//bytes to servocontroller
TxByte  |= 0xAA; //envia byte de inicio (170 en decimal)
TxByte  |= 0x0C;  //numero de dispositivo (12 por default)
TxByte  |= 0x04; //byte de comando
TxByte  |= servo; //numero de servo
TxByte  |= (((angle>>7)&0x3f));
TxByte  |= (angle&0x7f);
UCA0TXBUF = TxByte;  
}

Link to post
Share on other sites

Try this:

 

#include "msp430g2553.h"
unsigned char TxByte = 0;
unsigned int result;
unsigned int del;

void in(unsigned int servo, unsigned int angle);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;					// Stop WDT
BCSCTL1 = CALBC1_1MHZ;						// Set DCO to 1MHz
DCOCTL = CALDCO_1MHZ;
P1SEL = BIT1 + BIT2;						// Set P1.1 to RXD and P1.2 to TXD
P1SEL2 = BIT1 + BIT2;	
UCA0CTL1 |= UCSSEL_2;						// Have USCI use SMCLK AKA 1MHz main CLK
UCA0BR0 = 104;								// Baud: 9600, N= CLK/Baud, N= 10^6 / 9600
UCA0BR1 = 0;								// Set upper half of baud select to 0
UCA0MCTL = UCBRS_1;							// Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST;						// Start USCI

while (1)
{
	in(0, 1000);							//in(num servo, position)
	__delay_cycles(10000);
	//__bis_SR_register(CPUOFF + GIE);			//Enter LPM0 with interrupts
}
}
void in(unsigned int servo, unsigned int angle)
{
//bytes to servocontroller
TxByte |= 0xAA;								//envia byte de inicio (170 en decimal)
TxByte |= 0x0C;								//numero de dispositivo (12 por default)
TxByte |= 0x04;								//byte de comando
TxByte |= servo;							//numero de servo
TxByte |= (((angle >> 7) & 0x3f));
TxByte |= (angle & 0x7f);
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = TxByte;
}

 

 

Remember to use the correct pin:

 

post-7895-13513553982_thumb.png

 

What are you using to program the chip, CCS, IAR or MSPGCC?

Link to post
Share on other sites

Here is another attempt:

 

#include "msp430g2553.h"
const unsigned char setup[] = {0x80, 0x01, 0x01, 0x00, 0x01}; 
const unsigned char pos_1[] = {0x80, 0x01, 0x04, 0x00, 13, 127};
const unsigned char pos_2[] = {0x80, 0x01, 0x04, 0x00, 35, 127};
unsigned char i;

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;					// Stop WDT
BCSCTL1 = CALBC1_1MHZ;						// Set DCO to 1MHz
DCOCTL = CALDCO_1MHZ;
P1SEL = BIT1 + BIT2;						// Set P1.1 to RXD and P1.2 to TXD
P1SEL2 = BIT1 + BIT2;	
UCA0CTL1 |= UCSSEL_2;						// Have USCI use SMCLK AKA 1MHz main CLK
UCA0BR0 = 104;								// Baud: 9600, N= CLK/Baud, N= 10^6 / 9600
UCA0BR1 = 0;								// Set upper half of baud select to 0
UCA0MCTL = UCBRS_1;							// Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST;						// Start USCI

for(i = 0; i < 5; i++)
{
	while(!(IFG2 & UCA0TXIFG));
	UCA0TXBUF = setup[i];
}
__delay_cycles(100000);

while (1)
{
	for(i = 0; i < 6; i++)
	{
		while(!(IFG2 & UCA0TXIFG));
		UCA0TXBUF = pos_1[i];
	}
	__delay_cycles(100000);

	for(i = 0; i < 6; i++)
	{
		while(!(IFG2 & UCA0TXIFG));
		UCA0TXBUF = pos_2[i];
	}
	__delay_cycles(100000);
}
}

 

Does it doing anything?

Link to post
Share on other sites

//bytes to servocontroller
TxByte  |= 0xAA; //envia byte de inicio (170 en decimal)
TxByte  |= 0x0C;  //numero de dispositivo (12 por default)
TxByte  |= 0x04; //byte de comando
TxByte  |= servo; //numero de servo
TxByte  |= (((angle>>7)&0x3f));
TxByte  |= (angle&0x7f);
UCA0TXBUF = TxByte;  
}

 

First of all, you are incorrectly assigning value to TxByte, do not OR it.

 

Second, shouldn't you be sending each byte individually?

Something like that:

 

//bytes to servocontroller 
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = 0xAA; //envia byte de inicio (170 en decimal) 
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = 0x0C;  //numero de dispositivo (12 por default)
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = 0x04; //byte de comando
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = servo; //numero de servo
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = (((angle>>7)&0x3f));
while(!(IFG2 & UCA0TXIFG));
UCA0TXBUF = (angle&0x7f);
}

 

This could be optimized by adding a loop of course.

Link to post
Share on other sites

I think that is correct but im a begginer and im learning jeje, here is a code that shows how to control a servo controller via serial commands using a pic, this is an example of the pololu servo controller webpage.

 

#include<18f4550.H>

#fuses HSPLL, NOMCLR, PUT, BROWNOUT, BORV43, NOWDT, NOPROTECT, NOLVP

#fuses NODEBUG, USBDIV, PLL5, CPUDIV1, VREGEN, CCP2B3

#use delay(clock=48000000)

 

#define TTL_TX1 PIN_C6

#define TTL_RX1 PIN_C7

 

#use rs232(xmit=TTL_TX1, rcv=TTL_RX1, bits=8, parity=N)

 

void main() {

delay_ms(2000);

 

while(true) {

// Send a Set Target command using the Pololu protocol.

putc(0xAA); // Start Byte

putc(0x0C); // Device ID = 12

putc(0x04); // Command = Set Target

putc(0x00); // Channel = 0

putc(0x20); // Target position = 1000 us (typical minimum for servos)

putc(0x1F);

delay_ms(1000);

 

// Send another Set Target command using the Pololu protocol.

putc(0xAA);

putc(0x0C);

putc(0x04);

putc(0x00);

putc(0x70); // Target position = 1500 us (typical neutral for servos)

putc(0x2E);

delay_ms(1000);

}

}

Link to post
Share on other sites

Yep, this is exactly what my code snipped above does.

putc(0xXX) - is a function call that sends one char

while(!(IFG2 & UCA0TXIFG)) - this is a loop that will execute until TX buffer is ready for another byte

UCA0TXBUF = 0xXX - put the char in the buffer and send

 

// Send a Set Target command using the Pololu protocol.

putc(0xAA); // Start Byte

putc(0x0C); // Device ID = 12

putc(0x04); // Command = Set Target

putc(0x00); // Channel = 0

putc(0x20); // Target position = 1000 us (typical minimum for servos)

putc(0x1F);

 

You could also create putc function:

 

void putc(char c) {
   while(!(IFG2 & UCA0TXIFG));
   UCA0TXBUF = c;
}

 

One more thing, you do have crystal soldered, right?

Link to post
Share on other sites

Ok this is the last code with the putc function, yes I soldered the crystal but is the same. :(

 

#include "msp430g2553.h"
unsigned char TxByte=0; 
unsigned int result;
unsigned int del;
void putc(char c);
void in(unsigned int servo, unsigned int angle); 
void main(void)
{
 WDTCTL = WDTPW + WDTHOLD;                
 P1SEL = BIT1 + BIT2 ;                     // P1.1 = RXD, P1.2=TXD               
 UCA0CTL1 |= UCSSEL_1;                     // ACLK = 32.768kHz  (PAG. 435 SLAU144) 
 UCA0BR0 = 0x03;                           // Baud rate de 9600, 32kHz/9600 = 3.41 (PAG. 435 SLAU144)
 UCA0BR1 = 0x00;                     //(PAG. 435 SLAU144)
 UCA0MCTL = UCBRS1 + UCBRS0;               // Modulacion UCBRSx = 3 (PAG. 435 SLAU144)
 UCA0CTL1 &= ~UCSWRST;                     // Inicializa USCI (PAG. 451 SLAU144)

 while (1)
{ 
 in(0,1000);      //in(num servo, position)
 for (del=10000; del>0x01; del--);   
 }

}
void putc(char c) {
   while(!(IFG2 & UCA0TXIFG));
   UCA0TXBUF = c;
}

void in(unsigned int servo, unsigned int angle)
{
  //bytes to servocontroller
putc(0xAA); //envia byte de inicio (170 en decimal) 
putc(0x0C);  //numero de dispositivo (12 por default)
putc(0x04); //byte de comando
putc(servo); //numero de servo
putc(((angle>>7)&0x3f));
putc(angle&0x7f);
}

 

Any other advice?

Link to post
Share on other sites

I added the P1SEL2 line and change the clock to DCO, Now is working and this is the final code :D

 

#include "msp430g2553.h"
unsigned char TxByte=0; 
unsigned int result;
unsigned int del;
void putc(char c);
void in(unsigned int servo, unsigned int angle); 
void main(void)
{

WDTCTL = WDTPW + WDTHOLD;                
 P1SEL = BIT1 + BIT2 ;                     // P1.1 = RXD, P1.2=TXD               
 P1SEL2 = BIT1 + BIT2;
 UCA0CTL1 |= UCSWRST;
 UCA0CTL1 |= UCSSEL_2;
 UCA0BR0 = 0x78;
 UCA0BR1 = 0x00;     
 UCA0MCTL = UCBRS_1 + UCBRF_0;
 UCA0MCTL = UCBRS2;
 UCA0CTL1 &= ~UCSWRST;                     // Inicializa USCI (PAG. 451 SLAU144)


 while (1)
{ 
 in(0,100);      //in(num servo, position)
for (del=10000000; del>0x01; del--);   
in(0,5000);      //in(num servo, position)
for (del=10000000; del>0x01; del--);

 }

}
void putc(char c) {
   while(!(IFG2 & UCA0TXIFG));
   UCA0TXBUF = c;
}

void in(unsigned int servo, unsigned int angle)
{
  //bytes to servocontroller
putc(0xAA); //envia byte de inicio (170 en decimal) 
putc(0x0C);  //numero de dispositivo (12 por default)
putc(0x04); //byte de comando
putc(servo); //numero de servo
putc(((angle>>7)&0x3f));
putc(angle&0x7f);
}   

 

RobG and turd Thank you very much!!! :clap:

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...