Skip to content

Commit ee414ba

Browse files
committed
Add DAC2 Unit, Miniscale Unit bug fix.
1 parent 1f8a0f6 commit ee414ba

File tree

5 files changed

+164
-1
lines changed

5 files changed

+164
-1
lines changed

m5stack/libs/unit/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"WEIGHTUnit": "weight",
4141
"SCALESUnit": "scales",
4242
"MiniScaleUnit": "miniscale",
43+
"DAC2Unit": "dac2",
4344
}
4445

4546

m5stack/libs/unit/dac2.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# -*- encoding: utf-8 -*-
2+
'''
3+
@File : _dac2.py
4+
@Time : 2023/12/27
5+
@Author : TONG YIHAN
6+
7+
@License : (C)Copyright 2015-2023, M5STACK
8+
'''
9+
10+
# Import necessary libraries
11+
from machine import I2C
12+
from .pahub import PAHUBUnit
13+
from .unit_helper import UnitError
14+
import struct
15+
import sys
16+
17+
if sys.platform != "esp32":
18+
from typing import Union
19+
20+
21+
class DAC2Unit:
22+
"""! DAC2 is a Digital to Analog Converter, GP8413 15bit DAC.
23+
24+
@en DAC2 is a Digital to Analog Converter, includes GP8413 15bit DAC. The GP8413, through the I2C interface, linearly converts to two channels of analog voltage output, 0-5V and 0-10V.
25+
@cn DAC2 是一个数字模拟转换器,包含GP8413 15位DAC。GP8413通过I2C接口线性转换为两个通道的模拟电压输出,0-5V和0-10V。
26+
27+
@attr RANGE_5V output from 0 to 5V
28+
@attr RANGE_10V output from 0 to 10V
29+
@color #0FE6D7
30+
@link https://docs.m5stack.com/en/unit/dac
31+
@image https://static-cdn.m5stack.com/resource/docs/products/unit/dac/dac_01.webp
32+
"""
33+
RANGE_5V = 0
34+
RANGE_10V = 1
35+
CHANNEL_0 = 0,
36+
CHANNEL_1 = 1,
37+
CHANNEL_BOTH = 2,
38+
39+
def __init__(self, i2c: Union[I2C, PAHUBUnit], addr=0x59):
40+
"""! Initialize the DAC.
41+
42+
@param port I2C port to use.
43+
@param addr I2C address of the sensor.
44+
"""
45+
self.i2c = i2c
46+
self.addr = addr
47+
self._available()
48+
self._range = self.RANGE_5V
49+
self.setDACOutputVoltageRange(self._range)
50+
51+
def _available(self):
52+
"""! Check if sensor is available on the I2C bus.
53+
54+
Raises:
55+
Exception: If the sensor is not found.
56+
"""
57+
if not (self.addr in self.i2c.scan()):
58+
raise UnitError("DAC2 Unit not found.")
59+
60+
def setDACOutputVoltageRange(self, _range: int = 0):
61+
"""!
62+
63+
@en Set the DAC %1 output voltage range to %2.
64+
@cn 设置DAC %1 输出电压范围为 %2。
65+
66+
@param range The DAC range to set.
67+
"""
68+
data = 0x00
69+
self._range = _range
70+
if _range == self.RANGE_5V:
71+
self.i2c.writeto_mem(self.addr, 0x01, struct.pack('b', data))
72+
else: # _range == self.RANGE_10V:
73+
data = 0x11
74+
self.i2c.writeto_mem(self.addr, 0x01, struct.pack('b', data))
75+
76+
def setVoltage(self, voltage: float, channel: int = 2):
77+
"""!
78+
@en Set %1 channel %3 to %2 V.
79+
@cn 设置DAC %1 通道 %3 的输出电压为 %1 V。
80+
81+
@param voltage The DAC voltage to set, from 0.0 to range.
82+
@param channel [field_dropdown] The DAC channel to set.
83+
@options {
84+
[Channel 0, CHANNEL_0]
85+
[Channel 1, CHANNEL_1]
86+
[Both Channel, CHANNEL_BOTH]
87+
}
88+
"""
89+
if self._range == self.RANGE_5V:
90+
max_voltage = 5.0
91+
else: # self._range == self.RANGE_10V:
92+
max_voltage = 10.0
93+
if voltage > max_voltage:
94+
voltage = max_voltage
95+
elif voltage < 0.0:
96+
voltage = 0.0
97+
data = int((voltage / max_voltage) * 0xFFFF)
98+
if channel == self.CHANNEL_BOTH:
99+
self.i2c.writeto_mem(self.addr, 0x02, struct.pack('<HH', data, data))
100+
elif channel == self.CHANNEL_0:
101+
self.i2c.writeto_mem(self.addr, 0x02, struct.pack('<H', data))
102+
elif channel == self.CHANNEL_1:
103+
self.i2c.writeto_mem(self.addr, 0x04, struct.pack('<H', data))
104+
105+
def setVoltageBoth(self, voltage0: float, voltage1: float):
106+
"""!
107+
@en Set the DAC %1 channel 0 %2 V, channel 1 %3 V.
108+
@cn 设置 %1 通道0的电压为 %2 V,通道1的电压为 %3 V。
109+
110+
@param voltage0 The DAC voltage of channel 0 to set.
111+
@param voltage1 The DAC voltage of channel 1 to set.
112+
"""
113+
114+
if self._range == self.RANGE_5V:
115+
max_voltage = 5.0
116+
else: # self._range == self.RANGE_10V:
117+
max_voltage = 10.0
118+
if voltage0 > max_voltage:
119+
voltage0 = max_voltage
120+
elif voltage0 < 0.0:
121+
voltage0 = 0.0
122+
if voltage1 > max_voltage:
123+
voltage1 = max_voltage
124+
elif voltage1 < 0.0:
125+
voltage1 = 0.0
126+
data0 = int((voltage0 / max_voltage) * 0xFFFF)
127+
data1 = int((voltage1 / max_voltage) * 0xFFFF)
128+
self.i2c.writeto_mem(self.addr, 0x02, struct.pack('<HH', data0, data1))

