2012-12-20 132 views
0

因为我改变每当电机进入反转不制动时,它应该到我的马达控制器...Arduino的串行通信

向前走,是好的,它运行只要我按住按钮在控制台应用程序。 左右转动时,倒车电机将不停止运转。 向后移动,两者都会不停地运行。

// Firmware for the Android Shield Board for tank robots 
// Pan/tilt servos now work: 0 pin off, 255 pin on, 1~254 8 bit granularity servo movement (5 microseconds). 
#define PwmPinMotorA 11 
#define PwmPinMotorB 6 
#define DirectionPinMotorA 3 
#define DirectionPinMotorB 5 
#define ServoPin1 0 
#define ServoPin2 0 
#define ServoFlip1 false 
#define ServoFlip2 false 

#define mySerialSpeed 9600 // arduino 2009: 4800 or lower! 
#define debugSerialSpeed 9600 // arduino 2009: 4800 or lower! 
#define BufferLength 16 
#define LineEnd1 13 
#define LineEnd2 10 
#define ServoTimingStep 5 
#define ServoCenter 1500 
#define ServoTimingFloor ServoCenter-(127*ServoTimingStep) 

//#define serialout 
#define debugout 

#include <SoftwareSerial.h> 

SoftwareSerial mySerial(12, 255); // rx only 

char charin = 80; 
char inputBuffer[BufferLength]; 
int value = 128; 
int speed = 128; 
int timer = 15; 
int timermax = 15; 
int inputLength = 0; 
int servoval1 = 127; 
int servoval2 = 127; 
int tempval1, tempval2; 

void setup() 
{ 
    // motor pins must be outputs 
    pinMode(PwmPinMotorA, OUTPUT); 
    pinMode(PwmPinMotorB, OUTPUT); 
    pinMode(DirectionPinMotorA, OUTPUT); 
    pinMode(DirectionPinMotorB, OUTPUT); 
    mySerial.begin(mySerialSpeed); 
#ifdef debugout 
    Serial.begin(debugSerialSpeed); 
#endif 
} 

// process a command string 
void HandleCommand(char* input, int length) 
{ 
#ifdef debugout 
    Serial.print(">"); 
    Serial.print(input); 
    Serial.print("<"); 
    Serial.print(length); 
    Serial.println("|"); 
#endif 
    if (length < 1) { // not a valid command 
    return; 
    } 
    // calculate number following command (d10~d255) 
    if (length > 1) { 
    value = atoi(&input[1]); 
    if (value > 255) 
     value = 255; 
    if (value < 0) 
     value = 0; 
    switch(input[0]) 
    { 
    case 'd': 
    case 'D': 
     if (value > 127) 
     value = 127; 
     speed = value*2; 
     break; 
    case '/': 
     timermax = value; 
     break; 
    case 'c': 
    case 'C': 
     #ifdef ServoFlip1 
     servoval1 = 256 - value; 
     #else 
     servoval1 = value; 
     #endif 
     break; 
    case 'v': 
    case 'V': 
     #ifdef ServoFlip2 
     servoval2 = 256 - value; 
     #else 
     servoval2 = value; 
     #endif 
     break; 
    default: 
     break; 
    } 
    } 

    timer = timermax; 

    int* command = (int*)input; 
    // check commands 
    // note that the two bytes are swapped, ie 'RA' means command AR 



    switch(*command) { 


    case '2': 
    case '2j': 
    case '2J': 
    analogWrite(PwmPinMotorB, speed); 
    digitalWrite(DirectionPinMotorB, LOW); 
    analogWrite(PwmPinMotorA, speed); 
    digitalWrite(DirectionPinMotorA, HIGH); 
    break; 

    case '8': 
    case '8j': 
    case '8J': 
    analogWrite(PwmPinMotorB, speed); 
    digitalWrite(DirectionPinMotorB, HIGH); 
    analogWrite(PwmPinMotorA, speed); 
    digitalWrite(DirectionPinMotorA, LOW); 
    break; 

    case '6': 
    case '6j': 
    case '6J': 
    analogWrite(PwmPinMotorB, speed); 
    digitalWrite(DirectionPinMotorB, HIGH); 
    analogWrite(PwmPinMotorA, speed); 
    digitalWrite(DirectionPinMotorA, HIGH); 
    break; 

    case '4': 
    case '4j': 
    case '4J': 
    analogWrite(PwmPinMotorB, speed); 
    digitalWrite(DirectionPinMotorB, LOW); 
    analogWrite(PwmPinMotorA, speed); 
    digitalWrite(DirectionPinMotorA, LOW); 
    break; 

    case '9': 
    case '9j': 
    case '9J': 
    analogWrite(PwmPinMotorB, speed); 
    digitalWrite(DirectionPinMotorB, HIGH); 
    break; 

    case '1': 
    case '1j': 
    case '1J': 
    analogWrite(PwmPinMotorB, speed); 
    digitalWrite(DirectionPinMotorB, LOW); 
    break; 

    case '3': 
    case '3j': 
    case '3J': 
    analogWrite(PwmPinMotorA, speed); 
    digitalWrite(DirectionPinMotorA, HIGH); 
    break; 

    case '7': 
    case '7j': 
    case '7J': 
    analogWrite(PwmPinMotorA, speed); 
    digitalWrite(DirectionPinMotorA, LOW); 
    break; 

    default: // stop, just to be safe 
    analogWrite(PwmPinMotorA, 0); 
    digitalWrite(DirectionPinMotorA, LOW); 
    analogWrite(PwmPinMotorB, 0); 
    digitalWrite(DirectionPinMotorB, LOW); 
    break; 

    } 
} 

