ROS output PWM for Raspberry Pi (4B)ubuntu

a brief introdction

Due to the needs of the project, the Raspberry Pi needs to be used to output PWM to control the servo. Therefore, several different solutions have been adopted, but the effects are not the same. I will record them here.

Wiring Pi solution

Because the pins of the Raspberry Pi are used to output PWM, some libraries that control the pins of the Raspberry Pi need to be used. WiringPi is just one of them. In addition, there are libraries such as gpiozero and pigpio. It is said that pigpio can be used in ubuntu20.04 Download the libraries that are normally used. The implication is that the other two libraries may have some problems, but most of the functions can be used when I use WiringPi. Some people say that PI4B is not supported, but I can use it just fine. . .

Wiring Pi installation

sudo apt-get install wiringpi
//对于树莓派2019年5月之后的系统(早于之前的可不用执行),可能需要进行升级:
wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb
gpio -v
// 运行gpio -v会出现2.52版本,如果没有出现说明安装出错

Here is a brief introduction to what hardware PWM and software PWM mean respectively?
Hardware PWM means the two PWM ports marked with red lines in the pins in the picture below. These are ports provided by the Raspberry Pi itself that can output PWM. There is no need to write cumbersome codes.
Software PWM means that everyone knows the principle of PWM. Just set the time to output high and low levels by yourself, so the software PWM can control any Pin port, and the function written by the Wiring Pi library controls the PWM output.

But for us, the process of writing code is almost the same as calling functions. Anyway, the software PWM has library functions that can be written for you. Just call it yourself.

Although the Raspberry Pi provides two PWM channels on the hardware, after testing, when PWM0 is running, the waveforms output by the two pins to ground are the same, that is, when PWM0 is used, the waveforms output by GPIO 1 and GPIO 26 are the same. of.

WiringPi Pin BCM Pin Physical Pin PWM0、PWM1
GPIO 1 GPIO 18 Pin 12 PWM0
GPIO 26 GPIO 12 Pin 32 PWM0
GPIO 23 GPIO 13 Pin 33 PWM1
GPIO 24 GPIO 19 Pin 35 PWM1

You can see that the wiringpi library has three pin numbering methods, which are:
BCM numbering method - uses the GPIO pin number of the chip.

Wiringpi library numbering method - use the numbering method specified by the wiringpi library itself.

Pin numbering method of the pin header - follow the pin numbering method of the 20*2 pin header on the Raspberry Pi.

Here, taking the wiringPi-Python library as an example, four configuration functions are provided:

wiringPiSetup ——> wiringpi number

wiringPiSetupGpio ——> BCM number

wiringPiSetupPhys ——> pin header physical number

wiringPiSetupSys ——> BCM number, the mapping under /sys/class/gpio used
is here .

wiringpi number
Insert picture here112

BCM number
Insert image description here

Correspondence
Insert image description here

Wiring Pi hardware output PWM

For hardware PWM, you can refer to here and here or here
. Here is a simple example of hardware output PWM, LED breathing light.

#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>
// 设置GPIO1为LED灯的控制引脚
#define PWM_PIN     1//可以换成23 24 26
int main(void)
{
    
    
    int bright ;
    printf("wiringPi-C PWM test program\n") ;
    // 配置gpio
    wiringPiSetup();//使用wiringpi编号
    // 配置GPIO1为PWM模式
    pinMode(PWM_PIN, PWM_OUTPUT);
    while(1) {
    
    
        for(bright = 0 ; bright < 1000; bright++) {
    
    
            // bright为 0 ~ 1000,最大是1023
            pwmWrite(PWM_PIN, bright);
            delay(1) ;
        }
        for(bright = 1000; bright >= 0; bright--) {
    
    
            pwmWrite(PWM_PIN, bright);
            delay(1) ;
        }
    }
    return 0 ;
}

Save the code to the led_pwm.c file, and then execute the compile command:

Show some below 内联代码片.

gcc led_pwm.c -o led_pwm -lwiringPi

Run program

sudo ./led_pwm

To use the hardware PWM interface, you need to include the header file:#include <wiringPi.h>

pwmSetClock (int divisor)
parameters: divisor: Set the frequency division of the PWM clock. Range: 2 ~ 4095.
Note: The PWM basic clock is 19.2MHz. When the WiringPi library is initialized, the default divisor value is 32, so the default PWM clock is PWMfreq = 19.2 x 1000 x 1000 / 32 = 600KHz.

