Skip to content

Commit cda3dbc

Browse files
authored
zero: introduce adaptor for Radxa Zero (hybridgroup#1128)
1 parent c986109 commit cda3dbc

10 files changed

+870
-12
lines changed

examples/zero_analog.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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/radxa/zero"
17+
)
18+
19+
// Wiring:
20+
// PWR : 1, 17 (+3.3V, VCC), 2, 4 (+5V), 6, 9, 14, 20, 25, 30, 34, 39 (GND)
21+
// ADC (max. 1.8V): header pin 15 is input for channel 1, pin 26 is input for channel 2
22+
func main() {
23+
const (
24+
inPin0 = "15_mean"
25+
inPin1 = "26"
26+
inVoltageScale = 0.439453125 // see README.md of the platform
27+
)
28+
29+
scaler := aio.AnalogSensorLinearScaler(0, 4095, 0, 1.8)
30+
31+
adaptor := zero.NewAdaptor()
32+
ana0 := aio.NewAnalogSensorDriver(adaptor, inPin0, aio.WithSensorScaler(scaler))
33+
ana1 := aio.NewAnalogSensorDriver(adaptor, inPin1)
34+
35+
work := func() {
36+
gobot.Every(500*time.Millisecond, func() {
37+
v0, err := ana0.Read()
38+
if err != nil {
39+
log.Println(err)
40+
}
41+
42+
v1, err := ana1.Read()
43+
if err != nil {
44+
log.Println(err)
45+
}
46+
47+
fmt.Printf("%s: %1.3f V, %s: %2.0f (%4.0f mV)\n", inPin0, v0, inPin1, v1, v1*inVoltageScale)
48+
})
49+
}
50+
51+
robot := gobot.NewRobot("adcBot",
52+
[]gobot.Connection{adaptor},
53+
[]gobot.Device{ana0, ana1},
54+
work,
55+
)
56+
57+
if err := robot.Start(); err != nil {
58+
panic(err)
59+
}
60+
}

examples/zero_direct_pin.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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/radxa/zero"
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 24 is input, pin 32 used as normal output, pin 36 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 the state changes
26+
func main() {
27+
const (
28+
inPinNum = "24"
29+
outPinNum = "32"
30+
outPinInvertedNum = "36"
31+
)
32+
// note: WithGpiosOpenDrain() is optional, if using WithGpiosOpenSource() the LED's will not light up
33+
board := zero.NewAdaptor(adaptors.WithGpiosActiveLow(outPinInvertedNum),
34+
adaptors.WithGpiosOpenDrain(outPinNum, outPinInvertedNum), adaptors.WithGpiosPullUp(inPinNum))
35+
36+
inPin := gpio.NewDirectPinDriver(board, inPinNum)
37+
outPin := gpio.NewDirectPinDriver(board, outPinNum)
38+
outPinInverted := gpio.NewDirectPinDriver(board, outPinInvertedNum)
39+
40+
work := func() {
41+
level := byte(1)
42+
43+
gobot.Every(500*time.Millisecond, func() {
44+
read, err := inPin.DigitalRead()
45+
fmt.Printf("pin %s state is %d\n", inPinNum, read)
46+
if err != nil {
47+
fmt.Println(err)
48+
if level == 1 {
49+
level = 0
50+
} else {
51+
level = 1
52+
}
53+
} else {
54+
level = byte(read)
55+
}
56+
57+
err = outPin.DigitalWrite(level)
58+
fmt.Printf("pin %s is now %d\n", outPinNum, level)
59+
if err != nil {
60+
fmt.Println(err)
61+
}
62+
63+
err = outPinInverted.DigitalWrite(level)
64+
fmt.Printf("pin %s is now not %d\n", outPinInvertedNum, level)
65+
if err != nil {
66+
fmt.Println(err)
67+
}
68+
})
69+
}
70+
71+
robot := gobot.NewRobot("pinBot",
72+
[]gobot.Connection{board},
73+
[]gobot.Device{inPin, outPin, outPinInverted},
74+
work,
75+
)
76+
77+
if err := robot.Start(); err != nil {
78+
panic(err)
79+
}
80+
}

examples/tinkerboard_servo.go examples/zero_servo.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,26 @@ import (
1313
"gobot.io/x/gobot/v2"
1414
"gobot.io/x/gobot/v2/drivers/gpio"
1515
"gobot.io/x/gobot/v2/platforms/adaptors"
16-
"gobot.io/x/gobot/v2/platforms/asus/tinkerboard"
16+
"gobot.io/x/gobot/v2/platforms/radxa/zero"
1717
)
1818

1919
// Wiring
20-
// PWR Tinkerboard: 1 (+3.3V, VCC), 2(+5V), 6, 9, 14, 20 (GND)
21-
// PWM Tinkerboard: header pin 33 (PWM2) or pin 32 (PWM3)
20+
// PWR: 1, 17 (+3.3V, VCC), 2, 4 (+5V), 6, 9, 14, 20, 25, 30, 34, 39 (GND)
21+
// PWM: header pin 18 (PWM_C), 40 (PWMAO_A)
22+
// Servo SG90: red (+5V), brown (GND), orange (PWM)
2223
func main() {
2324
const (
24-
pwmPin = "32"
25+
pwmPin = "18"
2526
wait = 3 * time.Second
2627

2728
fiftyHzNanos = 20 * 1000 * 1000 // 50Hz = 0.02 sec = 20 ms
2829
)
2930
// usually a frequency of 50Hz is used for servos, most servos have 0.5 ms..2.5 ms for 0-180°,
3031
// however the mapping can be changed with options:
31-
adaptor := tinkerboard.NewAdaptor(
32+
adaptor := zero.NewAdaptor(
3233
adaptors.WithPWMDefaultPeriodForPin(pwmPin, fiftyHzNanos),
33-
adaptors.WithPWMServoDutyCycleRangeForPin(pwmPin, time.Millisecond, 2*time.Millisecond),
34-
adaptors.WithPWMServoAngleRangeForPin(pwmPin, 0, 270),
34+
adaptors.WithPWMServoDutyCycleRangeForPin(pwmPin, 500*time.Microsecond, 2500*time.Microsecond),
35+
adaptors.WithPWMServoAngleRangeForPin(pwmPin, 0, 180),
3536
)
3637
servo := gpio.NewServoDriver(adaptor, pwmPin)
3738

examples/tinkerboard_yl40.go examples/zero_yl40.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ import (
1313

1414
"gobot.io/x/gobot/v2"
1515
"gobot.io/x/gobot/v2/drivers/i2c"
16-
"gobot.io/x/gobot/v2/platforms/asus/tinkerboard"
16+
"gobot.io/x/gobot/v2/platforms/radxa/zero"
1717
)
1818

1919
func main() {
2020
// Wiring
21-
// PWR Tinkerboard: 1 (+3.3V, VCC), 6, 9, 14, 20 (GND)
22-
// I2C1 Tinkerboard: 3 (SDA), 5 (SCL)
21+
// PWR : 1, 17 (+3.3V, VCC), 6, 9, 14, 20, 25, 30, 34, 39 (GND)
22+
// I2C3: 3 (SDA), 5 (SCL), I2C1: 24/16 (SDA), 23/13 (SCL), I2C4: 7 (SDA), 11 (SCL)
2323
// YL-40 module: wire AOUT --> AIN2 for this example
2424
//
2525
// Note: temperature measurement is often buggy, because sensor is not properly grounded
2626
// fix it by soldering a small bridge to the adjacent ground pin of brightness sensor
27-
board := tinkerboard.NewAdaptor()
28-
yl := i2c.NewYL40Driver(board, i2c.WithBus(1))
27+
board := zero.NewAdaptor()
28+
yl := i2c.NewYL40Driver(board, i2c.WithBus(3))
2929

3030
work := func() {
3131
// the LED light is visible above ~1.7V

platforms/radxa/zero/LICENSE

+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)