// switch parts int switch_pwm_A = 0; int switch_pwm_B = 0; bool usePIDCompute = false; float spd_rate_A = 1.0; float spd_rate_B = 1.0; bool heartbeatStopFlag = false; void movtionPinInit(){ pinMode(AIN1, OUTPUT); pinMode(AIN2, OUTPUT); pinMode(PWMA, OUTPUT); pinMode(BIN1, OUTPUT); pinMode(BIN2, OUTPUT); pinMode(PWMB, OUTPUT); ledcSetup(channel_A, freq, ANALOG_WRITE_BITS); ledcAttachPin(PWMA, channel_A); ledcSetup(channel_B, freq, ANALOG_WRITE_BITS); ledcAttachPin(PWMB, channel_B); digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); } void switchEmergencyStop(){ digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); } void switchPortCtrlA(float pwmInputA){ int pwmIntA = round(pwmInputA * spd_rate_A); if(abs(pwmIntA) < 1e-6){ digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); return; } if(pwmIntA > 0){ digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); ledcWrite(channel_A, pwmIntA); } else{ digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); ledcWrite(channel_A,-pwmIntA); } } void switchPortCtrlB(float pwmInputB){ int pwmIntB = round(pwmInputB * spd_rate_B); if(abs(pwmIntB) < 1e-6){ digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); return; } if(pwmIntB > 0){ digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); ledcWrite(channel_B, pwmIntB); } else{ digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); ledcWrite(channel_B,-pwmIntB); } } void switchCtrl(int pwmIntA, int pwmIntB) { switch_pwm_A = pwmIntA; switch_pwm_B = pwmIntB; switchPortCtrlA(switch_pwm_A); switchPortCtrlB(switch_pwm_B); } void lightCtrl(int pwmIn) { switch_pwm_A = pwmIn; switchPortCtrlA(-abs(switch_pwm_A)); } void setSpdRate(float inputL, float inputR) { inputL = abs(inputL); if (inputL > 1) { inputL = 1; } inputR = abs(inputR); if (inputR > 1) { inputR = 1; } spd_rate_A = inputL; spd_rate_B = inputR; } void getSpdRate() { jsonInfoHttp.clear(); jsonInfoHttp["T"] = CMD_GET_SPD_RATE; jsonInfoHttp["L"] = spd_rate_A; jsonInfoHttp["R"] = spd_rate_B; String getInfoJsonString; serializeJson(jsonInfoHttp, getInfoJsonString); Serial.println(getInfoJsonString); } // movtion parts. // A-left, B-right ESP32Encoder encoderA; ESP32Encoder encoderB; static unsigned long lastTime = 0; static unsigned long lastLeftSpdTime = 0; static unsigned long lastRightSpdTime = 0; int lastEncoderA = 0; int lastEncoderB = 0; double speedGetA; double speedGetB; double plusesRate = 3.14159265359 * WHEEL_D / ONE_CIRCLE_PLUSES; void initEncoders() { // if(SET_MOTOR_DIR){ // encoderA.attachHalfQuad(AENCB, AENCA); // encoderB.attachHalfQuad(BENCB, BENCA); // }else{ encoderA.attachHalfQuad(AENCA, AENCB); encoderB.attachHalfQuad(BENCA, BENCB); // } encoderA.setCount(0); encoderB.setCount(0); } void getWheelSpeed() { unsigned long currentTime = micros(); long encoderPulsesA = encoderA.getCount(); long encoderPulsesB = encoderB.getCount(); if (!SET_MOTOR_DIR) { speedGetA = (plusesRate * (encoderPulsesA - lastEncoderA)) / ((double)(currentTime - lastTime) / 1000000); speedGetB = (plusesRate * (encoderPulsesB - lastEncoderB)) / ((double)(currentTime - lastTime) / 1000000); } else { speedGetA = (plusesRate * (lastEncoderA - encoderPulsesA)) / ((double)(currentTime - lastTime) / 1000000); speedGetB = (plusesRate * (lastEncoderB - encoderPulsesB)) / ((double)(currentTime - lastTime) / 1000000); } lastEncoderA = encoderPulsesA; lastEncoderB = encoderPulsesB; lastTime = currentTime; } void getLeftSpeed() { unsigned long currentTime = micros(); long encoderPulsesA = encoderA.getCount(); if (!SET_MOTOR_DIR) { speedGetA = (plusesRate * (encoderPulsesA - lastEncoderA)) / ((double)(currentTime - lastLeftSpdTime) / 1000000); } else { speedGetA = (plusesRate * (lastEncoderA - encoderPulsesA)) / ((double)(currentTime - lastLeftSpdTime) / 1000000); } lastEncoderA = encoderPulsesA; lastLeftSpdTime = currentTime; } void getRightSpeed() { unsigned long currentTime = micros(); long encoderPulsesB = encoderB.getCount(); if (!SET_MOTOR_DIR) { speedGetB = (plusesRate * (encoderPulsesB - lastEncoderB)) / ((double)(currentTime - lastRightSpdTime) / 1000000); } else { speedGetB = (plusesRate * (lastEncoderB - encoderPulsesB)) / ((double)(currentTime - lastRightSpdTime) / 1000000); } lastEncoderB = encoderPulsesB; lastRightSpdTime = currentTime; } // --- PID Controller --- PID_v2 pidA(__kp, __ki, __kd, PID::Direct); PID_v2 pidB(__kp, __ki, __kd, PID::Direct); double outputA = 0; double outputB = 0; double setpointA = 0; double setpointB = 0; int setpoint_interval = 200; unsigned long setpoint_cmd_recv = millis(); unsigned long setpoint_last_time = millis(); float setpointA_buffer; float setpointB_buffer; float setpointA_last; float setpointB_last; float change_offset = 0.005; bool new_setpoint_flag = false; void pidControllerInit() { pidA.Start(speedGetA, outputA, setpointA); pidA.SetOutputLimits(-255, 255); pidA.SetMode(PID::Automatic); pidB.Start(speedGetB, outputB, setpointB); pidB.SetOutputLimits(-255, 255); pidB.SetMode(PID::Automatic); } void leftCtrl(float pwmInputA){ int pwmIntA = round(pwmInputA); if (mainType != 3) { speedGetA = pwmIntA; } if(SET_MOTOR_DIR){ if(pwmIntA < 0){ digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); ledcWrite(channel_A, abs(pwmIntA)); } else{ digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); ledcWrite(channel_A, abs(pwmIntA)); } }else{ if(pwmIntA < 0){ digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); ledcWrite(channel_A, abs(pwmIntA)); } else{ digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); ledcWrite(channel_A, abs(pwmIntA)); } } } void rightCtrl(float pwmInputB){ int pwmIntB = round(pwmInputB); if (mainType != 3) { speedGetB = pwmIntB; } if(SET_MOTOR_DIR){ if(pwmIntB < 0){ digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); ledcWrite(channel_B, abs(pwmIntB)); } else{ digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); ledcWrite(channel_B, abs(pwmIntB)); } }else{ if(pwmIntB < 0){ digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); ledcWrite(channel_B, abs(pwmIntB)); } else{ digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); ledcWrite(channel_B, abs(pwmIntB)); } } } void setGoalSpeed(float inputLeft, float inputRight) { // setpoint_cmd_recv = millis(); if (mainType == 3) { usePIDCompute = true; if(inputLeft < -2.0 || inputLeft > 2.0){ return; } if(inputRight < -2.0 || inputRight > 2.0){ return; } setpointA = inputLeft*spd_rate_A; setpointB = inputRight*spd_rate_B; if (setpointA != setpointA_buffer) { pidA.Setpoint(setpointA); setpointA_buffer = inputLeft; } if (setpointB != setpointB_buffer) { pidB.Setpoint(setpointB); setpointB_buffer = inputRight; } } else { usePIDCompute = false; leftCtrl(inputLeft * 512 * spd_rate_A); rightCtrl(inputRight * 512 * spd_rate_B); } } void pidControllerCompute() { if (!usePIDCompute) { return; } outputA = pidA.Run(speedGetA); if (abs(outputA) HEART_BEAT_DELAY) { if (!heartbeatStopFlag) { heartbeatStopFlag = true; setGoalSpeed(0, 0); // leftCtrl(0); // rightCtrl(0); } } } void changeHeartBeatDelay(int inputCmd) { HEART_BEAT_DELAY = inputCmd; } void mm_settings(byte inputMain, byte inputModule) { mainType = inputMain; moduleType = inputModule; if (mainType == 1) { WHEEL_D = 0.0800; ONE_CIRCLE_PLUSES = 2100; TRACK_WIDTH = 0.125; SET_MOTOR_DIR = false; // checked usePIDCompute = false; } else if (mainType == 2) { WHEEL_D = 0.0800; ONE_CIRCLE_PLUSES = 1650; TRACK_WIDTH = 0.172; SET_MOTOR_DIR = true; // checked usePIDCompute = false; } else if (mainType == 3) { WHEEL_D = 0.0523; ONE_CIRCLE_PLUSES = 1092; TRACK_WIDTH = 0.141; SET_MOTOR_DIR = true; // checked usePIDCompute = true; } plusesRate = 3.14159265359 * WHEEL_D / ONE_CIRCLE_PLUSES; // initEncoders(); if (mainType == 1) { screenLine_2 = "RaspRover"; } else if (mainType == 2) { screenLine_2 = "UGV02"; } else if (mainType == 3) { screenLine_2 = "UGV01"; } if (moduleType == 0) { screenLine_2 += " Null"; } else if (moduleType == 1) { screenLine_2 += " Arm"; } else if (moduleType == 2) { screenLine_2 += " PT"; } }