Closed Jacalz closed 3 years ago
IS there any ETA for servo support on arduino uno/nano?
I wrote a test code that can control servos, however this does not work on 8-bit AVR boards (like Arduino Unos and Nanos), probably not until they can get more accurate timing support.
Modified: making ServoRoutine timing more accurate.
package main
import (
"machine"
"time"
)
type Device struct {
pin machine.Pin
on bool
angle uint8
pulseMin uint16
pulseMax uint16
}
func Init(pin machine.Pin) Device {
pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
return Device{pin: pin, on: false, pulseMin: 600, pulseMax: 2400}
}
func (d *Device) ServoRoutine() {
for {
if d.attached {
pulse := valueMapping(int32(d.angle), 0, 180, d.pulseMin, d.pulseMax)
d.pin.High()
time.Sleep(time.Microsecond * time.Duration(pulse))
d.pin.Low()
time.Sleep(time.Microsecond * time.Duration(20000.0-pulse))
}
}
}
func (d *Device) Angle(angle uint8) {
if angle < 0 {
angle = 0
} else if angle > 180 {
angle = 180
}
d.on = true
d.angle = angle
}
func (d *Device) PulseRange(min, max uint16) {
d.pulseMin = min
d.pulseMax = max
}
func (d *Device) Deinit() {
d.on = false
}
func valueMapping(value, min, max, newMin, newMax uint16) float32 {
scale := float32(value-min) / float32(max-min)
return float32(newMin) + scale*float32(newMax-newMin)
}
func main() {
servo1 := Init(machine.P8)
servo2 := Init(machine.P12)
go servo1.ServoRoutine()
go servo2.ServoRoutine()
for i := 0; i <= 2; i++ {
servo1.Angle(0)
servo2.Angle(0)
time.Sleep(time.Millisecond * 1000)
servo1.Angle(90)
servo2.Angle(90)
time.Sleep(time.Millisecond * 1000)
servo1.Angle(180)
servo2.Angle(180)
time.Sleep(time.Millisecond * 1000)
}
// stop "PWM" signal (otherwise the servos may turn again when main() ended)
servo1.Deinit()
servo2.Deinit()
}
alankrantas: I wrote code very similar to that this weekend for a Cortex M4 (sam19g). I found it was not nearly low enough in jitter to allow for stable servo control. Did you get it to work in practice? Also, a minor comment. The period of the signal should be 20 mSec to provide a 50Hz update, In your code, the period is 20mS + the pulse width.
@ewwaller I tested it on micro:bit and Arduino Nano 33 IoT and it actually worked well enough on several types of servos. I guess I was being lazy, since 0.5-2.5 ms is small compared to 20ms.
How about this?
func (d *Device) ServoRoutine() {
for {
if d.attached {
pulse := valueMapping(int32(d.angle), 0, 180, d.pulseMin, d.pulseMax)
d.pin.High()
time.Sleep(time.Microsecond * time.Duration(pulse))
d.pin.Low()
time.Sleep(time.Microsecond * time.Duration(20000.0-pulse))
}
}
}
Looks right. I am interested in why it may have been more stable on the Nano 33 vs the Cortex M4. Which scheduler were you using?
The default one I think, never tried to change it.
Just did a test on my Metro M4 (powered via the DC jack). Works fine except some very small jittering.
Won't work on Arduino UNO on any scheduler (none, tasks, coroutines)
I have a prototype servo driver that works on both the nrf52832 and Arduino Uno (AVR) and probably works on the SAM D21 too (so far untested). It is totally jitter free with the one servo I have, a problem that I've heard is common with Servo.h
and should allow driving multiple servos from a single PWM instance.
@aykevl can you give us a link? :)
@Nerzal here is the WIP code: https://github.com/tinygo-org/drivers/compare/dev...servo It currently does not compile with https://github.com/tinygo-org/tinygo/pull/1121 as I changed the interface a little bit.
Thank U ❤️
See #264 so now closing.
For Arduino programming using their language, a specific driver library exists for easy and simple control over Servo parts. This seems to be non supported at the moment when using tinygo.
This functionality would be very useful for especially Arduino users that want to use their servos, but I guess that it might be useful for other boards too, depending on implementation. I will mostly be using it on an Arduino Uno though...
See the Servo Reference and Servo Library Repository for more information.
Related to https://github.com/tinygo-org/tinygo/issues/855 about PWM support needed to implement this.