pwmSetMode (int mode)

Parameters: mode: The PWM generator can work in 2 modes, Balanced and Mark:Space modes (duty cycle mode), corresponding setting parameters: PWM_MODE_BAL and PWM_MODE_MS. Mark:Space is the traditional PWM mode, and the Raspberry Pi defaults to PWM working in Balanced mode. If the duty cycle needs to be reset, it must be set to Mark:Space mode.

pwmSetRange (int range)

Parameters: range: used to set the period of PWM, the default value is 1024. Calculation method: For example, 600KHz PWM clock,
range = (600 x 1000Hz) / PWMfreq

pwmWrite (int pin, int value)
parameters:
pin: hardware PWM pin number (number in WiringPi), a PWM wave will be generated on this pin.
value: Set the duty cycle, value range: 0 ~ range, default range: 0-1023. Because a cycle is divided into equal parts of the range, the duty range is 0~range.

At this point, basically if you run the executable file generated above, you can detect the corresponding PWM on the corresponding pin port.
But my requirement is not just that, but to control it in ROS, and the duty cycle can be changed at any time to control the servo.
When I wrote the above program into my topic or service, the problem occurred. The specific error was because I did not have permission to control the specified pin port.

No access to /dev/mem. Try running as root!

There is no such problem when running the executable file generated above because sudo was added before. When running rosrun, adding sudo will report an error.
Therefore, we have to change to another idea, which is to use the following command to increase the permissions according to the needs.

sudo shmod 777 /dev/gpiomem
sudo shmod 777 /dev/mem

Basically, it’s the two above. When I ran the above two commands, the result was still an error, which made me unable to complete the purpose of controlling pwm in ros, so I had to switch to another method. If there is any A master knows how to do it. Please leave a message in the comment area or message me privately. Thank you.

-------------------------------------------------- -Dividing line
2023-5-6
My own problem, I solved it myself

    import RPi.GPIO as GPIO
    import time"
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    
    GPIO.setup(24, GPIO.OUT)
    GPIO.setup(16, GPIO.OUT)

    p24 = GPIO.PWM(24, 100)//100为频率
    p16 = GPIO.PWM(16, 100)

    p24.start(0)
    p16.start(0)
    
    p16.ChangeDutyCycle(50)
    p24.ChangeDutyCycle(50)

This is a soft pwm output using wiring pi. Just write this to pwm.py and then run python pwm.py. After testing, it was found that when running it alone, the pwm output is relatively stable, and it is basically not possible to control the LED light. Will flash. But when running it, and then running other programs, for example, I need to run the relevant nodes of ros, so the pwm output in this way is unstable, and the phenomenon corresponding to the LED is that the light is flashing. It feels like it’s caused by uneven distribution of resources.

The corresponding code in my ros is

int pwm_function_from_python(int a, int leftright) {
    
    

    //int res;
    //PyObject *pModule,*pFunc;
    //PyObject *pArgs, *pValue;
    //PyObject *pName = NULL;
    
    
    
    sprintf(str, "%d", a);
    if(leftright == 1)
    {
    
    stt = "p24.ChangeDutyCycle(";}//motor 26  light 24
    if(leftright == 2)
    {
    
    stt = "p16.ChangeDutyCycle(";} 
    stt = stt + str + ")";
    // if(leftright == 3)
    //   {stt = "pi.write(23, 1)";}
    // else if(leftright == -3)
    //   {stt = "pi.write(23, 0)";}
    // if(leftright == 4)
    //   {stt = "pi.write(24, 1)";}
    // else if(leftright == -4)
    //   {stt = "pi.write(24, 0)";}
    strcpy(str,stt.c_str());
    
    if(b == 3){
    
    
    b=4;
    
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import os");

    
    PyRun_SimpleString("sys.path.append('/home/ubuntu/wsh/catkin_ws/src/learning_communication')");//若python文件在c++工程下
    PyRun_SimpleString("sys.path.append('./')");
    //PyRun_SimpleString("print(sys.path)");
    PyErr_Print();
    /* import */
    PyRun_SimpleString("import RPi.GPIO as GPIO");
    PyRun_SimpleString("import time");
    PyRun_SimpleString("GPIO.setmode(GPIO.BCM)");
    PyRun_SimpleString("GPIO.setwarnings(False)");
    
    PyRun_SimpleString("GPIO.setup(24, GPIO.OUT)");
    PyRun_SimpleString("GPIO.setup(16, GPIO.OUT)");

    PyRun_SimpleString("p24 = GPIO.PWM(24, 100)");
    PyRun_SimpleString("p16 = GPIO.PWM(16, 100)");

    PyRun_SimpleString("p24.start(0)");
    PyRun_SimpleString("p16.start(0)");
    PyRun_SimpleString(str);
    }
    if(b != 3)
    {
    
    PyRun_SimpleString(str);} 

    return a;
}

