Forum: Mikrocontroller und Digitale Elektronik Mit Impuls schalten


von Sefco (Gast)


Lesenswert?

Hallo zusammen!

Ich würde gerne, ganz einfach mit einem Spannungsimpuls eine Led 
blinkend schalten, und wenn dieser Impuls nochmal angelegt wird, dann so 
die LED wieder aufhören zu blinken. (Atmega 8)
Die Forensuche hat leider nicht geholfen. Ich habe schon viele C Codes 
kopiert und versucht auf mein Problem umzuschreiben aber es gelingt mir 
einfach nicht. Die meinsten Beispielprojekte sind mit zwei Tastern und 
ohne blinkende LEDs.

Ich hoffe das meine Frage verständlich formuliert ist und hoffe auf 
schnelle Antwort.

Schönen Gruß & Danke!!!

von Harald Wilhelms (Gast)


Lesenswert?

Sefco schrieb:
> Hallo zusammen!
>
> Ich würde gerne, ganz einfach mit einem Spannungsimpuls eine Led
> blinkend schalten, und wenn dieser Impuls nochmal angelegt wird, dann so
> die LED wieder aufhören zu blinken. (Atmega 8)
> Die Forensuche hat leider nicht geholfen. Ich habe schon viele C Codes
> kopiert und versucht auf mein Problem umzuschreiben aber es gelingt mir
> einfach nicht. Die meinsten Beispielprojekte sind mit zwei Tastern und
> ohne blinkende LEDs.
>
> Ich hoffe das meine Frage verständlich formuliert ist und hoffe auf
> schnelle Antwort.
>
> Schönen Gruß & Danke!!!

Meinst Du ein Stromstossrelais plus Blinkled, oder muss es
unbedingt ein uC Progranmm sein?
Gruss
Harald

von Peter II (Gast)


Lesenswert?

dann zeigt doch mal was du bis jetzt hast - aber da diese aufgabe recht 
überschaubar ist, würde ich sagen du fängst bei 0 an und kopierst nichts 
aus dem netzt - dann lernt man etwas.

Impuls erkennen -> (wenn timer aktiv -> timer abschalten)
                   (wenn timer abgeschalter-> aktivieren)

von Sefco (Gast)


Lesenswert?

Hey!

Ich möchte nüchtern ausgedrückt mit dem uC ein Haftrelais ersetzten.

while (1)
{
Impuls an PD2: Led blinkt
Impuls an PD2: Led hört auf
}

Das bräuchte ich dringend. Und das würde ich gerne mit nem uC machen 
weil ich den halt hier habe. C Code wäre am besten.

Gruß!

von Tip (Gast)


Lesenswert?

Fang mit einem kleinen Programm an, das einfach nur eine LED blinken 
läßt.

von Ano N. (oorim)


Lesenswert?

1
/* Pseudo, aber sowas von Pseudo Code */
2
if(impuls&&!blinken)
3
blinken=1
4
else if(impuls&&blinken)
5
blinken = 0
6
(else /* Unnötig */
7
asm(" nop");
8
)
9
ISR(timer)
10
if(blinken)
11
led^=1

Musst dir ja nur merken ob die LED schon blinkt oder nicht. Blinkt sie, 
schalteste das Blinken uas, Blinkt sie nicht schaltest du das Blinken 
ein.

von Sefco (Gast)


Lesenswert?

@ Peter II

Das Problem ist, dass ich wenn ich bei 0 anfange, das gesammte Tut lesen 
muss. Ich habe leider momentan nicht so viel Zeit dafür. Wenn ich nen 
Code hätte, dann könnte ich es mir daran schneller erklären. Das hätte 
ich hier zusammenkopiert:


#include <stdlib.h>
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>                  // definiert _delay_ms()

#define delay_us(us)  _delay_loop_2 (((F_CPU/4000)*us)/1000)    // 
wartet µs


void delay_ms(int ms)                        // wartet ms Millisekunden
{
  int t;
  for(t=0; t<=ms; t++)
  _delay_ms(1);
}


unsigned int on=0; //Varibale zum Schalten des Blinkers


ISR(INT0_vect) //Die Interruptroutine. Kein ";" dahinter sonst 
Fehlermeldung beim Compilieren!
        // INT0_vect ist der Interruptvektor.

{

  if(on==0)
  {
    on=1;
  } else
  {
    on=0;
  }

}


int main (void)

