Forum: Compiler & IDEs Nicht nachvollziehbarer Stopp des Programms (Arduino UNO)


von Simon K. (simon_k96)


Lesenswert?

Hallo Community!

Ich bin gerade dabei eine Entfernungsmessung mit 2 Ultraschallsensoren
(HC-SR04) zu programmieren. Das Ziel ist es zurzeit noch, dass wenn 
einer der beiden Ultraschallsensoren etwas erkennt, das näher als 10cm 
ist, soll der angeschlossene DC-Motor stoppen, sonst soll er sich ganz 
normal drehen.
Das funktioniert soweit auch ganz gut, nur wenn ich jetzt einen 
Standard-Servo  in das Programm integriere und auch am Arduino UNO 
anschließe, stoppt das Programm und führt keinen Schritt mehr durch. Es 
handelt sich hier nur um diese 4 Zeilen:
1
Servo myservo;  // create servo object to control a servo 
2
int lenken = 0;
3
4
myservo.attach(10);  // attaches the servo on pin 3 to the servo object
5
myservo.write(100);  // attaches the servo on position 100(middle)
Ich habe sonst noch keinen weiteren Code für den Servo eingefügt.

Ich würde mich sehr über Hilfe oder Lösungsvorschlage dazu freuen.
mfg Simon K.


Code:
1
#include <TimerOne.h>
2
#include <Ultrasonic.h>
3
#include <Servo.h> 
4
5
6
#define TRIGGER_PIN  7
7
#define ECHO_PIN     6
8
#define TRIGGER_PIN1  5
9
#define ECHO_PIN1     4
10
11
int alle_x_sekunden = 1;
12
int x = 0;
13
Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN);
14
Ultrasonic ultrasonic1(TRIGGER_PIN1, ECHO_PIN1);
15
float cmMsec, inMsec;
16
float cmMsec1, inMsec1;
17
18
/*Servo myservo;  // create servo object to control a servo 
19
 int lenken = 0;*/
20
21
int fahren = 0;
22
23
void setup()
24
{
25
  Serial.begin(9600);
26
  Timer1.initialize(alle_x_sekunden*1000000);
27
  Timer1.attachInterrupt(messen);
28
29
  pinMode(12, OUTPUT); //Initiates Motor Direction A
30
  pinMode(9, OUTPUT);  //Initiates Break Channel A 
31
32
  /*myservo.attach(10);  // attaches the servo on pin 3 to the servo object
33
   myservo.write(100);  // attaches the servo on position 100(middle)*/
34
}
35
36
void loop(){
37
  if(x==0){
38
    Timer1.attachInterrupt(messen);
39
  }
40
  if(x==1){
41
    Timer1.attachInterrupt(messen1);
42
  }
43
44
  if(cmMsec > 10){
45
    fahren =2;
46
  }
47
  else{
48
    fahren =0;
49
50
  }  
51
52
  switch(fahren){
53
  case 0:
54
    {
55
      digitalWrite(9, HIGH);
56
      break;
57
    }
58
  case 1:
59
    {
60
      digitalWrite(12, HIGH); //Establishes forward direction of Channel A
61
      digitalWrite(9, LOW);   //Disengage the Brake for ChannelA
62
      analogWrite(3, 125);   //Spins the motor on Channel A  
63
      break;
64
    }
65
  case 2:
66
    {
67
      digitalWrite(12, HIGH); //Establishes forward direction of Channel A
68
      digitalWrite(9, LOW);   //Disengage the Brake for ChannelA
69
      analogWrite(3, 255);   //Spins the motor on Channel A 
70
      break;
71
    }
72
  }
73
74
}
75
76
void messen(){
77
78
  long microsec = ultrasonic.timing();   //funktion, welche die zeit berechnet
79
80
  cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM); //rechnet die gemessene Zeit in cm um
81
  inMsec = ultrasonic.convert(microsec, Ultrasonic::IN);   // Inch
82
  Serial.print("MS: ");
83
  Serial.print(microsec);
84
  Serial.print(", CM: ");
85
  Serial.print(cmMsec);
86
  Serial.print(", IN: ");
87
  Serial.println(inMsec);
88
  x=1;
89
90
}
91
92
void messen1(){
93
94
  long microsec1 = ultrasonic1.timing();   //funktion, welche die zeit berechnet
95
96
  cmMsec1 = ultrasonic1.convert(microsec1, Ultrasonic::CM); //rechnet die gemessene Zeit in cm um
97
  inMsec1 = ultrasonic1.convert(microsec1, Ultrasonic::IN);   // Inch
98
  Serial.print("MS1: ");
99
  Serial.print(microsec1);
100
  Serial.print(", CM1: ");
101
  Serial.print(cmMsec1);
102
  Serial.print(", IN1: ");
103
  Serial.println(inMsec1);
104
  x=0;
105
}

von Karl H. (kbuchegg)


Lesenswert?

Simon K. schrieb:

> anschließe, stoppt das Programm und führt keinen Schritt mehr durch. Es
> handelt sich hier nur um diese 4 Zeilen:

Es handelt sich nicht NUR um diese 4 Zeilen.

Servos anzusteuern hat mit exaktem Timing zu tun. Hinter exaktem Timing 
steckt oft ein Timer.

Die Frage lautet daher: wie erzeugt eigentlich die 'Servo' Klasse ihr 
Timing?
Die Chancen stehen nicht schlecht, dass die Servo Klasse dazu einen 
Timer einsetzt. Und wenn das dann zufällig auch noch der Timer 1 ist, 
dann kannst du hier
1
...
2
   Timer1.initialize(alle_x_sekunden*1000000);
3
   Timer1.attachInterrupt(messen);
4
...

nicht dein eigenes Süppchen mit dem Timer 1 kochen.

Also: welche Resourcen, sprich 'welchen Timer', benötigt die Servo 
Klasse?

von Simon K. (simon_k96)


Angehängte Dateien:

Lesenswert?

In der Servo.h-library ist vermerkt, dass unter anderem auch der Timer1 
verwendet wird.. (Screenshot im Anhang)

Habe ich mit dem Arduino Uno sonst eine Möglichkeit, einen 2. Timer zu 
verwenden (als Beispiel MsTimer2.h?), um meine Ultraschallsensoren in 
genau definierten Zeitabständen einlesen zu können?

Mit dem Hintergedanken, dass der Servo auch in Betrieb genommen wird.

mfg Simon K.

von Karl H. (kbuchegg)


Lesenswert?

Simon K. schrieb:

> verwenden (als Beispiel MsTimer2.h?), um meine Ultraschallsensoren in
> genau definierten Zeitabständen einlesen zu können?


Von welcher Genauigkeit sprechen wir, wenn du von 'genau definierte 
Zeitabstände' redest.

Eine einfache, Arduino konforme Möglichkeit, für regelmässig 
auszuführende Aktionen ist es ja, das ganze an der Arduino 'Systemuhr' 
aufzuhängen.
1
unsigned long previousMillis = 0;
2
3
void loop()
4
{
5
6
  if (millis() - previousMillis > 1000) {    // alle 1 Sekunde
7
    previousMillis = millis();
8
9
    // mach was im Sekunden Abstand
10
    // ....
11
  }  
12
13
  ...
14
}

Die vom if abhängigen Aktionen finden im Sekundenabstand statt, wobei 
sich ein eventueller Fehler nicht akkumuliert. D.h. wenn die Aktion mal 
um 1 Millisekunde zu spät kommt, kommt die nächste um 1 Millisekunde zu 
früh, so dass auf längere Sicht gesehen die Aktion tatsächlich im 
Sekundentakt erfolgt.

Wenn dir das reicht, und ich kann mir ehrlich gesagt keinen Grund 
vorstellen, warum es so wichtig ist, die Sensoren auf die Mykrosekunde 
genau abgefragt werden, dann ist das eine Lösung, in der du überhaupt 
keinen Timer brauchst.
D.h. du benutzt implizit schon einen Timer, der steckt in millis() 
drinnen. Aber der springende Punkt ist, dass der ins System integriert 
ist und sich die Macher der Servo Klasse meines Wissens auch darum 
gekümmert haben, da sauber mitzuspielen - ganz im Gegensatz zu deinem 
Timer Versuch.

von Peter D. (peda)


Lesenswert?

Welcher AVR steckt denn in dem Uno?

Die ATmega haben ja mindestens 3 Timer.
T1 würde ich für die Ultraschallmessung benutzen, da der einen 
Capture-Eingang hat. Der läßt sich auch über den ADMUX auf mehrere 
Sensoren umschalten.
T0 mit seinen PWM-Ausgängen für die Servos.
Und T2 als Zeitgeber.

Die Nutzung der Hardwareeinheiten hat auch den Vorteil, daß sie sich 
nicht durch Programmlaufzeiten gegenseitig stören.

von Kaj (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Welcher AVR steckt denn in dem Uno?
Standardmäßig ein 328

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.