Author Topic: uart and servos, timer interrupt problems  (Read 5208 times)

0 Members and 1 Guest are viewing this topic.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,653
  • Helpful? 169
    • Society of Robots
uart and servos, timer interrupt problems
« on: June 27, 2007, 06:10:15 PM »
I am trying to get my uart to work but it causes a problem with my servos . . .

Using this code in my main, the servos work fine:
Code: [Select]
sei(); // Enable interrupts
delay_cycles(20);
cli(); // Disable interrupts
servo_do_something();

but this code makes my servos spasm:
Code: [Select]
sei(); // Enable interrupts
rprintf("Hello, World! Read My Analog: %u\r\n", rangefinder);//output message to serial (use hyperterminal)
delay_cycles(20);
cli(); // Disable interrupts
servo_do_something();

this code, moving the delay after turning interrupts off, also causes spasms:
Code: [Select]
sei(); // Enable interrupts
rprintf("Hello, World! Read My Analog: %u\r\n", rangefinder);//output message to serial (use hyperterminal)
cli(); // Disable interrupts
delay_cycles(20);
servo_do_something();

This is an example of my servo code . . .
Code: [Select]
void delay_cycles(unsigned long int cycles)
{
while(cycles > 0)
cycles--;
}

void servo_left(signed long int speed)
{
PORT_ON(PORTD, 7);
delay_cycles(speed);
PORT_OFF(PORTD, 0);//keep off
}

I first thought that maybe the uart timer interrupt was causing my delay function to take longer . . . but it appears its not the interrupts (at least partly) . . . I put the 20 cycle delay after turning off interrupts thinking that perhaps the uart was slow-ish and causing interrupts after I turned it off . . .

Changing it to a 100 cycle delay fixes the problem, but I'd like to understand exactly what is going on here . . . Im guessing the delay will be dependent on how much data I send, no? How do I calculate this delay?

I'd rather not use timer interrupt based servo control as it uses up a timer and complicates the code . . . Im a MechE, what did you expect?! :P

Offline megaman935

  • Robot Overlord
  • ****
  • Posts: 182
  • Helpful? 0
Re: uart and servos, timer interrupt problems
« Reply #1 on: June 27, 2007, 06:12:59 PM »
Code: [Select]
sei(); // Enable interrupts
delay_cycles(20);
cli(); // Disable interrupts
servo_do_something();
Code: [Select]
sei(); // Enable interrupts
rprintf("Hello, World! Read My Analog: %u\r\n", rangefinder);//output message to serial (use hyperterminal)
delay_cycles(20);
cli(); // Disable interrupts
servo_do_something();
Code: [Select]
sei(); // Enable interrupts
rprintf("Hello, World! Read My Analog: %u\r\n", rangefinder);//output message to serial (use hyperterminal)
cli(); // Disable interrupts
delay_cycles(20);
servo_do_something();
Code: [Select]
void delay_cycles(unsigned long int cycles)
{
while(cycles > 0)
cycles--;
}

void servo_left(signed long int speed)
{
PORT_ON(PORTD, 7);
delay_cycles(speed);
PORT_OFF(PORTD, 0);//keep off
}
........c-a-n-'t u-n-d-e-r-s-t-a-n-d y-o-u-r l-a-n-g-u-a-g-e......(it hurts my head  :'( )
sry I'm no help at all....  :P
« Last Edit: June 27, 2007, 06:14:35 PM by megaman935 »

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,653
  • Helpful? 169
    • Society of Robots
Re: uart and servos, timer interrupt problems
« Reply #2 on: June 27, 2007, 06:18:33 PM »
correction . . . it must have been a fluke . . . because adding that delay_cycles(100) no longer fixes it . . .

so basically, whether I have interrupts enabled or disabled, delays, or anything else, my code only breaks if I have this line in it:
rprintf("Hello, World! Read My Analog: %u\r\n", rangefinder);

why?!?!

btw, the servos try to go to the correct position, but they just spasm a lot in the process . . .

Offline rgcustodio

  • Robot Overlord
  • ****
  • Posts: 217
  • Helpful? 0
  • Use "Search" and ye might find answers!
Re: uart and servos, timer interrupt problems
« Reply #3 on: June 27, 2007, 06:31:46 PM »
I don't have the full code to work with so here are several food for thoughts. I'm making an assumption that you're using an ATmega16 (based on your old posts). I'll also make an assumption that your UART is interrupt-based.

Other clues?!?

I earlier said:
Quote
You might be using the same timer/counter for the UART and your servo control. You might want to use one for UART and one for the servo controls.
I think this is incorrect. H/W based UART does not a timer, it uses the oscillator directly internally.

2nd guess. Now I am looking at the Photovore code. I am assuming this is the base of most of your code.
In your code you are using PD0 and PD1 as the servo port BUT for an ATmega8 (and ATmega16) those ports are also the ones for RXD and TXD respectively. That is bad!