Wiring Pi software output PWM

Here is a simple example of software output PWM, LED breathing light.

#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>
// 定义控制LED灯的GPIO引脚,使用GPIO0
#define PWM_PIN     0
int main(void)
{
    
    
    int bright ;
    printf("wiringPi-C Software PWM test program\n") ;
    // 初始化
    wiringPiSetup();
    pinMode(PWM_PIN, OUTPUT);
    softPwmCreate(PWM_PIN, 0, 100);
    while(1) {
    
    
        for(bright = 0; bright < 100; bright++) {
    
    
            softPwmWrite(PWM_PIN, bright);
            delay(10);
        }
        for(bright = 100; bright >= 0; bright--) {
    
    
            softPwmWrite(PWM_PIN, bright);
            delay(10);
        }
    }
    return 0 ;
}

To use the software PWM interface, you need to include the header file: #include <softPwm.h>
softPwmCreate (int pin, int value, int range)
is used to create software-controlled PWM and can generate PWM waves on any GPIO port.
Parameters:
pin: GPIO pin number to generate PWM wave.
value: Specify any initial value between PWM range.
range: PWM frequency range. Set range to 100, then the PWM frequency is 100Hz, and the value range is from 0 to 100. These values ​​are useful for generating PWM with different duty cycles.
Note: PWMfreq = 1 x 10^6 / (100 x range), the unit is Hz, where 100 is a fixed parameter of the source code.

void softPwmWrite (int pin, int value)
parameters:
pin: the GPIO port to be controlled, that is, the GPIO port set in the softPwmCreate function.
value: duty cycle value, range: 0~range.

void softPwmStop (int pin)
parameters:
pin: GPIO port to be closed.

If you don’t know much about duty cycle and frequency here, you can refer here or here
. Note: the higher the PWM frequency, the more CPU resources are required. Pay special attention to the need to find a balance.
However, here, the problem arises again. PWM can be generated, but it is not stable enough. The specific form of instability is that after the duty cycle is set to a certain value, it will keep beating. Although the range of the beating is not large, it corresponds to the rudder. On the machine, the reaction was that the servo was shaking. This phenomenon was extremely intolerable, so I had to try another library to control gpio, pigpio. If anyone has a solution to this problem, please feel free to discuss it in the comment area.

In addition, you can refer to the usage of other Wiring Pi control pins here.

The pigpio library manual is also available here: link: https://pan.baidu.com/s/1ff-fwkx7640TgH6Mm2VmaQ
extraction code: xqap

Pigpio solution

pigpio official website

Pigpio installation

There are many installation methods, just use one of them without having to repeat the installation:

Direct installation

sudo apt-get update
sudo apt-get install pigpio python-pigpio python3-pigpio

make installation

You can install it using make, there are several methods, please refer to the following steps:
Please note: If you have installed before, please delete or rename any existing pigpio zip or tar file first. Delete or rename any existing PIGPIO or pigpio-master directories (remember to save your own files in that directory first).
method one:

rm pigpio.zip
sudo rm -rf PIGPIO
wget abyz.me.uk/rpi/pigpio/pigpio.zip
unzip pigpio.zip
cd PIGPIO
make
sudo make install

Method Two:

rm pigpio.tar
sudo rm -rf PIGPIO
wget abyz.me.uk/rpi/pigpio/pigpio.tar
tar xf pigpio.tar
cd PIGPIO
make
sudo make install

Method three:

rm master.zip
sudo rm -rf pigpio-master
wget https://github.com/joan2937/pigpio/archive/master.zip
unzip master.zip
cd pigpio-master
make
sudo make install

After successful installation using any of the above methods, run the following test:

sudo ./x_pigpio // check C I/F
sudo pigpiod    // 开启守护进程
./x_pigpiod_if2 // check C      I/F to daemon
./x_pigpio.py   // check Python I/F to daemon
./x_pigs        // check pigs   I/F to daemon
./x_pipe        // check pipe   I/F to daemon

Pigpio loses PWM

pigpio is a library function written in C language and provides a Python interface. But most of the programs I write are in C++, so I want to find a C interface, but I searched a lot of information on the Internet and couldn't find it. They all use Python, so I had to come up with a strange idea to call Python functions in C++. . . It finally succeeded. Not only was the call successful, but the PWM generation was also stable.

Let’s first talk about Pigpio generating PWM. You can refer to here

1. Before running the written code, you need to execute the following command

sudo pigpiod

This is done to open a thread for running the library. If you don't do this, an error will be prompted when running the code. If you finish running the program and want to close the library, you can use the following command

sudo killall pigpiod

2. Write code

import pigpio
import time
pi = pigpio.pi()          // 初始化
if not pi.connected:      // 检查是否连接成功 
   exit()
user_gpio = 26
pulsewidth = 1500         // 可以设置500至2500,这是电平为1的时间,单位是微秒
//为伺服电机产生PWM信号,设置频宽为1500 us,该信号频率默认为50Hz
pi.set_servo_pulsewidth(user_gpio, pulsewidth)
time.sleep(10)            // 延迟10秒
pi.wave_tx_stop() 
pi.wave_clear()
pi.stop()

This is a relatively elementary method that cannot change the frequency (the frequency is 50Hz, which is exactly the frequency of controlling the servo). The duty cycle can be modified according to pulsewidth. For a more complex and practical method, refer to [here], (https ://blog.csdn.net/weixin_52157994/article/details/124054827?spm=1001.2014.3001.5502)
This default frequency already meets my requirements, so I will ignore the more complicated ones, hahaha.

--------------------------------------------------Dividing line
2023- 5-6
Now that we have a solution, we can still adjust the frequency when using PIgpio.
First, we provide a method for hardware output pwm. PWM is very stable and not affected by other programs and resources (this is the solution provided to me by chatgpt)

import pigpio
import time

pi = pigpio.pi()

if not pi.connected:
   exit()

user_gpio = 18
frequency = 1000 # 设置频率为1kHz
duty_cycle = 500000 # 设置占空比为50%

pi.hardware_PWM(user_gpio, frequency, duty_cycle)

time.sleep(10)

pi.hardware_PWM(user_gpio, 0, 0) # 停止PWM输出

pi.stop()

In this example, we use the hardware_PWM() method to set the PWM frequency and duty cycle. The frequency parameter is used to set the frequency of the PWM in Hertz. The duty_cycle parameter is used to set the duty cycle in microseconds. Note that the duty cycle range is 0 to 1000000, representing a duty cycle of 0% to 100%.

In this example, we set the PWM frequency to 1kHz and the duty cycle to 50%. This will produce a square wave with a period of 1ms, where the high level duration is 0.5ms and the low level duration is also 0.5ms.

You can change the frequency and duty cycle values ​​as needed to control the PWM output.

The above method provides hard pwm, which is very stable, but the hard pwm only has those ports 12 13 18 19. 18 is used here. After testing, 19 is also acceptable. If you use other than these four running codes, an error will be reported. But my requirements are not satisfied with just these few ports. I want to use an ordinary GPIO port to output stable PWM, so I used the default 50Hz method above. I didn’t know how to modify the frequency of PWM before. Recently, I asked chatgpt and it provided me with a solution

This is the first solution it provides, and it is also the solution I used to set the frequency with set_PWM_frequency before. After my test, the frequency has not changed and is still the default 50Hz.

import pigpio
pi = pigpio.pi()
if not pi.connected:
    exit()
pi.set_mode(13, pigpio.ALT5) # 设置GPIO13ALT5模式
pi.set_PWM_frequency(13, 100) # 设置GPIO13PWM频率为100 Hz
pi.set_PWM_range(13, 100) # 设置GPIO13PWM范围为100
pi.set_PWM_dutycycle(13, 50) # 设置GPIO13PWM占空比为50%

So, when pressed by me, it gave me the solution:

import pigpio
import time

pi = pigpio.pi()
if not pi.connected:
    exit()

gpio_pin = 13
pi.set_mode(gpio_pin, pigpio.OUTPUT)  # 设置 GPIO 13 为输出模式
pi.set_PWM_range(gpio_pin, 100)      # 设置 PWM 范围为 0-100
pi.set_PWM_frequency(gpio_pin, 100)  # 设置 PWM 频率为 100 Hz
pi.set_PWM_dutycycle(gpio_pin, 50)   # 设置 PWM 占空比为 50%

time.sleep(5)  # 等待 5 秒钟

pi.set_PWM_dutycycle(gpio_pin, 0)    # 停止 PWM 信号输出
pi.stop()

pi.set_PWM_frequency(13, 100) This sentence is used to set the PWM frequency corresponding to GPIO 13, but it should be noted that this function is only effective when GPIO 13 is set to PWM mode.

Therefore, before using set_PWM_frequency(), you need to call the set_PWM_range() method and set it to an appropriate value, and then you can call the set_PWM_frequency() method to change the PWM frequency.

The above is a simple example showing how to use the pigpio library to set the PWM frequency to 100 Hz and output a PWM signal with a duty cycle of 50%.

This solution perfectly solved my problem. The output is stable and it is a regular gpio port. This method belongs to soft pwm. I can only say that the pigpio library is more powerful.

C++ calls Python

You can refer to here , here , here are important interfaces and explanations of each function.

Write python file: great_module.py

def great_function(a):
    print("hello python")
    return a + 1
   // 就这么多,不需要import 把这些内容写到great_module.py文件就可以了

Write .c file: test.c

#include <Python.h>
#include "track.h"

int great_function_from_python(int a) {
    
    
    int res;
    PyObject *pModule,*pFunc;
    PyObject *pArgs, *pValue;

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");//若python文件在c++工程下
    PyRun_SimpleString("print(sys.path)");
    /* import */
    PyRun_SimpleString("import sys");
    pModule = PyImport_ImportModule("great_module");
    PyErr_Print();
    if (!pModule) {
    
    
        printf("Can not open python file!\n");
        return -1;
    }

    /* great_module.great_function */
    pFunc = PyObject_GetAttrString(pModule, "great_function"); 
    
    /* build args */
    pArgs = PyTuple_New(1);
    PyTuple_SET_ITEM(pArgs,0, PyLong_FromLong(a));
      
    /* call */
    pValue = PyObject_CallObject(pFunc, pArgs);
    
    res = PyLong_AsLong(pValue);
    return res;
}

int main(int argc, char *argv[]) {
    
    
    Py_Initialize();
    printf("%d",great_function_from_python(2));
    Py_Finalize();
}

Output result:

hello python
3

The CMakeList file needs to be updated, but there is no need to change too much. Just delete the corresponding unused dynamic libraries and source files.
CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(c_python_test VERSION 0.1.0)

if(CMAKE_COMPILER_IS_GNUCC)
    message("COMPILER IS GNUCC")
        ADD_DEFINITIONS ( -std=c++11 )
endif(CMAKE_COMPILER_IS_GNUCC)

#SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -ggdb3")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

# 添加头文件路径
include_directories(${
    
    CMAKE_CURRENT_SOURCE_DIR})
include_directories(/home/dreamdeck/anaconda3/envs/track/include/python3.8) # 虚拟环境python头文件

# 添加链接库
LINK_DIRECTORIES(/home/dreamdeck/anaconda3/envs/track/lib)  #虚拟环境中python库的文件夹
LINK_LIBRARIES(python3.8)

# 添加要编译的可执行文件
add_executable(${
    
    PROJECT_NAME} test.c )

# 隐式链接库文件
# target_link_libraries(${
    
    PROJECT_NAME} python3.8)
#target_link_libraries(${
    
    PROJECT_NAME} track.cpython-38-x86_64-linux-gnu.so)

# 开启调试
SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -g")
message($(CMAKE_CXX_FLAGS))

It should be OK here, but when I was testing, I kept returning Can not open python file!
In fact, PyImport_ImportModule returned null. To put it bluntly, the .py file could not be found.
In fact, it can be modified according to PyErr_Print();the error message returned, that is It cannot be found in that path. The solution can be found here and here .

If it still can't be solved, please change the .py file to another location and then change its name. Hahaha, don't ask me how I know.
The one above is for reference.
Specifically, my program is:
PWM.py

def pwm_function(b):
    pi.set_servo_pulsewidth(26, b)
    return b
    
def Init_function(a):
    print("Init python")
    if not pi.connected:      # 检查是否连接成功 
        exit()
    user_gpio = 26
    pulsewidth = a         # 可以设置5001500,这是电平为1的时间,单位是微秒
    pi.set_servo_pulsewidth(user_gpio, pulsewidth)
    return 

C++


int pwm_function_from_python(int a) {
    
    

    int res;
    PyObject *pModule,*pFunc;
    PyObject *pArgs, *pValue;
    PyObject *pName = NULL;
    
    
    if(b ==3){
    
    
    b=4;
    
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import os");

    
    PyRun_SimpleString("sys.path.append('/home/ubuntu/wsh/catkin_ws/src/learning_communication')");//若python文件在c++工程下
    PyRun_SimpleString("sys.path.append('./')");
    PyRun_SimpleString("print(sys.path)");
    PyErr_Print();
    /* import */
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import pigpio");
    PyRun_SimpleString("import time");

    pName = PyUnicode_FromString("PWM");
    pModule = PyImport_Import(pName);
    if (pModule == NULL) {
    
    
        PyErr_Print();
        printf("Can not open python file!\n");
    }

    /* great_module.great_function */
    pFunc = PyObject_GetAttrString(pModule, "pwm_function");
    PyErr_Print();
    pFuncInit = PyObject_GetAttrString(pModule, "Init_function");
    PyErr_Print();
    /* build args */
    pArgs = PyTuple_New(1);
    PyTuple_SET_ITEM(pArgs,0, PyLong_FromLong(a));
    
    /* call */
    pValue = PyObject_CallObject(pFuncInit, pArgs);
    PyErr_Print();
    res = PyLong_AsLong(pValue);
    }
    if(b != 3)
    {
    
        
    pArgs = PyTuple_New(1);
    PyTuple_SET_ITEM(pArgs,0, PyLong_FromLong(a));
    pValue = PyObject_CallObject(pFuncInit, pArgs);
    PyErr_Print();
    res = PyLong_AsLong(pValue);} 

    return a;
}


This can indeed output PWM, but I cannot change the duty cycle at will during the execution of ROS. If I change it, an error will be reported. The specific reason for the error is that there are too many pi.connected connections, but when I call pwm_function directly without connecting, it will show me Pi is not defined, which is awkward. Forced into desperation, I checked the PyRun_SimpleString() function, which seemed to mean executing python code in a single line, just like in a shell environment, executing python code sentence by sentence. Since my python code is not complicated and can be done like this, I changed it to this:

int pwm_function_from_python(int a, int leftright) {
    
    
    sprintf(str, "%d", a);
    if(leftright == 1)
    {
    
    stt = "pi.set_servo_pulsewidth(26,";}
    else
    {
    
    stt = "pi.set_servo_pulsewidth(16,";} 
    stt = stt + str + ")";
    strcpy(str,stt.c_str());
    
    if(b ==3){
    
    
    b=4;
    
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import os");

    
    PyRun_SimpleString("sys.path.append('/home/ubuntu/wsh/catkin_ws/src/learning_communication')");//若python文件在c++工程下
    PyRun_SimpleString("sys.path.append('./')");
    //PyRun_SimpleString("print(sys.path)");
    PyErr_Print();
    /* import */
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import pigpio");
    PyRun_SimpleString("import time");
    PyRun_SimpleString("pi = pigpio.pi() ");
    //PyRun_SimpleString("pi.set_servo_pulsewidth(26, 1400)");
    PyRun_SimpleString(str);
    if(b != 3)
    {
    
    PyRun_SimpleString(str);} 

    return a;
}

In this way, I can repeatedly execute PyRun_SimpleString(“pi.set_servo_pulsewidth(26, 1400)”);this line of code to change 1400, and the PWM.py file is not needed.

Finally, I succeeded. I can freely change the PWM duty cycle by using the service to communicate with customers in the ROS environment.

reference

1. Raspberry Pi accurately controls pwm output and controls stepper motors
2. [Raspberry Pi Series] Getting started with the PWM interface of the WiringPi library (C and Python)
3. Raspberry Pi PWM output
4. How to control Raspberry Pi generation and reading Get pwm wave - pigpio library function usage guide: Part 1: Basic introduction and installation
5. [Raspberry Pi] Using pigpio library (3) How to send a specified number of pulse signals
6. C++ to adjust python under Ubuntu
7. How to control Raspberry Pi generates and reads PWM waves - pigpio library function usage guide: Part 3: PWM waveform generation

Guess you like

Origin blog.csdn.net/weixin_41756645/article/details/125417549