m5stack/libs/unit/manifest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"op.py",
4040
"lora_e220_jp.py",
4141
"miniscale.py",
42+
"dac2.py",
4243
"rfid.py",
4344
"weight.py",
4445
"scales.py",

m5stack/libs/unit/miniscale.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def _available(self):
3333
Raises:
3434
UnitError: If the sensor is not found.
3535
"""
36-
if not (self.i2c_addr in self.i2c.scan()):
36+
if not (self.addr in self.i2c.scan()):
3737
raise UnitError("MiniScale Unit not found.")
3838

3939
@property

tools/parse_backtrace.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import sys
2+
import subprocess
3+
import re
4+
5+
def parse_backtrace(elf_file_path, backtrace):
6+
addresses = backtrace.split(' ')
7+
for address in addresses:
8+
if ':' in address:
9+
addr = address.split(':')[0] # 只需要冒号前的地址部分
10+
11+
# 构建命令
12+
command = f"xtensa-esp32-elf-addr2line -pfiaC -e {elf_file_path} {addr}"
13+
14+
# 运行命令并捕获输出
15+
result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
16+
17+
# 打印结果
18+
print(result.stdout)
19+
20+
# 错误处理
21+
if result.stderr:
22+
print("Error:", result.stderr)
23+
24+
if __name__ == '__main__':
25+
if len(sys.argv) != 3:
26+
print("Usage: python parse_backtrace.py <elf_path> <backtrace_string>")
27+
sys.exit(1)
28+
29+
elf_file_path = sys.argv[1]
30+
backtrace = sys.argv[2]
31+
32+
33+
parse_backtrace(elf_file_path, backtrace)

0 commit comments

Comments
 (0)