Go Down

Topic: Bluetoothverbindung (Read 1 time) previous topic - next topic

PFMarkus

Hallo zusammen,

ich hab ein Problem mit der Ausführung von per Bluetooth übertragenen Daten. Ich will eine Streckenposition an meinen uC senden, der auf einem fahrbaren Wagen sitzt. Dieser misst seine eigene Position auf regelt dann auf die ihm übertragene Position. Das Empfangen der Daten funktioniert auch die Weiterverarbeitung wie die Überprüfung durch den Serial Monitor gezeigt hat. Allerdings wird die errechnete Stellgröße, also das PWM-Signal für den Motor nicht an diesen Motor gesendet. Es bewegt sich nix!
Hab dann einfach mal probiert eine LED blinken zu lassen. Auch das funktioniert nicht.

Hier mal der Testcode:

int ledpin = 13;
char *i;
int x = 0;
int zustand = 0; // 0 = selbstfahrend, 1 = Bluetooth gesteuert
char *z, *w;
int zeichen = 0;
char daten[6];
float sollwert = 0;

void setup()
{
  pinMode(ledpin, OUTPUT);
  digitalWrite(ledpin, HIGH);
  Serial.begin(9600);
  Serial1.begin(57600);
}

void loop()
{
        ///// Daten auslesen /////
      if(Serial1.available() > 0) //Abfrage, ob serielle Daten empfangen werden
      {
        do // wenn Daten verfuegbar sind, 5 Zeichen in Array daten schreiben
        {
          if (Serial1.available())
          {
            daten[zeichen] = Serial1.read();  //Zeichen werden in Char Array geschoben
            zeichen++;
          }
        } while (zeichen < 5);
        daten[zeichen] = 0; // abschliessende Null fuer gueltigen String
        zeichen=0;
  Serial.println(daten);
        z = strtok_r(daten, ";", &i); // string vor ; einlesen
        zustand = atof(z); //atof wandelt den char in int um
  Serial.println(zustand);
        w = strtok_r(NULL, ";", &i); // string nach ; einlesen
        sollwert = atof(w); //atof wandelt den char in int um
  Serial.println(sollwert);
        if (zustand == 1);
        {
          ledpin = LOW;
          Serial.println("Test funktioniert");
        }
      }
}

Ich übergeb den String 1;123
Im Serial Monitor zeigt er an:
1;123
1
123,00
Test funktioniert

D.h. der Code funktioniert, allerdings leuchtet die Diode nicht. Und genau das gleiche Problem gibts beim eigentlichen Code. Die Überprüfung hat gezeigt, dass alles richtig eingelesen und berechnet wird, allerdings gibt es keine Ausgaben. Es leuchten keine LEDs das berechnete PWM-Signal wird nicht an den Motor gesendet usw.

Hat wer eine Lösung?

lg
Markus

Webmeister

Ist das der gesamte Code?
Da du zwei serielle Ports ohne Bibliothek verwendest, ist das ein Arduino Mega.

Blinken wird hier keine LED, da der Ausgang nur in der Setup-Routine auf HIGH gesetzt wird.

Im Hauptprogramm loop() fehlt eine Ansteuerung der LED und auch kein PWM-Signal wird ausgegeben.

Wo und in welcher Art wird das PWM-Signal an den Motor gesendet?



PFMarkus

ja stimmt ist ein Mega
ja stimmt in der If-Abfrage müsste stehen: digtialWrite(ledpin, LOW);
jetzt gehts sie aus, wenn ich was eingebe. Allerdings nicht nur bei 1 sondern bei jedem Wert --> Warum?

In diesem Code gibt es kein pwm-signal, dass ist in meinem richtigen Code. Der hier ist nur als Beispiel da um mein Problem zu zeigen.

Im richtigen Code ist es so:

ich übergeb 1;100
dann ist zustand = 1, und sollwert = 100

aus seiner momentanen position und dem sollwert errechnet er die wegdifferenz. Daraus dann wiederum durch die Differenzialgleichung eines PID-Reglers die stellgröße y.
dann schreib ich:

analogWrite(pwmMotor, y);
im Serial Monitor zeigt er für y einen Wert von 220 an. Der Motor bewegt sich allerdings kein Stück.
Ich verstehs einfach nicht warum nicht.

Webmeister

@Markus

vielleicht kannst du nochmals den gesamten, überarbeiteten Code zeigen.
Code einfügen bitte über das Icon # (Insert Code)

PFMarkus

ok hier mal der gesamte code.
hier ist zu sagen, dass der untere Teil auch schon in einem anderen Code verwendet wird und dort passts  :)
Code: [Select]
#include <TimerOne.h> // Einbindern der TimerOne-Library