3rd guess. If you caught #2 above then you have a bug. Look at "PORT_OFF(PORTD, 0)" should it be "PORT_OFF(PORTD, 7)" instead???
Code: [Select]
void servo_left(signed long int speed)
{
PORT_ON(PORTD, 7);
delay_cycles(speed);
PORT_OFF(PORTD, 0);//keep off change to PORT_OFF(PORTD, 7) ????
}

Am all out of guess!
« Last Edit: June 27, 2007, 06:59:38 PM by rgcustodio »
The best thing one can do when it's raining is to let it rain. - H. W. Longfellow

understanding is the path to enlightenment

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,653
  • Helpful? 169
    • Society of Robots
Re: uart and servos, timer interrupt problems
« Reply #4 on: June 27, 2007, 07:30:20 PM »
Im using an ATmega168.

Yea, the code is very similar to what I have for the $50 Robot:
http://www.societyofrobots.com/downloads/sbs_source_photovore_v1.zip
(but not exact)

I am using AVRlib with the included uart, rprintf, buffer, timerx8, etc.
. . . forgot to mention that part . . . oops . . .

Quote
2nd guess. Now I am looking at the Photovore code. I am assuming this is the base of most of your code.
In your code you are using PD0 and PD1 as the servo port BUT for an ATmega8 (and ATmega16) those ports are also the ones for RXD and TXD respectively. That is bad!

Im not that dumb! :P
Nothing is connected to the TX/RX pins and Im not telling the pins to do anything in software.

This is the only code that touches those pins:
Code: [Select]
//************CONFIGURE PORTS************
//configure ports for input or output - specific to ATmega8
void configure_ports(void)
{
DDRC = 0x00;  //configure all C ports for input
PORTC = 0x00; //make sure pull-up resistors are turned off
DDRD = 0xFF;  //configure all D ports for output
DDRB = 0xC7;  //configure B ports 0, 1, 2, 6, 7 for output (google search '0b11000111 to hex')
}
//***************************************

Quote
3rd guess. If you caught #2 above then you have a bug. Look at "PORT_OFF(PORTD, 0)" should it be "PORT_OFF(PORTD, 7)" instead???

Oops, glad you found that bug. But I wasn't actually using that servo though, just other servos in the robot arm that didnt have the typo . . .

So nope, problem not solved :-\

Offline rgcustodio

  • Robot Overlord
  • ****
  • Posts: 217
  • Helpful? 0
  • Use "Search" and ye might find answers!
Re: uart and servos, timer interrupt problems
« Reply #5 on: June 27, 2007, 08:09:56 PM »
Quote
Im not that dumb! :P
Nothing is connected to the TX/RX pins and Im not telling the pins to do anything in software.

Sorry  :'(
Even the good ones sometimes forget  ::) doesn't hurt to double check, always.

Quote
This is the only code that touches those pins:
Code: [Select]
//************CONFIGURE PORTS************
//configure ports for input or output - specific to ATmega8
void configure_ports(void)
{
DDRC = 0x00;  //configure all C ports for input
PORTC = 0x00; //make sure pull-up resistors are turned off
DDRD = 0xFF;  //configure all D ports for output
DDRB = 0xC7;  //configure B ports 0, 1, 2, 6, 7 for output (google search '0b11000111 to hex')
}
//***************************************
Which servos are behaving erratically? To which specific ports are they connected?
The best thing one can do when it's raining is to let it rain. - H. W. Longfellow

understanding is the path to enlightenment

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,653
  • Helpful? 169
    • Society of Robots
Re: uart and servos, timer interrupt problems
« Reply #6 on: June 27, 2007, 08:23:56 PM »
Quote
Which servos are behaving erratically? To which specific ports are they connected?
I didnt try all ports, but I am current using D4, B6, and B7. Each have the same problem.

I also noticed that the spasms are much more pronounced on the servos that have a counter torque applied to it. With no counter torque at all, its hardly noticeable unless I put my hand on it to feel the vibration.


Offline rgcustodio

  • Robot Overlord
  • ****
  • Posts: 217
  • Helpful? 0
  • Use "Search" and ye might find answers!
Re: uart and servos, timer interrupt problems
« Reply #8 on: June 28, 2007, 08:30:01 AM »
I didnt try all ports, but I am current using D4, B6, and B7. Each have the same problem.

I still don't have any ideas. Hmmn. The only thing common to them are their relation to a timer.
PD4/XCK/T0/PCINT20
Quote
XCK, USART external clock.
T0, Timer/Counter0 counter source.
PCINT20: Pin Change Interrupt source 20. The PD4 pin can serve as an external interrupt source.

PB6/XTAL1/TOSC1/PCINT6
Quote
XTAL1: Chip clock Oscillator pin 1. Used for all chip clock sources except internal calibrated RC Oscillator. When used as a clock pin, the pin can not be used as an I/O pin.
TOSC1: Timer Oscillator pin 1. Used only if internal calibrated RC Oscillator is selected as chip clock source, and the asynchronous timer is enabled by the correct setting in ASSR. When the AS2 bit in ASSR is set (one) to enable asynchronous clocking of Timer/Counter2, pin PB6 is disconnected from the port, and becomes the input of the inverting Oscillator amplifier. In this mode, a crystal Oscillator is connected to this pin, and the pin can not be used as an I/O pin.
PCINT6: Pin Change Interrupt source 6. The PB6 pin can serve as an external interrupt source. If PB6 is used as a clock pin, DDB6, PORTB6 and PINB6 will all read 0.

