mikrocontroller.net

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


Autor: Phil Wurglits (wurglitsphil)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "uart.h"

#define F_CPU       8000000UL

extern void init_io(void);
void USART_Init( unsigned int baud );
void USART_Transmit( unsigned int data );
void USART_Receive();

int x;
unsigned char zeichen;
unsigned char empfangen;
unsigned int c;
volatile uint8_t uart_str_complete=0;
volatile uint8_t uart_str_count=0;
volatile uint8_t uart_timeout=0;
volatile char uart_string[10]={'\0'};
int spur1=0;
int spur2=0;
#define UART_BAUD_RATE      9600 


int main(void)
{
  DDRB=0xFF;
  DDRD=0xF2;
  GIMSK|=(1<<INT0)|(1<<INT1);
  MCUCR|=(1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);

  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
  sei();

  for(x=0;x<3;x++)
  {
    PORTB|=(1<<PB0);
    _delay_ms(200);
    PORTB &=~(1<<PB0);
    _delay_ms(200);
  }
  PORTB|=(1<<PB0);
  uart_putc('9');
  
  while(1)
    {  
    
    if (spur1>0)
      {
        uart_putc('1');
        spur1--;
      }
    if (spur2>0)
      {
        uart_putc('2');
        spur2--;
      }
    }
}

SIGNAL (SIG_INT0)
{
    spur1++;
}
SIGNAL (SIG_INT1)
{
    spur2++;
}

Autor: (tsaG) sneJ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... uart.h in der Glaskugel bestaune ....

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>int spur1=0;
>int spur2=0;

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

Autor: Michael Wittmann (miwitt001)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Phil Wurglits (wurglitsphil)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Phil Wurglits (wurglitsphil)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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-Tu...

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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.