volatile int schaltvorgang = LOW; // Variable, die angibt, ob Hallsensor geschaltet hat oder nicht
//volatile int abbrechen = LOW; // Varibale, die angibt, ob Ausschalter gedrückt wird oder nicht
volatile int timerabgelaufen = LOW; // Variable, die angibt, ob der Timer abgelaufen ist oder nicht
volatile int bluetoothSteuerung = LOW; // Variable, die angibt, ob Daten uebertragen werden oder nicht
volatile int abbrechen = 44; // Ausschalttaster mit Digitalpin 44 verbunden
int motorDrehrichtung_1 = 46; // Digitalpin, bestimmt Motordrehrichtung
int motorDrehrichtung_2 = 48; // Digitalpin, bestimmt Motordrehrichtung
int pwmMotor = 4;  // PWM-Ausgang für Motor mit Digitalpin 4 verbunden
int drehwinkelsensor = 8; // Drehwinkelsensor mit Analogpin 8 verbunden
float umdrehung = 0;
float startwinkel = 0;
float drehwinkel = 0;
float weg_istwert = 0;
float sollwert = 0;
float differenz = 0; // Variable, fuer die Wegdifferenz zwischen Wagen und Patient
float differenz_alt = 0; // Variable, in der die Wegdifferenz des vorherigen Durchlaufs gespeichert wird
float diff = 0; // Variable, in der der Betrag der Differenz Patient - Wagen gespeichert wird
float differenzSumme = 0; // Variable, in der die Wegdifferenzen für die Regelung addiert werden
float differenzSumme_alt = 0; // Variable in der die Wegdifferenzsumme des vorherigen Durchlaufs gespeichert wird
const float Kp = 180; // Verstärkung des Reglers
const float Ki = 0; // Ki des Reglers in 1/us (hier wird nur PD-Regler verwendet --> kein I-Anteil noetig)
const float Kd = 10000000; // Kd des Reglers in us
const float Ta = 10000; // Abtastzeit in us (0.01 s)
float stellgroesse = 0; // Variable fuer die Stellgroesse der Regelung
int anzahlMagneten = 0;
int zeichen = 0;
char daten[6];
int variable = 1;
int fahrRichtung = 1;
char *i;
int x = 0;
int zustand = 0; // 0 = selbstfahrend, 1 = Bluetooth gesteuert
char *z, *w;

void setup()
{
  Serial.begin(9600);
      Serial.println("TEST");
  Serial1.begin(57600); // Serielle/Bluetooth Kommunikation
  digitalWrite(2, HIGH); // Setzt Pin 2 an dem Interrupt 0 angeschlossen ist auf HIGH
  digitalWrite(3, HIGH); // Setzt Pin 3 an dem Interrupt 1 angeschlossen ist auf HIGH
  pinMode(abbrechen, INPUT); // Eingang für Ausschalttaster
  digitalWrite(abbrechen, HIGH); // Setzt den Eingang vom Ausschalttaster auf HIGH
  pinMode(motorDrehrichtung_1, OUTPUT);  // Ausgang fuer die Drehrichtung zur H-Bruecke
  pinMode(motorDrehrichtung_2, OUTPUT);  // Ausgang fuer die Drehrichtung zur H-Bruecke
  attachInterrupt(0, Hallsensor_schaltet, RISING); // Interrupt, das ausgeloest wird, wenn Hallsensor schaltet
  // attachInterrupt(1, Regelung_abbrechen, CHANGE); // Interrupt, das ausgeloest wird, wenn Ausschalter gedrückt wird
  Timer1.initialize(10000); // Setzt die Timerzeit auf 0.01 s
  Timer1.attachInterrupt(Timer); // Interrupt, das ausgeloest wird, wenn Timer abgelaufen ist
  // attachInterrupt_x(x,Datenuebertragung, RISING); // Interrupt, das ausgeloest wird, wenn Daten ueber Bluetooth uebertragen werden
}
//////////////////////////////////////////////////////////////////////////////////////////////
void Antrieb_rechts() // Routine für Motordrehrichtung nach rechts
{
  digitalWrite(motorDrehrichtung_1, LOW);
  digitalWrite(motorDrehrichtung_2, HIGH);
}
//////////////////////////////////////////////////////////////////////////////////////////////
void Antrieb_links() // Routine für Motordrehrichtung nach links
{
  digitalWrite(motorDrehrichtung_1, HIGH);
  digitalWrite(motorDrehrichtung_2, LOW);
}
//////////////////////////////////////////////////////////////////////////////////////////////
void Antrieb_stop() // Routine um Antriebsmotor zu stoppen
{
  digitalWrite(motorDrehrichtung_1, HIGH);
  digitalWrite(motorDrehrichtung_2, HIGH);
}
////////////////////////////////////////////////////////////////////////////////////////////
void Hallsensor_schaltet() // ISR, die ausgefuehrt wird, wenn Interrupt 0 ausgeloest wird
{
  schaltvorgang = !schaltvorgang; // Variable, die angibt, ob Hallsensor geschaltet hat, wird auf HIGH gesetzt
  anzahlMagneten++;
}
////////////////////////////////////////////////////////////////////////////////////////////
void Timer() // ISR des Timers, die ausgefuehrt wird, wenn implementierter Timer ausgeloest wird
{
  timerabgelaufen = !timerabgelaufen; // Variable, die angibt, ob der Timer abgelaufen ist, wird auf HIGH gesetzt
}
/////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{   
      ///// Daten auslesen /////
      if(Serial1.available() > 0) //Abfrage, ob serielle Daten empfangen werden
      {
        do // wenn Daten verfuegbar sind, 3 Zeichen in Array daten schreiben
        {
          if (Serial1.available())
          {
            daten[zeichen] = Serial1.read();  //Zeichen werden in Char Array geschoben
            zeichen++;
          }
        } while (zeichen < 5);
        daten[zeichen] = 0; // abschliessende Null fuer gueltigen String
        zeichen=0;
  Serial.println(daten);
        z = strtok_r(daten, ";", &i);
        zustand = atof(z); //atof wandelt den char in int um
  Serial.println(zustand);
        w = strtok_r(NULL, ";", &i);
        sollwert = atof(w); //atof wandelt den char in int um
        sollwert = sollwert / 100;
  Serial.println(sollwert);
        //Serial.flush();
   
        ///// Begrenzungen, damit Wagen nicht am Ende hinausfaehrt
        if (sollwert > 5.5)
        {
          sollwert = 5.5;
        }
        if (sollwert < 0)
        {
          sollwert = 0;
        }
      }
