Atmega UART tranfer data to Matlab via USB.

Before reading the blog to be able to actually understand the core working of the process one must have the some knowledge of the foll0wing:-

1) Using USART on atmega microcontrollers (code is specific to atmega 32 ).

2)Prior experience with avr studio for coding (embedded c) and knowledge to burn code onto the microcontroller.

3)Prior experience and/or knowledge of Matlab and using it on Laptop/PC.

If you feel you posses (adequately) the awesome skills mentioned above you may now continue reading the blog post 🙂

Lets start of by knowing what the USART actually is capable off.

THE USART

Ok so being specific to atmega 32 , POINTS TO REMEMBER

1)Can be used in synchronous or asynchronous mode.(We’ll be using async)

2) There are many baud rates which u can set (make sure to use the same baud rate in your Matlab code).

3) Can use parity for error correction(not used since i’m presuming communication is over short wires with not many electromagnetic interference sources nearby) 😛

4) Can select character size from 5 bits to a max of 9 bits.(we’ll stick with the standard 8-bits characters)

Point to remember sending a number from 0-255 is possible directly but numbers greater than 255 have to broken up into 8-bit data values and sent independently and then re-assembled as a whole number at the receiving end(laptop/pc). More on this later.

LETS GET CODING:

You can type(copy-paste) the code below in your version of AVRSTUDIO (i use studio5)

SAMPLE CODE:

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#define F_CPU 16000000 //make sure you set this according to the freq your board operates at

#include <inttypes.h>

 

void uart_init(uint16_t);

char uart_read_byte(void);

void uart_write_char(char);

 

void uart_init(uint16_t ubrr_value) // Function to initiate UART

{

UBRRL = ubrr_value; //Baud rate setting //UBRR = (F_CPU / (16 * BAUD)) – 1 //formula

UBRRH = (ubrr_value>>8);

UCSRC=(1<<URSEL)|(3<<UCSZ0); //setting for 8-bit data tx and rx

UCSRB=(1<<RXEN)|(1<<TXEN); //Enable transmission and reception by setting RXEN and TXEN bits to 1

}

 

char uart_read_byte(void)             //Function to read the data

{                               // received from matlab or any other sources

while(!(UCSRA & (1<<RXC))) ;       //wait for character to  be received

return UDR; //received character present in UDR register

}

 

void uart_write_char(char data)      //Function to send data to

{                                    //matlab or to any other device

while(!(UCSRA & (1<<UDRE)))      //wait for transmit data buffer to go empty

UDR=data; //writing to UDR transmits the byte.

}

 

void main()

{

unsigned char data1;

DDRA=0x01;

uart_init(103); //9600 baud rate reffer data sheet //refer to formula in uart_init function

while(1)

{

data1=uart_read_byte();         //reading data

uart_write_char(data1);         //send same data as received

}

}// End of SAMPLE CODE

Alright once you’ve written the code, corrected for any errors, etc and have finally got a hex file with the same name as you gave for the C code, Here’s what the above code is meant to do…

It’s called an “Echo” code, simply because whatever the Microcontroller hears(Receives) it will speak out(Transmit). The comments in the code make it pretty self explanatory if you follow it step by step.

 

Next burn the code and your Microcontroller is ready to communicate with a PC.

No not really 😛

You will need an interface between your PC and the microcontroller for them to understand each other.  (Communication protocols differ)

Assuming you want to communicate to your laptop/PC via the USB port(Serial ports not considered). You will need a convertor, more specifically USB to TTL convertor. One such is available on the following Link (tried and tested).

usb_to_serial_ttl_cmos_logic

(http://www.nex-robotics.com/index.php?option=com_virtuemart&page=shop.product_details&flypage=flypage.tpl&category_id=59&product_id=267&Itemid=45)

You must download the drivers and the serial terminal present in the same link.

Also you will require USB cable with TYPE ‘B’ USB connector at one end and TYPE ‘A’ USB connector at the other end.

https://i0.wp.com/ecx.images-amazon.com/images/I/4109I2PdxCL._SY300_.jpg

The USB is interfacing with the convertor module is quite straightfoward.

When you are using this module for first time then install its necessary drivers by downloading and installing drivers from the same link.

DRIVER INSTALLATION GUIDE:

1) Connect USB cable to PC and convertor module.

2) Open “Device Manager” on your system.

3) Search for the device marked in image below.

 

 

 

4) Right-click and click on “Update Device Driver Software”

5) A new pop-up window will then ask you whether you want windows to search for the driver online or if u have it on your system. Select browse my system option.