{



  DDRD &= ~(1<<DDD2); //setzt PD2 (INT0) auf Eingang

  DDRB |= (1<<PB1); //setzt PB1 auf Ausgang. Hier ist eine LED 
angschlossen.


  MCUCR |= (1<<ISC01) | (1<<ISC00); //(Ausloesen des Interrupts bei 
steigende Flanke an INT0)

  GICR |= (1<<INT0); //Aktiviert den Pin PD2 (INT0) und den Pin PD3 
(INT1) des Atmega8

  sei(); //einschalten der Interrupts. Setzt das Global Interrupt Enable 
Bit im Status Register.

  while(1)
  {

    if (on==1)
     {
      PORTB = PINB ^ ( 1 << PB0 );    // LED an PB0 umschalten
      delay_ms (800);
     }


  }

  return 0;
}

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Das Problem ist, dass ich wenn ich bei 0 anfange, das gesammte Tut lesen
> muss. Ich habe leider momentan nicht so viel Zeit dafür.
du hast bestimmt schon mehr zeit mit testen verbracht als wenn du bei 
den Grundlagen angefangen hättest.

> ISR(INT0_vect) //Die Interruptroutine. Kein ";" dahinter sonst
> Fehlermeldung beim Compilieren!

wenn ich das schon lesen, dann sollest du dir erstmal C lernen und dich 
dann zu einen µC vorarbeiten.

von Sefco (Gast)


Lesenswert?

Ich kann C.
Wie gesagt, dass ist kopiert, denn Kommentar habe ich nicht geschrieben.

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Ich kann C.

dann schreibt man sotwas nicht:
//Die Interruptroutine. Kein ";" dahinter sonst
> Fehlermeldung beim Compilieren!

von Sefco (Gast)


Lesenswert?

Hast du gelesen was ich geschrieben habe?

Ich sags dir gerne nochmal: Ich habe das nicht geschrieben, dass ist 
kopiert aus einem Tutorial.

Ich weiß sehr wohl, dass bei Funktionen ein ";" nichts zu suchen hat, 
sondern Funktionen mit { und } begonnen und beendet werden.

Willst du mir jetzt helfen oder weiter motzen?♠

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> willst du mir jetzt helfen oder weiter motzen?♠
wenn du jetzt noch sagst wo das Problem mit dem code ist könnte man 
eventuell doch helfen.

Was geht und was geht nicht?

von Sefco (Gast)


Lesenswert?

Das Problem ist, dass die LED einfach aus ist.

Sie ist mit Minus an PB0 angeschlossen und über einen Widerstand an +5V.
Ich habe mir dann das Kabel von meinem Multimeter mit der Messspitze 
genommen, ins Netzteil eingesteckt was den uC versorgt und an PD2 kurz 
gehalten.

Passiert einfach nix. Led bleibt aus.

Der Code stimmt soweit?

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Der Code stimmt soweit?

PORTB = PINB ^ ( 1 << PB0 );

das sieht mir ein wenig merkwürdig aus.

teste mal mit:

PORTB = PORTB ^ ( 1 << PB0 );

von Sefco (Gast)


Lesenswert?

Hatte noch was falsch. Hab die LED an PB0, also sollte ich auch

DDRB |= (1<<PB0);

machen.

LED ist dauerhaft an. Sonst passiert nichts.

von Sefco (Gast)


Lesenswert?

Sobald ich hier das schreibe:
...
unsigned int on=0;
...

  while(1)
  {
    if (on==0)
    {
      PORTB = PORTB ^ ( 1 << PB0 );    // LED an PB0 umschalten
      delay_ms (700);
    }

  }

blinkt die LED.



Sobald ich

...
unsigned int on=0;
...
  while(1)
  {
    if (on==1)
    {
      PORTB = PORTB ^ ( 1 << PB0 );    // LED an PB0 umschalten
      delay_ms (700);
    }

  }

leuchtet die LED dauerhaft.

Komisch?!

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Komisch?!

leider kannst du ja in den code nicht beeinflussen welchen status die 
LED hat wenn der Impuls erkannt wird. Sie blinkt zwar nicht mehr, bleibt 
aber im letzen Status.

teste doch erstmal den input.

while(1)
  {
    if ( PIND & (1<<PD2) )
    {
      PORTB = PORTB ^ ( 1 << PB0 );    // LED an PB0 umschalten
      delay_ms (700);
    }

  }

jetzt sollte die LED nur blinken wenn die an PD2 den high pegel hast. Du 
solltest ein definierten pegel an PD2 haben, etweder den Pull-UP 
aktivieren oder mit einem Pull-down auf masse legen - ein offener 
eingang kann 0 oder 1 sein!

