Forum: Mikrocontroller und Digitale Elektronik Summensignal Auswertung (Mega644p)


von Philipp M. (lord-maricek)


Lesenswert?

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

von Krapao (Gast)


Lesenswert?


von Philipp M. (lord-maricek)


Lesenswert?

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

von Krapao (Gast)


Lesenswert?

> 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.

von Philipp M. (lord-maricek)


Lesenswert?

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
Noch kein Account? Hier anmelden.