16 Servo Controller - conection too slow

Hello,

some time ago, I bought myself a 16 Servo-controller from pololu. Ever since I tried to run some servos, the red light from the controller is lit constantly and the yellow light flashes. According to the manual that means, that the connection is too slow. As I am a newbie to robotics, I do not really know, what is wrong. Following the source-code in C:


#include <avr/io.h>
#include <util/delay.h>     
#include <stdlib.h>

void long_delay(uint16_t ms) 
{
 for(; ms>0; ms--) _delay_ms(1);
}

void uart_putc (unsigned char c) 
{
 while (!(UCSR0A & (1<<UDRE0))) 
 {
 }

 UDR0 = c;  /
}

void uart_puts (char *s) 
{
 while (*s) 
 {
  uart_putc(*s);
  s++;
 }
}

int servo_data (int a0,int a1,int a2,int a3,int a4,int a5)
{
// int a0; int a1; int a2; int a3; int a4;
// int a5; int a6; int a7;

 uart_putc(a0);
 uart_putc(a1);
 uart_putc(a2);
 uart_putc(a3);
 uart_putc(a4);
 uart_putc(a5);
// uart_putc(a6);
// uart_putc(a7);
 return 0;
}

int main (void)
{

// long_delay(2000); // Break for initialization of servo controller.

// USART --> Init.
 UCSR0B |= (1<<TXEN0)|(1<<RXEN0);   // UART TX und RX einschalten.
 UBRR0H = 0; // Baudregister high.
 UBRR0L = 129; // Baudregister low.

 long_delay(2000);

 while(1)
 {
// Startbyte, ID, command, servonumber, Data1, Data2.
  servo_data(128,1,2,0,127,0); // Servo auf 90°.
  long_delay(1000);   // Pause.
  servo_data(128,1,2,0,0,0); // Servo auf Ausgangsposition.
  long_delay(1000);   // Pause.


 }
} 

Thanks in advance for the help for such a simple problem.

Bak.

Hi Bak,

What is the baud rate supposed to be? Looks like it being set to 129 baud (very slow).

Mike

Hello.

Actually, it’s just the UBBR (baud rate register) that’s 129. While this determines the baud rate, it doesn’t mean the rate is 129 bps. One crucial element of the conversion between the baud rate register value and the actual baud rate is the CPU clock frequency of the AVR. What is the clock frequency? Also, without defining F_CPU at the top of your program, I don’t expect your delay routines to work properly.

- Ben

Thanks for the quick reply.

@Mike: The value for the UBBR can be computed with this formula: UBBR=(f_osc/(16*BAUD))-1
whereby f_osc is the resonator-frequency and BAUD is the value for the desired baud rate. If I remember correctly, some combinations of f_osc and BAUD work more stable, than others. In my case, with a desired BAUD-rate of 9600 and a frequency of 20MHz the connection is supposed to be stable.

@Ben: I am using AVR-Studio 4 from Atmel in combination with WIN-AVR. F_CPU can be defined via a dropdown-menu (Project --> Configuration Options --> Frequency). As controller, I use a ATMega 328P (Baby-Orangutan with 20MHz from Pololu). I will try it out to define the frequency of the resonator in the program and not via the dropdown-menu, as you suggested, but I am not sure, if this is the reason for the encountered problem.

I am able to send single data to a terminal-program and back so this is why I think, that the UART is working properly. I connected the servo-controller a follows:

Orang-Utan —> 16-Servo-Controller

PD1 (TX) —> I (serial input)
PD0 (RX) —> O (serial output)
(external source) 5V —> R (Reset-Pin, necessary if no USB is used)
(external source) 5V —> 5V (logic supply)
GND —> GND

Again, thanks for the replies and the suggestions you already offered and the ones to come.
Bak.

Hello Bak,

Have you tried using the Pololu AVR C library’s Orangutan serial port communication functions?

- Ryan

Hi Ryan,

Good question, good idea, simple answer: not yet.

To look into the Orangutan-Library is a very good idea. I am sure, it will work and I will also be able to understand why it will work. I will try it right on monday. If I find something out, I will post it here.

Thanks and have a nice weekend,
Bak

Hi all,

problem solved. There was an error in the initialization of the UART of the mikrocontroller. The corrected lines in source code are as follows:

// Initialisization of the USART.
 UCSR0B |= (1<<TXEN0)|(1<<RXEN0);   // UART TX and RX enable.

// UBRR0 for 20MHz an 9600 Baud.  
 UBRR0H = 0; // Baudregister high. Always first bit to set. 
 UBRR0L = 129; // Baudregister low.

// Servo-controller needs communication-format 8N1. This can be configured for the 328P in the register UCSR0C.
// UMSEL01/00: enable asynchronous mode, USBS0: 1 stop-bit, UCSZ0n: 8 data-bits.  
 UCSR0C |= (0<<UMSEL01)|(0<<UMSEL00)|(0<<USBS0)|(UCSZ02<<0)|(UCSZ01<<1)|(UCSZ00<<1); // Modus 8N1.

It is clear now, that without a correct format, it is difficult for the servo-controller to determine the baud-rate of the UART automatically. That is why the LEDs sent an error-code for an insufficient speed of the connection.

Again thanks for your comments, ideas and remarks.
Bak.

Bak,

The quoted line above is wrong in so many ways! Did you write it yourself or copy it from somewhere? It’s hard to imagine it doing anything other than completely corrupting the state of the UCSR0C register.

  1. You should never be bit-shifting 0 because it doesn’t accomplish anything (bit-shifting is equivalent to multiplying or dividing by two, and zero multiplied or divided by anything is always still zero).

  2. ORing zero with anything doesn’t accomplish anything since x | 0 = x. You can’t clear a bit by ORing with zero; rather, you need to use the AND operator to clear a bit. If you want the UMSEL01 bit to be zero, you would use the following line of code:

UCSR0C &= ~(1 << UMSEL01); // UCSR0C |= (0 << UMSEL01) doesn't change USCR0C at all!

  1. Why did you change the order of operation in the middle of your code? You started out with the bit locations on the right side of the operation (e.g. (0<<UMSEL01)) and then changed them to the left side of the operation (e.g. (UCSZ00<<1)). Do you understand what the << operator does? 1 << 3 is not the same as 3 << 1! If you want the UCSZ00 bit to be a 1, you need to OR the UCSR0C byte with a 1 in the UCSZ00 location, which is accomplished by the following:

UCSR0C |= 1 << UCSZ00;

- Ben

Hello Ben,

some comments on your comments.

@3: This is a simple input-problem. The computers I use in my office do only have internet in a virtual linux-environment (a safety matter), copy and paste is not possible. I just entered the lines quickly via keyboard, changing between two windows. It is just a simple input mistake. The code-lines I used, do have the correct order of operation.

@1 and 2: Those are beginner|noob|rookie|amateur-mistakes. I understand now, why the lines are wrong. I am still learning C and am not able yet, to think in those structures. But mistakes like the ones I made in combination with comments like yours, help me (and I think many others) in the understanding of C. Therefore thank you very much for the help.

I just was happy, that the servo-controller finally made a servo move. Hopefully it will continue to do so after I corrected the source-code, but I am sure it will. Anyway, the key problem is solved in my opinion: the connection is not too slow it just had the wrong format.

Thank you very much for spending time in commenting/correcting such basic problems, like the ones I had.

Bak/Rainer