PB7/XTAL2/TOSC2/PCINT7
Quote
XTAL2: Chip clock Oscillator pin 2. Used as clock pin for crystal Oscillator or Low-frequency crystal Oscillator. When used as a clock pin, the pin can not be used as an I/O pin.
TOSC2: Timer Oscillator pin 2. Used only if internal calibrated RC Oscillator is selected as chip clock source, and the asynchronous timer is enabled by the correct setting in ASSR. When the AS2 bit in ASSR is set (one) and the EXCLK bit is cleared (zero) to enable asynchronous clocking of Timer/Counter2 using the Crystal Oscillator, pin PB7 is disconnected from the port, and becomes the inverting output of the Oscillator amplifier. In this mode, a crystal Oscillator is con nected to this pin, and the pin cannot be used as an I/O pin.
PCINT7: Pin Change Interrupt source 7. The PB7 pin can serve as an external interrupt source. If PB7 is used as a clock pin, DDB7, PORTB7 and PINB7 will all read 0.

There are no known (at least to me) fuse bits settings that could be changed to turn off these clock/timer settings which leads me to a conclusion that once the DDR bits are set you should be good to go.

If these pins are indeed doing something bogus maybe connecting them to a oscilloscope will help in debugging your issue.

Have you tried swapping out servos? Maybe some are bad.

Maybe someone else has encountered this before.
« Last Edit: June 28, 2007, 08:40:00 AM by rgcustodio »
The best thing one can do when it's raining is to let it rain. - H. W. Longfellow

understanding is the path to enlightenment

Offline DomoArigato

  • Full Member
  • ***
  • Posts: 54
  • Helpful? 1
Re: uart and servos, timer interrupt problems
« Reply #9 on: June 28, 2007, 12:50:30 PM »
Do you still have this problem?  Have you tried using a different timer?  My servo's spazed a little when I didn't use the right frequeny, you've probably tried different delays though...  I have some code for phase and frequency correct PWM on the ATmega128 if you want to try it.  I don't know how different your chip is though.

Offline dunk

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 1,086
  • Helpful? 21
Re: uart and servos, timer interrupt problems
« Reply #10 on: June 29, 2007, 03:56:29 PM »
hi Admin,
i experienced exactly the same issues on the atmega8.

as long as i kept the UART ISR as short as possible there was only fairly minor (but very annoying) jitter in the servos.

i eventually decided the problem was as described in your first post: the UART interupt was delaying the servo timing pulse.

i think the only real solution is to use one of the hardware PWM modules to generate the servo pulses.

i didn't put too much work into solving this though as my finnished application doesn't need a UART and servos on the same AVR.
i get round the issue by having one AVR with a UART send commands out by i2c.
the servo controller receives commands over i2c and controls servos accordingly.

interestingly the i2c interupt dousn't intefere with the servo timing pulse.
something to do with the order of interupt priorities if I remember correctly. (can't look up the datasheet just now. typing on annoying blackberry handheld thing.)

dunk.
(in hotel room in Oslo.)

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: uart and servos, timer interrupt problems
« Reply #11 on: July 01, 2007, 11:35:15 AM »
Unless you set it up to do so, the PWM hardware won't cause a interrupt at all so even if
you are in the middle of a high interrupt period (Serial or i2c) it won't get messed up.
As a general rule if you are timing using a while loop, any interrupt will throw it off...

If you are paying for the hardware of a ATmega you might as well use it if you have it  ;)
I thought I posted some files that should work for a 16Mhz clock on almost any ATmega
for servo PWM. Did you want me to repost them?

Offline KambeiX

  • Full Member
  • ***
  • Posts: 79
  • Helpful? 0
Re: uart and servos, timer interrupt problems
« Reply #12 on: July 01, 2007, 03:28:29 PM »
Try segmenting the serial output

rprintf("Hello,");
rprintf("World!");
rprintf("Read My");
rprintf("Analog: %u\r\n", rangefinder);

Also try using a higher baud rate, and if that doesn't work, print each character separately, like char hello[]="Hello world";

and then rputc(hello); in a 0 to N loop

Other alternative is setting the interrupt a little lower, like 15~19 ms because servos stop when they don't recieve a signal after 21-22ms but they work ok at faster frecuencies.


Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,653
  • Helpful? 169
    • Society of Robots
Re: uart and servos, timer interrupt problems
« Reply #13 on: October 30, 2007, 10:15:21 AM »
forgot to mention that I fixed it . . .

apparently the timer was calling interrupts that added time to my servo delays . . .

getting rid of the timer (or increasing the prescale to /128 or higher) fixed it.

 


Get Your Ad Here