Skip to content

Commit 514330e

Browse files
authored
orangepi5pro: introduce adaptor for OrangePi 5 Pro (hybridgroup#1129)
1 parent cda3dbc commit 514330e

12 files changed

+756
-89
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ platforms are currently supported:
271271
- [NATS](http://nats.io/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/nats)
272272
- [Neurosky](http://neurosky.com/products-markets/eeg-biosensors/hardware/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/neurosky)
273273
- [OpenCV](http://opencv.org/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/opencv)
274+
- [OrangePi 5 Pro](http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5-Pro.html) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/orangepi/orangepi5pro)
274275
- [Particle](https://www.particle.io/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/particle)
275276
- [Parrot ARDrone 2.0](http://ardrone2.parrot.com/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/ardrone)
276277
- [Parrot Bebop](http://www.parrot.com/usa/products/bebop-drone/) <=> [Package](https://github.com/hybridgroup/gobot/blob/release/platforms/parrot/bebop)

examples/beaglebone_direct_pin.go

-47
This file was deleted.

examples/beaglebone_servo.go

-42
This file was deleted.

examples/orangepi5pro_direct_pin.go

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//go:build example
2+
// +build example
3+
4+
//
5+
// Do not build by default.
6+
7+
package main
8+
9+
import (
10+
"fmt"
11+
"time"
12+
13+
"gobot.io/x/gobot/v2"
14+
"gobot.io/x/gobot/v2/drivers/gpio"
15+
"gobot.io/x/gobot/v2/platforms/adaptors"
16+
"gobot.io/x/gobot/v2/platforms/orangepi/orangepi5pro"
17+
)
18+
19+
// Wiring
20+
// PWR : 1, 17 (+3.3V, VCC), 2, 4 (+5V), 6, 9, 14, 20, 25, 30, 34, 39 (GND)
21+
// GPIO : header pin 32 is input, pin 38 used as normal output, pin 40 used as inverted output
22+
// Button: the input pin is wired with a button to GND, the internal pull up resistor is used
23+
// LED's: the output pins are wired to the cathode of the LED, the anode is wired with a resistor (70-130Ohm for 20mA)
24+
// to VCC
25+
// Expected behavior: always one LED is on, the other in opposite state, if button is pressed for >2 seconds the state
26+
// changes
27+
func main() {
28+
const (
29+
inPinNum = "32"
30+
outPinNum = "38"
31+
outPinInvertedNum = "40"
32+
debounceTime = 2 * time.Second
33+
)
34+
// note: WithGpiosOpenDrain() is optional, if using WithGpiosOpenSource() the LED's will not light up
35+
board := orangepi5pro.NewAdaptor(adaptors.WithGpiosActiveLow(outPinInvertedNum),
36+
adaptors.WithGpiosOpenDrain(outPinNum, outPinInvertedNum),
37+
adaptors.WithGpiosPullUp(inPinNum),
38+
adaptors.WithGpioDebounce(inPinNum, debounceTime))
39+
40+
inPin := gpio.NewDirectPinDriver(board, inPinNum)
41+
outPin := gpio.NewDirectPinDriver(board, outPinNum)
42+
outPinInverted := gpio.NewDirectPinDriver(board, outPinInvertedNum)
43+
44+
work := func() {
45+
level := byte(1)
46+
47+
gobot.Every(500*time.Millisecond, func() {
48+
read, err := inPin.DigitalRead()
49+
fmt.Printf("pin %s state is %d\n", inPinNum, read)
50+
if err != nil {
51+
fmt.Println(err)
52+
if level == 1 {
53+
level = 0
54+
} else {
55+
level = 1
56+
}
57+
} else {
58+
level = byte(read)
59+
}
60+
61+
err = outPin.DigitalWrite(level)
62+
fmt.Printf("pin %s is now %d\n", outPinNum, level)
63+
if err != nil {
64+
fmt.Println(err)
65+
}
66+
67+
err = outPinInverted.DigitalWrite(level)
68+
fmt.Printf("pin %s is now not %d\n", outPinInvertedNum, level)
69+
if err != nil {
70+
fmt.Println(err)
71+
}
72+
})
73+
}
74+
75+
robot := gobot.NewRobot("pinBot",
76+
[]gobot.Connection{board},
77+
[]gobot.Device{inPin, outPin, outPinInverted},
78+
work,
79+
)
80+
81+
if err := robot.Start(); err != nil {
82+
panic(err)
83+
}
84+
}

examples/orangepi5pro_servo.go

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//go:build example
2+
// +build example
3+
4+
// Do not build by default.
5+
6+
package main
7+
8+
import (
9+
"fmt"
10+
"log"
11+
"time"
12+
13+
"gobot.io/x/gobot/v2"
14+
"gobot.io/x/gobot/v2/drivers/gpio"
15+
"gobot.io/x/gobot/v2/platforms/adaptors"
16+
"gobot.io/x/gobot/v2/platforms/orangepi/orangepi5pro"
17+
)
18+
19+
// Wiring
20+
// PWR: 1, 17 (+3.3V, VCC), 2, 4 (+5V), 6, 9, 14, 20, 25, 30, 34, 39 (GND)
21+
// PWM: 7(pwm13-m2), 11(pwm14-m1), 12(pwm3-m3), 13(pwm15-m1), 27(pwm0-m2), 28(pwm1-m2), 32(pwm14-m2), 33(pwm15-m3)
22+
// Servo SG90: red (+5V), brown (GND), orange (PWM)
23+
func main() {
24+
const (
25+
pwmPin = "7"
26+
wait = 3 * time.Second
27+
28+
fiftyHzNanos = 20 * 1000 * 1000 // 50Hz = 0.02 sec = 20 ms
29+
)
30+
// usually a frequency of 50Hz is used for servos, most servos have 0.5 ms..2.5 ms for 0-180°,
31+
// however the mapping can be changed with options:
32+
adaptor := orangepi5pro.NewAdaptor(
33+
adaptors.WithPWMDefaultPeriodForPin(pwmPin, fiftyHzNanos),
34+
adaptors.WithPWMServoDutyCycleRangeForPin(pwmPin, 500*time.Microsecond, 2500*time.Microsecond),
35+
adaptors.WithPWMServoAngleRangeForPin(pwmPin, 0, 180),
36+
)
37+
servo := gpio.NewServoDriver(adaptor, pwmPin)
38+
39+
work := func() {
40+
fmt.Printf("first move to minimal position for %s...\n", wait)
41+
if err := servo.ToMin(); err != nil {
42+
log.Println(err)
43+
}
44+
45+
time.Sleep(wait)
46+
47+
fmt.Printf("second move to center position for %s...\n", wait)
48+
if err := servo.ToCenter(); err != nil {
49+
log.Println(err)
50+
}
51+
52+
time.Sleep(wait)
53+
54+
fmt.Printf("third move to maximal position for %s...\n", wait)
55+
if err := servo.ToMax(); err != nil {
56+
log.Println(err)
57+
}
58+
59+
time.Sleep(wait)
60+
61+
fmt.Println("finally move 0-180° (or what your servo do for the new mapping) and back forever...")
62+
angle := 0
63+
fadeAmount := 45
64+
65+
gobot.Every(time.Second, func() {
66+
if err := servo.Move(byte(angle)); err != nil {
67+
log.Println(err)
68+
}
69+
angle = angle + fadeAmount
70+
if angle < 0 || angle > 180 {
71+
if angle < 0 {
72+
angle = 0
73+
}
74+
if angle > 180 {
75+
angle = 180
76+
}
77+
// change direction and recalculate
78+
fadeAmount = -fadeAmount
79+
angle = angle + fadeAmount
80+
}
81+
})
82+
}
83+
84+
robot := gobot.NewRobot("motorBot",
85+
[]gobot.Connection{adaptor},
86+
[]gobot.Device{servo},
87+
work,
88+
)
89+
90+
if err := robot.Start(); err != nil {
91+
panic(err)
92+
}
93+
}

examples/orangepi5pro_thermalzone.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//go:build example
2+
// +build example
3+
4+
//
5+
// Do not build by default.
6+
7+
package main
8+
9+
import (
10+
"fmt"
11+
"log"
12+
"time"
13+
14+
"gobot.io/x/gobot/v2"
15+
"gobot.io/x/gobot/v2/drivers/aio"
16+
"gobot.io/x/gobot/v2/platforms/orangepi/orangepi5pro"
17+
)
18+
19+
// Wiring: no wiring needed
20+
func main() {
21+
adaptor := orangepi5pro.NewAdaptor()
22+
therm0 := aio.NewThermalZoneDriver(adaptor, "soc_thermal")
23+
therm1 := aio.NewThermalZoneDriver(adaptor, "npu_thermal", aio.WithFahrenheit())
24+
25+
work := func() {
26+
gobot.Every(500*time.Millisecond, func() {
27+
t0, err := therm0.Read()
28+
if err != nil {
29+
log.Println(err)
30+
}
31+
32+
t1, err := therm1.Read()
33+
if err != nil {
34+
log.Println(err)
35+
}
36+
37+
fmt.Printf("SOC: %2.3f °C, NPU: %2.3f °F\n", t0, t1)
38+
})
39+
}
40+
41+
robot := gobot.NewRobot("thermalBot",
42+
[]gobot.Connection{adaptor},
43+
[]gobot.Device{therm0, therm1},
44+
work,
45+
)
46+
47+
if err := robot.Start(); err != nil {
48+
panic(err)
49+
}
50+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2025 The Hybrid Group
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

0 commit comments

Comments
 (0)