Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
mewakitty
PostPosted: Jun 28, 2012 - 07:50 PM
Wannabe


Joined: May 28, 2012
Posts: 91


JohanEkdahl wrote:
When you're through grasping ring buffers, then pop over to your uni dept and talk to the person(s) in charge of course and curriculum contents. Tell them that they need to incorporate the concept if a queue data structure, and it's implementation by using a ring buffer, into their CS101 (or 102, which I would expect to be entitled "Algorithms and Data Structures" or some such). Wink


Well, I'm not a computer science student (nor am I a software engineer). What I'm learning is kind of my own initiative, I'm sure they cover buffers and such in relevant courses, but suggesting it to my own department would probably not end up being very productive Wink
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 28, 2012 - 09:44 PM
Wannabe


Joined: May 28, 2012
Posts: 91


Alright, I don't know what to do.

I put a circular buffer in (which seems to work in simulation at least). Except the damn thing doesn't seem to want to accept my UART commands. I can see on the scope that the value changes momentarily, but always goes back to the default value.

I can also get it to glitch out and set lines high forever.

Could my chip be resetting? I remember a cause for this could be an enabled interrupt that doesn't have an ISR. Maybe this is what is going on? I'll have to scout the datasheet to see if I enabled anything by accident.
I don't have mad servo flinging anymore, it just doesn't respond to commands.

Or maybe I'm doing something in code? I used Dean's (Four walled cubicle) code for the circle buffer as a basis, I only changed the variable names. I watched the memory in simulation and things are updated as I think they should.

Anyway, here is the new snippet of my main loop:
Code:

     ring_init((Ring_t*)&UARTbuf);
     for (int i = 0; i <20; i++)
     {
        ring_insert((Ring_t*)&UARTbuf, (i+32));
     }

     while(1){
           if (ring_has18((Ring_t*)&UARTbuf))
         {
            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
            {
                  for (int i = 0; i < 18; i++)
               {
                cRB[i] = ring_retrieve((Ring_t*)&UARTbuf) - 32;
               }
            }
              update_counts(cRB);
         }    
     }


And the Rx interrupt:
Code:

ISR(USART0_RX_vect)
{
   uint8_t ch_r = UDR0;
   ring_insert((Ring_t*)&UARTbuf, ch_r);
}


And ring_has18:
Code:

bool ring_has18(Ring_t* const buffer)
{
   return (ring_getcount(buffer) >= 18);
}


I can post the other functions too, but they are all from here: http://www.fourwalledcubicle.com/AVRCodeSamples.php
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 28, 2012 - 11:03 PM
Wannabe


Joined: May 28, 2012
Posts: 91


I found some stuff out.

First of all, it doesn't like this:
Code:
 cRB[i] = ring_retrieve((Ring_t*)&UARTbuf) - 32;

That does something, I think.

Secondly, I am pretty certain it is resetting. I have it hooked up to my LCD screen right now with servos turned off. It should display received data on the screen so that I can make sure it's working. The data most of the time doesn't get displayed, instead the LCD blinks (like power cycling blinking) and shows the default values. Sometimes it will display a series of 18 characters. If I get really lucky, after about 3 sends (and no resets), I finally see my characters.

Thirdly, I'm sending different characters to see if there is a pattern (yet again). What is the meaning of this character that looks like 4 parallel bars? I don't think I'm retrieving the right characters from the buffer.

Fourthly, I'm a moron for initializing 20 characters into the buffer.
 
 View user's profile Send private message  
Reply with quote Back to top
skeeve
PostPosted: Jun 28, 2012 - 11:22 PM
Raving lunatic


Joined: Oct 29, 2006
Posts: 2648


mewakitty wrote:
Secondly, I am pretty certain it is resetting.
More probable is an interrupt without an ISR.
By any chance did you get rid of the overflow ISR, but keep the interrupt enabled?
You don't need to keep the interrupt enabled to use the interrupt flag.

_________________
Michael Hennebry
Iluvatar is the better part of Valar.
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 28, 2012 - 11:40 PM
Wannabe


Joined: May 28, 2012
Posts: 91


skeeve wrote:
mewakitty wrote:
Secondly, I am pretty certain it is resetting.
More probable is an interrupt without an ISR.
By any chance did you get rid of the overflow ISR, but keep the interrupt enabled?


That's what I'm thinking as well. I looked through my code, but I don't see anything that I knowingly enabled.

I commented out my Timer 1 initializations, but that didn't help. So I ran a simulation and paused it once all interrupts were enabled. I found I have Input Capture Flag set on Timer 1, but not the interrupt for it. Does that matter? I don't think so.

