Uart code again?

I hav ethe orangutan w the 168. PORTD.1 is used for serial TRX. I wrote some code to send serial dat to my dsmc but i get nothing. Here’s my code:

#define FOSC 1843200 // Clock Speed
#define BAUD 9600
#define MYUBRR (FOSC/(16*BAUD))-1
#define F_CPU 800000UL

#include <avr/io.h>

void main (void)
{
	DDRD |= _BV(1);//Set PORTD1 as an output
	USART_Init(MYUBRR);
	USART_Trans (0x80);
	USART_Trans (0x02);
	USART_Trans (0x00);
}

void USART_Init (unsigned char ubrr)
{
	//set buad rate at 9600
	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char) ubrr;
	//enable transmitter
	UCSR0B = (1 <<RXEN0 | 1 << TXEN0 );
	//Set frame format for 8bit with 1 stop
	UCSR0C = (3<<UCSZ00);
}

void USART_Trans (unsigned char data)
{

	//wait for transmit empty
	while (!(UCSR0A & (1<<UDRE0)))
	{
		UDR1 = data;
	}
}

Any suggestions???
Please???

Simple UART transmitting is next on my list of things to do with my Orangutan. I don’t have it at home with me, but I’ve been reading through the ATMega168 data book (as I see you have!) and other sample code, and I see a couple of minor discrepancies (not that the book is necessarily correct):

  1. Your F_CPU is missing a zero, if you have your fuses set to run the ATMega168 at full 8Mhz (which you should), it should read:

#define F_CPU 8000000UL

  1. While (FOSC/(16*BAUD))-1 is mathematically equivalent to FOSC/16/BAUD-1, the first way generates an integer overflow warning in AVR Studio, which might mean the compiler is truncating some important digits. I would write it out in the data book format just to be safe:

#define MYUBRR F_CPU/16/BAUD-1

  1. And anyway, your FOSC isn’t 1843200 like in the data book sample code, it’s 8000000. You can set FOSC to that, or just delete it and use F_CPU instead (make sure to move its definition up above MYBURR):

#define F_CPU 8000000UL
#define MYUBRR F_CPU/16/BAUD-1

  1. In your USART_Trans function, you write to UDR1, which I think should be UDR0 for the ATMega168.

UDR0=data;

  1. Also in your USART_Trans function, I don’t think UDR0=data statement should be inside the while loop. In the data book, the while loop has a semicolon after it (indented on the next line), before the UDR0=data command, so it delays writing the data until the registers in the while statement are clear:

while (!(UCSR0A & (1<<UDRE0)));
UDR0=data;

  1. Style points: either main should be your last function (copy and paste it to the bottom) or your other functions need prototypes. The code can still compile, but you may have problems caused by assumptions made by the compiler when you declare functions implicitly like that (yes, I know it’s how they do it in the data book sample code. It’s still wrong!).

While it shouldn’t hurt, I don’t think it is necessary to set PD1 to output; just in case I’m commenting it out. And since you probably want your motors to do something to show that they’re working, lets output 0x80,0x00,0x01,0x7F to drive motor 0 at full speed ahead (motor address 0 always works, regardless of settings).

SO, after all that, the code should look something like this:

#define BAUD 9600
#define F_CPU 8000000UL
#define MYUBRR F_CPU/16/BAUD-1

#include <avr/io.h>

void USART_Init (unsigned char ubrr){
	//set buad rate at 9600
	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char) ubrr;
	//enable reciever & transmitter
	UCSR0B = (1 <<RXEN0 | 1 << TXEN0 );
	//Set frame format for 8bit with 1 stop
	UCSR0C = (3<<UCSZ00);
}

void USART_Trans (unsigned char data){
	//wait for transmit empty
	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = data;
}

void main (void){
//	DDRD |= _BV(1);//Set PORTD1 as an output
	USART_Init(MYUBRR);
	USART_Trans (0x80);//start byte
	USART_Trans (0x00);//DSMC device ID
	USART_Trans (0x01);//motor 0 (always works) fwd
	USART_Trans (0x7F);//full speed!
}

