Forum: Mikrocontroller und Digitale Elektronik Motorshield und Servo gleichzeitig steuern (Timer 1)


von Laurin (wildatheart)


Angehängte Dateien:

Lesenswert?

Hallo

Ich habe ein Timer-Problem. Für meinen Roboter verwende ich ein Arduino 
Uno zusammen mit einem Pololu VNH5019 Motortreiber. Da ich über den 
Atmega328p per PWM noch einen Servo steuern will, bin ich mit einem 
Timer-Konflikt konfrontiert. Ich habe mit zusärtlichem Code (siehe 
Anhang)versucht, für den Servo den Timer 2 zu verwenden, doch es will 
nicht funktionieren. Der Servo zuckt nur nervös herum (auch ohne Last) 
und reagiert nicht auf meine Steuersignale. Ich habe den Servo bereits 
(ohne ein Motorshield) erfolgreich angesteuert. Zudem wird der Servo 
nicht über VDD des Arduino Uno, sondern unabhängig gespiesen.
Hat jemand eine Idee, wo der Fehler liegt?
Ich danke Euch schon jetzt für Inputs!

von Cyblord -. (cyblord)


Lesenswert?

Typische Arduino Kacke halt. Da wird halt eine Ressource mehrfach 
benötigt. Mit Arduino Bordmitteln lässt sich das nicht lösen. Da musst 
du raus aus deiner Arduino Welt. Sorry.

von Thomas V. (Gast)


Lesenswert?


von Peter D. (peda)


Lesenswert?

Wenn die Servoroutine schonmal funktioniert hat, dann wird vermutlich 
die nicht gezeigte Motorroutine sie beeinflussen.
Sei es, sie benutzt auch T2 oder verzögert andere Interrupts sehr lange.
Die nicht gezeigte Bluetooth-Routine könnts aber auch sein.

von Laurin (wildatheart)


Angehängte Dateien:

Lesenswert?

Danke für eure Inputs! Ich habe inzwischen mich dazu entschieden, die 
Servo-Steuerung separat einem kleinen Arduino Mini Board zu überlassen, 
das ich noch rumliegen hatte. Das heisst, ich habe den RX vom 
RF-Empfäneger-Modul auf beide Boards geführt. Das Uno bekommt 'A' bis 
'T' für den switch cmd (Motor- und LED-Steuerung) und das "Mini" den 
Servo-Winkel von 0-180 Grad. Doch leider funktioniert mein Plan noch 
nicht, denn der Servo zuckt immer noch planlos rum. Alle restlichen 
Steuersignale kommen korrekt an. Ich weiss nicht wie ich die 
Character-Signale von den Integer sauber trennen kann..

Im Anhang sind Code vom Sender und vom Empfänger für den Servo.

von Peter D. (peda)


Lesenswert?

Laurin E. schrieb:
>    val = bluetooth.read();
>    if (val >= '0' && val <= '180'){

Ob das unter C++ geht, hab ich meine Zweifel (kann nur C), unter C geht 
das auf keinen Fall.
Unter C sind Variablen und Strings völlig verschieden. Man braucht 
Funktionen (itoa, atoi, sprintf, sscanf) zur Umwandlung.

Und vor allem braucht man ein Protokoll, wenn die UART mehr als ein Byte 
übertragen soll. Sonst weiß der Empfänger nicht, wann ein Kommando 
anfängt und wann es aufhört.

von Laurin (wildatheart)


Lesenswert?

Ich habe mich inzwischen mal auf die Servosteuerung beschränkt, um zu 
testen, ob der Servo ohne die restlichen Steuersignale, also ohne den 
switch case, läuft.
Was mir ein "Serial.println" nach bluetooth.read liefert erklärt wohl, 
weshalb ich ein Signal-Chaos habe.
Der Serial Monitor zeigt Zeichen wie "´1" oder "Œ1" und sonstige 
kyrillisches Zeugs. Hat jemand ne Erklärung warum nicht "val", also der 
Winkel (0-180), der Senderseitig korrekt gemappt wird (per Serial.print 
überprüft), ankommt?

Sender-Code:
1
#include <SoftwareSerial.h>
2
SoftwareSerial BTserial(2, 3); // RX | TX
3
char *controller;
4
int x;
5
int y;
6
int led;
7
int buttonPin = 8;
8
int buttonPin2 = 7;
9
int potpin;
10
int val; 
11
int buttonState = 0;
12
int buttonState2 = 0;
13
void setup() {
14
  pinMode(buttonPin, INPUT);
15
  pinMode(buttonPin2, INPUT);
16
  pinMode(potpin, INPUT);
17
  Serial.begin(9600);
18
  BTserial.begin(9600);
19
  controller = "0";
20
}
21
22
void loop() {
23
  x = analogRead(A0);
24
  y = analogRead(A1);
25
  led = analogRead(A2);
26
  buttonState = digitalRead(buttonPin);
27
  buttonState2 = digitalRead(buttonPin2);
28
  val = analogRead(A3);
29
  val = map(val, 0, 1023, 0, 180);
30
  BTserial.write(val);
31
}




Empfänger-Code:
1
void setup() {
2
  bluetooth.begin(9600);
3
  Serial.begin(9600); // set up Serial library at 9600 bps
4
  pinMode(led, OUTPUT); // IR-LEDs
5
  pinMode (ledPin, OUTPUT);
6
  pinMode (buttonpin, OUTPUT);
7
  md.init();
8
9
}
10
11
void loop() {
12
 
13
  if (bluetooth.available()) {
14
    cmd = bluetooth.read();
15
    Serial.println(bluetooth);
16
    Serial.write(cmd);

von Achim S. (achim_kaarst)


Lesenswert?

> Serial.println(bluetooth);

Das sieht mir sehr seltsam aus. Die Variable bluetooth kann man nicht 
printen, das ist ein Zeiger.
Was willst du denn hier ausgeben?

: Bearbeitet durch User
von Laurin (wildatheart)


Angehängte Dateien:

Lesenswert?

Hallo Achim

Ja Du hast natürlich recht. Es sollte Serial.println(cmd) sein. Das Ziel 
mit dem Serial.print war, dass ich sehe was für Zeichen beim Empfänger 
ankommen. Jetzt sehe ich auch, dass ein Zahlen-Wert zwischen 0 und 180 
ankommt, wie ich es wollte. Das sehr Seltsame ist aber, dass die Motoren 
und Relais, welche vom switch case Befehle bekommen (folgt weiter im 
loop) auch reagieren wenn ich z.B. den Wert 55 (Grad) sende. Dies obwohl 
im switch case nur Buchstaben von 'A' bis 'T' vorkommen. Hast Du eine 
Erklärung dafür?

Danke und Grüsse
Laurin

von Peter D. (peda)


Lesenswert?

Laurin E. schrieb:
> BTserial.write(val);

Da würde ich mal vermuten, daß es alle Ziffern dumpf hintereinder sendet 
und man nicht den einen Wert von dem nächsten unterscheiden kann. Es 
fehlt nämlich ein Protokoll.

Laurin E. schrieb:
> Dies obwohl
> im switch case nur Buchstaben von 'A' bis 'T' vorkommen.

Ehrlich gesagt, macht mich das ganz konfus, daß man unter C++ Werte, 
Zeichen und Strings bunt durcheinander würfeln kann. Ich sehe daher in 
Deinem Code überhaupt nicht durch.
Auch kenne ich die Deklarationen von bluetooth.read, Serial.println usw. 
nicht. Man kann daher nur grob mutmaßen, was Du von den Funktionen 
erwartest. Aber ob sie das auch tun?

Ich mag die Ordnung in C, daß alle Typen verschieden sind und nur dann 
ineinander umgeformt werden, wenn ich es explizit hinschreibe oder ich 
krieg ne Warnung vor den Latz geknallt.

In C würde man ein char-Array anlegen dort hinein mit sprintf einen 
Kennbuchstaben, den Wert und ein Paketendezeichen (z.B. '\n') 
reinschreiben und es dann versenden.

Der Empfänger würde alle Bytes prüfen, bis er den Kennbuchtsaben erkennt 
und dann weiter in ein char-Array einlesen, bis er das Paketende 
erkennt. Dann würde er das char-Array per atoi in den Wert zurück 
wandeln und ihn dann der PWM übergeben.

Aber in C++: keine Ahnung.
Ich hab da so meine Zweifel, ob C++ wirklich Deine Gedanken lesen kann, 
was Du gerade für einen Argumenttyp auszuwerten wünschst.

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.