AdrianH
|
| posted on 6/1/10 at 09:26 PM |
|
|
Any Atmel AVR C programmers on here?
A very long shot, but this hobby programmer is getting stuck with his locost based project.
Adrian
Why do I have to make the tools to finish the job? More time then money.
|
|
|
|
|
coozer
|
| posted on 6/1/10 at 09:31 PM |
|
|
? wot u on about eh?
1972 V8 Jago
1980 Z750
|
|
|
MikeR
|
| posted on 6/1/10 at 09:51 PM |
|
|
haven't done c in years, not done atmel - but willing to help out if i can.
|
|
|
Madinventions
|
| posted on 6/1/10 at 09:59 PM |
|
|
I do a lot of PIC and 68B09 C coding...
What's the problem?
Ed.
Mojo build diary: http://www.madinventions.co.uk
Solo music project: Syrrenfor http://www.reverbnation.com/syrrenfor
View my band website:
http://www.shadowlight.org.uk
http://www.eastangliankitcars.co.uk/
|
|
|
Bluemoon
|
| posted on 6/1/10 at 10:17 PM |
|
|
Just started playing but with the simple Arduino boards, worth a look as it's very simple to program, and based on the AVR..
Dan
|
|
|
AdrianH
|
| posted on 6/1/10 at 10:22 PM |
|
|
Long story short.
Sticking an accelerometer chip to an Atmega 168 with LCD.
Uses ADC to read the output from acc'n chip and want to display 'g' in LCD going from - to + depending on brake or accelerating.
Have problem using itoa() function and do not really understand where going wrong in understanding
xacc is value from Analogue to digital, ADC and ranges from 0 to 1023 but in HEX so 0 to 3FF.
Zero g is hapening at 480 or 1E0, around mid range.
When I have 1 g the value is 730, so it increases by 250, when -1 g it drops to 230.
So trying to use the following
int16_t xacc=0, // signed integer value for g
char numstr[4]; // string variable
xacc = ((480-ADC)/25);
itoa(xacc,numstr,10); // convert integer to string
i=0;
while(i<3){
lcd_gotoxy(i,1);
lcd_putc(numstr);
i++;
}
I must be messing up variable types but can never get negative numbers to display correctly or even the maths to work properly.
Being an occasional C user does not help.
Adrian
p.s.
It takes a long time to type this stuff in.
I use Studio 4 and boards from tuxgraphics, it is fun when things work but after trying for two nights and getting no further, I need a push.
Just find many programming forums tend to assume you know C like you know how to walk and can not understand we are not all experts!
pps
No idea why all this italicised text has happened
[Edited on 6-1-10 by AdrianH]
Why do I have to make the tools to finish the job? More time then money.
|
|
|
iank
|
| posted on 6/1/10 at 10:39 PM |
|
|
[quote][i]Originally posted by AdrianH[/i]
Long story short.
Sticking an accelerometer chip to an Atmega 168 with LCD.
Uses ADC to read the output from acc'n chip and want to display 'g' in LCD going from - to + depending on brake or accelerating.
Have problem using itoa() function and do not really understand where going wrong in understanding
xacc is value from Analogue to digital, ADC and ranges from 0 to 1023 but in HEX so 0 to 3FF.
Zero g is hapening at 480 or 1E0, around mid range.
When I have 1 g the value is 730, so it increases by 250, when -1 g it drops to 230.
So trying to use the following
int16_t xacc=0, // signed integer value for g
char numstr[4]; // string variable
xacc = ((480-ADC)/25);
itoa(xacc,numstr,10); // convert integer to string
i=0;
while(i<3){
lcd_gotoxy(i,1);
lcd_putc(numstr[i]);
i++;
}
I must be messing up variable types but can never get negative numbers to display correctly or even the maths to work properly.
Being an occasional C user does not help.
Adrian
p.s.
It takes a long time to type this stuff in.
I use Studio 4 and boards from tuxgraphics, it is fun when things work but after trying for two nights and getting no further, I need a push.
Just find many programming forums tend to assume you know C like you know how to walk and can not understand we are not all experts!
pps
No idea why all this italicised text has happened
[Edited on 6-1-10 by AdrianH] [/quote]
italicised text is due to the [i] in lcd_putc(numstr[i]);
Try [code][/code] tags or switching off BBCode (tickybox at bottom of text entry section.
First thing I'd try is to directly output ADC
i.e.
xacc = ADC;
That way you know if you are getting sensible values from the device.
Does itoa correctly deal with signed 16 bit numbers? It seems to me that the itoa function will be trying to fill your 3 character plus NULL string
with 4/5 characters, all bets are off as to the effects as you're overrunning the string by 2 characters into the next variable on the stack.
Try making the string 8 rather than 4 (powers of 2 work best )
Final edit for now, why are you using a while loop at the end? Seems to be more suited to a for() loop both for readability and to give the compiler
an opportunity for some more optimisation.
[Edited on 6/1/10 by iank]
[Edited on 6/1/10 by iank]
[Edited on 6/1/10 by iank]
[Edited on 6/1/10 by iank]
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
AdrianH
|
| posted on 6/1/10 at 10:53 PM |
|
|
If I use xacc = ADC then the same itoa function.
The display will work going from 230 to 780 depending on which way up the chip is, so know it is all OK with normal integers.
Just after I have done the maths on it strange things happen, not liking negative numbers I think.
Just going to use fixed numbers and forget the ADC to see what result is.
Why I use a particular loop is just lack of knowledge, self training for me tends to mean, if it works use it again until I learn another way
[Edited on 6-1-10 by AdrianH]
Why do I have to make the tools to finish the job? More time then money.
|
|
|
iank
|
| posted on 6/1/10 at 10:57 PM |
|
|
quote: Originally posted by AdrianH
If I use xacc = ADC then the same itoa function.
The display will work going from 230 to 780 depending on which way up the chip is, so know it is all OK with normal integers.
Just after I have done the maths on it strange things happen, not liking negative numbers I thing.
Just going to use fixed numbers and forget the ADC to see what result is.
Try making the string longer as a first step to guarantee you avoid any overruns (unless atoi works differently on AVR targets).
Debugging on microcontrollers can get a bit frustrating as you need to fiddle around to see what's going on but it's very rewarding when
it all comes together.
Sorry for the train of conciousness edits on the above message
Edit: Sorry I'm probably talking tosh as the /25 should knock it down to fewer characters.
[Edited on 6/1/10 by iank]
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
Madinventions
|
| posted on 6/1/10 at 11:04 PM |
|
|
Taking the ADC input as 230, 430 and 730 and the output 'G' as -1,0,+1 then the equation to convert this is:
G = ( 0.003947 * adc ) -1.8289
To get this, I plotted the graph in Excel, then added a trendline and displayed the equation.
I guess you can't use floating point maths? If you could then it'd be a simple case of using this formula and then a function such as
'ftoa' to convert it to an ascii string to print.
If you are stuck with integer maths then you need to convert his formula to integers. Currently, you are defining 'xacc' as an integer so
it will only ever display -1,0,1,2 etc. The usual trick to getting around this is to scale the integer with fixed point math, so you would scale
everything by 100 for 2 decimal places, or 1000 for 3 etc. Basicall this means that you would calculate the G to be '100' when the adc is
730, and you'd display the 100 as 1.00 by inserting a decimal point in the output string. I'll explain more in a moment...
So, to scale the formula to integer math, we do the following:
Original formula:
xacc = ( 0.003947 * adc ) -1.8289
Scale so output is -100, 0, +100
xacc = ( 0.3947 * adc ) -182.89
Instead of multiplying with 0.3947, you could divide by 1/0.3947 which is about 2.53.
xacc = (adc/2.5) - 183
The 2.5 is still not an integer value, so it needs to be scaled too:
xacc = ((adc/5)*2)-183
You can check this all out in Excel - it should work ok...
So we've now got a value for xacc of -100 when adc=230, 0 when adc=430 and +100 when adc=730. It's actually -91, -11, 109 but this is
close enough for what is required.
To display this as -0.91, -0.11 and 1.09 you need to modify the display routine to insert the decimal point in the correct place.
--- CODE ---
int16_t xacc=0, // signed integer value for g
char numstr[8]; // string variable
xacc = ((adc/5)*2)-183;
itoa(xacc,numstr,10); // convert integer to string
if (xacc<0)
{
lcd_gotoxy(0,1);
lcd_putc(numstr[0]); // print '-' symbol
lcd_gotoxy(1,1);
lcd_putc(numstr[1]); // print x.00 value
lcd_gotoxy(2,1);
lcd_putc( '.' ) ; // print decimal point
lcd_gotoxy(3,1);
lcd_putc(numstr[2]); // print 0.x0 value
lcd_gotoxy(4,1);
lcd_putc(numstr[3]); // print 0.0x value
}else{
lcd_gotoxy(0,1);
lcd_putc( ' ' ) ; // print a space for positive numbers (or '+' )
lcd_gotoxy(1,1);
lcd_putc(numstr[0]); // print x.00 value
lcd_gotoxy(2,1);
lcd_putc( '.' ) ; // print decimal point
lcd_gotoxy(3,1);
lcd_putc(numstr[1]); // print 0.x0 value
lcd_gotoxy(4,1);
lcd_putc(numstr[2]); // print 0.0x value
}
--- END OF CODE ---
This all assumes that itoa() converts -100 as "-100" and 100 as "100 ". I've laid the printing routine out line by line
to try and make it easier to follow.
As others have said, I've made the string buffer bigger just in case...
No guarantees this works exactly, but it should point you in the right direction.
Ed.
Mojo build diary: http://www.madinventions.co.uk
Solo music project: Syrrenfor http://www.reverbnation.com/syrrenfor
View my band website:
http://www.shadowlight.org.uk
http://www.eastangliankitcars.co.uk/
|
|
|
MikeR
|
| posted on 6/1/10 at 11:05 PM |
|
|
oooh this takes me back to the days when i had to code without a debugger.....
output each step to the screen so you can see what happens.
atoi definately should handle negatives.
When handling strings in C you've got to be aware all you're doing is copying memory - if you get it wrong you trash lots of memory and
things go bang. Always make sure you're string is one character bigger than you need. Eg if you want to write HELLO - you have 5 characters
therefore you make your string 6 characters. Also - always make sure your string is full of nulls before you do anything with it, memset is one way of
doing this.
|
|
|
AdrianH
|
| posted on 6/1/10 at 11:11 PM |
|
|
As to the number of characters, this was my working!
ADC max possible count is 1023 or 3FF Hex reading for '0 g' is 480. Would like to show eventually from 0.0 to 1.5 g I can add the
decimal point without going to floating maths.
So for 1.5 g the ADC should be a value of around 480 + 250 + 125 = 855.
The maths should get this down to a 2 digit ascii number
as in (855-480)/25 = 15 change to 1.5 g later.
If it was braking and the reading was -1.5 g the ADC should be approx
(105-480)/25 = -15.
So assumed the string length would be a max of 3.
ps
I really need to type responses faster.
Thanks for the input guys keep it comming, just may take me a while to respond as I need to follow it all as well!
So to display '-15' my string length needs to be 4 characters?
It does say that it handles neg numbers.
NOTE, I am not clearing the string before I reuse it!!!
Just used
xacc = ADC
yacc = 0 (Zero)
zacc = -5
Display shows
XACC YACC ZACC
482...0||2...-5||
The . are just to keep the spacing.
But the || must be the termination character and 2 is left over from xacc = ADC.
Does that make sence?
[Edited on 6-1-10 by AdrianH]
[Edited on 6-1-10 by AdrianH]
[Edited on 6-1-10 by AdrianH]
Why do I have to make the tools to finish the job? More time then money.
|
|
|
Madinventions
|
| posted on 6/1/10 at 11:16 PM |
|
|
With these values, the Excel equation becomes:
xacc = (0.04 * adc) - 19.2
Again, modify the ' * 0.04 ' to integer math and you get:
xacc (adc/25) - 19
Ed.
Mojo build diary: http://www.madinventions.co.uk
Solo music project: Syrrenfor http://www.reverbnation.com/syrrenfor
View my band website:
http://www.shadowlight.org.uk
http://www.eastangliankitcars.co.uk/
|
|
|
iank
|
| posted on 6/1/10 at 11:17 PM |
|
|
Just run your algorithm and all seems fine (needed to make a few changes to run on gcc but the code is essentially the same.
Used
#include <stdio.h>
void itoa(short value, char * str, int base)
{
sprintf(str, "%d", value);
}
void gtest(short adc)
{
short xacc=0; // signed integer value for g
char numstr[4]; // string variable
short i;
xacc = ((480-adc)/25);
itoa(xacc,numstr,10); // convert integer to string
i=0;
while(i<3){
// lcd_gotoxy(i,1);
putc(numstr[i], stdout);
i++;
}
}
int main()
{
short xx;
for (xx=230; xx<=720; xx++)
{
gtest(xx);
printf(", ");
}
printf("n");
return 0;
}
Produces this list of numbers
10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3,
-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
-4, -4, -4, -4, -4, -4, -4, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -6, -6, -6, -6, -6,
-6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7,
-7, -7, -7, -7, -7, -7, -7, -7, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -9, -9, -9, -9,
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
Madinventions
|
| posted on 6/1/10 at 11:22 PM |
|
|
Ah...
Change your print routine to exit when numstr [ i ] = 0 (termination character).
[Edited on 6/1/10 by Madinventions]
Mojo build diary: http://www.madinventions.co.uk
Solo music project: Syrrenfor http://www.reverbnation.com/syrrenfor
View my band website:
http://www.shadowlight.org.uk
http://www.eastangliankitcars.co.uk/
|
|
|
rf900rush
|
| posted on 6/1/10 at 11:23 PM |
|
|
Long shot as I,m a novice in Pic's with C.
But is your string length " char numstr[4]; // string variable" not too short?
as for example -1234 has 6 -,1,2,3,4,+end of string.
Found LINKY if it's any help.
As a note when you get it going
I built a 3 axis +/-18, +/-18, +/-30 PIC base version for a Foamie RC plane.
Results had upto 12G peaks.
I thought wow until I plotted them , looks like it was the propeller vibration, causing most of it.
Mark II will have to wait for a while.
Martin
|
|
|
Madinventions
|
| posted on 6/1/10 at 11:24 PM |
|
|
i=0;
while(numstr [ i ] !=0 && i<4)
{
lcd_gotoxy( i, 1) ;
lcd_putc(numstr [ i ] ) ;
i++;
}
Quick and dirty... there's a million ways to do it better!
[Edited on 6/1/10 by Madinventions]
Mojo build diary: http://www.madinventions.co.uk
Solo music project: Syrrenfor http://www.reverbnation.com/syrrenfor
View my band website:
http://www.shadowlight.org.uk
http://www.eastangliankitcars.co.uk/
|
|
|
iank
|
| posted on 6/1/10 at 11:26 PM |
|
|
quote: Originally posted by Madinventions
Ah...
Change your print routine to exit when numstr = 0 (termination character).
Good point, well made, but that just prevents garbage characters, doesn't affect the failure to print '-' signs or correct values
(unless it corrupts the LCD in a very strange way)
I suspect the itoa function...
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
iank
|
| posted on 6/1/10 at 11:32 PM |
|
|
quote: Originally posted by Madinventions
i=0;
while(numstr [ i ] !=0 && i<4)
{
lcd_gotoxy( i, 1) ;
lcd_putc(numstr [ i ] ) ;
i++;
}
Quick and dirty... there's a million ways to do it better!
[Edited on 6/1/10 by Madinventions]
Indeed if itoa() is guaranteed to put a NULL in the right place you can just do
i=0;
while(numstr [ i ])
{
lcd_gotoxy( i, 1) ;
lcd_putc(numstr [ i ] ) ;
i++;
}
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
Madinventions
|
| posted on 6/1/10 at 11:35 PM |
|
|
Just used
xacc = ADC
yacc = 0 (Zero)
zacc = -5
Display shows
XACC YACC ZACC
482...0||2...-5||
Does this mean that the xacc=482 showed 482, yacc=0 showed 0||2, and zacc=-5 showed -5|| ? If so then stopping when the null terminator is detected
will get rid of the || on the display and the extra '2' in the yacc example.
Adrian - can you confirm this?
Ed.
I wish I could type faster...!
Edit to say: I'm not sure if you can guarantee itoa() to put the null terminator in the right position. In my experience, -15 will convert to
"-15<null>' (null in pos 3)and +15 will convert to "15<null>" (null in pos 2) so it is different for positive and
negative values, let alone single digit values where the null is in position 1 for positive and position 2 for negative.
I added the ' && i<4' part as a safeguard just in case there is ever a case when the buffer overruns or the itoa() function has
a wobbly moment. It's not strictly necessary but it's standard code practice in the line of work I do to make sure every event is
covered. It makes for robust code if nothing else.
Ed.
[Edited on 6/1/10 by Madinventions]
[Edited on 6/1/10 by Madinventions]
Mojo build diary: http://www.madinventions.co.uk
Solo music project: Syrrenfor http://www.reverbnation.com/syrrenfor
View my band website:
http://www.shadowlight.org.uk
http://www.eastangliankitcars.co.uk/
|
|
|
iank
|
| posted on 6/1/10 at 11:39 PM |
|
|
quote: Originally posted by Madinventions
Just used
xacc = ADC
yacc = 0 (Zero)
zacc = -5
Display shows
XACC YACC ZACC
482...0||2...-5||
Does this mean that the xacc=482 showed 482, yacc=0 showed 0||2, and zacc=-5 showed -5|| ? If so then stopping when the null terminator is detected
will get rid of the || on the display and the extra '2' in the yacc example.
Adrian - can you confirm this?
Ed.
I wish I could type faster...!
Think you've got it.
Probably trying to display
4 0 -5
but junk from the stack (in the string memory space) is getting printed out.
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
AdrianH
|
| posted on 6/1/10 at 11:40 PM |
|
|
Madinventions
Using ADC/25-19
will display from 10 to -10, still have the issue with the || symbol, but this is a later task.
Still finding it strange, when I have defined xacc as a signed 16 bit interger should it not have a range from - 32767 to + 32767 ?
So still not understanding why (ADC-480)/25 would not work when ADC/25 - 19 does????
I tried at one point ((ADC-480)*5)/2 at one point to get 100 range.
I need to read these replies for a bit longer.
This would have been an ideal thread for the chat room.
So
Why do I have to make the tools to finish the job? More time then money.
|
|
|
AdrianH
|
| posted on 6/1/10 at 11:44 PM |
|
|
How do I cope with the variable null position?
Or changing null position even
[Edited on 6-1-10 by AdrianH]
Why do I have to make the tools to finish the job? More time then money.
|
|
|
iank
|
| posted on 6/1/10 at 11:47 PM |
|
|
quote: Originally posted by AdrianH
Madinventions
Using ADC/25-19
will display from 10 to -10, still have the issue with the || symbol, but this is a later task.
If the fragment I posted doesn't work then force all the string values to zero
( numstr[0]=0; numstr[1]=0; numstr[2]=0; numstr[3]=0; ugly but usually quicker than any other way)
quote:
Still finding it strange, when I have defined xacc as a signed 16 bit interger should it not have a range from - 32767 to + 32767 ?
Yes it does
quote:
So still not understanding why (ADC-480)/25 would not work when ADC/25 - 19 does????
I tried at one point ((ADC-480)*5)/2 at one point to get 100 range.
I need to read these replies for a bit longer.
This would have been an ideal thread for the chat room.
So
--
Never argue with an idiot. They drag you down to their level, then beat you with experience.
Anonymous
|
|
|
AdrianH
|
| posted on 6/1/10 at 11:47 PM |
|
|
I have got to add that the members on this board really do blow my mind as to the varied knowledge that is on here.
Why do I have to make the tools to finish the job? More time then money.
|
|
|
|