/////////////////////// ab hier wurde der Code schon wo anders verwendet und hat funktioniert ///////////////////////////////
///////////////////////                                                                       ///////////////////////////////
      ///// Weg- und Soll-Istwert-Differenzberechnung /////
      drehwinkel = analogRead(drehwinkelsensor); // Auslesen des momentanen Drehwinkels
      if (drehwinkel > 915 && variable == 1)
      {
        umdrehung++;
        variable = 0;
      }
      if (drehwinkel < 110 && variable == 0)
      {
        variable = 1;
      }
      weg_istwert = umdrehung * 0.12 + (drehwinkel / 925) * 0.12; // Umfang vom Rad 0,12 m
Serial.println(weg_istwert);
      differenz = sollwert - weg_istwert;
Serial.println(differenz);
     
      ///// Umrechnung, sodass nur positive Distanz auftritt und Festlegung der entsprechenden Fahrrichtung /////
      if (differenz < 0) // bei negativer Distanz, Invertierung ins Positive
      {
        diff = differenz * (-1);
        Antrieb_links();
      }
      else if (differenz > 0) // bei positiver Distanz keine Veränderungen
      {
        diff = differenz;
        Antrieb_rechts();
      }
      differenzSumme = differenzSumme + diff; // Integrierung
      differenz_alt = diff; // Wegdifferenz zwischen Wagen und Patient als vorherigen Wert übergeben
     
      ///// Wegregelung /////   
      ///// Implementierung des PID-Reglers ///// 
      if (timerabgelaufen) // immer, wenn der Interrupttimer abgelaufen ist, wird eine neue Stellgroesse berechnet
      { 
        stellgroesse = Kp * diff + Kd * (diff - differenz_alt) / Ta; // Berechnung der Stellgroesse des PID-Reglers (Differenzialgleichung für den zeitdiskreten PID-Regler)

        ///// Anti_Windup /////
        if (stellgroesse > 255) // Abfrage, ob max. Stellgroesse ueberschritten ist
        {
          stellgroesse = 255; // die max. Stellgroesse zuweisen
        }
        if (stellgroesse < 0) // Abfrage, ob min. Stellgroesse unterschritten ist
        {
          stellgroesse = 0; // die min. Stellgroesse zuweisen
        }
        if (diff < 0.1) // Ansprechschwelle (wenn die Differenz Wagen - Patient unter 0.1 m betraegt, erfolgt keine weitere Regelung (kein Pendeln --> Getriebe schonen)
        {
          stellgroesse = 0;
        }
Serial.println(stellgroesse);       
        analogWrite(pwmMotor, stellgroesse); // Motor mit Stellgroesse als PWM-Signal ansteuern
      } 
}

Webmeister

Quote
Serial.println(stellgroesse);       
analogWrite(pwmMotor, stellgroesse); // Motor mit Stellgroesse als PWM-Signal ansteuern

Wenn der Wert hier korrekt angezeigt wird, sollte dieser auch korrekt als PWM-Signal ausgegeben werden.

Was für eine Motoransteuerung ist am PWM-Signal angeschlossen?

PFMarkus

ich benutze eine RN-Mini H-Bridge

ich hab die Test mit angeschlossenem USB-Kabel gemacht, d.h. der uC wurde über das USB-Kabel versorgt. Hier passt alles. Dies verwende ich aber nur zum raufspielen der Programme. Ansonsten wird der uC extern versorgt. Der uC ist aber auf einem Wagen montiert, die Antriebseinheit ist von einer Modelleisenbahn. Die Stromaufnahme passiert also über die Räder bzw. Schleifkontakte.
Wenn ich den uC per USB-Kabel versorge funktionieren die Ausgaben. Stelle ich allerdings den Wagen auf die Gleise funktionierts nicht mehr.
Muss aber dazu sagen, dass ich zuvor schon einige andere Programme laufen hab lassen wo es in beiden Fällen einwandfrei funktioniert hat.

Go Up