Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How would I translate this Python PWM code to go with go-rpio? #48

Open
kramer65 opened this issue Oct 8, 2019 · 8 comments
Open

How would I translate this Python PWM code to go with go-rpio? #48

kramer65 opened this issue Oct 8, 2019 · 8 comments

Comments

@kramer65
Copy link

kramer65 commented Oct 8, 2019

I'm trying to convert some working Python code to run in go. The Python is as follows:

import RPi.GPIO as GPIO
import time

servoPIN = 13
GPIO.setmode(GPIO.BCM)
GPIO.setup(servoPIN, GPIO.OUT)

p = GPIO.PWM(servoPIN, 50) # GPIO 13 for PWM with 50Hz
p.start(2.5) # Initialization
try:
  while True:
    p.ChangeDutyCycle(5)
    time.sleep(0.5)
    p.ChangeDutyCycle(7.5)
    time.sleep(0.5)
    p.ChangeDutyCycle(10)
    time.sleep(0.5)
    p.ChangeDutyCycle(12.5)
    time.sleep(0.5)
    p.ChangeDutyCycle(10)
    time.sleep(0.5)
    p.ChangeDutyCycle(7.5)
    time.sleep(0.5)
    p.ChangeDutyCycle(5)
    time.sleep(0.5)
    p.ChangeDutyCycle(2.5)
    time.sleep(0.5)
except KeyboardInterrupt:
  p.stop()
  GPIO.cleanup()

This Python code works. The servo moves constantly.

So I tried translating the code to Go using go-rpio. I got to this:

package main

import (
	"fmt"
	rpio "github.com/stianeikeland/go-rpio"
	"time"
)
const PWM_PIN_NUMBER = 13

func main() {
	err := rpio.Open()
	if err != nil {
		panic("Opening the pin goes wrong")
	}

	defer rpio.Close()

	pin := rpio.Pin(PWM_PIN_NUMBER)
	fmt.Println(pin)
	pin.Mode(rpio.Pwm)
	pin.Freq(50)
	pin.DutyCycle(0, 50)

	for {
		fmt.Println(5)
		pin.DutyCycle(uint32(5), 50)
		time.Sleep(1 * time.Second)

		fmt.Println(7)
		pin.DutyCycle(uint32(7), 50)
		time.Sleep(1 * time.Second)

		fmt.Println(10)
		pin.DutyCycle(uint32(10), 50)
		time.Sleep(1 * time.Second)

		fmt.Println(12)
		pin.DutyCycle(uint32(12), 50)
		time.Sleep(1 * time.Second)

		fmt.Println(10)
		pin.DutyCycle(uint32(10), 50)
		time.Sleep(1 * time.Second)
	}
}

The code runs, but the servo doesn't move at all.

Does anybody know what I'm doing wrong here?

@drahoslove
Copy link
Collaborator

drahoslove commented Oct 11, 2019

Hi,
in PWM mode the freq method does not set the output frequency, but the base clock frequency of the channel. You have to multiply it by the cycle length (because the output frequency is given by base clock frequency divided by cycle length as it is written in the doc).
This should work:

	pin.Mode(rpio.Pwm)
	pin.Freq(50 * 50)
	pin.DutyCycle(0, 50)
...
        pin.DutyCycle(7, 50)

or this:

	pin.Mode(rpio.Pwm)
	pin.Freq(50 * 100)
	pin.DutyCycle(0, 100)
...
        pin.DutyCycle(15, 100) // this will give you the 7.5/50 ratio you have in your python code

@shanghuiyang
Copy link

this is my golang codes using pwm to control motor, FYI.
https://github.com/shanghuiyang/rpi-devices/blob/master/app/car/car.go

@AndrewKovalenko
Copy link

I have similar issue. I try to control electric motor speed with hardware PWM.
Just to test that go-rpio is working I created a simple example which suppose to make motor spinning at ~75% of max RPM:

	if err := gpio.Open(); err != nil {
		log.Printf("Error opening GPIO: %s", err.Error())
		return err
	}
	defer func() {
		gpio.StopPwm()
		gpio.Close()
	}()

	pin := gpio.Pin(18)
	pin.Pwm()
	pin.DutyCycle(3, 4)
	pin.Freq(5000 * 4) // 5000Hz * 4 cycle length
	gpio.StartPwm()

	time.Sleep(10 * time.Second)

Running this code has zero effect.
Could you pls help me to troubleshoot it?

@drahoslove
Copy link
Collaborator

drahoslove commented Jun 6, 2020

@AndrewKovalenko

  • What Raspberry pi generation you have? There might be some incompatibility witch the newest version.
  • What number is your pin? Only some pins support the PWM mode.
  • Are you sure that 5000Hz s what your motor needs to operate? (edited)
  • Are you running the code as root? PWM modes require that.

@AndrewKovalenko
Copy link

@drahoslove thank you for quick response.

  • I use Raspberry Pi 4 Model B 2 GB
  • As you can see form my example - I use pin 18 which suppose to support hardware PWM. I checked the wiring and it is correct. I see voltage change if I set this pin to output and high
  • As for freq - it would be easier for me to run pwm signal at lower frequencies but I found a comment in go-rpio code saying Param freq should be in range 4688Hz - 19.2MHz to prevent unexpected behavior so I set frequency to 5kHz to stay within recommended range. My motor should work fine on those frequencies.
  • I tried both root and non-root. I found that if I just set pin to high with pin.High() function call - it doesn't work when I run my app with sudo but works fine without it.
    For PWM - I don't see any signal coming out either way: with or without sudo

@drahoslove
Copy link
Collaborator

@AndrewKovalenko
The RPi 4 model is not fully supported, but I merged the pull-request #50 which might solve your issue. Please try it.

@AndrewKovalenko
Copy link

AndrewKovalenko commented Jun 6, 2020

@drahoslove thank you. I just tried to pull the latest - it seems like I still have an issue.

To exclude the problem with the motor I connected an LED instead of motor and control it from pin 18 via 2n222 transistor.

Here is a listing of my "testing app":

package main

import (
	"log"
	"time"

	gpio "github.com/stianeikeland/go-rpio/v4"
)

const cycleLength = 100
const pmwClockFrequency = 50 * cycleLength // 50kHz

func main() {
	if err := gpio.Open(); err != nil {
		log.Fatalf("Error opening GPIO: %s", err.Error())
	}

	defer func() {
		log.Println("Stop PWM")
		gpio.StopPwm()
		gpio.Close()
	}()

	pin := gpio.Pin(18)

	pin.Output()

	for i := 0; i < 10; i++ {
		log.Printf("Toggle pin. i=%d \n", i)
		pin.Toggle()
		time.Sleep(time.Second)
	}

	pin.Pwm()

	pin.Freq(pmwClockFrequency)
	log.Println("Start PWM")
	gpio.StartPwm()

	log.Println("10%")
	pin.DutyCycle(10, cycleLength)
	time.Sleep(3 * time.Second)

	log.Println("30%")
	pin.DutyCycle(30, cycleLength)
	time.Sleep(3 * time.Second)

	log.Println("50%")
	pin.DutyCycle(50, cycleLength)
	time.Sleep(3 * time.Second)

	log.Println("70%")
	pin.DutyCycle(70, cycleLength)
	time.Sleep(3 * time.Second)

	log.Println("100%")
	pin.DutyCycle(100, cycleLength)
	time.Sleep(10 * time.Second)
}

The interesting issue I observe is:
when I run this app for the first time - LED is blinking while the pin is in output mode and then nothing happens in PWM mode. However if I run the same app second time - LED doesn't blink any more. It just turns on for 10 sec and goes off once pin is set to PWM. This issue persists until I reboot RasPi.

@rami-dabain
Copy link

related #68

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants