当前位置: 代码迷 >> 综合 >> 基于BBB的4轮移动轮式机器人系统设计与实现(四)--BeagleBone Black PWM 应用程序开发
  详细解决方案

基于BBB的4轮移动轮式机器人系统设计与实现(四)--BeagleBone Black PWM 应用程序开发

热度:99   发布时间:2024-01-21 06:50:00.0

在BBB开发板中,PWM的应用程序一共有三个类:PWM基类、PWM舵机类、PWM电机控制类


PWM基类表示PWM引脚的通用功能,如加载PWM引脚所对应的设备树、加载PWM定时器等


PWM基类定义

/** BeagleBonePWM.h**  Created on: 2014-6-9*      Author: sfe1012*/#ifndef BEAGLEBONEPWM_H_
#define BEAGLEBONEPWM_H_#include <string>
#include <dirent.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <unistd.h>const std::string PIN_MOTOR_FORWARD("P8_13");
const std::string PIN_MOTOR_BACK("P8_19");
const std::string PIN_SERVO_DERECTION("P9_14");
const std::string PIN_SERVO_SHOOK_HEAD("P9_16");
const std::string PIN_SERVO_NOD_HEAD("P9_21");const int MICRSECONDS_TO_NANOSECONDS = 1000;//微秒 转换 纳秒
const int MILLISECONDS_TO_MICROSECONDS = 1000;//毫秒 转换 微妙
const int MILLISECONDS_TO_NANOSECONDS = MILLISECONDS_TO_MICROSECONDS * MICRSECONDS_TO_NANOSECONDS; //毫秒 转 纳秒
const long MODULE_DELAY_TIME_US = 100 * MILLISECONDS_TO_MICROSECONDS; //  Time to wait for module to be loaded and the sysfs interface setup//#define DEBUG_VERBOSE_OUTPUT 1namespace PWM
{template<class T> inline std::string ToString(const T & value) //模板函数 数据类型转换{std::stringstream ss;ss << value;return ss.str();}inline void WriteToFile(const std::string & filePath, const std::string & value)//命令字写入相应的 管脚 对应的 属性文件{
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Writing: " << value << " to: " << filePath << std::endl;
#endifstd::ofstream out;out.open(filePath.c_str());out.exceptions(std::ios::badbit);out << value << std::endl;out.close();}// A bunch of helper functions to get us locations in the file system.// They are used so that we can manipulate the pwm driver through the /sys interface//这个函数将会返回在 dirname目录下  文件名称为filenameTofind 文件名std::string GetFullNameOfFileInDirectory(const std::string & dirName, const std::string & fileNameToFind);std::string GetCapeManagerSlotsPath();//获得slots 目标名称std::string GetOCPPath();//获得ocp的文件目录int GetCapeManagerSlot(const std::string & moduleName);//获取设备模块 当得到的时候 就返回 设备号void LoadDeviceTreeModule(const std::string & name);//加载设备模块 到 设备树void UnloadDeviceTreeModule(const std::string name);//卸载设备模块 设备树class Pin //管脚类{public:enum RunStatus{Free = -2, WaitingForSetp, Disabled, Enabled,//-1、0、1};enum Polarity{PolaritryHigh = 0, PolarityLow, // 1};private:std::string m_dutyFilePath;//管脚 占空比设置 文件位置std::string m_periodFilePath;//管脚  周期设置 文件位置std::string m_polarityFilePath;//管脚 输出占空比 极性  (BBB默认情况下,1表示占空比的输出为负,0表示为正)std::string m_runFilePath;//管脚 运行 控制位std::string m_pinName;//管脚 命名long m_periodNS; // 周期  纳秒单位long m_dutyNS; //占空比   纳秒单位Polarity m_polarity; //极性RunStatus m_runStatus;  //运行状态public:/*********SFE ADD*****************/void LoadDeviceTreeModuleForEspecial(const std::string &strName)const{LoadDeviceTreeModule(strName);//加载设备模块 到 设备树}/************************************/const std::string &GetDutyFilePath() const//获取占空比设置文件的位置{return m_dutyFilePath;}const std::string &GetPeriodFilePath() const//获取周期设置文件的位置{return m_periodFilePath;}const std::string &GetPolarityFilePath() const//获取极性设置文件的位置{return m_polarityFilePath;}const std::string &GetPinName() const//获取管脚的名字{return m_pinName;}const std::string &GetRunFilePath() const //获取管脚 运行管理的文件位置{return m_runFilePath;}const RunStatus &GetRunStatus() const  //获取管脚 运行状态{return m_runStatus;}const long &GetPeriodNS() const  //获取周期  纳秒为单位{return m_periodNS;}const Polarity &GetPolarity() const  //获取 管脚的极性{return m_polarity;}const long &GetDutyNS() const // 获取  管脚的占空比  纳秒为单位{return m_dutyNS;}private:void WriteDutyNSToFile()  //向占空比 设置文件 写入命令{WriteToFile(GetDutyFilePath(), ToString(GetDutyNS()));}void WritePeriodNSToFile() // 向周期 设置文件 写入命令{WriteToFile(GetPeriodFilePath(), ToString(GetPeriodNS()));}void WritePolarityToFile() //向 极性控制 文件 写入命令{WriteToFile(GetPolarityFilePath(), GetPolarity() == PolaritryHigh ? std::string("0") : std::string("1"));}public://占空比设置void SetDutyNS(const long & dutyNS)//纳秒{m_dutyNS = std::min(dutyNS, GetPeriodNS());if (GetRunStatus() == Enabled)WriteDutyNSToFile();}void SetDutyUS(const int &dutyUS)//微妙{SetDutyNS((long) dutyUS * MICRSECONDS_TO_NANOSECONDS);}void SetDutyMS(const int &dutyMS)//毫秒{SetDutyNS((long) dutyMS * MILLISECONDS_TO_NANOSECONDS);}void SetDutyPercent(const float &percent){SetDutyNS(long(GetPeriodNS() * percent));}//周期设置void SetPeriodNS(const long & periodNS)//纳秒{if (GetRunStatus() == Enabled || GetRunStatus() == Disabled){std::cout << "Trying to set the period but we need to release the PWM module first!" << std::endl;throw std::bad_exception();return;}m_periodNS = periodNS;if (GetRunStatus() == Enabled)WritePeriodNSToFile();}void SetPeriodUS(const int &periodUS) //微妙{SetPeriodNS((long) periodUS * MICRSECONDS_TO_NANOSECONDS);}void SetPeriodMS(const int &periodMS) //毫秒{SetPeriodNS((long) periodMS * MILLISECONDS_TO_NANOSECONDS);}void SetPolarity(const Polarity & polarity)//设置极性{m_polarity = polarity;if (GetRunStatus() == Enabled)WritePolarityToFile();}private:void SetRunStatus(const RunStatus & newRunStatus)  // 运行状态设置{if (newRunStatus != GetRunStatus()){if (newRunStatus == Disabled){WriteToFile(GetRunFilePath(), std::string("0"));}else if (newRunStatus == Enabled){if (GetRunStatus() == Free){InitPinFS();}// Force write the file values outWritePeriodNSToFile();WriteDutyNSToFile();WritePolarityToFile();WriteToFile(GetRunFilePath(), std::string("1"));}else if (newRunStatus == Free){if (GetRunStatus() != Disabled){SetRunStatus(Disabled);}UnloadDeviceTreeModule(GetPinName());}}m_runStatus = newRunStatus;}public:void Enable()  //运行状态 设置为 开始运行{SetRunStatus(Enabled);}void Disable(){SetRunStatus(Disabled);}void Release(){SetRunStatus(Free);}public:~Pin(){Release();}Pin(){}//默认构造函数中的  周期为20毫秒  占空比为 0 毫秒Pin(const std::string & pinName, const long & periodNS = 20 * MILLISECONDS_TO_NANOSECONDS, const long & dutyNS = 0* MILLISECONDS_TO_NANOSECONDS) :m_pinName(pinName){// If the pin is already in use then we need to free it!if (GetCapeManagerSlot(GetPinName()) != -1)//查找当强的管脚是否已经被应用 ,yes:释放它UnloadDeviceTreeModule(GetPinName());m_runStatus = WaitingForSetp;InitPinFS();SetPeriodNS(periodNS);//周期SetDutyNS(dutyNS);//占空比SetPolarity(PolaritryHigh);//极性//InitPinFS();}void InitPinFS() //设置BBB定时器  管脚命名  获取相应文件的位置 信息{//LoadDeviceTreeModule(std::string("am33xx_pwm"));//加入pwm定时器std::string pinModule = std::string("sc_pwm_") + GetPinName();//LoadDeviceTreeModule(pinModule);//加入pinstd::string pinInterfacePath = GetOCPPath() + GetFullNameOfFileInDirectory(GetOCPPath(), GetPinName()) + "/";m_dutyFilePath = pinInterfacePath + "duty";m_periodFilePath = pinInterfacePath + "period";m_polarityFilePath = pinInterfacePath + "polarity";m_runFilePath = pinInterfacePath + "run";#if DEBUG_VERBOSE_OUTPUTstd::cout << GetDutyFilePath() << std::endl;std::cout << GetPeriodFilePath() << std::endl;std::cout << GetPolarityFilePath() << std::endl;std::cout << GetRunFilePath() << std::endl;
#endif}};
}#endif /* BEAGLEBONEPWM_H_ */

PWM基类实现

/** BeagleBonePWM.cpp**  Created on: 2014-6-9*      Author: sfe1012*/
#include "BeagleBonePWM.h"namespace PWM
{// A bunch of helper functions to get us locations in the file system.// They are used so that we can manipulate the pwm driver through the /sys interface//这个函数将会返回在 dirname目录下  文件名称为filenameTofind 文件名std::string GetFullNameOfFileInDirectory(const std::string & dirName, const std::string & fileNameToFind){DIR *pDir;dirent *pFile;if ((pDir = opendir(dirName.c_str())) == NULL){std::cout << "Directory name: " << dirName << " doesnt exist!" << std::endl;throw std::bad_exception();}while ((pFile = readdir(pDir)) != NULL){std::string currentFileName = (pFile->d_name);if (currentFileName.find(fileNameToFind) != std::string::npos)//string  查找函数{return currentFileName;}}return std::string("");}std::string GetCapeManagerSlotsPath()//获得slots 目标名称{static std::string g_capeManagerSlotsPath;if (g_capeManagerSlotsPath.length() <= 0){
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Setting up cape manager path" << std::endl;
#endifstd::string capeBasePath("/sys/devices/");std::string fileName = GetFullNameOfFileInDirectory(capeBasePath, std::string("bone_capemgr."));g_capeManagerSlotsPath = capeBasePath + fileName + "/slots";}return g_capeManagerSlotsPath;}std::string GetOCPPath()  //获得ocp的文件目录{static std::string g_ocpPath;if (g_ocpPath.length() == 0){std::string ocpBasePath("/sys/devices/");std::string ocpName = GetFullNameOfFileInDirectory(ocpBasePath, std::string("ocp."));g_ocpPath = ocpBasePath + ocpName + '/';}return g_ocpPath;}int GetCapeManagerSlot(const std::string & moduleName){
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Trying to find slot for module: " << moduleName << std::endl;
#endifstd::ifstream in(GetCapeManagerSlotsPath().c_str());//找到 /sys/devices/bone_capemgr.9/slotsin.exceptions(std::ios::badbit);//读取slots 文件int slot = -1;while (in >> slot){std::string restOfLine;std::getline(in, restOfLine); //获取slots 中的一行if (restOfLine.find(moduleName) != std::string::npos)//在这一行中查找是否有这个管脚{
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Found Module: " << moduleName << " at slot: " << slot << std::endl;
#endifreturn slot;}}
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Module: " << moduleName << " not found in cape manager!" << std::endl;
#endifreturn -1;}void LoadDeviceTreeModule(const std::string & name){int slot = GetCapeManagerSlot(name);//查找是否存在  不存在返回 -1if (slot == -1){
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Adding Module: " << name << std::endl;std::cout << "Its going in: " << GetCapeManagerSlotsPath() << std::endl;
#endifWriteToFile(GetCapeManagerSlotsPath(), name);//命令写入其中usleep(MODULE_DELAY_TIME_US);}else{
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Module " << name << " is already in here!" << std::endl;
#endif}}void UnloadDeviceTreeModule(const std::string name){int currentSlot = GetCapeManagerSlot(name);if (currentSlot == -1){std::cout << "Why is the module " << name << " being unloaded when its not in use?" << std::endl;throw std::bad_exception();}
#if DEBUG_VERBOSE_OUTPUTstd::cout << "Unloading module: " << name << std::endl;
#endifWriteToFile(GetCapeManagerSlotsPath(), std::string("-") + ToString(currentSlot));usleep(MODULE_DELAY_TIME_US);}
}



PWM舵机控制类定义

/** BeagleBonePwmServo.h**  Created on: 2014-6-10*      Author: sfe1012*/
#ifndef BEAGLEBONEPWMSERVE_H_
#define BEAGLEBONEPWMSERVE_H_
#include "BeagleBonePWM.h"
#include "BeagleBonePwmMotor.h"
class BeagleBonePwmServo:public BeagleBonePwmMotor
{
public:BeagleBonePwmServo(const std::string &strPinName,const long &lPeriodTimeNs,const long &lDutyTimeNs,const long &lDrive,const long &lServoRightLimitUs,const long &lServoLeftLimitUs,const long &lServoCenterUs);~BeagleBonePwmServo();
public:const long &GetCenterValue()const;void  SetCenterValue(const long &lCenterValueUs);
public:void EnableMotorPwm();//void UpdateCurrentPwm();void UpdateMotorPwmSignalByStep(const long &lTargetDrive);void UpdateMotorPwmSignalBySetCurrentDriveNs(const long &lCurrentDrive);
private:long m_lServoRightLimitUs;long m_lServoLeftLimitUs;long m_lServoCenterUS;long m_lServoCurrentUS;long m_lServoStep;
};
#endif /* BEAGLEBONEPWMSERVE_H_ */

PWM舵机控制类实现

/** BeagleBonePwmServo.cpp**  Created on: 2014-6-13*      Author: sfe1012*/
#include"BeagleBonePwmServo.h"
BeagleBonePwmServo::BeagleBonePwmServo(const std::string &strPinName,const long &lPeriodTimeNs,const long &lDutyTimeNs,const long &lDrive,const long &lServoRightLimitUs,const long &lServoLeftLimitUs,const long &lServoCenterUs):BeagleBonePwmMotor(strPinName,lPeriodTimeNs,lDutyTimeNs,lDrive){m_lServoRightLimitUs = lServoRightLimitUs;//1000m_lServoLeftLimitUs = lServoLeftLimitUs;//2000m_lServoCenterUS = lServoCenterUs;//1500m_lServoCurrentUS = 0;m_lServoStep = (lServoLeftLimitUs - lServoRightLimitUs)/lDrive;
}
BeagleBonePwmServo::~BeagleBonePwmServo(){
}
const long &BeagleBonePwmServo::GetCenterValue()const{return m_lServoCenterUS;
}
void BeagleBonePwmServo::SetCenterValue(const long &lCenterValueUs){m_lServoCenterUS = lCenterValueUs;
}
void BeagleBonePwmServo::EnableMotorPwm(){GetPwmPinClass().SetDutyUS(m_lServoCenterUS);GetPwmPinClass().Enable();m_lServoCurrentUS = m_lServoCenterUS;
}
void BeagleBonePwmServo::UpdateMotorPwmSignalByStep(const long &lTargetDrive){m_lServoCurrentUS += lTargetDrive;if(m_lServoCurrentUS > m_lServoLeftLimitUs){m_lServoCurrentUS = m_lServoLeftLimitUs;}else if(m_lServoCurrentUS < m_lServoRightLimitUs){m_lServoCurrentUS = m_lServoRightLimitUs;}GetPwmPinClass().SetDutyUS(m_lServoCurrentUS*m_lServoStep);// Write out to PWM GetCurrentDrive()
}
void BeagleBonePwmServo::UpdateMotorPwmSignalBySetCurrentDriveNs(const long &lCurrentDrive){long lCurrentDriveTemp = 0 ;if(lCurrentDrive > m_lServoLeftLimitUs*1000){lCurrentDriveTemp = m_lServoLeftLimitUs*1000;}else if(lCurrentDrive < m_lServoRightLimitUs*1000){lCurrentDriveTemp = m_lServoRightLimitUs*1000;}elselCurrentDriveTemp = lCurrentDrive;std::cout<<"lCurrentDriveTemp:"<<lCurrentDriveTemp<<std::endl;GetPwmPinClass().SetDutyNS(lCurrentDriveTemp);// Write out to PWM GetCurrentDrive()
}

PWM电机控制类定义

/** BeagleBonePwmMotor.h**  Created on: 2014-6-13*      Author: sfe1012*/#ifndef BEAGLEBONEPWMMOTOR_H_
#define BEAGLEBONEPWMMOTOR_H_
#include "BeagleBonePWM.h"
class BeagleBonePwmMotor
{
public:BeagleBonePwmMotor();BeagleBonePwmMotor(const std::string &strPinName,const long &lPeriodTimeNs,const long &lDutyTimeNs,const long &lDrive);virtual ~BeagleBonePwmMotor();
public:PWM::Pin &GetPwmPinClass();const long &GetTargetDriveStep()const;void SetTargetDriveStep(const long & lTargetDriveStep);const long &GetCurrentDrive()const;void SetCurrentDrive(const long & lCurrentPWM);void LoadDeviceTreeModule(const std::string &strName)const;
public:virtual void EnableMotorPwm();virtual void UpdateCurrentPwm();virtual void UpdateMotorPwmSignalByStep(const long &lTargetDrive);virtual void UpdateMotorPwmSignalBySetCurrentDriveUs(const long &lCurrentDrive);virtual void UpdateMotorPwmSignalBySetCurrentDriveNs(const long &lCurrentDrive);
private:PWM::Pin m_Pin;long m_lCurrentDrive;long m_lTargetDriveStep;//在当前的档位上 加多少 还是 减掉 多少long m_lDrive; //一共有多少个前进档位long m_lStep; //每个档位代表多少个 微妙的占空比
};
#endif /* BEAGLEBONEPWMMOTOR_H_ */



PWM电机控制类实现

/** BeagleBonePwmMotor.cpp**  Created on: 2014-6-13*      Author: sfe1012*/
#include"BeagleBonePwmMotor.h"
BeagleBonePwmMotor::BeagleBonePwmMotor(const std::string &strPinName,const long &lPeriodTimeNs,const long &lDutyTimeNs,const long &lDrive):m_Pin(strPinName, lPeriodTimeNs,lDutyTimeNs){m_lCurrentDrive = 0;m_lTargetDriveStep = 0;m_lDrive = lDrive;m_lStep = lPeriodTimeNs / (m_lDrive*1000);
}
BeagleBonePwmMotor::BeagleBonePwmMotor()
{
}
BeagleBonePwmMotor::~BeagleBonePwmMotor(){
}
PWM::Pin &BeagleBonePwmMotor::GetPwmPinClass(){return m_Pin;
}
const long &BeagleBonePwmMotor::GetTargetDriveStep()const{return m_lTargetDriveStep;
}
void BeagleBonePwmMotor::SetTargetDriveStep(const long & lTargetDriveStep){m_lTargetDriveStep = lTargetDriveStep;
}
const long &BeagleBonePwmMotor::GetCurrentDrive()const{return m_lCurrentDrive;
}
void BeagleBonePwmMotor::SetCurrentDrive(const long & lCurrentDrive){m_lCurrentDrive = lCurrentDrive;
}
void BeagleBonePwmMotor::EnableMotorPwm(){GetPwmPinClass().Enable();
}
void BeagleBonePwmMotor::UpdateCurrentPwm(){if(m_lTargetDriveStep > 0 || m_lTargetDriveStep == 0){m_lCurrentDrive += m_lTargetDriveStep;}else if(m_lTargetDriveStep < 0){m_lCurrentDrive += m_lTargetDriveStep;}if(m_lCurrentDrive > m_lDrive){m_lCurrentDrive = m_lDrive;}else if(m_lCurrentDrive < 0){m_lCurrentDrive = 0;}#ifdef DEBUG_VERBOSE_OUTPUTstd::cout<<"m_lCurrentDrive :"<<m_lCurrentDrive<<std::endl;#endif
}
void BeagleBonePwmMotor::UpdateMotorPwmSignalByStep(const long &lTargetDriveStep){SetTargetDriveStep(lTargetDriveStep);UpdateCurrentPwm();#ifdef DEBUG_VERBOSE_OUTPUTstd::cout<<"UpdateMotorPwmSignalByStep : GetCurrentDrive()*m_lStep::"<<GetCurrentDrive()*m_lStep<<std::endl;#endifGetPwmPinClass().SetDutyUS(GetCurrentDrive()*m_lStep);// Write out to PWM GetCurrentDrive()
}
void BeagleBonePwmMotor::UpdateMotorPwmSignalBySetCurrentDriveUs(const long &lCurrentDrive)
{
//	long lCurrentDriveTemp = 0;
//	if(lCurrentDrive > m_lDrive || lCurrentDrive == 0)
//	{
//		lCurrentDriveTemp = m_lDrive;
//	}
//	if(lCurrentDrive < 0)
//	{
//		lCurrentDriveTemp = 0;
//	}#ifdef DEBUG_VERBOSE_OUTPUTstd::cout<<"UpdateMotorPwmSignalBySetCurrentDrive : GetCurrentDrive()*m_lStep::"<<lCurrentDrive*m_lStep<<std::endl;#endifGetPwmPinClass().SetDutyUS(lCurrentDrive*m_lStep);// Write out to PWM GetCurrentDrive()
}
void BeagleBonePwmMotor::UpdateMotorPwmSignalBySetCurrentDriveNs(const long &lCurrentDrive)
{#ifdef DEBUG_VERBOSE_OUTPUTstd::cout<<"UpdateMotorPwmSignalBySetCurrentDrive :"<<lCurrentDrive<<std::endl;#endifGetPwmPinClass().SetDutyNS(lCurrentDrive);// Write out to PWM GetCurrentDrive()
}
void BeagleBonePwmMotor::LoadDeviceTreeModule(const std::string &strName)const
{m_Pin.LoadDeviceTreeModuleForEspecial(strName);
}


应用方法:

#include <stdlib.h>
#include"GraduationHead.h"
#include"BeagleBonePwmMotor.h"
#include"BeagleBonePwmServo.h"
using namespace std;
int main(){cout << "!!! Hello BeagleBone Black !!!" << endl; // prints !!!Hello World!!!/***PIN_MOTOR_BACK***********PWM Init**********PIN_MOTOR_FORWARD*********/BeagleBonePwmMotor PWMTimeLoad;PWMTimeLoad.LoadDeviceTreeModule("am33xx_pwm");BeagleBonePwmMotor MotorForward(PIN_MOTOR_FORWARD,20 * MILLISECONDS_TO_NANOSECONDS,0,100);//BeagleBonePwmMotor MotorBack(PIN_MOTOR_BACK,20 * MILLISECONDS_TO_NANOSECONDS,0,100);BeagleBonePwmServo ServoShookHead(PIN_SERVO_SHOOK_HEAD,20 * MILLISECONDS_TO_NANOSECONDS,0,100,1000,2000,1500);BeagleBonePwmServo ServoNodHead(PIN_SERVO_NOD_HEAD,20 * MILLISECONDS_TO_NANOSECONDS,0,100,1000,2000,1500);BeagleBonePwmServo ServoDerection(PIN_SERVO_DERECTION,20 * MILLISECONDS_TO_NANOSECONDS,0,100,1370,1650,1500);MotorForward.EnableMotorPwm();MotorBack.EnableMotorPwm();ServoShookHead.EnableMotorPwm();ServoNodHead.EnableMotorPwm();ServoDerection.EnableMotorPwm();usleep(MODULE_DELAY_TIME_US);;//等待PWM定时器设置成功/****************Data Analaze*******************/SerialDataAnalaze oSerialDataAnalaze;/**********************PWM Data*****************/long olMotorForward = 500; //nslong olMotorBack = 0;//500; //nslong olServoShookHead = 1500000; //nslong olServoNodHead = 1500000; //nslong olServoDerection = 1500000; //nslong lButtonNum = 0;while(1){MotorForward.UpdateMotorPwmSignalBySetCurrentDriveNs(olMotorForward);//usleep(MODULE_DELAY_TIME_US);;//等待设置成功MotorBack.UpdateMotorPwmSignalBySetCurrentDriveNs(olMotorBack);//usleep(MODULE_DELAY_TIME_US);;//等待设置成功ServoShookHead.UpdateMotorPwmSignalBySetCurrentDriveNs(olServoShookHead);//usleep(MODULE_DELAY_TIME_US);;//等待设置成功ServoNodHead.UpdateMotorPwmSignalBySetCurrentDriveNs(olServoNodHead);//usleep(MODULE_DELAY_TIME_US);;//等待设置成功ServoDerection.UpdateMotorPwmSignalBySetCurrentDriveNs(olServoDerection);//usleep(MODULE_DELAY_TIME_US);;//等待设置成功}return 0;
}

  相关解决方案