And of course, don’t forget to pull the reset pin up! Man, I can’t wait to try this out on my Orangutan in the morning! Let me know if this works for you, and good luck!

-Adam

I made all The changes you suggested but still bubcass. The neat little led on the dsmc isnt blinking. So this is why I believe it to be a no go.

Also my project is due in a week do you think I should switch to a butterfly or maybe a pic?

A Butterfly is an AVR ATMega169, so it’s not that big a change. Only difference is it has an RS-232 level shifter on board, which you’d need to bypass to hook it up to the DSMC (that’d be my guess, anyway… DSMC talks TTL voltage levels, right?) In any case you’d be right back to writing AVR UART code.

A PIC would be a change, but it’d mean starting over from scratch.

Do you have any other TTL serial devices? Problem is you’re troubleshooting two things at once: First question is have you got the Orangutan’s UART talking at all? Second question is whether the DSMC is listening to you. The Orangutan could be talking fine and you might not know it.

I don’t know how much time I’ll have to try this out today, but I’d be happy to give your UART code a go to see what I get. I saw you also posted this question to AVRFreaks. Good choice. When I checked the thread last night it more or less gave you the same advice Adam has already given you. Keep checking both threads and try stuff out.

FWIW, Orangutan-lib 0.2 has UART code in it. It’s basically Pascal Stang’s buffered interrupt-driven UART code with some tweaks from Steve. I didn’t have my hardware in time to test it, but Steve’s using that code pretty extensively one one of his projects, having a Baby-O talk to a serial servo controller. So it does work if you want to give it a try.

Meanwhile I’ll give your code a try.

Don’t give up yet! A week’s a lot of time for troubleshooting.

Tom

This one worked:


// #define F_CPU 8000000UL
// I'm testing on a Baby-O, which runs at 20MHz
#define F_CPU 20000000UL

// At 8MHz this = 51
// At 20MHz this = 129
// This checks out according to the datasheet.  AOK.
#define MYUBRR F_CPU/16/BAUD-1


#include <avr/io.h>

void USART_Init (unsigned int ubrr){
   //set buad rate at 9600
   UBRR0H = (unsigned char)(ubrr>>8);
   UBRR0L = (unsigned char) ubrr;
   //enable reciever & transmitter
   UCSR0B = (1 <<RXEN0) | (1 << TXEN0); // Parens were wrong here
   //Set frame format for 8bit with 1 stop
   UCSR0C = (3<<UCSZ00);
}

void USART_Trans (unsigned char data){
   //wait for transmit empty
   while (!(UCSR0A & (1<<UDRE0)));
   UDR0 = data;
}

int main (void){


	USART_Init(MYUBRR);

	USART_Trans (0x80);//start byte
	USART_Trans (0x00);//DSMC device ID
	USART_Trans (0x01);//motor 0 (always works) fwd
	USART_Trans (0x7F);//full speed! 

	return(0);
} 

There was one parenthesis error when the pins were enabled. Each pin needs parenthesis around it with an or in between.

And to the folks at Pololu, those RS-232 level shifters are nice pieces of hardware. Wish I’d picked some up ages ago. (Can’t wait to try the USB serial converter!!)

FWIW it looks like all this code came out of the datasheet. This is a very very good way to get going on the Orangutan. I was basically lost 'till I started reading the datasheet. It’s good to see other people reading it, too.

Best of luck on your project. Hey, let us know how it turns out!

Tom

Crud… Forgot, there was one other change I made. In the datasheet, the UART_Init() routine took an unsigned int rather than an unsigned char. Since the UART will clock from very high bit rates to very very low, that value really can exceed 255. So I switched it to an unsigned int. Shouldn’t affect you in this case, but it’s one of those things in code-reuse that can come back and bite you later.

Tom

Sorry to keep chain-posting, but one more thing worth mentioning:

