Society of Robots - Robot Forum

Electronics => Electronics => Topic started by: Karlis.Rasis on March 19, 2012, 08:42:23 AM

Title: Atmega16 USART works incorect?
Post by: Karlis.Rasis on March 19, 2012, 08:42:23 AM
Sorry for my English, I' am from Latvia and Working on my bachelor's work.

Project is Control Robot via Bluetooth.
Months was spent before I get some results, but they are far from necessary

I use Atmega16 and connected Bluetooth module "linvor" to receive and send characters via Hyper-terminal on integrated Bluetooth adapter in my laptop. Bluetooth is connected tx-rx, rx-tx, gnd-gnd directly to MCU.
I found code that sends received character back. I modificate code and flashed to Atmega16.
When i send Characters via hyper-terminal it sends it back but, not all symbols.
To test all this for next steps I connected 3 leds on ports PB0-PB2 and want to get this- when i send characters- 'l' first diode light up, when 'n'- second, when 'p' third, when "r" all power down.

Problem is  when i send those characters 'l, n, p' or 'r' nothing happened. But first diode light up when i press 'j' on keyboard second when 'k' and third when 'l' ,to switch all off  'm'.
That means MCU understands l as j, n as k, p as l,  and r as m...
how it can be?
Maybe there is problems with BoudRate or clock speed, or protocol at all?

I readed many websites, and MCU Atmega16, Atmega8 Datasheets, but can not find information, about my problem. Hope someone will help.


Waiting for posts, thank You!
Code-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define F_CPU 7372800UL //Defines clock speed
#include <avr/io.h>
#include <avr/interrupt.h>
#define USART_BAUDRATE 115200 //Baudrate for serial comm.
#define BAUD_PRESCALE 3
 
//Serial com. Interrupt Service Routine (runs each time a byte is received)
ISR(USART_RXC_vect)
{
    char ReceivedByte;
    ReceivedByte = UDR; // Retrieves byte from serial port (bluetooth module)
    UDR = ReceivedByte; // Echoes it back for fun
 
    switch (ReceivedByte) //Which ASCII character was received?
    {
        case 'p':   PORTB =  0b00000100;//l
                    break;
 
        case 'n':   PORTB =  0b00000010;//k
                    break;
 
        case 'r':   PORTB =  0;//m
                    break;
 
        case 'l':   PORTB =  0b00000001;//j
                    break;
 
        default:    break; //Character unknown to my routine, discard character
 
    }
 
}
 
int main(void)
{
    //I/O Initialization
    DDRB |= (1<<PIN0) | (1<<PIN1) | (1<<PIN2); //DIR1, DIR2 and Enable pins as outputs
    PORTB=0; //All initialized to 0
 
    //UART
    UCSRB |= (1 << RXEN) | (1 << TXEN); //Enable Tx and Rx
    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
    UBRRL = BAUD_PRESCALE;          //Sets
    UBRRH = (BAUD_PRESCALE >> 8); //baudrate registers
    UCSRB |= (1 << RXCIE); //Enable USART-interrupt
 
    sei(); //Enable global interrupt
 
    /* This program is completely interrupt driven, so nothing goes on in while loop*/
    while(1); //Never gets out from here!
 
    return 0; //Never reaches this point!
}
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 19, 2012, 08:53:41 AM
Hi bralis  ;)

Your English is all fine, so don't worry too much.

I recently had same problem, and issue indeed was incorrect baud rate. What do You use as clock source?
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 19, 2012, 09:04:15 AM
Hi :)

