Connect atmel atmega32 to ssc-32

Please help me…

I can’t get my ssc-32 servo controller work together with my atmega32.
when i connect the ssc-32 to my pc it all works fine…
Also when i connect my atmega32 to my pc it works fine.
I configured them both with a baudrate of 9600.

but when i connect the ssc-32 to my atmega32 nothing happens. The little light starts to blink when the atmega32 sends something but my servo’s do nothing.
The only thing i doubt it how to send a . I use a ‘\r’.

I think i connected it wrong…
Can anyone tell me how it’s supposed to be connected?

I guess i’m doing something really stupid :stuck_out_tongue:

When we control the SSC-32 from a Basic Atom we select inverted data. You may need to do that as well. Programming gurus will need a code example at minimum order to help.

something to try is to connect the PC to the atmega32 board where the SSC-32 would be and use a terminal program like Hyperterm to see what the atmega32 is actually sending to the ssc-32.

[code]//
/* /
/
File: hexapod.c /
/
/
/
Version: 1.00 /
/
/
/
Interface of: 18 servo hexapod /
/
/
/
Date: 5-1-2009 /
/
/
/
Authors: Martijn Jonkers /
/
/
/
Change history: /
/
date: who: changes: /
/
---- — ------- /
/
*/
/
/

#include <pgmspace.h>
#include <io.h>
#include <stdlib.h>
#include <interrupt.h>
#include <string.h>
#include <hexapod.h>

//
/* /
/
Movements /
/
*/
/
/
#define NumForwardSteps 5
int Forward[NumForwardSteps][NumLegs][NumServosLeg] =
{ //leg1 LEG2 LEG3 LEG4 LEG5 LEG6
{{ICNTR,UP ,FAR} ,{STAY ,STAY,STAY} ,{RIGHT,UP ,STAY} ,{STAY,STAY,STAY} ,{LEFT ,UP ,STAY} ,{STAY ,STAY,STAY }},//11
{{STAY ,DOWN,STAY} ,{STAY ,STAY,STAY} ,{STAY ,DOWN,CLOSE},{STAY,STAY,STAY} ,{STAY ,DOWN,CLOSE},{STAY ,STAY,STAY }},//12
{{STAY ,STAY,CLOSE},{RIGHT,UP ,STAY} ,{LEFT ,STAY,OCNTR},{STAY,UP ,CLOSE},{RIGHT,STAY,OCNTR},{LEFT ,UP ,STAY }},//7
{{STAY ,STAY,STAY} ,{STAY ,DOWN,OCNTR},{STAY ,STAY,STAY} ,{STAY,DOWN,STAY} ,{STAY ,STAY,STAY} ,{STAY ,DOWN,OCNTR}},//13
{{STAY ,UP ,FAR } ,{LEFT ,STAY,CLOSE},{RIGHT,UP ,STAY} ,{STAY,STAY,FAR} ,{LEFT ,UP ,STAY} ,{RIGHT,STAY,CLOSE}} //7
};

#define NumInitSteps 2
int InitLegs[NumInitSteps][NumLegs][NumServosLeg] =
{ //leg1 LEG2 LEG3 LEG4 LEG5 LEG6
{{ICNTR,DOWN,OCNTR},{STAY ,STAY,STAY} ,{ICNTR,DOWN,OCNTR},{STAY ,STAY,STAY} ,{ICNTR,DOWN,OCNTR},{STAY ,STAY,STAY }},//9
{{STAY ,STAY,STAY} ,{ICNTR,DOWN,OCNTR},{STAY ,STAY,STAY} ,{ICNTR,DOWN,OCNTR},{STAY ,STAY,STAY} ,{ICNTR,DOWN,OCNTR}} //9
};

#define NumRotateRightSteps 4
int TurnRight[NumRotateRightSteps][NumLegs][NumServosLeg] =
{ //leg1 LEG2 LEG3 LEG4 LEG5 LEG6
{{RIGHT,UP ,STAY},{LEFT ,STAY,STAY},{RIGHT,UP ,STAY},{LEFT ,STAY,STAY},{RIGHT,UP ,STAY},{LEFT ,STAY,STAY}},//
{{STAY ,DOWN,STAY},{STAY ,STAY,STAY},{STAY ,DOWN,STAY},{STAY ,STAY,STAY},{STAY ,DOWN,STAY},{STAY ,STAY,STAY}},//
{{LEFT ,STAY,STAY},{RIGHT,UP ,STAY},{LEFT ,STAY,STAY},{RIGHT,UP ,STAY},{LEFT ,STAY,STAY},{RIGHT,UP ,STAY}},//
{{STAY ,STAY,STAY},{STAY ,DOWN,STAY},{STAY ,STAY,STAY},{STAY ,DOWN,STAY},{STAY ,STAY,STAY},{STAY ,DOWN,STAY}} //
};