6) Assuming you have downloaded the driver and unzipped it into some directory on your system, you should be able to select the driver folder from the directory you have unzipped the files into.

7) Once you have selected the driver folder it’s path will appear in the window. Click on “Next” and windows will do the needful 🙂

8) If everything has worked the way its meant to work your “Device Manager” will list the convertor module under PORTS(COM & LPT). (Refer to Image below. )

com port

P.S. The com port number will differ from user to user and should be noted down for further use.

This concludes interfacing convertor module to your PC.

 

Now we have to interface the convertor module to the Microcontroller.

Interfacing the convertor module with the microcontroller however requires some inspection of the microcontroller  datasheet , specifically the Pin Configurations. For your convenience I have added the DIP package Pin Config of ATmega 32 below.

pinout_atmega32

As shown in the pin config , the RX pin is PORTD pin0 and the TX pin is PORTD pin1.

You will also find RX and TX pins marked on the convertor module. Refer to image below.

convertor

 

We have to make the connections as follows

Rx of UC (PORTD Pin0)–> Tx of convertor module

Tx of UC (PORTD Pin1)–> Rx of convertor module

Also Ground of Uc –> Ground of convertor module(GND).

Lastly the jumper(marked red) present on the Convertor module should be on the 5v Logic side. Since ATmega TTL logic is at 5v.

(Brotip: If you want to interface raspberry pi the same way you must shift the jumper t0 3.3 v Logic)

This gives us the Null modem configuration.

Now we are finally ready to communicate with PC. The convertor will now act as an interface(communiction translator) between the microcontroller and your pc.

To test the configuration we will use serial terminal program also available in the same download link.

After downloading and installing the serial terminal program open the same.

serial terminal

The above window is the User interface of the serial terminal program.

First select the COM PORT number as assigned to the convertor module by your system.

Baud Rate:9600 ; Parity: None ; Data Bits:8 ; Stop Bits:One ; Data Mode: Text … These are set by default and match the communication protocols we have set for the USART of the ATmega 32 in our C program.

After the settings are done click on Connect.

Now presuming you have burnt the sample “Echo” code onto your microcontroller. Within the UI of the serial terminal program you can type any character you wish to send to the microcontroller by typing it in the “Send Data” field and click on “Send”.

serial terminal send

If you receive the same character back in the Text Area you have successfully set up communication between your PC and and the Micro controller. *round of applause* 🙂

Now for the main part i.e. Getting Data into Matlab for further processing, since that was our main aim to begin with.

To understand serial communication in Matlab first you have to understand the meaning of each Instruction that will be used in the Matlab program.

 

1)serial

Create serial port object

Syntax:

obj = serial(‘port’)

obj = serial(‘port’,’PropertyName’,PropertyValue,…)

Description:

obj = serial(‘port’) creates a serial port object associated with the serial port specified by port. If port does not exist, or if it is in use, you will not be able to connect the serial port object to the device.Port object name will depend upon the platform that the serial port is on. instrhwinfo (‘serial’) provides a list of available serial ports. This list is an example of serial constructors on different platforms: Platform Serial Port Constructor

Linux and Linux 64serial(‘/dev/ttyS0’);

Mac OS X 64serial(‘/dev/tty.KeySerial1’);

Windows 32 and Windows 64serial(‘com1’);

 

obj = serial(‘port’,’PropertyName’,PropertyValue,…) creates a serial port object with the specified property names and property values. If an invalid property name or property value is specified, an error is returned and the serial port object is not created.

Example:

s = serial(‘COM11′,’BaudRate’,9600,’DataBits’,8);          //obj “s” will refer to a com port “11” with “9600” as baud rate setting and character size of “8” data bits.

2)   fopen (serial)

Connect serial port object to device

Syntax:

fopen(obj)

Description:

fopen(obj) connects the serial port object, obj to the device.

 

3)   BytesAvailable

Number of bytes available in the input buffer

Description:

BytesAvailable indicates the number of bytes currently available to be read from the input buffer. The property value is continuously updated as the input buffer is filled, and is set to 0 after the fopen function is issued.

You can make use of BytesAvailable only when reading data asynchronously. This is because when reading data synchronously, control is returned to the MATLAB command line only after the input buffer is empty. Therefore, the BytesAvailable value is always 0.

The BytesAvailable value can range from zero to the size of the input buffer. Use the InputBufferSize property to specify the size of the input buffer. Use the ValuesReceived property to return the total number of values read.

 

4)    BytesToOutput

Number of bytes currently in the output buffer

Description:

