PulseIn und SoftwareSerial, Uno

Hallo,

ich habe ein Problem.

Ich verwende für ein GPS Modul und eine Fernsteuerung für ein autonomes Fahrzeug.

Wenn ich die Signale vom GPS einlesen über das SoftwareSerial wird das Signal der Fernsteuerung verfälscht. Es läuft dann intervalartig von 0 bis auf den normalen Wert des Fernsteuerkanal. Die Werte werden normal wenn ich das Signal vom GPS Modul abziehe.

Jemand eine Idee oder habe ich was übersehen?

Gruß
Morob

Das Einlesen der seriellen Schnittstelle braucht Zeit und wird per Interrupt eingelesen..

Wie wird das Signal der Fernsteuerung verfälscht? wie mißt Du genau das Fernsteuersignal?

Grüße Uwe

Guten Morgen,

ich hänge den Code mal ran.

Im Normalfall liegt der Wert bei 1450. Aber wenn das GPS dran hängt, geht der Wert bis 200 runter und kommt dann wieder bis 1450.

Ich habe auch noch anscheinend ein Problem mit der SoftwareSerial und dem GPS, er bekommt sehr schwer eine gültigen Datensatz, das scheint damit auch zusammen zu hängen.

#include <TinyGPS.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <Servo.h>

// remote rxtx
#define kanal1_pin 4                                        
#define kanal2_pin 7
unsigned long kanal1, kanal2;

// servo
#define servo_steering_pin 11
Servo servo_steering;
#define servo_engine_pin 10
Servo servo_engine;

// gps
#define gps_rx 12 //tx gps
#define gps_tx 13 //rx gps
#define gpsbaud 4800

SoftwareSerial GPSserial(gps_rx,gps_tx); // RX,TX
TinyGPS gps;

long lat, lon;
long target_lat,target_lon;
unsigned long fix_age, time, date, speed, course;
unsigned long chars;
unsigned short sentences, failed_checksum;

void setup() {
  // serial interface
  Serial.begin(9600);
  // i2c
  Wire.begin();
  // remote rxtx
  pinMode(kanal1_pin,INPUT); // kanal 1
  pinMode(kanal2_pin,INPUT); // kanal 2
  // servo (steering, engine)
  servo_steering.attach(servo_steering_pin);
  servo_steering.write(90);
  servo_engine.attach(servo_engine_pin);
  servo_engine.write(90);
  // gps
  GPSserial.begin(gpsbaud);
}

void loop() {
//  date=0; time=0;
  while(GPSserial.available()) {
    byte c=GPSserial.read();
//    Serial.print(char(c));
    if(gps.encode(c)) {
      gps.get_datetime(&date, &time, &fix_age);
    }
  }
  kanal1=0; kanal2=0;
  kanal1=pulseIn(kanal1_pin,HIGH);
  kanal2=pulseIn(kanal2_pin,HIGH);
  if (kanal1 >0 and kanal2 >0 ) {
    // remote rxtx on
    if ((kanal1>1399 and kanal1<1501) and (kanal2>1399 and kanal2<1501)) {
      // no remote handling
      //Serial.println("autonom doing");
      // gps data
      // retrieves +/- lat/long in 100000ths of a degree
      gps.get_position(&lat, &lon, &fix_age);
      // time in hhmmsscc, date in ddmmyy
      gps.get_datetime(&date, &time, &fix_age);
      // returns speed in 100ths of a knot
      speed = gps.speed();
      // course in 100ths of a degree
      course = gps.course();      
      // us sensoren data
      // way calc

    }
    else {
      // remote handling
      Serial.println("no autonom doing");
      servo_engine.write(int(kanal1/100));
      servo_steering.write(int(kanal2/100));
    } 
  }
  else {
    // remote rxtx off
    Serial.println("remote rxtx off");
    servo_engine.write(90);
    servo_steering.write(90);
  }
 
}

PulseIn() pausiert den Programmablauf ja weitestgehend, ähnlich wie ein delay(). Ich könnte mir das nur so erklären, dass der Pin Change Interrupt für die SoftwareSerial dir das Timing zerlegt.
Als erstes würde ich versuchen, das pulseIn() zu ersetzen, also recht einfach über die millis()-Funktion. Alternativ könnte ich mir auch vorstellen, ein Arduino-Board mit zusätzlicher Hardware-UART zu benutzen. Der Mega 2560 wäre die teurere Variante, der Leonardo tuts aber auch.

Hallo,

das wäre nicht gut, dann müßte das stellen der Servos ja auch Probleme machen. Ich mußte mir dann eine ganz andere Lösung ausdenken.

Bei den UAV Lösungen geht dies ja auch, ich muß mal schauen gehen.

:slight_smile:

Gruß
Morob

pulseIn() wartet bis ein angegebener Pin seinen Zustand ändert. In dieser Zeit kann der Interrupt ansprechen, welcher auf Signale auf der SoftwareSerial-Schnittstelle horcht. Das Problem ist jetzt, dass die SoftwareSerial-Implementation in diesem Interrupt-Handler ein ganzes Byte mit der selben Methode ("aktives Warten") einliest. Bis das Einlesen des Bytes abgeschlossen ist, wird also kein anderer Code ausgeführt.

Du hast zwei Möglichkeiten, dies zu ändern: Du kannst AltSoftSerial (AltSoftSerial Library, for an extra serial port) verwenden, das zwar auf fixe Pins beschränkt ist, aber über Timer-Interrupts gesteuert wird und somit viel weniger Zeit im Interrupt-Handler verbringt. Allerdings könnte dieser Code mit der Servo-Bibliothek kollidieren.
Oder Du verwendest eine serielle Schnittstelle, die in Hardware realisiert ist, wie das von sth77 schon vorgeschlagen wurde.

Bei den UAV Lösungen geht dies ja auch, ich muß mal schauen gehen.

Deshalb wird bei den UAV-Lösungen meist ein Mega2560 eingesetzt.

Hallo,
ich schau mir das mal mit der alten Bibliothek an, Danke.

Gruß
Morob

morob65:
ich schau mir das mal mit der alten Bibliothek an, Danke.

Wohl eher die alternative Bibliothek.:wink:

Hallo,

PulseIn kõnnte man auch austauschen, wãre eine Idee.

Gruß
Stephan

pylon:

Bei den UAV Lösungen geht dies ja auch, ich muß mal schauen gehen.

Deshalb wird bei den UAV-Lösungen meist ein Mega2560 eingesetzt.

Hallo,

es gibt auch eine Lösung mit einem 328 für den UAV.

Gruß