Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions as5600_tca9548a.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/python3
# Extended version of Matthias Wandel AS5600 example code:
# https://github.com/Matthias-Wandel/AS5600-Raspberry-Pi-Python/blob/master/as5600.py
#
# This extended version is for use with TCA9548A multiple(xer) AS5600 encoders
# https://www.ti.com/lit/ds/symlink/tca9548a.pdf
# https://www.mouser.com/pdfdocs/AMS_AS5600_Datasheet_EN.PDF
#
# Usage: python3 as5600_tca9548a.py <channel> or empty
# No given argument will disable TCA9548A switching and read from 0x36 directly
# channel is a number from 0 to 7, which will select the TCA9548A channel
#
# Very simple code to read AS5600 magnetic encoder with Python
# on raspberry pi
#
# Requires Python smbus module. Get it using:
# sudo apt-get install python3-smbus
#
# Make sure Pi's I2c is enabled using
# sudo raspi-config
#
# Connect Pi's ground to GND and DIR pins
# Connect Pi's 3.3 volts to VCC on AS5600
# Connect Pi's I2c SCL (pin 5) to AS5600 SCL pin
# Connect Pi's I2c SDA (pin 5) to AS5600 SDA pin
#
# Watchout: use a level shifter if you are using 5V AS5600
# ======================================================================
# bash commands:
#
# read i2c-bus: sudo i2cdetect -y 1
# set TCA9548A switching off: sudo i2cset -y 1 0x70 0x00
#
# set TCA9548A channel-0: sudo i2cset -y 1 0x70 0x01
# set TCA9548A channel-1: sudo i2cset -y 1 0x70 0x02
#
# read AS5600 raw angle: sudo i2cget -y 1 0x36 0x0C
# read AS5600 magnitude: sudo i2cget -y 1 0x36 0x1B

import smbus, time, sys, math

DEVICE_TCA9548A = 0x70 # TCA9548A default address (0x70-0x77)
DEVICE_AS5600 = 0x36 # AS5600 fixed address, AS5600L version is changeable
bus = smbus.SMBus(1)

# function TCA9548A channel switching
def SelectTCAChannel(channel):
if channel < 0 or channel > 7:
raise ValueError("channel must be between 0 and 7 ")
bus.write_byte(DEVICE_TCA9548A, 1 << channel)

#=====================================================================
# Code to read AS5600. x lines of python is all it takes.
def ReadRawAngle(): # Read angle (0-360 represented as 0-4096)
read_bytes = bus.read_i2c_block_data(DEVICE_AS5600, 0x0C, 2)
return (read_bytes[0] << 8) | read_bytes[1]

def ReadMagnitude(): # Read magnetism magnitude
read_bytes = bus.read_i2c_block_data(DEVICE_AS5600, 0x1B, 2)
return (read_bytes[0] << 8) | read_bytes[1]

#=====================================================================
xcenter = 40 # Assume center of text screen is 80 across, 24 down.
ycenter = 12 # if your screen is 80x50, change to 40 and 25.

def MoveCursor(x, y):
print("\033[%d;%dH" % (y, x), end="")

# if there is a command line argument, it is the TCA9548A channel
# and the TCA9548A switching is activated
try:
if len(sys.argv) != 2:
print("no channel given, direct access to AS5600")
#DisableTCAChannels()
current_channel = None # no channel
else:
current_channel = int(sys.argv[1])
if current_channel < 0 or current_channel > 7:
raise ValueError
SelectTCAChannel(current_channel)
except ValueError:
print("error: channel must be between 0 and 7")
sys.exit(1)

# Clear screen
print("\033[2J", end="")

# Draw x and y axis on screen
for a in range(-ycenter, ycenter):
MoveCursor(xcenter, ycenter + a)
print("|", end="")

for a in range(-xcenter, xcenter):
MoveCursor(xcenter + a, ycenter)
print("-")

histlen = 400
hist_index = 0
hist = [(0, 0)] * histlen

# TCA9548A-channel switching
if current_channel is not None:
SelectTCAChannel(current_channel)

while True:
# read
try:
raw_angle = ReadRawAngle()
magnitude = ReadMagnitude()

MoveCursor(0, 0)
if current_channel is not None:
print("Multiplexer Channel: %d | Raw angle: %4d" % (current_channel, raw_angle), "m=%4d" % (magnitude), "%6.2f deg " % (raw_angle * 360.0 / 4096))
else:
print("Direct Access. Raw angle: %4d" % (raw_angle), "m=%4d" % (magnitude), "%6.2f deg " % (raw_angle * 360.0 / 4096))

# X- und Y-Position berechnen und auf dem Bildschirm darstellen
xymag = magnitude / 1024.0
cx = int(xcenter + xcenter * xymag * math.cos(raw_angle * math.pi / 2048))
cy = int(ycenter + ycenter * xymag * math.sin(raw_angle * math.pi / 2048))

# Alte Markierung löschen (bis zu 400 auf dem Bildschirm)
oldpos = hist[hist_index]
MoveCursor(*oldpos)
if oldpos[0] == xcenter:
print("|", end="")
elif oldpos[1] == ycenter:
print("-", end="")
else:
print(" ", end="")

# Save new mark positon in array
hist[hist_index] = (cx, cy)
hist_index += 1
if hist_index >= histlen:
hist_index = 0

# Draw a '#' at the computed X,Y coordinate
MoveCursor(cx, cy)
print("#", end="")

except Exception as e:
MoveCursor(0, 0)
print(f"error while reading: {e}", end="")