AXON I2C on GPIO for PWM Controller

Hello.

I’m trying to use a PWM Controller connected to below pins in order to control a servo motor.

(I2C7 : SDA on Pin 18, SCL on Pin 17)

My code runs fine, but the servo does not move.

Same code, after changing the pin numbers, works fine on a Raspberry-Pi 4B.

I noted that the pins do not send the correct logic level voltage on the GPIO pins. I see a voltage of 2.7V. I think its supposed to be between 3.3V - 5V if I’m not wrong.

This is my kernel information. We were using Kernel v5 previously and had the same problem. Upgrading the kernel to 6.1.75 has not helped either.

sudo uname -a
Linux vicharak 6.1.75-axon axon SMP Mon Aug 4 10:17:13 IST 2025 aarch64 aarch64 aarch64 GNU/Linux

Has anyone seen this? Any thoughts on how to fix this.

Thank you

Before proceeding further, I hope you have enabled PWM and I2C overlays using vicharak-config.

And could it be possible to share whole code and share datasheet of servo motor you are using ?

PWM Documentation in Axon

I2C Documentation in Axon

Overlays enabled (from my vicharak-config screenshot):
Enable I2C7 on 30-Pin GPIO Header Axon V0.3 → ENABLED (required for PCA9685 on SDA pin 18 / SCL pin 17).
Enable PWM1_M1 on 30-Pin GPIO Header Axon V0.3 → ENABLED
Enable UART1 on 30-Pin GPIO Header Axon V0.3 → ENABLED (useful for my LiDAR UART connection).

I tried the Raspberry Pi servo test script — it works fine on RPi4B.
On Axon, I used the servo test script but the servo does not move.
vicharak@vicharak:~$ uname -r
6.1.75-axon

sudu i2cdetect -y 7
shows 0x40 as expected.

axon_servo_test.py (2.0 KB)
rpi_servo_test.py (695 Bytes)
MG90S.PDF (154.8 KB)

Working on it, will get back to soon asap.

@cycloneuav, Mostly it’s because you have not enabled pwm0 device.
I think you just have to add export, set the period, and enable the signal part to your code.

Note
We have found that without an enable signal, Voltage value of PWM GPIO pin is 2.7V.

As we don’t have PCA9685, we have tested directly connecting the Servo Motor wire to the Axon GPIO Header.

Pin 19 => PWM1_M1

Kindly run the script below :

#!/usr/bin/env python3
import os
import time

# PWM sysfs paths
PWM_PATH = "/sys/class/pwm/pwmchip0"
PWM0 = os.path.join(PWM_PATH, "pwm0")
EXPORT = os.path.join(PWM_PATH, "export")
UNEXPORT = os.path.join(PWM_PATH, "unexport")

# Servo PWM parameters (works on your RK3588 driver)
PERIOD = 2000000  # 2 ms period in nanoseconds
DUTY_MIN = 400000   # pulse width for 0°
DUTY_MAX = 1500000  # pulse width for 180°

def angle_to_duty(angle):
    """Convert 0-180° angle to duty cycle in ns"""
    return int(DUTY_MIN + (DUTY_MAX - DUTY_MIN) * angle / 180)

def write_pwm(path, value):
    with open(path, "w") as f:
        f.write(str(value))

def set_angle(angle):
    """Move servo to specified angle"""
    duty = angle_to_duty(angle)
    write_pwm(os.path.join(PWM0, "duty_cycle"), duty)
    print(f"Angle: {angle}°, Duty: {duty}")

def main():
    # Export PWM
    write_pwm(EXPORT, 0)
    time.sleep(1)

    # Set period and enable
    write_pwm(os.path.join(PWM0, "period"), PERIOD)
    write_pwm(os.path.join(PWM0, "enable"), 1)

    try:
        # Example drastic movements
        for angle in [0, 45, 90, 135, 180, 90, 0]:
            set_angle(angle)
            time.sleep(2)  # wait so movement is visible
    finally:
        # Disable and unexport PWM
        write_pwm(os.path.join(PWM0, "enable"), 0)
        write_pwm(UNEXPORT, 0)
        print("PWM operations completed.")

if __name__ == "__main__":
    main()