Fascinating stuff. thanks for your help. I'll start playing around soon :-)
Fascinating stuff. thanks for your help. I'll start playing around soon :-)
« Last post by bdeuell on December 11, 2014, 09:35:15 PM »
First for vibration ... without getting into the details of vibration dynamics and ignoring things such as natural frequencies:
I would be primarily concerned about the vibrations from an unbalanced or poorly designed drivetrain; as your drive shafts, gears, and wheels will be spinning quite fast any misalignment or unbalanced mass will result in high frequency vibrations (as well as many other issues). I recommend taking extra care in the design, manufacture, and assembly of these components to make them as precise as possible.
While vibration from the ground will certainly be present the effects will be lessened by the fact that most of your components will have a relatively low mass. I think you can address this vibration effectively without building a complex suspension system. Firstly using the wheels to adsorb some vibration is a great start. Secondly make sure all components are rigidly mounted (especially the heavier ones). Third use vibration isolating mounts on sensitive components (such as the electronics).
Now the rain protection issue (ingress protection):
I would not plan on any water being nonconductive; I doubt you would count on your computer being able to work in the rain. If you plan on using your robot outside and definitely if you plan on using it in the rain I would recommend some level of protection for your electronics (in particular the circuit boards that have closely spaced IC pins ... less distance for the electrons to travel).
The plastic enclosure on your receiver or even a piece of plexiglass over the electronics will offer some level of protection but if you truly want to operate in the rain i would go a step further. The integrity of any enclosure you build depends on your design and how well it is constructed (so its hard to give you an assessment on its effectiveness). Buying an enclosure might be a simpler option but be aware any modifications you make may impact the integrity of the enclosure. A little reading on Ingress Protection or NEMA ratings might give you some ideas on what level of protection is appropriate for your application.
Try BMP85 or BMP180 is new equivalent.
The compiler knows there are two local variables in the function block called:-
x - who's size is that of an (int *). For ATtinys this may be 8 bit, for other AVRs is probably 16 bit (thats why you need to tell the compiler the mcu !). But lets assume its a 16 bit (2 byte) address.
y - is just a local variable of type 'int' -say 2 bytes.
So it knows their name - but has no idea where in (absolute) memory they will be stored as they are not global. As locals then all the compiler can infer is their offset from the SP - ie they are relative to whatever the SP is - and is indirected via this register(s)
Assume x is at SP+0 and y is at SP+2 then the compiler will produce something like (in very rough pseudo code)
So to summarise: local vars have no 'fixed' address they are only relative to the SP. If in doubt then think of recursion - where a function can call itself but the caller and the callee need their own values of the variables.
I can imagine that y, being statically allocated, always resides in a known address and so the hex file may contain a static reference to itNope - y is 'local' to the function so its address is relative to SP and not fixed. Only global vars have a fixed address and, since they permanently hold onto memory, then you should use as few of them as possible! Global vars, especialy when using an OO lang like C++, are a debugging nightmare - I never use them.
Where do I learn this stuff?- 30 years of writing it ! micro-controllers are just smaller PC's after all. And a heck of a lot of assembler/low level coding, blood, sweat and tears!
A slightly more helpful answer would be: turn off all code optimisations in your compiler (or WebbotLib Studio). Write a very simple program. Compile it. Look at the .lst file which will show the assembly language op-codes. Refer to the Atmel datasheets to understand what the generated instructions are actually doing. Tweak th coe - analyse chnges. Once you ot your head around it - turn on optimisation. You may see that if a variable is never read then all of the code that writes new values to it gets removed - ie whats the point!
Yes, let's assume they are local. I suspect that makes it weirder?
Is this code inside a function? ie are x and y local to the function - I'm guesing that they are ie
Again, this is great. Thanks for all this.
One nagging question I still have and can't quite answer is this:
Let's say that the heap is indeed allocated as you say: two linked lists. Now, if I do this:
int *x = malloc(sizeof(int));
*x = 4;
int y = *x;
x is a new variable, but its name was known at compile time...I'm not even sure how to ask this question, but: what is it that stores the symbols and their addresses? That is, in the third line above, is it hard coded by the compiler where the program should look for the variables x and y? Is it different for variables that are dynamically allocated compared to statically allocated?
I can imagine that y, being statically allocated, always resides in a known address and so the hex file may contain a static reference to it. But x, being dynamic, will have a new memory address that isn't known at compile time. Since the third line above requires the processor to load y and x into registers, what is it that stores this new memory address for x and, more important, how is that indicated at compile-time? Is there some sort of memory space that holds uninitialized pointers that the program then looks up once they are used?
Does that question make any sense?
Oh, and a final question so I stop bugging you :-P Where do you learn all of this? I've been searching for information on the atmel website about this, but all they say is that there is such a thing as the stack and the heap, but not much else. is there a fundamental topic I'm missing that I can go find a good book on?
1) If I never use dynamic memory allocation, then the heap will only store global variables.- Correct
2) All local variables are pushed onto the stacketc. Correct other than
d) The above assumed that no dynamic memory allocation occurred. Magic code will clean up the SP for local vars but if you have dynamically created stuff via malloc(C) or 'new'(C++) then it is up to you to manage its life-cycle and make sure you free/delete it when needed. This dynamic stuff is on the heap - ie consider a function that contains:
3) There is no memory manager on an ATMegaYou are correct. Because of the 'block' nature of local variables/parameters then its like a stack of plates - you push on - and pull off - and the compiler does this for you on the stack. Dynamic allocation on the heap via malloc/calloc/new is way more complex (as I said - it's a book). The implementation is up to the compiler - it nrmally uses a linked list to iterate the used memory blocks and another linked list of previously allocated, but now freed, blocks. You are right in that freeing blocks may create holes. The allocation process will often try to find an existing 'hole' of the required size and then re-use it. But this isn't a simple choice. Say you need 10 new bytes and there is a hole of 12 bytes. Do you grab 10 and leave 2 or do you extend the heap for a fresh 12 bytes. This is all very compiler specific in implementation - and since AVR has no MMC - you can ednd up, over time, with memory fragmentation (just like a hard drive) - ie you need 100 bytes but all you've got is 50 x fragmented blocks of 2 bytes ie 100 bytes in total but not contiguous. This is a very complex issue - and hence why many folk say don't use dynamic allocation on a microcontroller - as the logic to handle it can be bigger than the total flash/code space on the chip!!
I note that Arduino now has a String class that uses dynamic allocation- which IMHO is suicide, as if your prog runs for a long time then it will eventually fail due to fragmentation.
If you want I can describe how a MMU works - ie change from early 8086 chips (no MMU) to newer 80x86 chips (with hardware MM). The 'sad' news is that there is no way (I know of) to achieve the same thing in software other than at O/S hardware level. eg the Java JVM does its own memory allocation and so suffers the exact same frag issue. eg if the JVM needs 100Mb then the host O/S MMU can give it a logical block of 100Mb (which may be mapped all over the place in physical memory) but Java then handles the breakdown (dynamic allocation) of this via software and is therefore subject to fragmentation - and hence you get the Java 'stop the world' events when it cannot honour a new memory allocation. Everything freezes whilst it does a software de-frag to slide all the used RAM together and consolidate the total unused RAM into one block.
Understand your frustration - and whilst I'm a 'guest' to this site just like you are - then a bit of site etiquette may help you to get a response.
If you stand back, without emotion, from your post then it sort of reads as -"I've downloaded something and it doesn't work - please fix - or else".
I know it makes perfect sense to you but it's not very clear to others and hence they will have to invest a load of time to discover all of the stuff that you, alone, probably already know. ie there is a LOT of code on this site.
You've mentioned Atmel Studio 6 - but is it 6.0, 6.1, 6.2? Loads of people on this site don't use Atmel Studio - or may not have the version you are using - and its a humongous download they may not want to spend time on it. They may not even be using Windows and so Atmel Studio is not even an option.
What code have you downloaded, from what page? How do I re-produce your problem?
How did you create it as a project in Atmel Studio? Or is it easier to upload a ZIP of the project with all of your settings ( (probably easiest for everyone else)?
To summarise: the more time/detail you invest in reporting the problem and the quicker it is for others to evaluate/reproduce then the more likely you will receive a response
Wow, that was great! Thanks a lot. I'm starting to realize the authority that the compiler has in these matters (so yes, the next step is to better research compilers).
If I understood all of this correctly, then:
1) If I never use dynamic memory allocation, then the heap will only store global variables.
2) All local variables are pushed onto the stack. The "magic code" you were talking about, I assume, deals with what happens when the "RET" instruction is called, is that right? Is it something like this:
a) Make all local variables
b) run the function appropriately
c) upon encountering a RET instruction...I assume that the program memory contains things like how far to move the stack pointer to get to the return address of the function?
d) The above assumed that no dynamic memory allocation occurred
3) There is no memory manager on an ATMega, so I assume that this is all handled at compile time. This means that dynamic memory allocation *and deallocation* will eventually use up all the memory even though there is still space available in the freed spots on the heap, right? I assume this because of my (perhaps flawed) understanding:
a) malloc makes a new variable
b) dealloc/free frees that memory, but the heap pointer has already moved on
c) if we then malloc a few new variables, the original variable's space is a "hole" in the heap. but there is nothing in the processor telling us that, so it just assumes that the heap is filling up (dealloc did nothing?)
Definitely time to keep reading.