2016-06-07 7 views
0

Arduino 무인 프로젝트는 출력이로드 될 때마다 (ESC에 "개방 회로"신호 핀 또는 심지어 지상 캡), 입력 "조향"명령은 글리치를 시작합니다 (실제 낮은 값인 < <).Arduino Drone 프로젝트는 출력이 "로드"될 때까지 (심지어 cap에서 GND로) 입력 "조향"명령이 흐트러지기 시작합니다.

모터 속도는 조향 명령과 스로틀의 기능입니다. (아래의 코드에서 보듯이 하나의 모터 만있는이 테스트 케이스에서, unMotorSpeed ​​= unThrottleIn +/- unSteeringIn)

스코프에 연결되면 물리적 입력 신호 (수신기에서 오는 스티어링 및 스로틀)는 다음과 같습니다. 그리고 수신기와 arduino 사이에 문제가 없는지 확인하기 위해 입력 핀을 바꿨습니다. 문제는 소프트웨어에서 오는 것 같지만, "로드"가 연결되어 있지 않을 때 입력 및 출력 값이 모두 훌륭하고 깨끗한 상태이므로 의미가 없습니다. (필자는 때때로 회로를 완성하기 위해 접지하지 않은 전자 속도 컨트롤러 (ESC)에 대한 수퍼 하이 임피던스 입력 신호이기 때문에 "로드"를 따옴표로 묶습니다.)

누구든지 코드를 확인하고 내가 누락 된 부분이 있는지 확인할 수 있습니까?

이 시점에서 다소 빠른 해결 방법은 새로운 글리치 값을 모터에 쓰지 않고 새 속도가 이전 속도보다 현저히 낮을 때마다 이전 속도 값을 유지하는 것입니다 (이 속도는 50khz 이상입니다). 그래서 분명히 한 걸음 만에 엄청난 도약이 조금 미친 것입니다.)

참고 : 코드에서 unMotorSpeed의 총 출력은 servoThrottle 핀에서 나옵니다. 원래의 명명 방식을 바꾸지는 않았지만 ... 코드를 읽고 모든 변수를 보면 분명합니다.

업데이트 : 이상한 것은 설정을 변경하지 않고 모든 작업을하지 않고 실행 한 것입니다. arduino를 여러 번 재검토하여 운이 좋지 않은 글리치가 아닌지 확인했습니다. 쪽으로. 그런 다음 리모콘을 바닥에 놓고 브레드 보드에있는 몇 개의 전선을 움직이면 설치가 다시 끝난 후 모든 것이 바뀌 었습니다. Idk 무엇을해야합니다!

// --> starting code found at: rcarduino.blogspot.com 
// See related posts - 
// http://rcarduino.blogspot.co.uk/2012/01/how-to-read-rc-receiver-with.html 
with.html 


#include <Servo.h> 

// Assign your channel in pins 
#define THROTTLE_IN_PIN 3 
#define STEERING_IN_PIN 2 


// Assign your channel out pins 
#define THROTTLE_OUT_PIN 9 
//#define STEERING_OUT_PIN 9 


// Servo objects generate the signals expected by Electronic Speed Controllers and Servos 
// We will use the objects to output the signals we read in 
// this example code provides a straight pass through of the signal with no custom processing 
Servo servoThrottle; 
//Servo 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; 
volatile uint16_t 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; 
uint32_t ulSteeringStart; 
//uint32_t ulAuxStart; 

void setup() 
{ 
    Serial.begin(9600); 

    // attach servo objects, these will generate the correct 
    // pulses for driving Electronic speed controllers, servos or other devices 
    // designed to interface directly with RC Receivers 
    servoThrottle.attach(THROTTLE_OUT_PIN); 

    // using the PinChangeInt library, attach the interrupts 
    // used to read the channels 
    attachInterrupt(digitalPinToInterrupt(THROTTLE_IN_PIN), calcThrottle,CHANGE); 
    attachInterrupt(digitalPinToInterrupt(STEERING_IN_PIN), calcSteering,CHANGE); 
} 

void loop() 
{ 
    // 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; 
    static uint16_t difference; 
    static uint16_t unMotorSpeed; // variable that stores overall motor speed 
    static uint8_t bUpdateFlags; // local copy of update flags 

    // 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 :-) 
    } 

    //Serial.println(unSteeringIn); 

    // do any processing from here onwards 
    // only use the local values unAuxIn, unThrottleIn and unSteeringIn, the shared 
    // variables unAuxInShared, 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-else chain commented out to determine/prove problem with steering signal --> buggy! 


    if(unSteeringIn < 1400) // if steering joystick moved left 
    { 
    difference = 1400 - unSteeringIn; 
    if(unThrottleIn - difference >= 0) 
    unMotorSpeed = unThrottleIn - difference; 
    } 
    else if(unSteeringIn > 1550) //if steering joystick moved right (needs to be tweaked, but works for now) 
    { 
    difference = unSteeringIn - 1600; 
    if(unThrottleIn + difference < 2000) 
     unMotorSpeed = unThrottleIn + difference; 
    } 
    else 
    { 
    unMotorSpeed = unThrottleIn; 
    } 

    //Serial.println(unMotorSpeed); 
    //Serial.println(unSteeringIn); 
    //Serial.println(unThrottleIn); 

    if(bUpdateFlags) 
    { 
    //Serial.println(servoThrottle.readMicroseconds()); 
    if(servoThrottle.readMicroseconds() != unMotorSpeed) 
    { 
     servoThrottle.writeMicroseconds(unMotorSpeed); 
     Serial.println(unMotorSpeed); 
    } 
    } 

    bUpdateFlags = 0; 
} 

// 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_IN_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); // pulse duration 

    // use set the throttle flag to indicate that a new throttle signal has been received 
    bUpdateFlagsShared |= THROTTLE_FLAG; 
    } 
} 

void calcSteering() 
{ 
    if(digitalRead(STEERING_IN_PIN) == HIGH) 
    { 
    ulSteeringStart = micros(); 
    } 
    else 
    { 
    unSteeringInShared = (uint16_t)(micros() - ulSteeringStart); // pulse duration 
    bUpdateFlagsShared |= STEERING_FLAG; 
    } 
} 
+0

당신이 결함의 성격에 대한보다 구체적인 수 있을까? 어떤 범위의 가치를 기대하며 어떤 가치 범위를 준수합니까? 소프트웨어로 패스 필터를 추가하고 특정 실제 너비의 펄스에 대한 값만 허용 할 수 있습니다. – Tim

+0

이 질문을 다듬을 수도 있습니다. 다소 장황하고 혼란 스럽습니다. 예를 들어, SO의 문맥에서 나는 첫 번째 문장을 "* Arduino 프로젝트 (즉, 컴파일 된 코드)의 출력이로드 될 때마다 (즉, 플래시로 레코딩) ... *"라고 즉시 해석합니다. 말이되지 않는다. * output * 및 * loaded *라는 용어는이 맥락에서 모호 합니다만, 분명히 내가 의도 한 해석을 의도하지 않았습니다. 전기 부하로서의 "부하"의 의미 에서조차, "개방 회로"는 실제로 * 전혀 부하가 걸리지 않기 때문에, 나는 당신이 의미하는 바에 관해서는 분명하지 않다. – Clifford

+0

'unSteeringIn'의 유효 범위는 얼마입니까? 통계는 모두 0으로 초기화되지만 사용되기 전에 모든 경로에서 유효한 값이 지정되는 것처럼 보이지는 않습니다. 실제 값으로 초기화 할 수 있습니다. – Clifford

답변

0

당신은 AttachInterrupt()의 설명서를 읽어야한다 - "인터럽트 서비스 루틴 정보"섹션에 인터럽트에서 호출 할 때 어떻게 행동하는지 특정 기능에 대한 정보를 제공합니다. micros()의 경우 :

마이크로 초()가 처음에는 작동하지만 1-2 밀리 초 후에 오류가 발생합니다.

ISR이 일반적으로 1ms가 아닌 1ms 이상 실행 된 것이므로이 경우에는 적용되지 않을 수 있지만 다음과 같은 경우에 타이밍을 수행하는 방법을 고려해야한다고 생각합니다. ISR. Arduino - 끔찍한 문서화에 문제가 있습니다!

원인이 될 수있는 명확한 문제는 unSteeringInShared이 비 원자력이라는 사실입니다. 8 비트 하드웨어에서 16 비트 값이므로 읽기 및 쓰기 작업을 여러 번 수행해야하므로 프로세스가 중단 될 수 있습니다. 따라서 loop() 컨텍스트에서 값의 1 바이트를 읽은 다음 두 번째 바이트를 읽기 전에 두 바이트를 인터럽트 컨텍스트에 의해 변경하도록 할 수 있으므로 두 개의 서로 다른 값을 두 개 반으로 늘릴 수 있습니다.

당신이 중 하나를 인터럽트를 비활성화 할 수이 문제를 해결하려면 동안 읽기 : 당신이 읽기 스핀 잠글 수 있습니다

noInterrupts() ; 
unSteeringIn = unSteeringInShared ; 
interrupts() ; 

또는 : 너무 당신은 unThrottleInShared에 대해 동일한 작업을 수행해야

do 
{ 
    unSteeringIn = unSteeringInShared ; 

} while(unSteeringIn != unSteeringInShared) ; 

왜하지만 당신은 그것이 불분명 한 어떤 문제도 보지 못합니다 - 이것은 아마도 당신이 현재 관찰하고있는 문제는 아니지만 어떠한 경우에도 확실히 문제입니다. 8 비트 해상도가 충분

또는 경우에 따라서 원자 8 비트 값으로 입력을 인코딩 할 수 있습니다 :

나머지 부분에 대한 변경이 필요합니다 0 255 2000 1000에서 스케일을 변경 물론
uint8_t unSteeringInShared ; 


... 


int32_t timeus = micros() - ulSteeringStart - 1000 ; 
if(timeus < 0) 
{ 
    unSteeringInShared = 0 ; 
} 
else if(timeus > 1000) 
{ 
    unSteeringInShared = 255; 
} 
else 
{ 
    unSteeringInShared = (uint8_t)(time * 255/1000) ; 
} 

코드의 예를 들어, 서보 펄스 폭에 255의 범위는 0의 값 x을 변환 :

pulsew = (x * 1000/256) + 1000 ; 
+0

철저한 답변 해 주셔서 감사합니다. 나는 사이트에 게시하는 것이 매우 새로운데, 나는 일을하는 가장 적절한 방법을 알지 못했다. 올바른 길을 찾아 주셔서 감사합니다. 기술 답변에 관해서는 메인 루프에서 처리하는 동안 이미 인터럽트를 중지하고 특정 시나리오 (스로틀 또는 조향)에 대한 비트 플래그가 변경된 경우에만 변수를 변경합니다. 이상하게도, 나는 변화없이 모든 설정을했고, 모든 일은 ... 그때 나는 리모컨을 바닥에 떨어 뜨렸다. Idk 무엇을해야합니다! – MS9T1

+0

@ MS9T1 : 하드웨어 결함 (예 : 마모되었거나 손상된 전위차계 트랙)처럼 들리는데,이 경우에는이 사이트에 대한 질문이 아닙니다.반면에 깨진 하드웨어를 사용할 수 있도록 소프트웨어에서 신호 컨디셔닝을 적용하는 것이 가능할 수도 있습니다. 그러나 그것은 다른 질문 일 것입니다. – Clifford