//
/* /
/
INITIALISATIE FUNCTIONS /
/
*/
/
/

void init_devices (void)
{
cli (); /* Disable global interrupts /
port_init (); /
Roep de functie om de poorten te initializeren aan /
timer1_init (); /
Roep de functie om de timer te initializeren aan /
uart_init (); /
Roep de functie om de uart te initializeren aan */

MCUCR = 0x00;	     /* Zoek betekenis hiervan op in de datasheet*/
GIMSK = 0x00;		 /* Zoek betekenis hiervan op in de datasheet*/
sei ();   	  			   	    				 /* Enable global interrupt */ 

}

void port_init (void)
{
PORTB = 0xFF; /* Pull-ups enabled /
DDRB = 0x83; /
PortB pins 0,1,7 are outputs, rest inputs */
}

void timer1_init (void)
{
TCCR1A = 0x00;
TCCR1B = 0x00; /* Stop timer during init /
OCR1A = 0x059D; /
Compare value = 1437 (10Hz) /
TIMSK = 0x10; /
CompareA interrupt enable /
TCCR1B = 0x0B; /
Clear on compare, presc. = 64 */
}

void uart_init (void)
{
UCSRB = 0x1C; /* Transmitter/Receiver enabled */
UBRRL = 0x05;
}

//
/* /
/
ISR /
/
*/
/
/

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
// PORTB = PORTB ^ 0x02; /* Toggle PB1 value (^ = EXOR) /
/
Hoog de teller op */
}

STATE state(void)//check current status
{
Uart_SendString(“Q\r”);// + \n for terminal use
switch(Uart_getchar())
{
case ‘.’:
status = READY;
break;
case ‘+’:
status = BUSY;
break;
default:
break;
}
return status;
}

void wait(void)//wai the movement to complete
{
while(state()==BUSY){}
}
//
/* /
/
FUNCTIES /
/
*/
/
/

void Uart_SendString (char p)
{
unsigned int uiCharpointer = 0; /
Wijzer naar eerste karakter in de string */

while (p[uiCharpointer] != '\0') 				    /* Einde van de string? */
{
	while ( !(UCSRA & (1<<UDRE)) );		
	UDR = p[uiCharpointer];	  /* Plaats huidige karakter in verzendregister */
	uiCharpointer++;				   /* Wijzer naar het volgende karakter */
}

}

void Uart_Send_P(const char *addr)
{
char c;
while ((c = pgm_read_byte(addr++)))
Uart_putchar©;
}

void Uart_putchar(char c)
{
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
}

char Uart_getchar(void)
{
char input = ‘\0’;
while (input == ‘\0’) //Wait for answer from JB
while (UCSRA & (1<<RXC)) //Do when RXC is true
input = UDR; //Receive one Character and put it in: input
return input;
}

//
/
/
/
Move /
/
/
/
/
int move(int direction][NumLegs][NumServosLeg],int numSteps)
{

char string[400]="";
char temp[5]="";
int status=1;
int legCounter=0;
int servoCounter=0;
int step=0;
int chnl=0;

for(step=0;step<numSteps;step++)
{
	for(legCounter=0;legCounter<NumLegs;legCounter++)
	{
		for(servoCounter=0;servoCounter<NumServosLeg;servoCounter++)
		{
			if(direction[step][legCounter][servoCounter]!=STAY)
			{
			    strcat(string,"#");
				itoa(channel[chnl],temp,10);
				strcat(string,temp);
				strcat(string,"P");
				itoa((direction[step][legCounter][servoCounter]+offset[channel[chnl]]),temp,10);
				strcat(string,temp);
			}
			chnl++;
		}
	}
	strcat(string,"T");
	strcat(string,SPEED);
	strcat(string,"\r");
	Uart_SendString(string);
	//Uart_SendString("\r\n");//test
	strcpy(string,"");
	wait();
	chnl=0;
}
if(error)
	status = 0;
return status;

}
//
/
/
/
All servo’s off /
/
/
/
/
void all_off(void)
{
char temp[3];
int motor = 0;

for(motor=0;motor<=31;motor++)
{	
	itoa(motor,temp,10);//convert channel number

	Uart_SendString("#");	
	Uart_SendString(temp);
	Uart_SendString(" L \r");// \n for terminal use
}
wait();

}