void loop() 
{ 
    // get a command string form the mySerial port 
    inputLength = 0; 
    do { 
    while (!mySerial.available()){ 
     // note: arduino cannot handle fullduplex on myserial so no output here! 

     // do servos here 
     tempval1 = (servoval1*ServoTimingStep) + ServoTimingFloor; 
     tempval2 = (servoval2*ServoTimingStep) + ServoTimingFloor; 
     if (servoval1 > 0) 
     digitalWrite(ServoPin1,HIGH); 
     delayMicroseconds(tempval1); 
     if (servoval1 < 255) 
     digitalWrite(ServoPin1,LOW); 
     if (servoval2 > 0) 
     digitalWrite(ServoPin2,HIGH); 
     delayMicroseconds(tempval2); 
     if (servoval2 < 255) 
     digitalWrite(ServoPin2,LOW); 
     delayMicroseconds(5000 - tempval1 - tempval2); 
     delay(15); // reduce/remove if we're doing more things here 

     // decrease the timer 
     if (--timer < 0) 
     { 
     timer=0; 
     analogWrite(PwmPinMotorA, 0); 
     analogWrite(PwmPinMotorB, 0); 
     } 
    }; 

    // wait for input 
    { 
     charin = mySerial.read(); // read it in 
#ifdef debugout 
     Serial.print(charin); 
     tempval1 = charin; 
     Serial.println(tempval1); 
#endif 

     if ((charin > 46 && charin < 58) || (charin=='d') || (charin=='j') || (charin=='c') || (charin=='v')) 
     { 
     inputBuffer[inputLength]=charin; 
     inputLength++; 

#ifdef serialout 
     mySerial.print("$PD,11,"); 
     mySerial.print(timer); 
     mySerial.print(","); 
     mySerial.print(value); 
     mySerial.println("*"); 
#endif 
     } 

    } 
    } 
    while (charin>46 && charin<119 && charin != LineEnd1 && charin != LineEnd2 && inputLength < BufferLength); 
    inputBuffer[inputLength] = 0; // add null terminator 
    HandleCommand(inputBuffer, inputLength); 
} 
+0

你能隔离你遇到问题的代码吗? – ArtB

+0

对不起,我知道这是很多代码,但我无法隔离问题。接收8j时,马达在接收2j时运行一秒钟,它们连续运行。 – user1919580

+3

代码越大,人们帮助你的可能性就越小。为了得到很好的答案,你真的需要把它缩小到一个小区域,或者希望有人对他们的时间非常慷慨。 – ArtB

回答

2

我编译的Arduino 1.0代码,并运行它在我临迷你16MHz的328与这些修改:

//#define debugout 

HardwareSerial mySerial = Serial; 

,跑在我的巨型16MHz的2560与这些修改:

#define PwmPinMotorA 7 

//#define debugout 

HardwareSerial mySerial = Serial; 

它似乎工作正常(由代码和我的示波器上的结果来判断)。

我一直在使用SoftwareSerial与我的GPS进行通话,我注意到它有奇怪的错误,如果我以9600波特运行它。我必须跑到4800才能进行无缝通信。

显然这并不能解释为什么你的--timer < 0会被忽略。我建议重写它,以便定时器功能始终处理如下:

unsigned long timeout = 2000; // 2 seconds 
unsigned long clrtime = 0; 
boolean  timecheck = false; 

// ... upon command set the event 
clrtime = millis() + timeout; 
timecheck = true; 

