Forum: Mikrocontroller und Digitale Elektronik Zeitnehmung für Carrera Bahn


von Phil W. (wurglitsphil)


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
}

von (tsaG) sneJ (Gast)


Lesenswert?

... uart.h in der Glaskugel bestaune ....

von holger (Gast)


Lesenswert?

>int spur1=0;
>int spur2=0;

Alles volatile außer die wichtigen Sachen;)
Und negativ wird deine Spur ja wohl auch nicht, oder?

von Michael W. (miwitt001)


Lesenswert?

spur1 und spur2 muss volatile sein. Außerdem meine ich, dass spur1++ 
kein atomarer Zugriff ist, weil du int verwendest. Dort könnte es 
Probleme geben.

mfg

von holger (Gast)


Lesenswert?

>>int spur1=0;
>>int spur2=0;

>Alles volatile außer die wichtigen Sachen;)
>Und negativ wird deine Spur ja wohl auch nicht, oder?

Und bei unsigned int ATOMAREN Zugriff nicht vergessen.

von STK500-Besitzer (Gast)


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

von Phil W. (wurglitsphil)


Lesenswert?

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.
Es geht wirklich nur darum via RS232 zu senden welche Lichtschranke 
unterbrochen wurde.

Werde einmal die Variable anders definieren...

von Karl H. (kbuchegg)


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.

von Phil W. (wurglitsphil)


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

von Karl H. (kbuchegg)


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

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.