von Sefco (Gast)


Lesenswert?

Peter II schrieb:
> Du
> solltest ein definierten pegel an PD2 haben, etweder den Pull-UP
> aktivieren oder mit einem Pull-down auf masse legen - ein offener
> eingang kann 0 oder 1 sein!

Das musst du mir bitte nochmal erklären.

Habe das gemacht was du gesagt hast: Nach dem schreiben in den 
Controller leuchtet die LED dauerhaft. Wenn ich den Impuls auf PD2 gebe, 
dann blinkt die LED ca 4 oder 5 mal und bleibt dann aus. Gebe ich den 
Impuls nochmal, blinkt sie wieder ein paar mal und bleibt dauer an. Und 
dann wieder von vorne.

Wieso blinkt die denn jetzt ein paar mal? Versteh ich nich so ganz.

von Sefco (Gast)


Lesenswert?

Genau genommen blinkt sie 3 mal.

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Wieso blinkt die denn jetzt ein paar mal? Versteh ich nich so ganz.

wenn du nichts an dem eingang angeschlossen hast, dann hast du weder 1 
noch 0 sondern das eingang inst undefiniert.

sorge also erstmal dafür das der Eingang immer auf Low oder High ist 
(interner PullUP oder externen PullDown)

von Sefco (Gast)


Lesenswert?

Wunderbar! Jetzt habe ich über 10k PD2 auf Masse gelegt und wenn ich 
Pulse, dann geht die LED an, und wenn ich wieder pulse geht sie aus. 
Schonmal super!

Wie bekommen wir das jetzt mit dem blinken hin?
Kannst du mir erklären, wass genau     if ( PIND & (1<<PD2) )
bedeutet?

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Kannst du mir erklären, wass genau     if ( PIND & (1<<PD2) )
> bedeutet?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Eing.C3.A4nge_.28Wie_kommen_Signale_in_den_.C2.B5C.29

das mit dem Puls wird ein wenig zufallen sein, halte doch mal länger den 
High pegel dann sollte dir auch klar sein was genau passiert.

von Sefco (Gast)


Lesenswert?

OK, das habe ich verstanden. Ich weiß jetzt aber leider immer noch nicht 
genau, wie ich das realisieren soll, was ich gerne hätte.
Wenn ich da richtig verstanden habe, dann hat  if ( PIND & (1<<PD2) ) ja 
garnichts mit Interrupts zutun, sondern ich lese hier nur den Port. Für 
mein Problem muss ich aber halt irgendwie Interrupts einbinden.

Das hier:
ISR(INT0_vect) //Die Interruptroutine. Kein ";" dahinter sonst 
Fehlermeldung beim Compilieren!
        // INT0_vect ist der Interruptvektor.

{

  if(on==0)
  {
    on=1;
  } else
  {
    on=0;
  }

}

Wird doch ausgeführt, wenn an PD2 eine 1 liegt, richtig?

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Wird doch ausgeführt, wenn an PD2 eine 1 liegt, richtig?

das ist abhängig von der Registern.

//(Ausloesen des Interrupts bei steigende Flanke an INT0)
MCUCR |= (1<<ISC01) | (1<<ISC00);

//Aktiviert den Pin PD2 (INT0) und den Pin PD3 (INT1) des Atmega8
GICR |= (1<<INT0);

schau doch mal im Datenblatt nach was du einschaltest - wenn die 
kommentare passen das müsste der Interupt bei jeder Steigenenden Flanke 
ausgelöst werden.

Hier ist aber das nächste Problem:

unsigned int on=0; //Varibale zum Schalten des Blinkers

der compiler weiss nichts davon das du die variable im interupt änderst, 
damit wird sie wegoptimiert und auserdem ist es eine ganz schöne 
verschwendung wenn du ein int für 1bit brauchst.

volatil uint8_t on = 0;

von Sefco (Gast)


Lesenswert?

Ich finds echt klasse, dass du mir so hilfst, aber sag mir doch bitte 
einfach wies geht. Zu jedem deiner Posts kommen mir wieder zich Fragen 
hoch. Z.b. wieso weiß der Compiler nichts davon das ich die Variable im 
Interrupt änder?
Sag mir bitte bitte bitte^^ einfach wies geht :P

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> einfach wies geht :P

steht doch da, lesen musst du schon selbst:

volatil uint8_t on = 0;

von Sefco (Gast)


Lesenswert?

on ist jetzt in jeder Funktion unbekannt?!