I cannot find any other stray interrupts.
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: Jun 29, 2012 - 02:13 AM
10k+ Postman


Joined: Sep 04, 2002
Posts: 21257
Location: Orlando Florida

Some folks write handlers for every interrupt that prints out 'unexpected capture interrupt' then hangs in a while(1) loop. Good for debug but bad for unattended operation.

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Kartman
PostPosted: Jun 29, 2012 - 05:33 AM
Raving lunatic


Joined: Dec 30, 2004
Posts: 8763
Location: Melbourne,Australia

Apart from your resetting problem, how do maintain synchronisation between your pc and the AVR? Your data packet has 18 chars, but how do we know the start and end of this? Simply expecting the 18 chars to magically line up probably wont work too well in the real world. ou'll find most protocols have a start token or sequence, an end token or sequence and probably some form of error check. Look at NMEA0183 which is what most GPS receivers output - it has a start token of $ and the end is a carriage return char. It also implements a simple checksum. There is plenty of example code on how to generate and decode this data. first up I'd suggest you skip the checksum to make testing a little easier. Again, Arduino would be a good source for ideas. Also have a look at setting up the streams in avrgcc so you can use printf.Carefully placed printf statements can help debugging immensely. Debug your serial and protocol first, then look to integrating this with your servo code - don't try to fight the war on a number of fronts.
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 29, 2012 - 05:44 AM
Wannabe


Joined: May 28, 2012
Posts: 91


Kartman wrote:
Apart from your resetting problem, how do maintain synchronisation between your pc and the AVR? Your data packet has 18 chars, but how do we know the start and end of this? Simply expecting the 18 chars to magically line up probably wont work too well in the real world.


I wrote the GUI on the PC. 18 characters is all it will send at a time, 100% of the time.

Quote:
Debug your serial and protocol first


I'm trying. I will look into streams in avrgcc.
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 29, 2012 - 05:46 AM
Wannabe


Joined: May 28, 2012
Posts: 91


bobgardner wrote:
Some folks write handlers for every interrupt that prints out 'unexpected capture interrupt' then hangs in a while(1) loop. Good for debug but bad for unattended operation.


I might have to do that tomorrow morning and see if that helps narrow it down. Right now I'm completely clueless as to what is causing the resetting. I'm kind of certain it's my servo code.
 
 View user's profile Send private message  
Reply with quote Back to top
Kartman
PostPosted: Jun 29, 2012 - 08:31 AM
Raving lunatic


Joined: Dec 30, 2004
Posts: 8763
Location: Melbourne,Australia

Whilst your app may only send 18 chars at a time, what about a stray character when you plug in or power up? Your code must be able to synchronise with your packet - if you blindly send out 18 chars with no way on the receiving end to determine where it starts and ends, then your protocol will be unreliable. For this method to work you would need to use a timer to reset your receiver after a period of no data. Then your protocol has a chance of working. Let's assume you have received your 18 chars and the AVR code has them nicely aligned in your array. How do you know you've received the correct data? You could blindly accept that it is correct as that is what the PC sent. Reality is that may not be the case for a number of real world reasons.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jun 29, 2012 - 10:51 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62281
Location: (using avr-gcc in) Finchingfield, Essex, England

Code:
 cRB[i] = ring_retrieve((Ring_t*)&UARTbuf) - 32;

What is the significance of the 32 in that? I know it's the ASCII value for ' ' but I'm not sure why you would be subtracting that from the received characters? If the intention is to turn ASCII digits into 0..9 binary values then you would use
Code:
 cRB[i] = ring_retrieve((Ring_t*)&UARTbuf) - '0';

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Brian Fairchild
PostPosted: Jun 29, 2012 - 11:09 AM
Hangaround


Joined: Oct 18, 2001
Posts: 358
Location: Eastern England.

mewakitty wrote:

I wrote the GUI on the PC. 18 characters is all it will send at a time, 100% of the time.

As Kartman says, that's such a bad assumption. It guarantees an unreliable comms link which precludes any recovery from errors without a reset.
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 29, 2012 - 04:40 PM
Wannabe


Joined: May 28, 2012
Posts: 91


clawson wrote:
Code:
 cRB[i] = ring_retrieve((Ring_t*)&UARTbuf) - 32;

What is the significance of the 32 in that? I know it's the ASCII value for ' ' but I'm not sure why you would be subtracting that from the received characters? If the intention is to turn ASCII digits into 0..9 binary values then you would use
Code:
 cRB[i] = ring_retrieve((Ring_t*)&UARTbuf) - '0';


