Hallo zusammen,
ich habe inzwischen den Empfänger am Arduino und leite die Daten dann an Motor und Steuerungservo weiter. Das funktioniert allerdings nur solange ich ENTWEDER steuere ODER beschleunige. Lenken UND beschleunigen geht nicht.
demcoderseinnachbar:
Hatte jemand das Problem oder eine Idee woran das liegt oder wie ich dem Problem auf die Schliche komme?
ja schon öfter...
Es kommen immer zu wenig Informationen.
Was sollen wir mit deinen Angaben anfangen ?
U-Boot bauen ?
Was für einen Arduino ?
Was für einen Empfänger ?
Was für einen Motor ?
Was für einen Servo ?
Was für einen Sketch ?
Den Sketch in Code-Tags posten.
Verwende dazu die Schaltfläche </> oben links im Editorfenster. Das kannst du auch nachträglich machen. Dazu den Sketch markieren und die Schaltfläche klicken.
Damit wird dieser für alle besser lesbar.
Für alles andere Links posten. Und wenn du schnelle Hilfe erwartest, dann bitte Hyperlinks verwenden.
DrDiettrich:
Kann es sein, daß die Batteriespannung zusammenbricht, sobald Servo und Motor angesteuert werden?
Hatte ich auch schon überlegt. Allerdings ist es so, dass z.B. der Motor weiterläuft, wenn ich den laufen lasse und dann lenke. Nur das lenken geht dann nicht. Wenn die Spannung zusammenbrechen würde, würde ich erwarten, dass auch die Motoransteuerung nicht mehr funktioniert oder?
Soweit ich die anderen Kommentare richtig verstehe, scheint das Problem einfach zu sein, dass pulseIn einfach blockiert und damit der andere Servo nicht mehr zum Zug kommt.
Whandall:
Ja.
Was hat dich auf die Idee gebracht, diese Information einfach zu ignorieren?
Zumal ja schon ein Beispiel für einen Channel dabei ist...
Naja ich wollte erstmal alles einfach halten und habe daher versucht Komplexität zu vermeiden. Ich habe es zu dem Zeitpunkt auch nicht genau verstanden - aber nun macht es an sich Sinn.
Je nach zu messendem Signal kann man auch mit der blockierenden Natur von pulseIn leben,
aber die Fernsteuerungs-PWM ist dafür wahrscheinlich zu langsam.
Das Beispiel finde ich etwas unglücklich, da der Messwert nicht automatisch aktualisiert wird,
sondern erst, nachdem er gelesen/bestätigt wurde.
Auch wurde darauf verzichtet digitalPinToInterrupt() zu benutzen, aber das ist eher ein Detail.
Der erste Punkt wird in der Fortsetzung korrigiert:
Vielen Dank für eure Hilfe. Mit Interrupt funtzt es!
Hier der angepasste Code:
// input pins
// Assign your channel in pins, these are pin numbers for use in digitalRead
#define THROTTLE_SERVO_OVERRIDE_PIN 2 // Pin 2 = Interrupt 0
#define STEERING_SERVO_OVERRIDE_PIN 3 // Pin 3 = Interrupt 1
// output pins
#define THROTTLE_SERVO_PIN 4
#define STEERING_SERVO_PIN 5
#include <Servo.h>
Servo servoThrottle, servoSteering;
// These bit flags are set in bUpdateFlagsShared to indicate which
// channels have new signals
#define THROTTLE_FLAG 1
#define STEERING_FLAG 2
// holds the update flags defined above
volatile uint8_t bUpdateFlagsShared;
// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint16_t unThrottleInShared, unSteeringInShared;
// These are used to record the rising edge of a pulse in the calcInput functions
// They do not need to be volatile as they are only used in the ISR. If we wanted
// to refer to these in loop and the ISR then they would need to be declared volatile
uint32_t ulThrottleStart, ulSteeringStart;
// simple interrupt service routine
void calcThrottle() {
// if the pin is high, its a rising edge of the signal pulse, so lets record its value
if(digitalRead(THROTTLE_SERVO_OVERRIDE_PIN) == HIGH) {
ulThrottleStart = micros();
} else {
// else it must be a falling edge, so lets get the time and subtract the time of the rising edge
// this gives use the time between the rising and falling edges i.e. the pulse duration.
unThrottleInShared = (uint16_t)(micros() - ulThrottleStart);
// use set the throttle flag to indicate that a new throttle signal has been received
bUpdateFlagsShared |= THROTTLE_FLAG;
}
}
void calcSteering()
{
if(digitalRead(STEERING_SERVO_OVERRIDE_PIN) == HIGH) {
ulSteeringStart = micros();
} else {
unSteeringInShared = (uint16_t)(micros() - ulSteeringStart);
bUpdateFlagsShared |= STEERING_FLAG;
}
}
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(9600);
Serial.println("V1.1\n");
servoThrottle.attach(THROTTLE_SERVO_PIN);
servoSteering.attach(STEERING_SERVO_PIN);
// using the PinChangeInt library, attach the interrupts
// used to read the channels
attachInterrupt(digitalPinToInterrupt(THROTTLE_SERVO_OVERRIDE_PIN), calcThrottle, CHANGE);
attachInterrupt(digitalPinToInterrupt(STEERING_SERVO_OVERRIDE_PIN), calcSteering, CHANGE);
}
void handleOverride()
{
// create local variables to hold a local copies of the channel inputs
// these are declared static so that thier values will be retained
// between calls to loop.
static uint16_t unThrottleIn;
static uint16_t unSteeringIn;
// local copy of update flags
static uint8_t bUpdateFlags;
// check shared update flags to see if any channels have a new signal
if (bUpdateFlagsShared)
{
noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables
// take a local copy of which channels were updated in case we need to use this in the rest of loop
bUpdateFlags = bUpdateFlagsShared;
// in the current code, the shared values are always populated
// so we could copy them without testing the flags
// however in the future this could change, so lets
// only copy when the flags tell us we can.
if (bUpdateFlags & THROTTLE_FLAG) {
unThrottleIn = unThrottleInShared;
}
if (bUpdateFlags & STEERING_FLAG) {
unSteeringIn = unSteeringInShared;
}
// clear shared copy of updated flags as we have already taken the updates
// we still have a local copy if we need to use it in bUpdateFlags
bUpdateFlagsShared = 0;
interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on
// as soon as interrupts are back on, we can no longer use the shared copies, the interrupt
// service routines own these and could update them at any time. During the update, the
// shared copies may contain junk. Luckily we have our local copies to work with :-)
}
// do any processing from here onwards
// only use the local values unThrottleIn and unSteeringIn, the shared
// variables unThrottleInShared, unSteeringInShared are always owned by
// the interrupt routines and should not be used in loop
// the following code provides simple pass through
// this is a good initial test, the Arduino will pass through
// receiver input as if the Arduino is not there.
// This should be used to confirm the circuit and power
// before attempting any custom processing in a project.
// we are checking to see if the channel value has changed, this is indicated
// by the flags. For the simple pass through we don't really need this check,
// but for a more complex project where a new signal requires significant processing
// this allows us to only calculate new values when we have new inputs, rather than
// on every cycle.
if (bUpdateFlags & THROTTLE_FLAG) {
if (servoThrottle.readMicroseconds() != unThrottleIn) {
//Serial.print("unThrottleIn:"); Serial.println(unThrottleIn);
servoThrottle.writeMicroseconds(unThrottleIn);
}
}
if (bUpdateFlags & STEERING_FLAG) {
if (servoSteering.readMicroseconds() != unSteeringIn) {
//Serial.print("unSteeringIn:"); Serial.println(unSteeringIn);
servoSteering.writeMicroseconds(unSteeringIn);
}
}
bUpdateFlags = 0;
}
// the loop function runs over and over again forever
void loop() {
handleOverride(); // look for an override signal
}