von Peter II (Gast)


Lesenswert?


von Sefco (Gast)


Lesenswert?

Könntest du den gesammten Quelltext mal bitte korrekt aufschreiben?
Ich habe die Variable on extra global definiert aber jetzt ist sie 
überall unbekannt.

von Peter II (Gast)


Lesenswert?

Peter II schrieb:
> #include <stdint.h>

Sefco schrieb:
> Könntest du den gesammten Quelltext mal bitte korrekt aufschreiben?

hast du auch das include hinzugefügt? Was kommen denn sonst noch für 
warnungen - hast du warnungen überhaupt eingeschlatet?

Ich dachte du kannst C?

von Sefco (Gast)


Lesenswert?

Auch durch includieren klappts nich. Schreibs bitte mal richtig auf 
hier.

von Peter II (Gast)


Lesenswert?

ich habe hier weder einen compiler noch eine etwicklungsumgebung. Nur 
aus dem Kopf bekomme ich es auch nicht sofort hin.

Welche Warnungen/Fehler bekommt du denn?

von Sefco (Gast)


Lesenswert?

#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <stdint.h>                      // definiert _delay_ms()

#define delay_us(us)  _delay_loop_2 (((F_CPU/4000)*us)/1000)    // 
wartet µs


void delay_ms(int ms)                        // wartet ms Millisekunden
{
  int t;
  for(t=0; t<=ms; t++)
  _delay_ms(1);
}

volatil uint8_t on = 0 //Varibale zum Schalten des Blinkers


ISR(INT0_vect) //Die Interruptroutine
         // INT0_vect ist der Interruptvektor.

{

  if(on==0)
  {
    on=1;
  } else
  {
    on=0;
  }

}

int main (void)

{

  DDRD &= ~(1<<DDD2); //setzt PD2 (INT0) auf Eingang
  DDRB |= (1<<PB0); //setzt PB1 auf Ausgang. Hier ist eine LED 
angschlossen.

  MCUCR |= (1<<ISC01) | (1<<ISC00); //(Ausloesen des Interrupts bei 
steigende Flanke an INT0)

  GICR |= (1<<INT0); //Aktiviert den Pin PD2 (INT0)

  sei(); //einschalten der Interrupts. Setzt das Global Interrupt Enable 
Bit im Status Register.



while(1)
  {
    //if ( PIND & (1<<PD2) )
  if (on==1)
    {
      PORTB = PORTB ^ ( 1 << PB0 );    // LED an PB0 umschalten
      delay_ms (700);
    }

  }

  return 0;
}


Fehler:
../Interrupt.c:20: error: expected '=', ',', ';', 'asm' or 
'__attribute__' before 'uint8_t'
../Interrupt.c: In function '__vector_1':
../Interrupt.c:28: error: 'on' undeclared (first use in this function)
../Interrupt.c:28: error: (Each undeclared identifier is reported only 
once
../Interrupt.c:28: error: for each function it appears in.)
../Interrupt.c: In function 'main':
../Interrupt.c:56: error: 'on' undeclared (first use in this function)

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> volatil -> volatile

ein bisschen selber mitmachen könntest du ja auch ...

von Sefco (Gast)


Lesenswert?

Entschuldige bitte das ich diesen Datentyp in einem Semester C nicht 
gelernt habe^^ Noch nie gehört dieses Wort.

Das klappt jetzt, aber nicht besonders gut. Ab und an bleibt die LED 
einfach ganz an oder ganz aus. Und ich habe das Gefühl ich muss immer ne 
kleine Pause machen zwischen dem Pulsen weil der uC sonst durcheinander 
kommt.
Teilweise blinkt er auch einfach weiter...

?

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> nd ich habe das Gefühl ich muss immer ne
> kleine Pause machen zwischen dem Pulsen weil der uC sonst durcheinander
> kommt.

nein, genau im gegenteil - wenn du dein draht an den Pin drück, dann 
bekommt der µC bestimmt 100 impulste oder auch 99.

aber zum glück gibt es ja auch hier wieder eine genau anleitung
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#.28Tasten-.29Entprellung

von Peter II (Gast)


Lesenswert?


von Sefco (Gast)


Lesenswert?

Ach das ist also entprellen....danke =)

Habe da schon einiges drüber gelesen aber den Link den du gepostet hast 
habe ich noch nicht gefunden.

von Sefco (Gast)


Lesenswert?

