Author Topic: UART recieve/xmit problems  (Read 4723 times)

0 Members and 1 Guest are viewing this topic.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
UART recieve/xmit problems
« on: October 24, 2007, 01:32:03 PM »
I have my AVR transmitting and receiving data properly, almost . . . I am using AVRlib uart.h functions, and hyperterminal to send/receive the data.

But Im having two problems with it . . .

The first is with typing text into hyperterminal to send commands. I am using this code:
Code: [Select]
//grab commands from keyboard
if(uartGetByte() == '1')
do_something=1;
if(uartGetByte() == '2')
do_something=2;
if(uartGetByte() == '3')
do_something=3;
if(uartGetByte() == '4')
do_something=4;
uartFlushReceiveBuffer();//flushes out entire recieve buffer

So if say I type '1' into the keyboard, do_something becomes 1. This works. Same if I press 2. But if I press 3 or 4 it doesnt work :-\
And is there a nicer way to write this code? For example:
Code: [Select]
do_something=uartGetByte();. . . but that doesn't work . . . this number designates the speed of my robot in the software . . .


The other problem is with printing out variable values. If I do this
Code: [Select]
unsigned int current=98;
rprintf("Current: %u \r\n", current);
then I get this in hyperterminal: 'Current: u'

But if I do this
Code: [Select]
unsigned int current=98;
rprintf("Current: %d \r\n", current);
then I get this in hyperterminal: 'Current: 98' (correct)

It just doesnt make sense to me why I can't use %u . . .


Thoughts for a weak programmer like me?

Offline JonHylands

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 562
  • Helpful? 3
  • Robot Builder/ Software Developer
    • Jon's Place
Re: UART recieve/xmit problems
« Reply #1 on: October 24, 2007, 03:24:37 PM »
Your problem is simple :-)

Your test is grabbing chars and discarding them as it goes.

You need something like this:

Code: [Select]
ch = uartGetByte ();
if (ch == '1')
    do_something_one
else if (ch == '2')
    do_something_two

- Jon

Offline dunk

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 1,086
  • Helpful? 21
    • dunk's robot
Re: UART recieve/xmit problems
« Reply #2 on: October 24, 2007, 03:28:40 PM »
hey Admin,
so my programming sucks as well but i think i see your problem.
in the first code section you are repeatedly calling uartGetByte().
every time you call it you are getting the next character from the buffer.

try something like this:
Code: [Select]
data = uartGetByte();
if(data == '1')
do_something=1;
if(data == '2')
do_something=2;
if(data == '3')
do_something=3;
if(data == '4')
do_something=4;


Quote
And is there a nicer way to write this code? For example:
Code:

do_something=uartGetByte();

you mean this sort of thing?
Code: [Select]
int doSomethingWithByte(char* cc){
        data = uartGetByte();
        if(data == '1')
                cc = "one something";
                return 1;
        else if(data == '2')
                cc = "two somethings";
                return 2;
        return 0 ;
}

int main(void){
        unsigned char cc ;      // this will contain the output from doSomethingWithByte() after it has run
        // this is your main section
        //

        while(1){
                if (doSomethingWithByte(cc)){
                       // put code to do something with cc in here.
                }
        }




Quote
The other problem is with printing out variable values. If I do this
Code:

unsigned int current=98;
rprintf("Current: %u \r\n", current);

then I get this in hyperterminal: 'Current: u'

But if I do this
Code:

unsigned int current=98;
rprintf("Current: %d \r\n", current);

then I get this in hyperterminal: 'Current: 98' (correct)

It just doesnt make sense to me why I can't use %u . . .

this is the expected behaviour unless you have defined RPRINTF_COMPLEX.

this is taken from /AVRlib/rprintf.h:
Quote
#ifdef RPRINTF_SIMPLE
        //! A simple printf routine.
        /// Called by rprintf() - does a simple printf (supports %d, %x, %c).
        /// Supports:
        /// - %d - decimal
        /// - %x - hex
        /// - %c - character
        int rprintf1RamRom(unsigned char stringInRom, const char *format, ...);
        // #defines for RAM or ROM operation
        #define rprintf1(format, args...)               rprintf1RamRom(STRING_IN_ROM, PSTR(format), ## args)
        #define rprintf1RAM(format, args...)    rprintf1RamRom(STRING_IN_RAM, format, ## args)

        // *** Default rprintf(...) ***
        // this next line determines what the the basic rprintf() defaults to:
        #define rprintf(format, args...)                rprintf1RamRom(STRING_IN_ROM, PSTR(format), ## args)
#endif

#ifdef RPRINTF_COMPLEX
        //! A more powerful printf routine.
        /// Called by rprintf() - does a more powerful printf (supports %d, %u, %o, %x, %c, %s).
        /// Supports:
        /// - %d - decimal
        /// - %u - unsigned decimal
        /// - %o - octal
        /// - %x - hex
        /// - %c - character
        /// - %s - strings
        /// - and the width,precision,padding modifiers
        /// \note This printf does not support floating point numbers.
        int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...);
        // #defines for RAM or ROM operation
        #define rprintf2(format, args...)               rprintf2RamRom(STRING_IN_ROM, format, ## args)
        #define rprintf2RAM(format, args...)    rprintf2RamRom(STRING_IN_RAM, format, ## args)

        // *** Default rprintf(...) ***
        // this next line determines what the the basic rprintf() defaults to:
        #define rprintf(format, args...)                rprintf2RamRom(STRING_IN_ROM, PSTR(format), ## args)