//
/* /
/
MAIN /
/
*/
/
/

int main (void)
{
init_devices(); /* Roep de initialisatie functies aan */
//Uart_Send_P(PSTR("#0 P1600 #1P1500 #12 P1600 #13 P1500 #27 P1500 #26 P1500 T2500 \r"));

move(InitLegs,NumInitSteps)	;	//init robot


int i=0;
do 
{			
	move(Forward,NumForwardSteps);
	i++;
} while (i<10);
all_off();




while(1)
{};

return 0;											   /* Eindeloze lus */

}
//
/* /
/
EINDE VAN HET PROGRAMMA /
/
*/
/
/
[/code]

[code]//
/* /
/
File: hexapod.h /
/
/
/
Version: 1.00 /
/
/
/
Interface of: hexapod /
/
/
/
Date: 5-1-2009 /
/
/
/
Authors: Martijn Jonkers /
/
/
/
Change history: /
/
date: who: changes: /
/
---- — ------- /
/
*/
/
/

//
/* /
/
Defines /
/
*/
/
/
#define NumLegs 6 //number of legs
#define NumServosLeg 3 //number of servo’s per leg
#define NumServos (NumLegs*NumServosLeg) //total number of servo’s

#define LEFT 1750 //inner servo left
#define RIGHT 600 //inner servo right
#define ICNTR 1150 //inner servo center
#define UP 1500 //middle servo up
#define DOWN 1150 //middle servo down
#define MCNTR 1350 //middle servo middle
#define FAR 1000 //outer servo far
#define CLOSE 1600 //outer servo close
#define OCNTR 1400 //outer servo middle
#define STAY 0 //0 Lets servo stay at current position

#define SPEED “2500” //robot movement speed (ms per move)

typedef enum {BUSY, READY} STATE;//robot state (moving/ready)
typedef enum {OK, WRONG} ERROR; //error state

#define UDRE 5
#define BAUD 9600 //baud rate
//
/* /
/
Functions /
/
*/
/
/

void init_devices (void);
void port_init (void);
void timer1_init (void);
void uart_init (void);
void Uart_putchar(char c);
char Uart_getchar(void);
void Uart_SendString (char *p);
STATE state(void);
void wait(void);
void all_off(void);
int move(int direction][NumLegs][NumServosLeg],int numSteps);

//
/* /
/
Global variables /
/
*/
/
/
STATE status = BUSY;
ERROR error = OK;

int channel[NumServos] = //all servo channels
{//inner middle outer
2, 1, 0, //leg 1
6, 5, 4, //leg 2
14, 13, 12, //leg 3
29, 30, 31, //leg 4
25, 26, 27, //leg 5
17, 18, 19 //leg 6
};

int offset[32] = //offset for all 32 channels
{
0, //0
0, //1
0, //2
0, //3
0, //4
0, //5
0, //6
0, //7
0, //8
0, //9
0, //10
0, //11
0, //12
0, //13
0, //14
0, //15
0, //16
0, //17
0, //18
0, //19
0, //20
0, //21
0, //22
0, //23
0, //24
0, //25
-100, //26
100, //27
0, //28
0, //29
0, //30
0 //31
};
//
/* /
/
End /
/
*/
/
/
[/code]

This is the complete code i use…
I hope someone can help me…
It is just such a small thing… and i just can’t get it work :S

That’s what i ment with it work fine when i connect the atmega32 to my pc… the data is exactly as i want…

thanx anyway…

ah, ok, cool. so just thinking this out for the obvious, do you use the same cable to connect from the PC to the SSC-32 as you do from the atmega32 to the SSC-32? Is it possible you need to flip the TXD/RXD signals in the cable, i.e. need a null-modem type cable rather than straight through?

no, it not the same cable… actually i only have 3 breadboard cables (TXD/RXD and GND).
witch i put in the connector :stuck_out_tongue:
pretty amateur acctually

But it must be enough right?

I seam to remember something about needing a line feed with the cr. I’m searching the forum for more info…

That was my first thought, but I did a search of the source code and it looks like the lf is eaten by the SSC-32 function, but I would probably try it anyway…