Ich beabsichtige, den Controller in einem RC Auto einzusetzen. Ich habe 
mir da mal durchgelesen, wie das Signal vom Empfänger an ein Servo 
aussieht. Das sollte doch perfekt sein für einen uC. Muss ich da 
eigentlich noch entprellen?

von Peter II (Gast)


Lesenswert?

Sefco schrieb:
> Ich beabsichtige, den Controller in einem RC Auto einzusetzen. Ich habe
> mir da mal durchgelesen, wie das Signal vom Empfänger an ein Servo
> aussieht. Das sollte doch perfekt sein für einen uC. Muss ich da
> eigentlich noch entprellen?

aber den dem Anschluss für ein Servo kommen sehr viel impulse pro 
sekunden, selbst wenn der Servo sich nicht bewegt. Und ja dafür 
bräuchtest du nichts entprellen.

von Sefco (Gast)


Lesenswert?

Ich will den Blinker von meinem RC Auto schalten, indem ich den Hebel an 
der Fernbedienung einfach einmal hoch mache und wieder zurück flitschen 
lasse.
Da kommen dann also sehr viele Impulse an...

Das heißt der uC macht den Blinker sehr oft an und aus und ich kann 
nicht garantieren, dass der Blinker dann auch angeht. Wie könnte ich das 
Problem lösen?

von Peter II (Gast)


Lesenswert?

du musst einen Programm erweitern.

als 1. Muss du erstmal die impule unterscheiden zwischen hebel unten und 
hebel oben. (Das sind aber nich bloss 3 code zeilen!)

als nächstes muss du nur übewachen ob er voher oben und jetzt unten ist 
und dann deinen Blinker umschalten.

von Tip (Gast)


Lesenswert?

Auf der Servo-Steuerleitung kommen so um die 50 Impulse pro Sekunde, 
unabhängig von der Stellung. Es ändert sich die Länge der Pulse.

von Sefco (Gast)


Lesenswert?

Oh Gott...wie soll ich das nur machen?
Eigentlich hab ich mir das so gedacht:

Hebel Hoch: Blinker links an.
Hebel Hoch: Blinker links wieder aus.

Hebel Runter: Blinker rechts an.
Hebel Runter: Blinker recht wieder aus.

von Karl H. (kbuchegg)


Lesenswert?

Sefco schrieb:
> Oh Gott...wie soll ich das nur machen?

Indem du die Grundlagen lernst

> Eigentlich hab ich mir das so gedacht:

Denken kann man vieles.
Aber in der Praxis funktionieren nun mal die Dinge ein klein wenig 
komplizierter als man das naiver Weise annimmt.

>
> Hebel Hoch: Blinker links an.
> Hebel Hoch: Blinker links wieder aus.
>
> Hebel Runter: Blinker rechts an.
> Hebel Runter: Blinker recht wieder aus.

Ist alles machbar. Nur halt nicht so einfach wie du dir das vorstellst. 
Denn: Was du die ganze Zeit verschwiegen hast (*): Zwischen Hebel und 
Blinker sitzt bei dir noch eine Fernsteuerungsstrecke. Der Auswertung 
ist es egal, ob du da einen Hebel hast oder nicht. Die bekommt 
Fernsteuerimpulse und muss die auswerten. Ob du an deinem Sender da 
einen Schalter, einen Taster, ein Drehrad oder einen Kreuzknüppel hast, 
ist der Auswertung völlig wurscht. Die sieht nur die Pulse, die sie vom 
Fernsteuerempfänger bekommt.
Und die müssen zunächst mal ausgewertet werden, denn in in der Pulslänge 
steckt die Information, in welcher Stellung sich der Schalter auf deiner 
Fernsteuerung befindet. Und erst dann kann man sich darüber unterhalten, 
wie man die Schalterstellungen bzw. den Wechsel dieser (der sich in den 
Pulsen versteckt) so auswertet, dass dein Blinker entsteht.


Alles in allem würde ich sagen, in 3 bis 4 Monaten fleissigem lernens 
bist du soweit, dass du über dein eigentlich zu lösendes Problem 
erstmals nachdenken kannst. In der Zwischenzeit heißt es: Grundlagen 
lernen.

AVR-Tutorial
AVR-GCC-Tutorial


(*) und genau das was du die ganze Zeit verschwiegen hast, nämlich das 
das über eine Fernsteuerung läuft, das ist der eigentliche Knackpunkt an 
der ganzen Geschichte. Das ist der komplizierte Teil. Den Blinker an die 
Pulslängen (wenn man sie einmal hat) zu koppeln ist der Pipifax Teil in 
deinem Projekt.

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.