// ... every loop check for event 
if (timecheck && millis() > clrtime) 
{ 
    timecheck = false; 
    analogWrite(PwmPinMotorA, 0); 
    analogWrite(PwmPinMotorB, 0); 
} 

这是处理定时事件的更安全的方法。注意不要覆盖Arduino用于delay(),delayMicroseconds(),micros()和millis()的Timer0。我还建议交换引脚3和6以保持Timer2作为两者的源。这里是我测试的最终代码:

// Firmware for the Android Shield Board for tank robots 
// Pan/tilt servos now work: 0 pin off, 255 pin on, 1~254 8 bit granularity 
// servo movement (5 microseconds). 



// Required Libraries ////////////////////////////////////////////////////////// 





// Pin Mapping ///////////////////////////////////////////////////////////////// 

// Arduino 3 [PD3](INT1/OC2B) OC2B (Timer/Counter2 Output Compare Match B Output) 
// Arduino 4 [PD4](XCK/T0) T0 (Timer/Counter 0 External Counter Input) 
// Arduino 5 [PD5](T1/OC0B) T1 (Timer/Counter 1 External Counter Input) 
//        OC0B (Timer/Counter0 Output Compare Match B Output) 
// Arduino 6 [PD6](AIN0/OC0A) OC0A (Timer/Counter0 Output Compare Match A Output) 
// Arduino 8 [PB0](ICP/CLKO) ICP1 (Timer/Counter1 Input Capture Input) 
// Arduino 9 [PB1](OC1A)  OC1A (Timer/Counter1 Output Compare Match A Output) 
// Arduino 10 [PB2](SS/OC1B) OC1B (Timer/Counter1 Output Compare Match B Output) 
// Arduino 11 [PB3](MOSI/OC2) OC2A (Timer/Counter2 Output Compare Match A Output) 
    #define PwmPinMotorA 11 
    #define PwmPinMotorB 3  // SWAPPED! 
    #define DirectionPinMotorA 6 // SWAPPED! 
    #define DirectionPinMotorB 5 
    #define ServoPin1 0 
    #define ServoPin2 0 
    #define ServoFlip1 false 
    #define ServoFlip2 false 





// Global Macros /////////////////////////////////////////////////////////////// 

    #define mySerialSpeed 9600 // arduino 2009: 4800 or lower! 
    #define debugSerialSpeed 9600 // arduino 2009: 4800 or lower! 
    #define BufferLength 16 
    #define LineEnd1 13 
    #define LineEnd2 10 
    #define ServoTimingStep 5 
    #define ServoCenter 1500 
    #define ServoTimingFloor ServoCenter-(127*ServoTimingStep) 





// Global Variables //////////////////////////////////////////////////////////// 

    HardwareSerial mySerial = Serial; 

    char charin = 80; 
    char inputBuffer[BufferLength]; 
    int value = 128; 
    int speed = 128; 
    int inputLength = 0; 
    int servoval1 = 127; 
    int servoval2 = 127; 
    int tempval1, tempval2; 
    unsigned long timeout = 2000; // 2 seconds 
    unsigned long clrtime = 0; 
    boolean  timecheck = false; 




// Hardware Setup ////////////////////////////////////////////////////////////// 

    void setup() 
    { 
    // motor pins must be outputs 
    pinMode(PwmPinMotorA, OUTPUT); 
    pinMode(PwmPinMotorB, OUTPUT); 
    pinMode(DirectionPinMotorA, OUTPUT); 
    pinMode(DirectionPinMotorB, OUTPUT); 
    mySerial.begin(mySerialSpeed); 
    } 
    // setup() 





// Main Code /////////////////////////////////////////////////////////////////// 

    void loop() 
    { 
    // get a command string form the mySerial port 
    inputLength = 0; 
    do { 
     while (!mySerial.available()){ 
     // note: arduino cannot handle fullduplex on myserial so no output here! 

     // do servos here 
     tempval1 = (servoval1*ServoTimingStep) + ServoTimingFloor; 
     tempval2 = (servoval2*ServoTimingStep) + ServoTimingFloor; 
     if (servoval1 > 0) 
      digitalWrite(ServoPin1,HIGH); 
     delayMicroseconds(tempval1); 
     if (servoval1 < 255) 
      digitalWrite(ServoPin1,LOW); 
     if (servoval2 > 0) 
      digitalWrite(ServoPin2,HIGH); 
     delayMicroseconds(tempval2); 
     if (servoval2 < 255) 
      digitalWrite(ServoPin2,LOW); 
     delayMicroseconds(5000 - tempval1 - tempval2); 
     delay(15); // reduce/remove if we're doing more things here 

     // handle the timeout 
     if (timecheck && millis() > clrtime) 
     { 
      timecheck = false; 
      analogWrite(PwmPinMotorA, 0); 
      analogWrite(PwmPinMotorB, 0); 
     } 
     }; 

     // wait for input 
     { 
     charin = mySerial.read(); // read it in 

     if ((charin > 46 && charin < 58) || (charin=='d') || 
      (charin=='j') || (charin=='c') || (charin=='v')) 
     { 
      inputBuffer[inputLength]=charin; 
      inputLength++; 
     } 

     } 
    } 
    while (charin>46 && charin<119 && charin != LineEnd1 && 
      charin != LineEnd2 && inputLength < BufferLength); 
    inputBuffer[inputLength] = 0; // add null terminator 
    HandleCommand(inputBuffer, inputLength); 
    } 
    // loop() 





