pdSink模块¶
状态 | 最后更新 | API版本 |
---|---|---|
Active | 2019-11-20 | V1.00.00 |
描述¶
此模块提供对PD作为Sink的访问
pdSink和fastChgTrig¶
您可能会认为,pdSink应当被fastChgTrig包含,毕竟PD也是一种快速充电协议。但是有几个让人不这么做的理由:
PD协议功能比其他快速充电协议更强大,使得其很难被抽象进其他协议的模型。
与fastChgTrig内的协议不同,PD不使用D+ D-作为通讯载体。事实上,PD与 fastChgTrig内的协议使用的硬件是完全独立的。
注意事项¶
使用这个模块需要一些PD协议的基础知识,其标准文档可在USB-IF的网站内找到。
尽管PD和其他协议的硬件是独立的(即理论上,它可以与其他协议同时运行),但充电器不接受同时运行两个协议这种做法,这会引起相互冲突的请求,产生不完全定义的行为。在使用pdSink之前,应当调用
fastChgTrig.open()
,正如使用fastChgTrig
模块一样,这可以避免上述情况。这个模块企图寻找使用复杂程度和灵活性间的平衡。即使您完全理解各API,如果您缺少对PD或该协议在此平台底层软件的实现的了解,您也可能会陷入代码无法工作的窘境。推荐您在编写代码前,先查看本页末尾的示例代码,对操作流程有大概的了解。
典型操作流程(面向过程)¶
下面列出与PD充电器间建立通讯并完成请求的典型流程:
1.调用 pdSink.init()
来初始化硬件和底层软件, 检查返回值, 如果返回值为 pdSink.OK
, 则继续操作。如果返回值不为pdSink.OK
,说明没有PD充电器连接。
2.反复查询 pdSink.isSrcCapReceived()
直到其返回值为true
(通常您需要设计2秒的超时), 如果超时, 则操作失败, 或者您需要调用 pdSink.sendHardReset()
然后重新开始步骤1.
需要注意的是,在PD充电器接入后,充电器只会在几秒钟内持续发送src_cap
消息,这意味着除非您的代码在表头上电后立刻启动,您大概率会无法收到src_cap
消息。此时,您需要调用pdSink.sendHardReset()
来复位充电头,此后,您应该能收到src_cap
消息。
3.调用 pdSink.getSrcCapNum()
和 pdSink.getSrcCap()
将PDO传输到lua中, 如果您已经预先知道您的电源的Source_Capability
,您可以略过这一步。
4.调用 pdSink.request()
来获得请求您想要的电压和电流。
pdSink.init()¶
描述¶
这将初始化pdSink模块,详细地,它将做以下工作:
检测
Source
的连接状态,如果没有Source
连接,返回pdSink.FAIL
。如果有连接被检测到,在对应的
CC
引脚上初始化PD通讯,复位底层软件状态,并返回pdSink.OK
您需要检查本函数的返回值,以决定是否需要下一步操作。
参数¶
nil
返回值¶
number
pdSink.FAIL
如果没有CC连接或其他失败情况发生.
pdSink.OK
如果初始化完成.
调用例¶
rtval = pdSink.init()
pdSink.getCCStatus()¶
描述¶
这个函数没有进行任何硬件操作,他只返回在pdSink.init()
调用后CC引脚的连接状态。
Parameters¶
nil
Return value¶
number
pdSink.CC1_SRC_ATTACHED
如果Source
连接在CC1。
pdSink.CC2_SRC_ATTACHED
如果Source
连接在CC2。
pdSink.NO_SRC_ATTACHED
如果没有Source
被检测到。
调用例¶
status = pdSink.getCCStatus()
pdSink.isSrcCapReceived()¶
描述¶
检查Source_Capability
消息是否已经收到,这个状态在pdSink.init()
或pdSink.deinit()
将被清除,在Source_Capability
收到时将会被置为true。
参数¶
nil
返回值¶
boolean
true
如果已收到Source_Capability
消息。
false
如果暂未收到Source_Capability
消息。
调用例¶
received = pdSink.isSrcCapReceived()
pdSink.getNumofSrcCap()¶
描述¶
获取Source_Capability
消息中PDO的个数。
参数¶
nil
返回值¶
number
Source_Capability
消息中PDO的个数。
调用例¶
pdo_num = pdSink.getNumofSrcCap()
pdSink.getSrcCap()¶
获Source_Capability
消息中指定PDO的信息
参数¶
Name | Type | Range | Usage |
---|---|---|---|
<index> | number | 0~6 | 指定要获取的PDO的索引 |
返回值¶
table 返回一个table,具有以下的结构:
域 | 类型 | 范围 | 用途 |
---|---|---|---|
type | number | pdSink.FIXED pdSink.BATTERY pdSink.VARIABLE pdSink.AUGMENTED | PDO的类型 |
voltage | number | 如果该PDO是FIXED的,那么该域的值为该PDO的固定电压值。如果该PDO是AUGMENTED的,那么该域的值为该PDO中报告的最小电压值。 | |
voltageMax | number | 如果PDO是FIXED的,该域没有意义。如果该PDO是AUGMENTED的,那么该域的值为该PDO中报告的最大电压值 | |
currentMax | number | 该PDO报告的最大电流值 |
调用例¶
pdo0 = pdSink.getSrcCap(0)
pdSink.request()¶
描述¶
请求使用一个指定PDO, 并指定电压和电流。
参数¶
返回值¶
名称 | 类型 | 范围 | 用途 |
---|---|---|---|
<pdo> | number | 0~6 | 指定要请求的PDO的索引 |
[voltage] | number | 如果该PDO是FIXED的, 那么该参数必须为该PDO唯一的电压。如果该PDO是AUGMENTED的,指定要请求的电压值,必须保证电压值在该PDO所报告的范围内。 如果该参数缺省,且该PDO是FIXED的,那么请求的电压值为该PDO唯一的电压。 | |
[current] | number | 指定要请求的作业电流,该参数必须在该PDO所报告的电流范围内。如果该参数缺省,作业电流为该PDO中报告的最大电流。 |
返回值¶
number
pdSink.OK
请求成功并且PS_Ready
已收到。
pdSink.FAIL
请求超时或者PS_Ready
未收到。
Example call¶
--Request PDO with index 1, voltage 9V, current 3A
result = pdSink.request(1,9.00,3.00)
pdSink.deinit()¶
描述¶
禁能PD通讯,并复位底层软件到默认状态。
请注意该函数不会复位充电器,如果您需要这么做,您需要额外调用pdSink.sendHardReset()
。
参数¶
nil
返回值¶
nil
调用例¶
pdSink.deinit()
pdSink.onSrcCapReceived()¶
描述¶
注册或取消注册在Source Capability收到时的回调函数。
参数¶
名称 | 类型 | 范围 | 用途 |
---|---|---|---|
<callback> | nil 或 function | 指定回调函数,当该事件发生时,回调函数被调用,且调用后不会被自动取消注册。要取消注册回调函数,用nil 作为参数调用本函数。 |
返回值¶
nil
调用例¶
function onSrcCapReceived()
print("Source Capability received.")
end
pdSink.onSrcCapReceived(onSrcCapReceived)
模块示例代码(过程)¶
--[[This is a demo for PD APIs.
You connect the meter to a PD charger with a C-C cable, and DO NOT plug-in any other device.
The output of the demo is on the debug terminal.
The demo detect if any source is attached first, if no source is detected, it exits.
Then it waits for src_cap, if not received, it sends a HARD_RST message to reset the charger, if still no src_cap is received, it exits.
After the src_cap received, it prints out the src_cap on the terminal.
Then it started to request FIXED pdos of the charger one by one.
If there is any AUGMENTED(PPS) pdo, it requests them one by one.
The voltage reading and request status is on the terminal.
Detailed Documentation:
Version: 191120
Author: yanke928
]]
function WaitForSourceCap()
i = 2000
while(i > 0) do
i = i - 1;
if(pdSink.isSrcCapReceived()) then
return true
end
delay.ms(1)
end
return false
end
function DemoEnd()
print("---End of PD demo---")
os.exit(0)
end
print("---Start of PD demo---")
--Open fastChgTrig
if(fastChgTrig.open() ~= fastChgTrig.OK) then
print("Failed to open fastChgTrig")
DemoEnd()
end
--Init PD
pdSink.init()
print("PD inited")
--Check if any source is attached
if(pdSink.getCCStatus() == pdSink.NO_SRC_ATTACHED) then
print("No CC attached")
DemoEnd()
end
print("Waiting for src_cap")
--Wait for src_cap.
received = WaitForSourceCap()
--In case of time out, try a hard reset
if(received == false) then
print("src_cap timeout, sending hard reset")
pdSink.sendHardReset()
pdSink.init()
print("Waiting for src_cap again.")
received = WaitForSourceCap()
--If we still cannot receive src_cap
if(received == false) then
print("No src_cap received, exiting...")
DemoEnd()
end
end
print("src_cap received")
delay.ms(1000)
--Get src_cap into table
src_cap_num = pdSink.getNumofSrcCap()
print(string.format("We have %d src_caps:",src_cap_num))
src_caps = {}
for i = 0,src_cap_num -1 do
src_caps[i] = pdSink.getSrcCap(i)
--Fixed type, print voltage and max current
if(src_caps[i].type == pdSink.FIXED) then
print(string.format("No.[%d] Type[FIXED] Voltage[%.2fV] Current[%.2fA]",i,src_caps[i].voltage,src_caps[i].currentMax))
elseif (src_caps[i].type == pdSink.AUGMENTED) then
print(string.format("No.[%d] Type[AUGMENTED] Voltage[%.2f~%.2fV] Current[%.2fA] ",i,src_caps[i].voltage,src_caps[i].voltageMax,src_caps[i].currentMax))
else
print(string.format("No.[%d] Unknown Type",i))
end
end
meter.setDataSource(meter.INSTANT)
print("Started to request FIXED PDOs")
for i = 0,src_cap_num -1 do
if(src_caps[i].type == pdSink.FIXED) then
print(string.format("Requesting FIXED No.%d",i))
if(pdSink.request(i,src_caps[i].voltage,src_caps[i].currentMax) ~= pdSink.OK) then
print("Request failed")
DemoEnd()
end
print(string.format("Request Success, voltage now: %.3fV",meter.readVoltage()))
delay.ms(1000)
end
end
print("Started to request AUGMENTED PDOs")
for i = 0,src_cap_num -1 do
if(src_caps[i].type == pdSink.AUGMENTED) then
--Here, we use the middle point of the PPS voltage to give an example.
req_volt = (src_caps[i].voltage + src_caps[i].voltageMax) / 2
print(string.format("Requesting AUGMENTED No.%d Voltage %.3fV",i,req_volt))
if(pdSink.request(i,req_volt,src_caps[i].currentMax) ~= pdSink.OK) then
print("Request failed")
DemoEnd()
end
print(string.format("Request Success, voltage now: %.3fV",meter.readVoltage()))
delay.ms(1000)
end
end
DemoEnd()
模块示例代码(事件驱动)¶
--[[This is a event-driven demo for PD APIs.
You connect the meter to a PD charger with a C-C cable, and DO NOT plug-in any other device.
The output of the demo is on the debug terminal.
The demo detect if any source is attached first, if no source is detected, it exits.
Then it waits for src_cap, if not received, it sends a HARD_RST message to reset the charger, if still no src_cap is received, it exits.
After the src_cap received, it prints out the src_cap on the terminal.
Then it started to request FIXED pdos of the charger one by one.
If there is any AUGMENTED(PPS) pdo, it requests them one by one.
The voltage reading and request status is on the terminal.
Detailed Documentation:
Version: 191120
Author: yanke928
]]
timeoutTimerCount = 0
srcCapOK = false
src_caps = {}
src_cap_num = 0
request_index = 0
function demoEnd()
print("----End of demo----")
os.exit()
end
function requestTimer_callback(tim)
if(src_caps[request_index].type == pdSink.FIXED) then
print(string.format("Requesting FIXED No.%d",request_index))
if(pdSink.request(request_index,src_caps[request_index].voltage,src_caps[request_index].currentMax) ~= pdSink.OK) then
print("Request failed")
DemoEnd()
end
print(string.format("Request Success, voltage now: %.3fV",meter.readVoltage()))
else if(src_caps[request_index].type == pdSink.AUGMENTED) then
--Here, we use the middle point of the PPS voltage to give an example.
req_volt = (src_caps[request_index].voltage + src_caps[request_index].voltageMax) / 2
print(string.format("Requesting AUGMENTED No.%d Voltage %.3fV",request_index,req_volt))
if(pdSink.request(request_index,req_volt,src_caps[request_index].currentMax) ~= pdSink.OK) then
print("Request failed")
DemoEnd()
end
print(string.format("Request Success, voltage now: %.3fV",meter.readVoltage()))
end
end
request_index = request_index + 1
if(request_index == src_cap_num) then
print("All PDO requested, exiting...")
demoEnd()
end
end
function timeoutTimer_callback(tim)
timeoutTimerCount = timeoutTimerCount + 1
if(srcCapOK ~= true) then
if(timeoutTimerCount == 2) then
print("No src_cap received, exiting...")
demoEnd()
end
print("src_cap timeout, sending hard reset...")
pdSink.sendHardReset()
pdSink.init()
else
requestTimer= tmr.new()
requestTimer:setup(0,1000,tmr.AUTO_RELOAD,requestTimer_callback)
requestTimer:start()
pdSink.onSrcCapReceived(nil)
tim:remove()
end
end
function onSrcCapReceived()
print("Source Capability Received")
srcCapOK = true
--Get src_cap into table
src_cap_num = pdSink.getNumofSrcCap()
print(string.format("We have %d src_caps:",src_cap_num))
for i = 0,src_cap_num -1 do
src_caps[i] = pdSink.getSrcCap(i)
--Fixed type, print voltage and max current
if(src_caps[i].type == pdSink.FIXED) then
print(string.format("No.[%d] Type[FIXED] Voltage[%.2fV] Current[%.2fA]",i,src_caps[i].voltage,src_caps[i].currentMax))
elseif (src_caps[i].type == pdSink.AUGMENTED) then
print(string.format("No.[%d] Type[AUGMENTED] Voltage[%.2f~%.2fV] Current[%.2fA] ",i,src_caps[i].voltage,src_caps[i].voltageMax,src_caps[i].currentMax))
else
print(string.format("No.[%d] Unknown Type",i))
end
end
end
print("----Start of demo----")
if(fastChgTrig.open() ~= fastChgTrig.OK) then
print("Failed to open fastChgTrig")
demoEnd()
end
--Init PD
pdSink.init()
print("PD inited")
--Check if any source is attached
if(pdSink.getCCStatus() == pdSink.NO_SRC_ATTACHED) then
print("No CC attached")
DemoEnd()
end
timeoutTimer = tmr.new()
timeoutTimer :setup(2000,2000,tmr.AUTO_RELOAD,timeoutTimer_callback)
timeoutTimer :start()
pdSink.onSrcCapReceived(onSrcCapReceived)
print("Waiting for src_cap...")