Forum: Mikrocontroller und Digitale Elektronik Servo-Pulssignalläge messen mit Atmega328p


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von l. w. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo liebes Forum,

ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messen 
und daraufhin LEDs ansteuern. Ich versuche aktuell von der Arduino IDE 
aufs Atmel Studio umzusteigen. In der Arduino IDE gibt es ja die 
PulseIn() Funktion. Jetzt hab ich mal im Internet nach einem Code fürs 
Atmel Studio gesucht und einen gefunden...
1
#define F_CPU 8000000UL    //internal 8MHz
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
6
unsigned long rc_value;
7
8
int main(void)
9
{
10
  DDRD = (0<<PD2); // port pd2 input rc signal
11
  DDRD = (1<<PD6); // port , output led
12
  
13
  //PORTD = (1<<PD6);    //test function led
14
  //char rc_pin_state = (PIND & (1<<PD2)); // read state of pin pd2 , put state variable
15
  
16
  while(1)
17
  {
18
    char rc_pin_state = (PIND & (1<<PD2));
19
    
20
    //timeout zone
21
    unsigned long numloops = 0;
22
    unsigned long maxloops = 500000;
23
    unsigned long width = 0;
24
    // wait previous pulse end
25
    while ( rc_pin_state == 1)
26
    {
27
      rc_pin_state = (PIND & (1<<PD2)); //keep reading pin until changes state
28
      if (numloops++ == maxloops) break;
29
    }
30
    // wait pulse start
31
    while (rc_pin_state == 0)
32
    {
33
      rc_pin_state = (PIND & (1<<PD2)); //keep reading pin until changes state
34
      if (numloops++ == maxloops) break;
35
    }
36
    
37
    // wait pulse stop @ here measuring pulse width = incrementing width value 1 each cycle. atmega328 1 micro second equal 16 cycles.
38
    while (rc_pin_state == 1)
39
    {
40
      rc_pin_state = (PIND & (1<<PD2));
41
      if (numloops++ == maxloops) break;
42
      width++;
43
    }
44
45
    rc_value = width/4;
46
    
47
    
48
    if(rc_value >= 0 && rc_value < 1600)
49
    {
50
      PORTD = (1<<PD6); // turn led on
51
    }
52
    
53
    /*else if(rc_value > 1600 && rc_value < 2200) 
54
    {
55
      PORTD = (0<<PD6); // turn led off
56
    }*/
57
  }
58
}

Hab den Code ausprobiert, aber er funktioniert nicht. Vielleicht kann 
mir da jemand weiterhelfen oder hatte schon mal ein ähnliches Projekt...
Schon mal Danke im Voraus!

von Peter D. (peda)


Bewertung
2 lesenswert
nicht lesenswert
Zählschleifen sind immer Mist, Du hast keinerlei Kontrolle über deren 
reale Laufzeit.
Nimm die Input Capture Funktion.
Und schließe ne UART oder ein LCD zum Anzeigen der Meßwerte an.

von MaWin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
l. w. schrieb:
> Hab den Code ausprobiert, aber er funktioniert nicht

Natürlich nicht.

width sollte man vor dem Zählen mal auf 0 setzen, und ob dein maxloops 
vorher nicht zum break führt weiss man auch nicht.
Wieso width gerade bis 6400 zählen soll weiss auch keiner, einen 
stabilen Bezug zu einem Zeitgeber hat dein Programm ja nicht, hängt ganz 
von den Vompilereinstellungen zu Optimierungen ab.

So geht es also schon mal nicht.

Ob man unbedingt gleich Input Capture mit Interrupts macht, oder einfach 
nur den Timer Zählerregister ausliest um zu erfahren, wie lange etwas 
gedauert hat, ist egal.

von Toxic (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
l. w. schrieb:
> ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messen

siehe Anhang wie man es machen kann.Ist zwar fuer einen Pic aber dies 
umzusetzen auf Atmal uc's sollte kein Problem sein

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
MaWin schrieb:
> Ob man unbedingt gleich Input Capture mit Interrupts macht, oder einfach
> nur den Timer Zählerregister ausliest um zu erfahren, wie lange etwas
> gedauert hat, ist egal.
Ich würde im ersten Anlauf einfach den Eingang pollen, dann den 
Zeitstempel aus dem Timer lesen und eine Differenz berechnen. Etwa so:
1
main ()
2
  char rcpinold, rcpin;
3
  unsigned long risetime, pulsdauer;
4
  :
5
  while(1) {
6
    :
7
    rcpin = (PIND & (1<<PD2));
8
    if (rcpin!=rcpinold) { // Flanke?
9
      if (rcpin) { // steigende Flanke
10
        risetime = lesetimeraus();
11
      }
12
      else {       // fallende Flanke  --> Pulsdauer berechnen
13
        pulsdauer = lesetimeraus() - risteime;
14
      }
15
    }
16
    rcpinold = rcpin;
17
    :
18
  }
19
}
Merke: man setzt einen Zähler nie zurück. Es sei denn, man weiß genau, 
was man da tut und kann die Folgen abschätzen.

Toxic schrieb:
> l. w. schrieb:
>> ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messen
> siehe Anhang wie man es machen kann.I
High-Zeit != Periodendauer   ;-)

: Bearbeitet durch Moderator
von Toxic (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Toxic schrieb:
> siehe Anhang wie man es machen kann.

falsches Bild gepostet...

von MaWin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
MaWin schrieb:
> width

Äh, numloops meinte ich.

von l. w. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Lothar M.

Kannst du mir bei der lesetimeraus() Funktion noch weiterhelfen. Hab mir 
das Datenblatt des ATmega328 jetzt ne Zeit lang angeschaut und auch 
schon ein bisschen herumprobiert aber hab da zu wenig Grundwissen zu 
Timer und Registern, dass ich das hinbekomme. Wahrscheinlich sind es nur 
ein paar Zeilen Code. Vlt kann mir da noch jemand weiterhelfen.

Schon mal danke !

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]
  • [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.

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