Mikrocontroller und Digitale Elektronik
›
Thread
Problem mit c Programm ATmega32
J
jan
Gast
06.02.2015 15:15
#4001413
Folgender code funktioniert: 1 while ( 1 )
2 {
3
4 if ( calculateRpm )
5 {
6 if ( rpmTemp > 0 )
7 {
8 //6 steps per revolution
9 //time per tick 32 us
10
11 rpmTemp *= 6 * 32 ; //get periodtime for one revolution
12 //period time in us
13
14 rpmTemp = 10000000 / rpmTemp ;
15 //temp is now 1/10 rpm;
16 rpmTemp *= 60 ;
17 lastRpms [ lastRpmsPos ] = rpmTemp & 0xFFFF ;
18 }
19 else
20 {
21 lastRpms [ lastRpmsPos ] = 0x00 ;
22 }
23
24
25
26 lastRpmsPos ++ ;
27 if ( lastRpmsPos >= lastRpmsSize )
28 {
29 lastRpmsPos = 0 ;
30 }
31
32 tempU32 = 0 ;
33 for ( counter = 0 ; counter < lastRpmsSize ; counter ++ )
34 {
35 tempU32 += lastRpms [ counter ];
36 }
37 rpmAverage = tempU32 / lastRpmsSize ;
38
39 if ( sendRpm == 1 )
40 {
41
42 rpm_to_string ( rpmString , rpmAverage , motor . direction );
43 UART_send_blocking_string ( rpmString );
44
45 sendRpm = 0 ;
46 }
47
48 calculateRpm = 0 ;
49 lockRpm = 0 ;
50 }
51
52 }
In diesem Fall bekomme ich am RS232 Terminal am pc "-0300.0".
jedoch bei dieser Version:
1 int main ( void )
2 {
3 uint32_t tempU32 ;
4 uint8_t counter ;
5
6 init ();
7
8
9
10 while ( 1 )
11 {
12
13 if ( calculateRpm )
14 {
15 if ( rpmTemp > 0 )
16 {
17 //6 steps per revolution
18 //time per tick 32 us
19
20 rpmTemp *= 6 * 32 ; //get periodtime for one revolution
21 //period time in us
22
23 rpmTemp = 10000000 / rpmTemp ;
24 //temp is now 1/10 rpm;
25 rpmTemp *= 60 ;
26 lastRpms [ lastRpmsPos ] = rpmTemp & 0xFFFF ;
27 }
28 else
29 {
30 lastRpms [ lastRpmsPos ] = 0x00 ;
31 }
32
33
34
35 lastRpmsPos ++ ;
36 if ( lastRpmsPos >= lastRpmsSize )
37 {
38 lastRpmsPos = 0 ;
39 }
40
41 tempU32 = 0 ;
42 for ( counter = 0 ; counter < lastRpmsSize ; counter ++ )
43 {
44 tempU32 += lastRpms [ counter ];
45 }
46 rpmAverage = tempU32 / lastRpmsSize ;
47
48 if ( sendRpm == 1 )
49 {
50
51 rpm_to_string ( rpmString , rpmAverage , motor . direction );
52 UART_send_blocking_string ( rpmString );
53
54 sendRpm = 0 ;
55 }
56
57
58 calculateRpm = 0 ;
59 lockRpm = 0 ;
60 }
61 }
62 }
Kommt am Terminal nur -0.000 an. Meine rpm_to_string Funktion und meine
UART_send_blocking_string Funktion funktioniert ja.
Variablen Definitionen (global): 1 volatile uint8_t motorDirection = 0 , motorRPM = 0 ;
2 volatile uint8_t readyToSend = 0 ;
3 volatile uint8_t timer0_overflows = 0 , timer0_overflow_error = 0 ;
4
5 uint32_t rpmTemp = 0 ;
6
7 #define lastRpmsSize 12
8 uint16_t lastRpms [ lastRpmsSize ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
9 uint8_t lastRpmsPos = 0 ;
10 volatile uint16_t rpmAverage ;
11
12 volatile uint8_t calculateRpm = 0 , lockRpm = 0 , sendRpm = 0 ;
13 volatile uint8_t rpmString [ 8 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 };
Versuch jetzt schon seit einer Stunde das Problem zu beheben, doch
leider finde ich keinen Fehler. Ich hoffe ihr könnt mir helfen.
MfG
Jan
PI
Peter II
Gast
06.02.2015 15:19
#4001420
jan schrieb:
> jedoch bei dieser Version:
beide Versionen sind doch gleich? (ich kann zumindest kein unterschied
finden)
J
jan
Gast
06.02.2015 15:25
#4001426
Sry hatte beim zweiten das falsche kopiert.
Das richtige 2. Beispiel:
1 int main ( void )
2 {
3 uint32_t tempU32 ;
4 uint8_t counter ;
5
6 init ();
7
8
9
10 while ( 1 )
11 {
12
13 if ( calculateRpm )
14 {
15 if ( rpmTemp > 0 )
16 {
17 //6 steps per revolution
18 //time per tick 32 us
19
20 rpmTemp *= 6 * 32 ; //get periodtime for one revolution
21 //period time in us
22
23 rpmTemp = 10000000 / rpmTemp ;
24 //temp is now 1/10 rpm;
25 rpmTemp *= 60 ;
26 lastRpms [ lastRpmsPos ] = rpmTemp & 0xFFFF ;
27 }
28 else
29 {
30 lastRpms [ lastRpmsPos ] = 0x00 ;
31 }
32
33
34
35 lastRpmsPos ++ ;
36 if ( lastRpmsPos >= lastRpmsSize )
37 {
38 lastRpmsPos = 0 ;
39 }
40
41 tempU32 = 0 ;
42 for ( counter = 0 ; counter < lastRpmsSize ; counter ++ )
43 {
44 tempU32 += lastRpms [ counter ];
45 }
46 rpmAverage = tempU32 / lastRpmsSize ;
47
48 calculateRpm = 0 ;
49 lockRpm = 0 ;
50 }
51 //sendRpm = 1;
52 if ( sendRpm == 1 )
53 {
54
55 rpm_to_string ( rpmString , rpmAverage , motor . direction );
56 UART_send_blocking_string ( rpmString );
57
58 sendRpm = 0 ;
59 }
60
61 }
62 }
Übrigens: wenn ich das //sendRpm = 1; einkommentiere, bekomm ich auch
die richtigen Werte.
PI
Peter II
Gast
06.02.2015 15:29
#4001429
1 volatile uint8_t calculateRpm = 0 , lockRpm = 0 , sendRpm = 0 ;
2 [ c ]
3 ich bin mir nicht sicher ob das volatile wirklich f ü r alle Variabel gilt .
4
5 schreibe es doch gleich lesbar .
6
7 [ c ]
8 volatile uint8_t calculateRpm = 0 ;
9 volatile uint8_t lockRpm = 0 ;
10 volatile uint8_t sendRpm = 0 ;
hätte sogar den Vorteil da man noch Kommentare für die Variablen
verwenden kann.
J
jan
Gast
06.02.2015 15:36
#4001438
Hab das bei allen Variablen gemacht, brachte keinen Unterschied.
Wie gesagt bei dieser Form funktioniert es ja:
1 int main ( void )
2 {
3 uint32_t tempU32 ;
4 uint8_t counter ;
5
6 init ();
7
8
9
10 while ( 1 )
11 {
12
13 if ( calculateRpm )
14 {
15 .....
16 }
17
18 sendRpm = 1 ;
19 if ( sendRpm == 1 )
20 {
21
22 rpm_to_string ( rpmString , rpmAverage , motor . direction );
23 UART_send_blocking_string ( rpmString );
24
25 sendRpm = 0 ;
26 }
27
28 }
29 }
Deswegen denke ich das der Fehler nicht am volatile liegt.
Zur Sicherheit noch meine Funktionen: 1 #define digit_to_char(digit) '0' + digit
2
3 void rpm_to_string ( volatile uint8_t * string , volatile uint16_t rpms , uint8_t direction )
4 {
5 uint8_t thousands , hundreds , tens , ones , tenths ;
6
7 thousands = rpms / 10000 ;
8 rpms = rpms % 10000 ;
9 hundreds = rpms / 1000 ;
10 rpms = rpms % 1000 ;
11 tens = rpms / 100 ;
12 rpms = rpms % 100 ;
13 ones = rpms / 10 ;
14 rpms = rpms % 10 ;
15 tenths = rpms ;
16
17 if ( direction == 1 )
18 * string = '-' ;
19 else
20 * string = '+' ;
21
22 string ++ ;
23 * string = digit_to_char ( thousands );
24 string ++ ;
25 * string = digit_to_char ( hundreds );
26 string ++ ;
27 * string = digit_to_char ( tens );
28 string ++ ;
29 * string = digit_to_char ( ones );
30 string ++ ;
31 * string = '.' ;
32 string ++ ;
33 * string = digit_to_char ( tenths );
34 string ++ ;
35 * string = 0 ;
36
37 }
38
39 uint8_t UART_send_blocking_string ( volatile uint8_t * data )
40 {
41 if ( UCSRA & ( 1 << UDRE )) //ready to send
42 {
43 while ( 1 )
44 {
45 if ( * data == 0x00 )
46 break ;
47
48 UART_send_blocking ( * data );
49 data ++ ;
50 }
51
52 return UART_success ;
53 }
54
55 return UART_failed ;
56 }
57
58 uint8_t UART_send ( uint8_t data )
59 {
60 if ( UCSRA & ( 1 << UDRE )) //ready to send
61 {
62 UDR = data ;
63 return UART_success ;
64 }
65
66 return UART_failed ;
67 }
Der Unterschied deiner 2 Varianten ist doch folgender:
1. Variante (die wohl geht):
rpm_to_string und UART_send_blocking_string wird nur ausgeführt, wenn
calculateRpm != 0 ist, und damit auch rpmAverage berechnet wurde.
Im 2. Fall hast du rpm_to_string und UART_send_blocking_string
ausserhalb von if(calculateRpm) plaziert, so dass es beim ersten
Durchlauf wohl so ist, dass rpmAverage 0 ist, und dies wird dann auch
auf den UART geschickt.
Wenn doch die 1. Variante geht, warum benutzt du dann nicht einfach
diese?
J
jan
Gast
06.02.2015 15:53
#4001462
Joe F. schrieb:
> Der Unterschied deiner 2 Varianten ist doch folgender:
> 1. Variante (die wohl geht):
> rpm_to_string und UART_send_blocking_string wird nur ausgeführt, wenn
> calculateRpm != 0 ist, und damit auch rpmAverage berechnet wurde.
>
> Im 2. Fall hast du rpm_to_string und UART_send_blocking_string
> ausserhalb von if(calculateRpm) plaziert, so dass es beim ersten
> Durchlauf wohl so ist, dass rpmAverage 0 ist, und dies wird dann auch
> auf den UART geschickt.
>
> Wenn doch die 1. Variante geht, warum benutzt du dann nicht einfach
> diese?
Komischerweise funktioniert der zweite Fall ja wenn ich "if(sendRpm =
1).." oder "sendRpm = 1; if(sendRpm)..." ja, das heist rpmAverage ist
nicht 0....
und ich kann die ersten Variante nicht verwenden weil calculateRpm nur
eins wird wenn ein neuer Wert reinkommt d.h. eine Flanke am encoder...
um Rechenleistung zu sparen. Und ich will ja die die Rpm's ja auch
senden können wenn der Motor steht ;).
Und weiter wird auf rpmAverage nur im main code zugegriffen, daher
wüsste ich nicht warum der Wert auf einmal 0 sein sollte.
Trotzdem Danke schonmal an eure Hilfe!
J
jan
Gast
06.02.2015 16:27
#4001505
So jetzt funktionierts:
1 int main ( void )
2 {
3 uint32_t tempU32 ;
4 uint8_t counter ;
5 uint16_t plsSendMeForGodsSake = 0 ;
6 init ();
7
8
9
10 while ( 1 )
11 {
12
13 if ( calculateRpm )
14 {
15 if ( rpmTemp > 0 )
16 {
17 //6 steps per revolution
18 //time per tick 32 us
19
20 rpmTemp *= 6 * 32 ; //get periodtime for one revolution
21 //period time in us
22
23 rpmTemp = 10000000 / rpmTemp ;
24 //temp is now 1/10 rpm;
25 rpmTemp *= 60 ;
26 lastRpms [ lastRpmsPos ] = rpmTemp & 0xFFFF ;
27 }
28 else
29 {
30 lastRpms [ lastRpmsPos ] = 0x00 ;
31 }
32
33
34
35 lastRpmsPos ++ ;
36 if ( lastRpmsPos >= lastRpmsSize )
37 {
38 lastRpmsPos = 0 ;
39 }
40
41 tempU32 = 0 ;
42 for ( counter = 0 ; counter < lastRpmsSize ; counter ++ )
43 {
44 tempU32 += lastRpms [ counter ];
45 }
46 rpmAverage = tempU32 / lastRpmsSize ;
47 plsSendMeForGodsSake = ( uint16_t ) rpmAverage ;
48 calculateRpm = 0 ;
49 lockRpm = 0 ;
50 }
51
52 //sendRpm = 1;
53 if ( sendRpm )
54 {
55 rpm_to_string (( uint8_t * ) rpmString , plsSendMeForGodsSake , motor . direction );
56 UART_send_blocking_string ( rpmString );
57 sendRpm = 0 ;
58 }
59 }
60 }
aber ich versteh noch immer nicht warum es mit Bsp. 2 nicht funktioniert
hatte.
Vielleicht findet irgendjemand das Problem, würde mich interessieren was
ich falsch hatte.
A
asdfasd
Gast
06.02.2015 23:37
#4002025
Mal davon abgesehen, dass die gesamte Programmlogik ziemlich konfus
aussieht, in dieser Funktion:
1 > uint8_t UART_send_blocking_string ( volatile uint8_t * data )
2 > {
3 > if ( UCSRA & ( 1 << UDRE )) //ready to send
4 > {
5 > while ( 1 )
6 > {
7 > if ( * data == 0x00 )
8 > break ;
9 >
10 > UART_send_blocking ( * data );
11 > data ++ ;
12 > }
13 >
14 > return UART_success ;
15 > }
16 >
17 > return UART_failed ;
18 > }
sieht das "if" falsch und überflüssig aus. Entweder "blocking" oder
nicht. Du scheisst den ganzen String weg, wenn noch ein Byte im
Transmitter ist.
Das volatile ergibt auch keinen Sinn. Übrig bleibt:
1 void UART_send_blocking_string ( uint8_t * data )
2 {
3 while ( * data )
4 UART_send_blocking ( * data ++ );
5 }
PS: Die Richtung solltest du in deinem Moving-Average evtl
mitberücksichtigen...
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
Noch kein Account?
Die Registrierung ist kostenlos und dauert nur eine Minute.
Jetzt registrieren