Moin, ich möchte mit meinem Mega644p ein RC Summensignal auswerten. Dazu habe ich ein paar Fragen. Wie das aussieht und wie ich es auswerten möchte weiß ich bereits, nur bei der Umsetzung haperts noch. Das Summensignal geht immer von Steigender Flanke zu Steigender Flanke, das möchte ich mit einem Interrupt abfragen, aber was ist sinnvoller INT oder PCINT, bzw. wo genau ist der Unterschied? Die einzelnen Signal gehen von 1-2ms, ich brauche die Werte in angaben von 0-255, also müsste der Timer 255 mal pro ms einen Overflow Interrupt haben. Bei Steigender Flanke wird der Timer wieder zurück gesetzt. Dazu wollte ich ihn in einen 8-bit in den "Clear Timer on Compare Match" Modus stellen und einen Overflow bei 72 machen. (F_CPU / Teiler)/ 256 * 1000ms/sekunde). F_CPU = 18.432Mhz Teiler = 8 Habt ihr noch Tipps für mich? Das Programm von ulrich radig kenne ich bereits. MfG Philipp
Hi, @Krapao: Danke, kenn ich aber schon. ich habe jetzt versucht, mich nach dem Code von Thomas Pfeiffer zu richeten. http://thomaspfeifer.net/ppm2usb_adapter.htm Das Problem ist, dass bei start ein paar Messungen durchgeführt werden (die Anzahln varriiert, mal 6, mal 30 usw.) Die Werte sind da auch richtig. Doch dann gehts nich mehr weiter, der Mega hängt sich irgentwie auf oder so. Die Led, auf dem Board ist dann auch an, obwohl sie nur beim Initialiesieren an sein sollte, aber sie ist dunkler, also ob sie schnell ann und aus gemacht wird, oder weniger Spannung bekommt. Hier der Code: Main.c
1 | #define BAUD 115200UL
|
2 | #define F_CPU 18432000UL
|
3 | #include <util/delay.h> |
4 | #include <avr/io.h> |
5 | #include <avr/interrupt.h> |
6 | #include <stdio.h> |
7 | #include <stdlib.h> |
8 | |
9 | #include "ppm.h" |
10 | |
11 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
12 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
|
13 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
|
14 | |
15 | #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
|
16 | #warning Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
|
17 | #endif
|
18 | |
19 | volatile unsigned long long time; |
20 | |
21 | void delay_ms(double t) |
22 | {
|
23 | for(int i=0;i<t;i++) |
24 | {
|
25 | _delay_ms(1); |
26 | }
|
27 | }
|
28 | |
29 | void uart_init(void) |
30 | {
|
31 | //UART0 GPS
|
32 | UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); |
33 | UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00); |
34 | |
35 | UBRR0H = UBRR_VAL >> 8; |
36 | UBRR0L = UBRR_VAL & 0xFF; |
37 | |
38 | //UART1 XBee
|
39 | UCSR1B |= (1<<RXEN1)|(1<<TXEN1);//|(1<<RXCIE1); |
40 | UCSR1C |= (1<<UCSZ11)|(1<<UCSZ10); |
41 | |
42 | UBRR1H = UBRR_VAL >> 8; |
43 | UBRR1L = UBRR_VAL & 0xFF; |
44 | }
|
45 | |
46 | int uart_putc(unsigned char c) |
47 | {
|
48 | while (!(UCSR1A & (1<<UDRE1))) |
49 | ;
|
50 | UDR1 = c; |
51 | return 0; |
52 | }
|
53 | |
54 | void uart_puts (char *s) |
55 | {
|
56 | while (*s) |
57 | {
|
58 | uart_putc(*s); |
59 | s++; |
60 | }
|
61 | }
|
62 | |
63 | int main(void) |
64 | {
|
65 | DDRB = (1<<0); |
66 | PORTB = (1<<0); |
67 | uart_init(); |
68 | ppmInit(); |
69 | sei(); |
70 | PORTB &= ~(1<<0); |
71 | |
72 | while(1) |
73 | {
|
74 | if(ppmNewData==1) |
75 | {
|
76 | ppmNewData = 0; |
77 | unsigned char p[6]; |
78 | for(int i=0;i<6;i++) |
79 | {
|
80 | p[i] = ppmGet(i); |
81 | }
|
82 | char out[255]; |
83 | int n = sprintf(out,"%d, %d, %d, %d, %d, %d\n",p[0],p[1],p[2],p[3],p[4],p[5]); |
84 | for(int i=0;i<n;i++) |
85 | uart_putc(out[i]); |
86 | }
|
87 | }
|
88 | }
|
ppm.h Den code habe ich fast komplett übernommen, nur ein paar Anpassungen gemacht, z.b. den Prescaler auf 64 gesetzt und die Register angepasst.
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #ifndef PPM_H_
|
5 | #define PPM_H_
|
6 | |
7 | extern volatile char ppmNewData; |
8 | void ppmInit(); |
9 | unsigned char ppmGet(int n); |
10 | |
11 | #endif /* PPM_H_ */ |
ppm.c
1 | #include "ppm.h" |
2 | |
3 | #define PPM_CHANNELS (6)
|
4 | volatile unsigned int ppm[PPM_CHANNELS]; |
5 | volatile int chan = -1; |
6 | |
7 | #define T_MIN ((1*F_CPU)/64/1000)
|
8 | #define T_MAX ((2*F_CPU)/64/1000)
|
9 | #define T_OUT ((3*F_CPU)/64/1000)
|
10 | |
11 | volatile char ppmNewData; |
12 | volatile unsigned int timeOld; |
13 | |
14 | |
15 | void ppmInit() |
16 | {
|
17 | TCCR1B = (1<<CS11)|(1<<CS10); //Prescaler 8 |
18 | TCCR1B |= (1<<ICNC1); //Noise canceler |
19 | TCCR1B |= (1<<ICES1); |
20 | TIMSK1 = (1<<ICIE1) | (1<<OCIE1A); |
21 | |
22 | ppmNewData=0; |
23 | chan=-1; |
24 | }
|
25 | |
26 | ISR(TIMER1_COMPA_vect) |
27 | {
|
28 | if(chan!=-1) |
29 | {
|
30 | ppmNewData = 1; |
31 | }
|
32 | chan=-1; |
33 | }
|
34 | |
35 | ISR(TIMER1_CAPT_vect) |
36 | {
|
37 | unsigned int time=ICR1; |
38 | OCR1A=time+T_OUT; |
39 | if (time>timeOld) |
40 | {
|
41 | time=time-timeOld; |
42 | }
|
43 | else
|
44 | {
|
45 | time=time+(0xffff-timeOld)+1; |
46 | }
|
47 | timeOld=ICR1; |
48 | if (chan>=0 && chan<PPM_CHANNELS) |
49 | {
|
50 | ppm[chan]=time; |
51 | }
|
52 | chan++; |
53 | }
|
54 | |
55 | unsigned char ppmGet(int n) { |
56 | unsigned int t=ppm[n]; |
57 | |
58 | // conversion T_MIN...T_MAX -> 0...255
|
59 | if (t<T_MIN) t=T_MIN; |
60 | t-=T_MIN; |
61 | t=t/((T_MAX-T_MIN)/255); |
62 | if (t>255) t=255; |
63 | |
64 | return ((unsigned char)t); |
65 | }
|
Die Verkabelung scheint richtig zu sein, weil die paar Messungen bis zum Ausfhängen richtig sind, außerdem überprüfe ich das Signal laufend mitnem Oszi. Was könnte sein? Manchmal habe ich probleme mit der sei() Funktion, habe auch schon mehrere Positionen im code getestet, geht aber alles nicht. MfG Philipp
> Die Led, auf dem Board ist dann auch an, obwohl sie nur > beim Initialiesieren an sein sollte, aber sie ist dunkler, also ob sie > schnell ann und aus gemacht wird Der AVR scheint sich im Fehlerfall laufend zu resetten. > UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); ^^^^^^^^^^^ Da hast du einen Interrupt eingeschaltet für den ich keine ISR sehe. Wenn der Interrupt dann (bei genug Störungen am offenem Eingang UART0-RXD?) käme, würde das zu einem Reset führen. Soweit ich sehe wird UART0 von dir nicht benutzt. Lass den Teil in uart_init weg.
Ok vielen Dank, es geht. Ich hatte den USART0_RX_vect nur auskommentiert, weil ich ihn für den test mit der Hardware nicht brauchte, jetzt hab ich alles vom UART0 rausgenommen und es geht. MfG Philipp
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.