Arduino:极简主义循环状态机的问题

时间:2015-01-18 17:07:46

标签: c++ arduino

这是一个简单机器人的Arduino Uno代码。

我有一个非常简单的循环状态机。我的问题是,当它应该折回到第一个状态(State0)时,它会重置固件。据我所知,限制设置正确,但显然,我错了......

这是状态机(.h和.cpp):

#ifndef MChSM_h
#define MChSM_h

#include <Arduino.h>
#include "MChLeg.h" //for the actions

const int MChmachinestateMax = 5; //max statemachine
const int MChmachinestateMax1 = MChmachinestateMax+1; //max statemachine for modulo counting

struct MChSMState{
  int stateId;
  void (*stateAction)(); //pointer to function for state
};


class MChStateMachine{
public:
    MChStateMachine();
    ~MChStateMachine();
    void setState(int);
    int getState();
    void incrementState();
    void addState(MChSMState state);
private:    
    int machinestate;
    MChSMState machinestates [MChmachinestateMax1];
    void doState();
};

#endif MChSM_h

#include "MChSM.h"

MChStateMachine::MChStateMachine(){
}

MChStateMachine::~MChStateMachine(){
}

int MChStateMachine::getState(){
  return this->machinestate;
}

void MChStateMachine::setState(int newState){
  this->machinestate = newState;
  this->doState();
}

void MChStateMachine::incrementState(){
    this->setState((this->getState() + 1) % MChmachinestateMax1);
}

void MChStateMachine::addState(MChSMState state){
  if ((state.stateId >= 0)&&(state.stateId < MChmachinestateMax)){
    this->machinestates[state.stateId] = state;
  }
}

void MChStateMachine::doState(){
    // set LEDs according to state
    void (*action)();
    action = this->machinestates[machinestate].stateAction;
    (*action)();
}

以下是代码的调用方式:

// Include application, user and local libraries
#include <Servo.h>
#include "MChButton.h"
#include "MChLeg.h"
#include "MChSM.h"


// pin connections
const int buttonIndex = 2; //pin for button
const int greenLed = 3;//pin for green Led
const int yellowLed = 4;//pin for yellow Led
const int redLed = 5;//pin for red Led
const int servoPin1 = 9;//pin for servo
const int servoPin2 = 10;//pin for servo
const int servoPin3 = 11;//pin for servo

//Input stuff
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete



//define persitent objects
MChButton theButton(buttonIndex); // declare the switch pin as an input
MChLeg rightLeg; // declare right leg 
MChLeg leftLeg;  // declare left leg

//build state machine
MChStateMachine myStateMachine;

//list states
void State0(){
    digitalWrite(greenLed, HIGH); // turn the green LED on pin 3 on
    digitalWrite(yellowLed, LOW);  // turn the red LED on pin 4 off
    digitalWrite(redLed, LOW);  // turn the red LED on pin 5 off
    leftLeg.setLeg(70, 70); // set leg to 0°
    rightLeg.setLeg(70, 70); //set leg to 0°
}
void State1(){
    digitalWrite(greenLed, HIGH);
    digitalWrite(yellowLed, HIGH);
    digitalWrite(redLed, LOW);
    leftLeg.setLeg(30, 30);
    delay(200);
    rightLeg.setLeg(80, 80);
}
void State2(){
    digitalWrite(greenLed, LOW);
    digitalWrite(yellowLed, HIGH);
    digitalWrite(redLed, LOW);
    leftLeg.setLeg(30, 30);
    rightLeg.setLeg(90, 90);
}
void State3(){
    digitalWrite(greenLed, LOW);
    digitalWrite(yellowLed, HIGH);
    digitalWrite(redLed, HIGH);
    leftLeg.setLeg(30, 30);
    rightLeg.setLeg(100,100);
}
void State4(){
    digitalWrite(greenLed, LOW);
    digitalWrite(yellowLed, LOW);
    digitalWrite(redLed, HIGH);
    rightLeg.setLeg(110, 110);
    delay(200);
    leftLeg.setLeg(70, 70);
}


// Setup phase
//
// Brief assign functions to pins and create objects
// Details tbd
//
void setup(){
    // say hello
    Serial.begin(9600);
    Serial.println("Robot6 started");

    // declare the LED pins as outputs
    pinMode(greenLed,OUTPUT);
    pinMode(yellowLed,OUTPUT);
    pinMode(redLed,OUTPUT);

    leftLeg.assignLeg(0, servoPin1); //right knee - hip
    rightLeg.assignLeg(servoPin2, servoPin3); //right knee - hip 

    MChSMState myState;
    myState.stateId = 0;
    myState.stateAction = &State0;
    myStateMachine.addState(myState);
    myState.stateId = 1;
    myState.stateAction = &State1;
    myStateMachine.addState(myState);
    myState.stateId = 2;
    myState.stateAction = &State2;
    myStateMachine.addState(myState);
    myState.stateId = 3;
    myState.stateAction = &State3;
    myStateMachine.addState(myState);
    myState.stateId = 4;
    myState.stateAction = &State4;
    myStateMachine.addState(myState);
    myStateMachine.setState(0);

}

// Loop phase
//
// Brief call functions on infinite loop
// Details tbd
//
void loop(){

    //check if there is an event, if there is one increment state machine counter and mark event done
    if (theButton.buttonEventGet()==true) {
        myStateMachine.incrementState();
    }

    // set LEDs according to state

    delay(10);
    if (stringComplete) {
        if (inputString == "next\n"){
          myStateMachine.incrementState();
        }
        Serial.println(inputString); 
        // clear the string:
        inputString = "";
        stringComplete = false;
    }

}

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read(); 
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    } 
  }
}

我检查过我经历过所有州,我认为我的限制或增量有问题,但我找不到问题。我尝试设置MChmachinestateMax = 4,但正如预期的那样,这确实阻止我达到State4。

1 个答案:

答案 0 :(得分:1)

答案发现,应该是:

void MChStateMachine::incrementState(){
    this->setState((this->getState() + 1) % MChmachinestateMax); //was MChmachinestateMax1... this was the bug I was looking forT
}