// Local Methods /////////////////////////////////////////////////////////////// 

    // process a command string 
    void HandleCommand(char* input, int length) 
    { 
    if (length < 1) { // not a valid command 
     return; 
    } 
    // calculate number following command (d10~d255) 
    if (length > 1) { 
     value = atoi(&input[1]); 
     if (value > 255) 
     value = 255; 
     if (value < 0) 
     value = 0; 
     switch(input[0]) 
     { 
     case 'd': 
     case 'D': 
     if (value > 127) 
      value = 127; 
     speed = value*2; 
     break; 
     case '/': 
     timeout = 100 * value; 
     break; 
     case 'c': 
     case 'C': 
     #ifdef ServoFlip1 
     servoval1 = 256 - value; 
     #else 
     servoval1 = value; 
     #endif 
     break; 
     case 'v': 
     case 'V': 
     #ifdef ServoFlip2 
     servoval2 = 256 - value; 
     #else 
     servoval2 = value; 
     #endif 
     break; 
     default: 
     break; 
     } 
    } 

    clrtime = millis() + timeout; 
    timecheck = true; 

    int* command = (int*)input; 
    // check commands 
    // note that the two bytes are swapped, ie 'RA' means command AR 



    switch(*command) { 

     case '2': 
     case '2j': 
     case '2J': 
     analogWrite(PwmPinMotorB, speed); 
     digitalWrite(DirectionPinMotorB, LOW); 
     analogWrite(PwmPinMotorA, speed); 
     digitalWrite(DirectionPinMotorA, HIGH); 
     break; 

     case '8': 
     case '8j': 
     case '8J': 
     analogWrite(PwmPinMotorB, speed); 
     digitalWrite(DirectionPinMotorB, HIGH); 
     analogWrite(PwmPinMotorA, speed); 
     digitalWrite(DirectionPinMotorA, LOW); 
     break; 

     case '6': 
     case '6j': 
     case '6J': 
     analogWrite(PwmPinMotorB, speed); 
     digitalWrite(DirectionPinMotorB, HIGH); 
     analogWrite(PwmPinMotorA, speed); 
     digitalWrite(DirectionPinMotorA, HIGH); 
     break; 

     case '4': 
     case '4j': 
     case '4J': 
     analogWrite(PwmPinMotorB, speed); 
     digitalWrite(DirectionPinMotorB, LOW); 
     analogWrite(PwmPinMotorA, speed); 
     digitalWrite(DirectionPinMotorA, LOW); 
     break; 

     case '9': 
     case '9j': 
     case '9J': 
     analogWrite(PwmPinMotorB, speed); 
     digitalWrite(DirectionPinMotorB, HIGH); 
     break; 

     case '1': 
     case '1j': 
     case '1J': 
     analogWrite(PwmPinMotorB, speed); 
     digitalWrite(DirectionPinMotorB, LOW); 
     break; 

     case '3': 
     case '3j': 
     case '3J': 
     analogWrite(PwmPinMotorA, speed); 
     digitalWrite(DirectionPinMotorA, HIGH); 
     break; 

     case '7': 
     case '7j': 
     case '7J': 
     analogWrite(PwmPinMotorA, speed); 
     digitalWrite(DirectionPinMotorA, LOW); 
     break; 

     default: // stop, just to be safe 
     analogWrite(PwmPinMotorA, 0); 
     digitalWrite(DirectionPinMotorA, LOW); 
     analogWrite(PwmPinMotorB, 0); 
     digitalWrite(DirectionPinMotorB, LOW); 
     break; 

    } 
    } 

因为我不能导致同样的错误,所以我不知道这是否解决了问题。祝你好运。