How is the two ATmegas (yours and the SSC-32 connected? Is it using the RS232 communications like when you are talking to the PC, or are you configured for TTL communications? ie on the SSC-32 do you remove the jumpers and then connect your three wire to the pins there. What do you do on the Atmega32 board?

Kurt

This is the most appropriate link I could find.
lynxmotion.net/viewtopic.php?t=365

It goes on to eventually say…

is the proper ending when using the LynxTerm.
VbCrLf is the proper ending when using Visual Basic
\r\n is the proper ending when using C++

i’ve done it before and that time i only used ‘\r’.

I use a MAX232 to connect to the ssc-32.
I’ve also tried to connect to the txd/rxd pins on the ssc-32 board

i’ve mentioned it before, but the green led is flashing when the atmega32 sends something… but nothing happens…

After reading so many posts concerning line feeds I’m quite certain the SSC-32 requires a carriage return AND and line feed. This is the required terminator. Without it the commands will never be acted on. The fact that the LED is blinking when you send data is a good thing. Because you are using the level shifter then there is no need to invert the data. There may be other problems that I can’t help with. But I’m quite sure about this.

So you are using the Max232, which implies that you are using RS232 level signals. So you should plug in the same cable as you used to connect to the PC into the RS232 connector (9 pin). If yo uconnect directly into the TXD/RXD pins of the SSC-32 board you will need to not use the Max232, but use TTL level signals directly.

The flashing means that it is receiving stuff, not necessarily that it is seeing valid stuff.

Things I would try include:

  1. try \r\n - as robot dude mentioned.
  2. Try connecting to 9 pin connector and try both normal and inverted levels. I don’t remember if you can configure this easily on Atmega32s usart or not. But I would think the USART on the Atmega128 would be compatible with the USART ona the Atmega on the SSC-32.
  3. Try bypassing the Max232 on your Atmega128 board and ouput TTL directly the the SSC-32.

That is all I can think of for now.

Kurt

your all so great!!

i will try it right now… and let you know if it works…

thank you all for your replies!!.. :smiley: :smiley:

i tried the ‘\r\n’ thing and the bypass… but still nothing…
the invert thing i don’t really get… How am i supposed to do that?

I’m out of ideas… Sorry

I really don’t think you can invert the UART signal levels on an ATmega32… and you should not need to. It’s got to be something too simple to be catching your eye. It displays the correct string on the PC, which you should verify has the same serial port settings as the SSC-32 is configured for… don’t let the PC auto-detect… force the settings to what they are on the SSC-32… which leads to make sure the jumpers on the SSC-32 select the DB-9 and the correct baud rate you think it does.

The Atmega board MAX232 output TXD pin should go right into pin 3 of the DB-9F
The Atmega board MAX232 RXD pin should go to pin 2 of the DB-9F
The Atmega board GND should go to pin 5 of the DB-9F

Remember the pin order of the DB-9F is backwards to that of the DB-9M when looking at the business end.

Beyond that I’m not sure where to go… maybe use a meter to make sure the RS-232 levels are +/- at least 3V on the pins when connected to the SSC-32. If you still can’t find it then find an o-scope and compare the signals between PC and Atmega at the TXD/RXD jumper pins of the SSC-32… these should be TTL level and nearly identical if both the PC and the ATmega32 board are sending the same format.

if ( received_char == ASCII_CR ) { // For carriage return, execute the command rx_char_valid = 0 ; execute_command ( ) ; } else if ( received_char == ASCII_ESC ) { // For ESCape, kill the current command if any rx_char_valid = 0 ; cmd_type = CMDTYPE_NONE ; } else if ( ( received_char == ' ' ) || ( received_char == ASCII_LF ) ) { // Discard leading spaces and line feeds rx_char_valid = 0 ; } else { // For any character but 0xFF, ESC, or CR, start parsing the name goto_parse_name ( ) ; }

// ASCII character defines #define ASCII_TAB 9 #define ASCII_LF 10 #define ASCII_CR 13 #define ASCII_ESC 27

This is a piece of code i found in the ssc-32 v2.02 source code…
this sais the carriage return character executes the command
line feeds are discarded.

So ‘\n’ is not needed… ‘\r’ is enough to execute the command

I was not stating that from experience, but from reading where other users said it was required. Sorry if it was wrong.

i know… but i just wanted to proof to myself it is not nescessery to place line feeds… :stuck_out_tongue:
Bacause i’ve done it before and it worked that time…