When I first started testing this, I got some weird WEIRD behavior in the simulator. It was only after I saw the “device” resetting when it exited UART_Init() that I realized something really was amiss.

I was compiling for an ATMega128, but simulating for an ATMega168. DOH!

When in doubt, check the obvious stuff. Is the compiler set to compile for your device? Is the simulator set up to simulate your device? (The simulator does really well for UART stuff, it turns out.) And is your programmer set up to load code on the right device? Any one of these not being true can make things simply not work.

Tom

Thanks for the insights Tom. In simulation 1<<RXEN0|1<<TXEN0 sets the bits properly in simulation, but just to be sure I switched to (1<<RXEN0)|(1<<TXEN0) like you did, and made USART_Init take an int. Also, I think you forgot to copy/paste #define BAUD 9600 in your code.

Kevin, UART control works now on my (your old) Orangutan with a Micro Dual Serial Motor Controller (identical protocol & pinout to the low voltage one you have).

Here is the exact code I used; I added some lines to use PB3 as the motor controller reset pin:

#define BAUD 9600
#define F_CPU 8000000UL
#define MYUBRR F_CPU/16/BAUD-1

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

void USART_Init(unsigned int ubrr){
	UBRR0H=(unsigned char)(ubrr>>8);//set buad rate at 9600
	UBRR0L=(unsigned char) ubrr;
	UCSR0B=(1<<RXEN0)|(1<<TXEN0);//enable reciever & transmitter
	UCSR0C=(3<<UCSZ00);//Set frame format for 8bit with 1 stop
}

void USART_Trans (unsigned char data){
	while(!(UCSR0A&(1<<UDRE0)));//wait for transmit empty
	UDR0=data;
}

int main (void){
	DDRC|=(1<<PC3);//set PC3 to output
	PORTC|=(1<<PC3);//bring DSMC reset high
	_delay_ms(100);//allow time for DSMC to wake up

	USART_Init(MYUBRR);

	USART_Trans (0x80);//start byte
	USART_Trans (0x00);//DSMC device ID
	USART_Trans (0x01);//motor 0 (always works) fwd
	USART_Trans (0x7F);//full speed!

	while(1);//just sit here

	return(0);
}

The (only) fuses I have set are:

  • Boot Flash section size=128 words…
  • Brown-out detection disabled
  • Int. RC Osc. 8 MHz…+65ms

Here is my wiring, which should match yours along the 9 pin edge of the low voltage dual serial motor controller:

http://www.umich.edu/~aborrell/orangutan/otodsmc.jpg

From left to right, the connections are:

  1. Motor supply, in this case +6V
  2. Common Ground
  3. Logic Supply from Orangutan header Vcc
  4. Serial Control Input from Orangutan header PD1
  5. Reset connected to Orangutan header PC3
  6. Motor 1 - (not connected)
  7. Motor 1 + (not connected)
  8. Motor 0 -
  9. Motor 0 +

Note that since the Orangutan is connected to a separate power source, I connected it to common ground (yellow wire, hard to see the end, but it plugs into a ground pin in the header).

I agree that switching controllers now would be probably more work than getting your current setup running. If this doesn’t work now, or you still have other problems, we could meet sometime this week and hammer out a working line follower.

-Adam

DOH! Guilty as charged. I had stuck a bunch of stuff at the top (I tested on a Baby-O, so I had a different F_CPU defined, among other things) so there was a fair bit of clean-out when I posted.

So this is for a line follower? (he asked, rubbing his hands together gleefully.) How interesting!

Mind my asking what the sensor setup is going to be?

I’m still playing around with a line follower design I need to get off my zud and finish. Waiting on motors. (Ok, waiting on my allowance to catch up with my need to buy motors, more to the point.) I wound up getting six Parallax QTI sensors. Heavy, probably unnecessary, but I was after plug 'n play components rather than rolling my own. As it turns out I’d probably have been better off to roll my own. Anyway, the QTIs all work now. Just need something to make the wheels go round 'n round.

Please do let us know how the project works out. I’d love to see the end result.

Tom