#endif


dunk.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: UART recieve/xmit problems
« Reply #3 on: October 25, 2007, 08:29:37 AM »
Where will I be without you guys!!! :)

Ok so your data = uartGetByte(); code fixed it. I made data an int.

Now about my other question . . .
do_something=uartGetByte();

What I meant was, can I just directly set whatever number I type into my keyboard to be directly the value of that variable? I mean, without any of the if statements . . .

As for the RPRINTF_COMPLEX, what I have works for now, but Ill look into it later if I must print out something other than a signed int. I guess Im just too used to CCSC for PICs.

Offline JonHylands

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 562
  • Helpful? 3
  • Robot Builder/ Software Developer
    • Jon's Place
Re: UART recieve/xmit problems
« Reply #4 on: October 25, 2007, 09:26:16 AM »
Almost. What you type in is an ASCII character, which means if you are looking for 0-9, then you need to subtract '0' (32) from the character in order to get a number out of it.

doSomething = uartGetByte() - 32;

assuming doSomething is declared as an int, should work.

This doesn't do any range checking, so you'll want to make sure the result value is between 1 and whatever your upper limit is. If you need more than 1-9, then it gets more complicated, because you have to input multiple characters, and do a smarter ascii-to-integer conversion.

- Jon

Offline krich

  • Robot Overlord
  • ****
  • Posts: 165
  • Helpful? 0
Re: UART recieve/xmit problems
« Reply #5 on: October 29, 2007, 09:47:54 PM »

try something like this:
Code: [Select]
data = uartGetByte();
if(data == '1')
do_something=1;
if(data == '2')
do_something=2;
if(data == '3')
do_something=3;
if(data == '4')
do_something=4;

To take this a step further, since data is an int you can use a switch statement rather than a series of if statements.  This is more efficient code:

Code: [Select]
int data=0;
data = uartGetByte();

switch (data) {
  case 32:
        do_something=0;
        break;
  case 33:
do_something=1;
        break;

etc...up to 41

  default:
        do_something=(some default value you select);
}

The nice thing about this is that it executes faster, you could call a subroutine instead of setting a variable, and it even gives you the ability to set a "failsafe" value or call a failsafe subroutine.  Something that, I suspect, is useful when programming them robot contraptions.  Now, if you're just going to print the data out, or assign a calculatable value to do_something, I agree with the subsequent posts that it can be and should be, done in a single statement.

Ken.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,703
  • Helpful? 173
    • Society of Robots
Re: UART recieve/xmit problems
« Reply #6 on: November 02, 2007, 03:10:47 PM »
What if I want to capture a fixed size stream of numbers/letters, such as "28 233 7 58 273 ACK" and save each grouping in a variable (x=28, y=233, z=7, etc.)?

Is uart.h capable of doing this? (Im thinking no)

I was going through the avrlib modules and couldn't figure out which to use . . . this maybe?
http://hubbard.engr.scu.edu/avr/avrlib/docs/html/group__bitbuf.html

A point in the right direction and I should be able to figure it out . . .

Offline krich

  • Robot Overlord
  • ****
  • Posts: 165
  • Helpful? 0
Re: UART recieve/xmit problems
« Reply #7 on: November 02, 2007, 04:21:54 PM »
You're on the right track.  I'd start with a Byte-Buffer rather than a bit-buffer.  (http://hubbard.engr.scu.edu/avr/avrlib/docs/html/group__buffer.html)  The data will be coming in as bytes, so no need to break them down into bits. 

Also, you say the stream will be fixed size, but the goal is to make the entire output a fixed size, so you'll need to pad fields if they might have numbers of different lengths so that the entire buffer will always be of a fixed size (e.g. 001, rather than 1).  This can be done efficiently using the printf statement you are using to output the values (%3u rather than just %u, I think).  It wastes bytes in the transmission, but makes processing much easier and faster. 

Next, iterate through your buffer, chopping things up with a 0x20 delimiter (or whatever 'space' is).

Finally, range check and convert your character based values into actual hex values.

As an aside:  You could also pass the values in true hex values rather than as character strings.  With one 16 bit word per grouping, plus a control byte, that's 11 bytes and there's no printf overhead at all.


 


Get Your Ad Here

data_list