It's to counteract what I'm doing in my code on the PC. I didn't want to send things like "tab" or "null" through, so I add 32 to every value before I send, and subtract when I receive. Anyway, that's not so important right now and I can deal with this later.

For other stuff, I will look into verification characters or w/e later. Once I get this part working to the extent I'd like (no resetting). While I appreciate the concern and advice, it is quite off topic right now.
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 29, 2012 - 05:36 PM
Wannabe


Joined: May 28, 2012
Posts: 91


New developments:

I found that the TX interrupt fires for some reason if I call USARTWrite within the while loop. I think it might have something to do with atomic being around there and the whole enabling/disabling business. This doesn't happen if I put USARTWrite elsewhere in the code. I wrote an empty ISR and now it doesn't reset. I can just remove the USARTWrite command from that loop (it was for debugging) later on and it should solve the problem.

While scrambling around in the disassembler, I found that it says it can't find "delay_basic.h" and "atomic.h". Which seems bad?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jun 29, 2012 - 05:40 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62281
Location: (using avr-gcc in) Finchingfield, Essex, England

Often a simple solution is to use a FIFOd RXC interrupt for data received by the AVR but just because you do RX by interrupt doesn't mean Tx has to be done by interrupt as well. Often for output it's fine just to sit in a loop doing some kind of polling UART_putchar() function so maybe consider a solution with RXCIE but no TXCIE/UDRIE.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
mewakitty
PostPosted: Jun 29, 2012 - 06:01 PM
Wannabe


Joined: May 28, 2012
Posts: 91


clawson wrote:
Often a simple solution is to use a FIFOd RXC interrupt for data received by the AVR but just because you do RX by interrupt doesn't mean Tx has to be done by interrupt as well. Often for output it's fine just to sit in a loop doing some kind of polling UART_putchar() function so maybe consider a solution with RXCIE but no TXCIE/UDRIE.


I'm not trying to do Tx by interrupt. I don't know why it enables at a certain point in time. I don't think I have it enabled by default:
Code:
UCSR0B = (0 << UDRIE0) | (0 << TXCIE0) | (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);


As I said, nowhere else in my code do I have this problem. Only around where I use ATOMIC.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Jun 29, 2012 - 06:38 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16295
Location: Wormshill, England

There are many RX interrupt example programs. e.g. CodeVision, Procyon, Fleury, Atmel app notes, ...

I suggest that you simply use one of these 'library' implementations. Quite honestly, there are several points to code carefully e.g. array sizes, indices, volatile, atomicity, ...

Once you have gained experience, you can simply add the proven code to each of your projects. Personally, I always suggest using <stdio.h> functions. They can use your primitive interrupt functions. (Now you end up like any PC program --- no missing data)

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
mewakitty
PostPosted: Jun 29, 2012 - 06:55 PM
Wannabe


Joined: May 28, 2012
Posts: 91


Fine.

I was trying to ask advice to learn, and not to go to these external libraries. The perception I'm getting in this forum is that:
a) People like to advise stuff that wasn't asked about (I get it. You're all amazing programmers).
b) Either you learn without asking, or you just face the fact that you will be told to use Arduino, external libraries, or both.

I like learning, and this was my goal. Any turkey can copy a library someone already made and put it in a project. There is no challenge, no opportunity to pick up something new. It works because everyone says it works, not because I wrote it.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Jun 29, 2012 - 07:11 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16295
Location: Wormshill, England

Please do not misunderstand. I am just being honest.

My first UART serial interrupts used the ASM code from a 6502 or 6800 textbook. I have no shame.

This does not mean that you do not follow the algorithm and understand how to write it from scratch. This is why textbooks were invented, and why people disseminate public domain source code.

Having said that I am quite capable of writing code from scratch, I will confess to making errors. Just the same as every other human being.

So I will compare my code with known proven code. In fact, I did exactly that when MY serial code was not working quite right.

So my general advice is to use respected libraries whenever possible. And make improvements / modifications as required. Then perhaps 'my' code will be better / more reliable. After all, the world progresses by building on prior knowledge.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
bobgardner
PostPosted: Jun 29, 2012 - 07:58 PM
10k+ Postman


Joined: Sep 04, 2002
Posts: 21257
Location: Orlando Florida

I just kills me when I work and work and work on something and its getting bigger and uglier and more complicated, then I see how someone else did it, and its smaller, simpler, easier to read. Crap. Ruins my day. Embedded programs is certainly an area where you can start right from a clean screen and type in every line of code that will execute on the microcontroller. If the program messes up, you know who to call.

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits