Zeitnehmung für Carrera Bahn

OP #1747833
Lesenswert?

Hallo!

Habe in meine Carrera Bahn zwei Gabellichtschranken eingebaut und
ein MC sendet via Rs232 ein Signal an den PC wenn ein Auto durchfährt.

Ich benutze die beiden Externen Interrupts dafür.

Habt ihr zu diesem Ablauf irgendwelche Bedenken?
Ich frage nach weil der MC manchmal nach einigen Durchfahrten nichts 
mehr sendet, da hilft nur mehr ein Reset.

Vielleicht habt ihr ja ein paar Kommentare und Verbesserungsvorschläge 
zum Code.

Danke
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#include "uart.h"
5

6
#define F_CPU       8000000UL
7

8
extern void init_io(void);
9
void USART_Init( unsigned int baud );
10
void USART_Transmit( unsigned int data );
11
void USART_Receive();
12

13
int x;
14
unsigned char zeichen;
15
unsigned char empfangen;
16
unsigned int c;
17
volatile uint8_t uart_str_complete=0;
18
volatile uint8_t uart_str_count=0;
19
volatile uint8_t uart_timeout=0;
20
volatile char uart_string[10]={'\0'};
21
int spur1=0;
22
int spur2=0;
23
#define UART_BAUD_RATE      9600 
24

25

26
int main(void)
27
{
28
  DDRB=0xFF;
29
  DDRD=0xF2;
30
  GIMSK|=(1<<INT0)|(1<<INT1);
31
  MCUCR|=(1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);
32

33
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
34
  sei();
35

36
  for(x=0;x<3;x++)
37
  {
38
    PORTB|=(1<<PB0);
39
    _delay_ms(200);
40
    PORTB &=~(1<<PB0);
41
    _delay_ms(200);
42
  }
43
  PORTB|=(1<<PB0);
44
  uart_putc('9');
45
  
46
  while(1)
47
    {  
48
    
49
    if (spur1>0)
50
      {
51
        uart_putc('1');
52
        spur1--;
53
      }
54
    if (spur2>0)
55
      {
56
        uart_putc('2');
57
        spur2--;
58
      }
59
    }
60
}
61

62
SIGNAL (SIG_INT0)
63
{
64
    spur1++;
65
}
66
SIGNAL (SIG_INT1)
67
{
68
    spur2++;
69
}
Gast #1748133
Lesenswert?

>Ich benutze die beiden Externen Interrupts dafür.

Sinnfrei. Der Controller lanweilt sich sowieso die ganze Zeit.
Da könntest du ihn auch schlafen legen.
Sollte es wirklich mal so sein, dass beide Lichtschranken exakt 
gleichzeitig ausgelöst werden, wird trotzdem einer der beiden Wagen 
"gewinnen", da es eine Interrupt-Priorität gibt, die einem der beiden 
Eingänge den Vorrang gibt (welche das ist, weiß ich nicht, steht aber im 
Datenblatt).

>Vielleicht habt ihr ja ein paar Kommentare und Verbesserungsvorschläge
>zum Code.

Was willst du mit den Daten, die in Spur1 und Spur2 drin sind machen?
Interessant ist doch die Rundenzeit, oder?
Besserer Ablauf:
Timer mit einer Interrupt-Periode von 1 oder 10ms starten (z.B. 
CTC-Modus).
Bei jedem Interrupt eine Uhr hochzählen und den Zustand der 
Gabellichtschranken überprüfen. Wenn eine unterbrochen wurde, die 
aktuelle Zeit speichern (und an der RS232 ausgeben).
Eine Auflösung einer Tausendstelsekunde sollte auf jeden Fall reichen.
Und das sind bei einer Taktfrequenz von 1MHz schon 1000 Takte...
#1748185
Lesenswert?

Phil Wurglits schrieb:
> STK500-Besitzer schrieb:
>> Was willst du mit den Daten, die in Spur1 und Spur2 drin sind machen?
>
> Die Auswertung und Zeitnehmung erfolgt am PC in Visual Basic.

Auf dem µC wärs genauer.

Erstens hast du die Übertragungszeit nicht drinnen. Was wenn die beiden 
Wagen relativ knapp einfahren, so dass die Messmarke des zweiten auf der 
UART warten muss.
Zum anderen hast du eine nicht wirklich kalkulierbare Verzögerungszeit 
auf dem PC. Windows legt auch schon mal gerne ein Päuschen ein, wenn die 
Festplatte kurz aufgeräumt werden muss.

> Werde einmal die Variable anders definieren...

und mach sie uint8_t. Mehr als 256 Runden wird dein µC sicherlich nie 
hinterherhinken, ehe er seine Messmarke per UART absetzen kann.


Messwerte nimmt man normalerweise so dicht am Geschehen wie möglich.
OP #1748197
Lesenswert?

Karl heinz Buchegger schrieb:
> Auf dem µC wärs genauer.

Da hast du sicher recht - professioneller wär es mit dieser Lösung!

Weiters gibt es ja noch das Problem bei der digitalen Carrera, dass man 
die Spur wechseln kann. Im Training wenn nur ein Auto fährt kein Problem 
aber im Rennen wenn zwei Autos fahren, müsste man noch das Signal von 
der Diode am Auto abfangen - da muss ich mich aber erst näher damit 
beschäftigen.

Habt ihr vielleicht einen Link wo diese Variablendeklerationen mit 
uint8_t und volatile usw. erklärt sind. Das hab ich noch nicht ganz 
gerafft was da die Unterschiede sind.

danke
#1748203
Lesenswert?

Phil Wurglits schrieb:

> Habt ihr vielleicht einen Link wo diese Variablendeklerationen mit
> uint8_t und volatile usw. erklärt sind. Das hab ich noch nicht ganz
> gerafft was da die Unterschiede sind.

Zu volatile gibts hundertausend Links hier im Forum
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Datenaustausch_mit_Interrupt-Routinen

uint8_t    _u_nsigned integer mit 8 Bit
int8_t     signed integer mit 8 Bit
uint16_t   _u_nsigned integer mit 16 Bit
int16_t    signed integer mit 16 Bit

int        wir überlassen es dem Compiler was er nimmt.
           Beim AVR-gcc sind das 16 Bit


Aber: Da der AVR eine 8 Bit Maschine ist
* dauert 16 Bit Bearbeitung länger, weil er sie nicht in einem
  Rutsch machen kann.
* darf eine 16 Bit Operation nicht unterbrochen werden, auch nicht
  von einem Interrupt, der genau auf diese Variable zugreift
  == atomarer Zugriff muss vom Programmierer sicher gestellt werden

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren