Previous
Camera
Add an encoder to your machine’s configuration so you can track motor position and direction from the Viam app and from code.
Encoders come in two main varieties:
Both connect to a board’s GPIO pins as digital interrupts. The encoder counts signal transitions (“ticks”) that correspond to motor shaft rotation.
Once you configure an encoder and reference it from a motor component, the
motor gains accurate position control. GoFor and GoTo use actual encoder
feedback instead of time-based estimates. Browse all available encoder models in the Viam registry.
left-encoder) and click Create.Incremental (quadrature) encoder:
{
"board": "my-board",
"pins": {
"a": "37",
"b": "35"
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
board | string | Yes | Name of the board component. |
pins.a | string | Yes | GPIO pin for channel A. |
pins.b | string | Yes | GPIO pin for channel B. |
Single-channel encoder:
{
"board": "my-board",
"pins": {
"i": "37"
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
board | string | Yes | Name of the board component. |
pins.i | string | Yes | GPIO pin for the signal channel. |
After creating the encoder, update your motor’s configuration to reference it:
{
"board": "my-board",
"max_rpm": 200,
"pins": { "a": "11", "b": "13", "pwm": "15" },
"encoder": "left-encoder",
"ticks_per_rotation": 600
}
ticks_per_rotation is the number of encoder ticks in one full rotation of
the motor shaft. Check your encoder’s datasheet. Common values are 12, 48,
200, or 600 depending on the encoder type and any gearing.
Click Save, then expand the TEST section for the encoder.
Then test the motor. GoFor should now stop accurately at the target
position.
Read the encoder position and reset it.
To get the credentials for the code below, go to your machine’s page in the Viam app, click the CONNECT tab, and select SDK code sample. Toggle Include API key on. Copy the machine address, API key, and API key ID from the code sample. When you run the code below, you’ll see the encoder’s current position, then reset it to zero. Manually rotate the motor shaft to verify the count changes.
pip install viam-sdk
Save this as encoder_test.py:
import asyncio
from viam.robot.client import RobotClient
from viam.components.encoder import Encoder
async def main():
opts = RobotClient.Options.with_api_key(
api_key="YOUR-API-KEY",
api_key_id="YOUR-API-KEY-ID"
)
robot = await RobotClient.at_address("YOUR-MACHINE-ADDRESS", opts)
encoder = Encoder.from_robot(robot, "left-encoder")
position, pos_type = await encoder.get_position()
print(f"Position: {position} ({pos_type})")
properties = await encoder.get_properties()
print(f"Ticks count supported: {properties.ticks_count_supported}")
print(f"Angle degrees supported: {properties.angle_degrees_supported}")
await encoder.reset_position()
print("Position reset to zero")
position, pos_type = await encoder.get_position()
print(f"Position after reset: {position}")
await robot.close()
if __name__ == "__main__":
asyncio.run(main())
Run it:
python encoder_test.py
mkdir encoder-test && cd encoder-test
go mod init encoder-test
go get go.viam.com/rdk
Save this as main.go:
package main
import (
"context"
"fmt"
"go.viam.com/rdk/components/encoder"
"go.viam.com/rdk/logging"
"go.viam.com/rdk/robot/client"
"go.viam.com/rdk/utils"
)
func main() {
ctx := context.Background()
logger := logging.NewLogger("encoder-test")
robot, err := client.New(ctx, "YOUR-MACHINE-ADDRESS", logger,
client.WithCredentials(utils.Credentials{
Type: utils.CredentialsTypeAPIKey,
Payload: "YOUR-API-KEY",
}),
client.WithAPIKeyID("YOUR-API-KEY-ID"),
)
if err != nil {
logger.Fatal(err)
}
defer robot.Close(ctx)
enc, err := encoder.FromProvider(robot, "left-encoder")
if err != nil {
logger.Fatal(err)
}
position, posType, err := enc.Position(ctx, encoder.PositionTypeUnspecified, nil)
if err != nil {
logger.Fatal(err)
}
fmt.Printf("Position: %.2f (%v)\n", position, posType)
properties, err := enc.Properties(ctx, nil)
if err != nil {
logger.Fatal(err)
}
fmt.Printf("Ticks count supported: %v\n", properties.TicksCountSupported)
fmt.Printf("Angle degrees supported: %v\n", properties.AngleDegreesSupported)
if err := enc.ResetPosition(ctx, nil); err != nil {
logger.Fatal(err)
}
fmt.Println("Position reset to zero")
}
Run it:
go run main.go
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!