BytesToOutput indicates the number of bytes currently in the output buffer waiting to be written to the device. The property value is continuously updated as the output buffer is filled and emptied, and is set to 0 after the fopen function is issued.

You can make use of BytesToOutput only when writing data asynchronously. This is because when writing data synchronously, control is returned to the MATLAB command line only after the output buffer is empty. Therefore, the BytesToOutput value is always 0.

 

5)fclose (serial)

Disconnect serial port object from device

Syntax:

fclose(obj)

Description:

fclose(obj) disconnects obj from the device, where obj is a serial port object or an array of serial port objects.

 

6)fprintf (serial)

Write text to device

Syntax:

fprintf(obj,’cmd’)

fprintf(obj,’format’,’cmd’)

fprintf(obj,’cmd’,’mode’)

fprintf(obj,’format’,’cmd’,’mode’)

Description:

fprintf(obj,’cmd’) writes the string cmd to the device connected to the serial port object, obj. The default format is %s\n. The write operation is synchronous and blocks the command-line until execution completes.

fprintf(obj,’format’,’cmd’) writes the string using the format specified by format.

fprintf(obj,’cmd’,’mode’) writes the string with command line access specified by mode. mode specifies if cmd is written synchronously or asynchronously.

fprintf(obj,’format’,’cmd’,’mode’) writes the string using the specified format. format is a C language conversion specification.

You need an open connection from the serial port object, obj, to the device before performing read or write operations.

Use the fopen function to open a connection to the device. When obj has an open connection to the device it has a Status property value of open. Refer to Troubleshooting Common Errors for fprintf errors.

To understand the use of fprintf refer to Completing a Write Operation with fprintf and Rules for Writing the Terminator.

 

7)fwrite (serial)

Write binary data to device

Syntax:

fwrite(obj,A)

fwrite(obj,A,’precision’)

fwrite(obj,A,’mode’)

fwrite(obj,A,’precision’,’mode’)

Description:

fwrite(obj,A) writes the binary data A to the device connected to the serial port object, obj.

fwrite(obj,A,’precision’) writes binary data with precision specified by precision.

precision controls the number of bits written for each value and the interpretation of those bits as integer, floating-point, or character values. If precision is not specified, uchar (an 8-bit unsigned character) is used. The supported values for precision are listed below in Tips.

fwrite(obj,A,’mode’) writes binary data with command line access specified by mode. If mode is sync, A is written synchronously and the command line is blocked. If mode is async, A is written asynchronously and the command line is not blocked. If mode is not specified, the write operation is synchronous.

fwrite(obj,A,’precision’,’mode’) writes binary data with precision specified by precision and command line access specified by mode.

 

8)fscanf (serial)

Read data from device, and format as text

Syntax:

A = fscanf(obj)

A = fscanf(obj,’format’)

A = fscanf(obj,’format’,size)

[A,count] = fscanf(…)

[A,count,msg] = fscanf(…)

Description:

A = fscanf(obj) reads data from the device connected to the serial port object, obj, and returns it to A. The data is converted to text using the %c format.

A = fscanf(obj,’format’) reads data and converts it according to format. format is a C language conversion specification. Conversion specifications involve the % character and the conversion characters d, i, o, u, x, X, f, e, E, g, G, c, and s. Refer to the sscanf file I/O format specifications or a C manual for more information.

A = fscanf(obj,’format’,size) reads the number of values specified by size. Valid options for size are:

n=Read at most n values into a column vector.

[m,n] =Read at most m-by-n values filling an m–by–n matrix in column order.

Size cannot be inf, and an error is returned if the specified number of values cannot be stored in the input buffer. If size is not of the form [m,n], and a character conversion is specified, then A is returned as a row vector. You specify the size, in bytes, of the input buffer with the InputBufferSize property. An ASCII value is one byte.

[A,count] = fscanf(…) returns the number of values read to count.

[A,count,msg] = fscanf(…) returns a warning message to msg if the read operation did not complete successfully.

 

Matlab Code

Type this code one after the another in command window

>>s = serial(‘COM11′,’BaudRate’,9600,’DataBits’,8);

>> fopen(s)

>>fwrite(s,’1’);

>>A=fscanf(s,’%c’,s.BytesAvailable);

>>disp(A); //display received character, should be same as sent character

>> fclose(s)

 

 

This post was written for Inventrom by Dattaprasad Naik. Datta has been working with Inventrom since 2013 and leads Learn, the department involved in training and workshops. Follow Datta on twitter via @datta_TECH

 

 

 

 

 

 

 

 

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s