I try internal and external oscillator. Now I have been connected external oscillator- 14.7456mhz... I can not found correct baud. MCU receives characters only when baud is 115200... And do not work in another... :(
Title: Re: Atmega16 USART works incorect Help Please.
Post by: joe61 on March 19, 2012, 09:53:33 AM

Code: [Select]
[code]
int main(void)
{
    //I/O Initialization
    DDRB |= (1<<PIN0) | (1<<PIN1) | (1<<PIN2); //DIR1, DIR2 and Enable pins as outputs
    PORTB=0; //All initialized to 0
 
    //UART
    UCSRB |= (1 << RXEN) | (1 << TXEN); //Enable Tx and Rx
    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
    UBRRL = BAUD_PRESCALE;          //Sets
    UBRRH = (BAUD_PRESCALE >> 8); //baudrate registers
    UCSRB |= (1 << RXCIE); //Enable USART-interrupt
 

Sometimes (always?) the order of access matters for 16 bit data registers. The data sheet shows UBRRH being set before UBRRL. Try it that way, you may not be getting the baud rate you think you are.

Just guessing here, I don't have time to verify this at the moment.

Joe
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 19, 2012, 10:15:46 AM
I think problem are not with order, I changed order and nothing will happened.
Can someone explain which frequency I must define my external clock source are 14.756Mhz.
If I want to set  USART_BAUDRATE 9600 without any errors!
And what does #define BAUD_PRESCALE exactly means?
At this moment nothing was helpful...
Title: Re: Atmega16 USART works incorect Help Please.
Post by: joe61 on March 19, 2012, 11:50:30 AM
Your code said the clock was
Code: [Select]
#define F_CPU 7372800UL //Defines clock speed

If it's really 14.756Mhz you'll need a different setting.  See the section in the data sheet titled "Examples of Baud Rate Setting". It has some tables you can use.

Joe
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 19, 2012, 01:50:41 PM
Thank You for replay Joe, i tried to change settings, but it is not work...
If I write BAUD_PRESCALE 3 or 4 or 5 hyper-terminal received characters back, but with errors. If 95 how Datasheet sad nothing happened...
Code: [Select]
#define F_CPU 14745600UL //Defines clock speed
#include <avr/io.h>
#include <avr/interrupt.h>
#define USART_BAUDRATE 9600 //Baudrate for serial comm.
#define BAUD_PRESCALE 95 //95 sad in Atmega16 datasheet for 14745600UL oscil

//Serial com. Interrupt Service Routine (runs each time a byte is received)
ISR(USART_RXC_vect)
{
    char ReceivedByte;
    ReceivedByte = UDR; // Retrieves byte from serial port (bluetooth module)
    UDR = ReceivedByte; // Echoes it back for fun
 
    switch (ReceivedByte) //Which ASCII character was received?
    {
 
        case 'p':   PORTB =  0b00000100;//l
                    break;

        case 'n':   PORTB =  0b00000010;//k
                    break;

        case 'r':   PORTB =  0;//m
                    break;
 
        case 'l':   PORTB =  0b00000001;//j
                    break;
 
        default:    break;
 
    }
 
}
 
int main(void)
{
    //I/O Initialization
    DDRB |= (1<<PIN0) | (1<<PIN1) | (1<<PIN2); //DIR1, DIR2 and Enable pins as outputs
    //PORTB=0; //All initialized to 0
 
    //UART
    UCSRB |= (1 << RXEN) | (1 << TXEN); //Enable Tx and Rx
    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
    UBRRL = BAUD_PRESCALE;          //Sets
    UBRRH = (BAUD_PRESCALE >> 8); //baudrate registers
    UCSRB |= (1 << RXCIE); //Enable USART-interrupt
 
    sei(); //Enable global interrupt
 
    /* This program is completely interrupt driven, so nothing goes on in while loop*/
    while(1); //Never gets out from here!
 
    return 0; //Never reaches this point!
}
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 19, 2012, 01:57:25 PM
Karlis.Rasis, can You set different baud rate in HyperTerminal? If so, then use set microcontroller to use internal 1MHz oscillator. Then, using datasheet set baud rate to be 4800, then set same baud rate for HyperTerminal. When I had same problem, I set internal oscillator to 8MHz, and baud rate to 0.5M.

Use [TUT] [SOFT] Using the USART - Interrupt driven serial comms (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48188) as a reference, only instead of 9600 baud, set it to 4800.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 19, 2012, 02:23:38 PM
Yes of course, I can change baud rate in hyper terminal. I done modifications, and became worse...
Now all characters was sended back by "xxxxxxxx"

Code: [Select]
#define F_CPU 1000000UL //Defines clock speed
#include <avr/io.h>
#include <avr/interrupt.h>
#define USART_BAUDRATE 4800 //Baudrate for serial comm.
//#define BAUD_PRESCALE 95 //95 sad in Atmega16 datasheet for 14745600UL oscil
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

//Serial com. Interrupt Service Routine (runs each time a byte is received)
ISR(USART_RXC_vect)
{
    char ReceivedByte;
    ReceivedByte = UDR; // Retrieves byte from serial port (bluetooth module)
    UDR = ReceivedByte; // Echoes it back for fun
 
    switch (ReceivedByte) //Which ASCII character was received?
    {
 
        case 'p':   PORTB =  0b00000100;//l
                    break;

        case 'n':   PORTB =  0b00000010;//k
                    break;

        case 'r':   PORTB =  0;//m
                    break;
 
        case 'l':   PORTB =  0b00000001;//j
                    break;
 
        default:    break;
 
    }
 
}
 
int main(void)
{
    //I/O Initialization
    DDRB |= (1<<PIN0) | (1<<PIN1) | (1<<PIN2); //DIR1, DIR2 and Enable pins as outputs
    //PORTB=0; //All initialized to 0
 
    //UART
    UCSRB |= (1 << RXEN) | (1 << TXEN); //Enable Tx and Rx
    UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
UBRRH = (BAUD_PRESCALE >> 8); //baudrate registers
    UBRRL = BAUD_PRESCALE;//Sets
    UCSRB |= (1 << RXCIE); //Enable USART-interrupt
 
    sei(); //Enable global interrupt
 
    /* This program is completely interrupt driven, so nothing goes on in while loop*/
    while(1); //Never gets out from here!
 
    return 0; //Never reaches this point!
}
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 19, 2012, 03:09:04 PM
Did You change fuses for microcontroller to use 8MHz clock with 8x Pre-scaler?
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 19, 2012, 04:43:19 PM
No I do not change fuses. Why should I change fuses, if internal clock setting are at 1Mhz?
Title: Re: Atmega16 USART works incorect Help Please.
Post by: joe61 on March 19, 2012, 06:38:25 PM
If you didn't change the fuses then how could you be running at the speeds you say you were?

If you're running at 1MHz then use the settings for 1MHz, and don't tell the program you're running at something else. The settings you've been showing in your code are wrong for a 1MHz clock.

Joe
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 02:27:31 AM
No I do not change fuses. Why should I change fuses, if internal clock setting are at 1Mhz?
I might be pointing the obvious, but just in case I have to mention it: #define F_CPU 1000000UL //Defines clock speed does not change actual clock speed, it only defines constant value for time based calculations. Say, if Delay(us) function was used, then compiler (using F_CPU value) would work out how many counter increments has to be done to waste (delay) required amount of time. In order to actually change clock source (and most likely speed) You have to use fuses. If You did not change fuses to start with, then You were running Your microcontroller on internal 8MHz clock with 8x pre-scaler  giving 1MHz clock; if that's the case - then we know the reason why Your USART comms failed.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 20, 2012, 04:23:18 AM
Thank You "newInRobotics", for information. I found that on #define BAUD_PRESCALE 5, USART commands are working normal.
I do not know how  ??? Maybe reason is fuses...
If I want to use 1Mhz internal clock i must change fuses, but now when all is working, it will not give even worse result?
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 04:38:14 AM
If You know what You're doing, then results will be as good as You set them to be. Datasheet, in this case (and many other cases), is Your best friend.

Also, You shouldn't guess values, but try to understand why certain things has to be the way they are. In the link I provided You before example shows how to define BAUD_PRESCALE:
Code: [Select]
#define F_CPU 1000000UL //Put clock speed here
#define USART_BAUDRATE 9600 //Put desired Baud Rate here
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) //This calculates Baud Prescale value for You

Moreover, tutorial I linked You to describes very well why all what there is has to be there in order for USART to work, read it, implement it and You should be good to go on Your own.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 04:54:45 AM
If I want to use 1Mhz internal clock i must change fuses, but now when all is working, it will not give even worse result?
If You've never touched fuses, why are You so sure that clock speed is not 1MHz? Are You using AVRstudio? If so, Can you printscreen fuses control panel and upload it here?
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 20, 2012, 06:04:36 AM
I agree with You and want to understand, why tutorial which You sent do not work in project and other tutorials have the same way to define USART Baud do not work too.
I 'am not sure that clock speed is not 1 MHz, but why value for 1MHz of #define BAUD_PRESCALE  "12" how says in Datasheet do not work? Yes I use AVRstudio.

Here is screen...
(http://dl.dropbox.com/u/68163809/fuses.jpg)
Title: Re: Atmega16 USART works incorect Help Please.
Post by: joe61 on March 20, 2012, 06:22:51 AM
Take a look at the "Memory Programming" section of the data sheet. For the Atmega16 page 261 shows the default settings for the fuse low byte (which is the byte that controls clock speed).

Keep in mind that a value of 1 means "not programmed". The chart at the top of that page shows a default value of 0xe1, which is what you show in the screen shot from AVR Studio. So you are running at the default factory setting of 1MHz.

Now look at Table 68 on page 168. It shows that at 1MHz, a setting of 6 will give you 9600 bps, but with a significant error rate.

If you want to do 9600 bps or faster, you'd really be better off running the chip with a faster clock. If you don't want to mess with fuses right now you probably will get better results at 2400 bps.

I don't use AVR Studio so I'm not sure how you set fuses there, but if you have to provide the value for the low fuse byte, you might want to settle for lower speeds until you understand fuses. An incorrect value could render the chip unusable.

Hope that helps.

Joe
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 06:39:32 AM
Create new project for Your ATmega16 and drop following code in, compile and upload to microcontroller.

Code: [Select]
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 1000000UL
#define USART_BAUDRATE 4800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

int main (void)
{
   UCSRB |= (1 << RXEN) | (1 << TXEN);   // Turn on the transmission and reception circuitry
   UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

   UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
   UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register

   UCSRB |= (1 << RCXIE); // Enable the USART Recieve Complete interrupt (USART_RXC)

   sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed

   for (;;) // Loop forever
   {
         // Do nothing - echoing is handled by the ISR instead of in the main loop
   }   
}

ISR(USART_RXC_vect)
{
   char ReceivedByte;
   ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
   UDR = ReceivedByte; // Echo back the received byte back to the computer
}

Then setup HyperTerminal so that:
*Bits per second = 4800;
*Data bits = 8
*Parity = None
*Stop bits = 1
*Flow control = None

Microcontroller should send all the incoming data back to computer.

Regarding clock speed - according to fuse SUT_CKSEL, uC is running at 1MHz as the fuse is set to Int. RC Osc. 1MHz, hence F_CPU should be 1000000UL.

When you're done, post back Your results.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 20, 2012, 06:51:24 AM
"newInRobotics" I tried it, but
Code: [Select]
UCSRB |= (1 << RCXIE); // Enable the USART Recieve Complete interrupt (USART_RXC) compiler shows error, I change it with this
Code: [Select]
UCSRB |= (1 << RXEN) | (1 << TXEN); //Enable Tx and Rxbuild and upload to MCU.

Than set Hyperterminal settings how You say

*Bits per second = 4800;
*Data bits = 8
*Parity = None
*Stop bits = 1
*Flow control = None

And get no information in hyper-terminal program... It only echos back correct characters at
Code: [Select]
#define F_CPU 1000000UL
#define USART_BAUDRATE 4800
#define BAUD_PRESCALE 5

But it is incorrect, something strange happened here...
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 07:00:46 AM
"newInRobotics" I tried it, but
Code: [Select]
UCSRB |= (1 << RCXIE); // Enable the USART Recieve Complete interrupt (USART_RXC) compiler shows error, I change it with this
Code: [Select]
UCSRB |= (1 << RXEN) | (1 << TXEN); //Enable Tx and Rxbuild and upload to MCU.
Oops  ;D sorry for typo  ;D change:
Code: [Select]
UCSRB |= (1 << RCXIE); // Enable the USART Recieve Complete interrupt (USART_RXC) to
Code: [Select]
UCSRB |= (1 << RXCIE); // Enable the USART Recieve Complete interrupt (USART_RXC)
RCXIE to RXCIE  ;D
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 20, 2012, 07:07:05 AM
Yes with change build was successful, but when i typed - abcdefghijklmnoprst... I get this
 (http://dl.dropbox.com/u/68163809/Untitled.png)

The same problem...  :-\
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 07:21:24 AM
I had same problems before, I thought that it was fault of HyperTerminal, so I wrote piece of software myself. I'm at work ATM, however after I came back home, I will send it to You. In the meantime You can try using RealTerm (http://realterm.sourceforge.net/). See how that works.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: joe61 on March 20, 2012, 08:39:25 AM
Yes with change build was successful, but when i typed - abcdefghijklmnoprst... I get this

Take a look at the tutorial at AVRFreaks (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48188). Looks like the same code NIR posted (including the typo), but the following comments might give some other things to look at. For example, you need to have the atmega output connected to the pc terminal input and vice versa.

Joe
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 08:43:24 AM
Take a look at the tutorial at AVRFreaks (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48188). Looks like the same code NIR posted (including the typo), but the following comments might give some other things to look at.
Just to make it clear - that is the same code, only baud rate value is changes and F_CPU definition added.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 03:14:50 PM
Right, I set my ATmega48 to 1MHz and flashed it with following code (not exactly the same code, as it had to be modified to fit ATmega48) :
Code: [Select]
#define F_CPU 1000000UL
#define USART_BAUDRATE 4800
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
UCSRB |= (1 << RXEN) | (1 << TXEN); //Turn ON transmission and reception circuitry

UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); //Data length of 8-Bit

UBRRH = (BAUD_PRESCALE >> 8); //Load upper 8-bits of BAUD_PRESCALE value
UBRRL = BAUD_PRESCALE;

UCSRB |= (1 << RXCIE); //Enable Rx Complete interrupt;

sei(); //Enable global interrupts;

for(;;) {}
}

ISR(USART_RX_vect) //Byte received interrupt routine
{
UDR = UDR;
}

Next, download attached testUSART.zip, extract it somewhere.

Have Your microcontroller running, then launch testUSART.exe. Default COM port is COM4, if Your's different, enter new name and click Change COM port button. In the upper field write any number from 0 to 255, click Send and see if microcontroller sends back same number. Everything gets printed in CMD console.
Title: Re: Atmega16 USART works incorect Help Please.
Post by: Karlis.Rasis on March 20, 2012, 05:09:41 PM
Thank You "newInRobotics" You are Genius with big G, problem was hyper-terminal!!!
Now when problem is solved, I will try to write Hyper-terminal program on C# exactly for my project.
I found tutorialhttp://kishordgupta.wordpress.com/2011/01/28/bluetooth-device-connection-in-c-winform-application-without-any-dll-for-windows-7/ (http://kishordgupta.wordpress.com/2011/01/28/bluetooth-device-connection-in-c-winform-application-without-any-dll-for-windows-7/) Maybe You do something like it? Thanks again :)
Title: Re: Atmega16 USART works incorect Help Please.
Post by: newInRobotics on March 20, 2012, 05:30:35 PM
Thank You [...]
I'm happy that we managed to sort it out  ;)

Maybe You do something like it?
Piece of software that I've attached was developed (or should I say quickly slapped together) by me. It lacks bells and whistles, which can be added later on, however it got job done for me and for You  ;D

Also, if need be, with current configuration You can get Baud Rate of 500000; all You need to do is to set SUT_CKSEL fuse to INTRCOSC_8MHZ_6CK-64MS (see image attached), in source code set F_CPU to 8000000UL, and USART_BAUDRATE to 500000.