0

モーターが逆転するたびにモーターコントローラーを交換したので、ブレーキがかかるはずのときにブレーキがかかりません...

コンソールアプリのボタンを押している限り実行されます。左右に回すと、逆転中のモーターが止まらずに走ります。後退すると、どちらも止まることなく走ります。

    // 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);
}
4

1 に答える 1

2

あなたのコードを Arduino 1.0 でコンパイルし、Pro Mini 16MHz 328 で次の変更を加えて実行しました。

//#define debugout

HardwareSerial mySerial = Serial;

これらの変更を加えて、Mega 16MHz 2560 で実行しました。

#define PwmPinMotorA 7

//#define debugout

HardwareSerial mySerial = Serial;

正常に動作しているようです(コードとオシロスコープの結果から判断)。

GPS と通信するために SoftwareSerial を使用していますが、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;

    }  
  } 

あなたと同じエラーを引き起こすことはできないので、これで問題が解決するかどうかわかりません。幸運を。

于 2012-12-20T22:06:26.453 に答える