Luci操作创龙(Tronlong)T113-i开发板PWM

第一步:验证PWM控制

# 引出pwm4
echo 4 > /sys/class/pwm/pwmchip0/export
# 设置周期为 1秒,数值以纳秒为单位
echo 1000000000 > /sys/class/pwm/pwmchip0/pwm4/period
# 设置300毫秒的占空比
echo 300000000 > /sys/class/pwm/pwmchip0/pwm4/duty_cycle
# 设置极性,normal为正极,inversed为负极
echo normal > /sys/class/pwm/pwmchip0/pwm4/polarity
# 使能pwm
echo 1 > /sys/class/pwm/pwmchip0/pwm4/enable
# 停止pwm
echo 0 > /sys/class/pwm/pwmchip0/pwm4/enable
# 删除pwm设备
echo 4 > /sys/class/pwm/pwmchip0/unexport

第二步:创建rpcd 插件

创建 /usr/libexec/rpcd/t113_pwm 文件

#!/bin/sh
. /usr/share/libubox/jshn.sh

case "$1" in
    list)
        echo '{ "set": {"is_positive": 1, "cycle": "1", "value": "0"} }'
        ;;
    call)
        if [ "$2" = "set" ]; then
            # 优先使用命令行参数
            json_input="$3"
            
            # 如果没有命令行参数,尝试读取标准输入
            [ -z "$json_input" ] && [ ! -t 0 ] && json_input=$(head -c 4096 2>/dev/null)
            
            [ -z "$json_input" ] && {
                echo '{ "error": "No JSON input provided" }'
                exit 1
            }
            
            json_load "$json_input" 2>/dev/null || {
                echo '{ "error": "Invalid JSON" }'
                exit 1
            }
            
            # 获取参数
            json_get_var cycle cycle
            json_get_var value value
            json_get_var is_positive is_positive
            
            # 默认值
            : ${cycle:=1}
            : ${value:=0}
            : ${is_positive:=1}
            
            # 参数验证
            case "$is_positive" in
                0|1) ;;
                *) echo '{ "error": "is_positive must be 0 or 1" }'; exit 1 ;;
            esac
            
            # 验证cycle
            echo "$cycle" | awk '{
                if ($0 <= 0) exit 1
                if ($0 !~ /^[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/) exit 1
            }' >/dev/null 2>&1 || {
                echo '{ "error": "cycle must be a positive number" }'
                exit 1
            }
            
            # 验证value
            echo "$value" | awk '{
                if ($0 < 0 || $0 > 100) exit 1
                if ($0 !~ /^[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/) exit 1
            }' >/dev/null 2>&1 || {
                echo '{ "error": "value must be 0-100" }'
                exit 1
            }
            
            # 计算PWM参数
            new_period_ns=$(echo "$cycle" | awk '{ printf "%.0f", $1 * 1000000000 }')
            new_duty_ns=$(echo "$new_period_ns $value" | awk '{ printf "%.0f", $1 * $2 / 100 }')
            
            # 确保占空比不超过周期
            [ "$new_duty_ns" -gt "$new_period_ns" ] && new_duty_ns="$new_period_ns"
            
            # PWM设备处理
            PWM_PATH="/sys/class/pwm/pwmchip0/pwm4"
            [ ! -e "$PWM_PATH" ] && {
                echo 4 > /sys/class/pwm/pwmchip0/export 2>/dev/null
                sleep 0.1
            }
            
            # 保存当前启用状态
            current_enabled=$(cat "$PWM_PATH/enable" 2>/dev/null || echo "0")
            
            # 读取当前实际的周期值
            current_period_ns=$(cat "$PWM_PATH/period" 2>/dev/null || echo "0")
            
            # 计算新周期与当前周期的比值
            # 如果当前周期为0,视为首次设置,按周期变大处理
            if [ "$current_period_ns" -eq 0 ] 2>/dev/null; then
                # 首次设置或当前周期为0,直接设置为新值
                period_ratio=0  # 特殊值,表示首次设置
            else
                # 计算比值:新周期 / 当前周期
                period_ratio=$(echo "$new_period_ns $current_period_ns" | awk '{printf "%.3f", $1/$2}')
            fi
            
            # 调试信息(可选)
            # echo "DEBUG: current_period_ns=$current_period_ns, new_period_ns=$new_period_ns, period_ratio=$period_ratio" >&2
            
            # 根据周期比值决定调整顺序
            if [ "$period_ratio" = "0" ]; then
                # 首次设置或当前周期为0
                # 直接设置周期,再设置占空比
                echo "$new_period_ns" > "$PWM_PATH/period" 2>/dev/null || {
                    echo '{ "error": "Failed to set period (initial setup)" }'
                    exit 1
                }
                
                echo "$new_duty_ns" > "$PWM_PATH/duty_cycle" 2>/dev/null || {
                    echo '{ "error": "Failed to set duty cycle (initial setup)" }'
                    exit 1
                }
                
            else
                # 非首次设置,比较周期比值
                # 使用awk进行浮点数比较
                compare_result=$(echo "$period_ratio 1.0" | awk '{
                    if ($1 < $2) print "smaller"
                    else if ($1 > $2) print "larger"
                    else print "equal"
                }')
                
                # 根据比较结果调整顺序
                case "$compare_result" in
                    smaller)
                        # 周期缩小:新周期 < 当前周期
                        # 先设置占空比(确保占空比不超过新周期)
                        
                        # 检查当前占空比是否可能超过新周期
                        current_duty_ns=$(cat "$PWM_PATH/duty_cycle" 2>/dev/null || echo "0")
                        if [ "$current_duty_ns" -gt "$new_period_ns" ] 2>/dev/null; then
                            # 当前占空比大于新周期,需要先设为0
                            echo 0 > "$PWM_PATH/duty_cycle" 2>/dev/null
                        fi
                        
                        # 先设置占空比
                        echo "$new_duty_ns" > "$PWM_PATH/duty_cycle" 2>/dev/null || {
                            echo '{ "error": "Failed to set duty cycle (period reduction)" }'
                            exit 1
                        }
                        
                        # 再设置周期
                        echo "$new_period_ns" > "$PWM_PATH/period" 2>/dev/null || {
                            echo '{ "error": "Failed to set period (period reduction)" }'
                            exit 1
                        }
                        ;;
                    
                    larger)
                        # 周期变大:新周期 > 当前周期
                        # 先设置周期,再设置占空比
                        
                        # 先设置周期
                        echo "$new_period_ns" > "$PWM_PATH/period" 2>/dev/null || {
                            echo '{ "error": "Failed to set period (period increase)" }'
                            exit 1
                        }
                        
                        # 再设置占空比
                        echo "$new_duty_ns" > "$PWM_PATH/duty_cycle" 2>/dev/null || {
                            echo '{ "error": "Failed to set duty cycle (period increase)" }'
                            exit 1
                        }
                        ;;
                    
                    equal)
                        # 周期不变
                        # 可以直接设置,但为了安全先周期后占空比
                        echo "$new_period_ns" > "$PWM_PATH/period" 2>/dev/null || {
                            echo '{ "error": "Failed to set period (no change)" }'
                            exit 1
                        }
                        
                        echo "$new_duty_ns" > "$PWM_PATH/duty_cycle" 2>/dev/null || {
                            echo '{ "error": "Failed to set duty cycle (no change)" }'
                            exit 1
                        }
                        ;;
                esac
            fi
            
            # 设置极性,一定要在设置完周期和占空比之后再设置
            [ "$is_positive" = "1" ] && polarity="normal" || polarity="inversed"
            echo "$polarity" > "$PWM_PATH/polarity" 2>/dev/null || {
                echo '{ "error": "Failed to set polarity" }'
                exit 1
            }

            # 启用pwm
            if [ "$current_enabled" -eq 0 ]; then
                echo 1 > "$PWM_PATH/enable" 2>/dev/null || {
                    echo '{ "error": "Failed to enable PWM" }'
                    exit 1
                }
            fi
            
            echo '{ "status": "ok", "period_ns": "'"$new_period_ns"'", "duty_ns": "'"$new_duty_ns"'", "value_percent": "'"$value"'", "period_ratio": "'"$period_ratio"'", "old_period_ns": "'"$current_period_ns"'" }'
        else
            echo '{ "error": "Method not found" }'
            exit 1
        fi
        ;;
    *)
        echo '{ "error": "Invalid command" }'
        exit 1
        ;;
esac

赋予执行权限

chmod +x /usr/libexec/rpcd/t113_pwm

第三步:重启rpcd服务

/etc/init.d/rpcd restart

第四步:验证ubus服务是否注册成功

ubus list | grep t113
# 应输出: t113_led t113_pwm

ubus call t113_pwm set '{"is_positive": 1, "cycle": 1, "value": 20 }'
# 应返回: { "status": "ok",
# 	"period_ns": "1000000000",
# 	"duty_ns": "200000000",
# 	"value_percent": "20",
# 	"period_ratio": "0",
# 	"old_period_ns": "0"
#  }

第五步:创建luci页面

  1. controller: /usr/lib/luci/controller/t113_led.lua
module("luci.controller.greeting", package.seeall)

function index()
    -- 使用 'view' 而非 'cbi',就是使用js来渲染
    -- entry({"admin", "system", "greeting"}, cbi("greeting"), _("Greeting"), 99)
    entry({"admin", "system", "greeting"}, view("eboy_light/greeting"), _("Greeting"), 99)
    entry({"admin", "system", "t113_led"}, view("eboy_light/t113_led"), _("T113_LED"), 98)
end
  1. view: /www/luci-static/resources/view/eboy_light/t113_pwm.js
'use strict';
'require rpc';
'require view';
'require uci';

var callPWMSet = rpc.declare({
    object: 't113_pwm',
    method: 'set',
    params: ['value','cycle','is_positive'],
    expect: { '': {} }
});

return view.extend({
    render: function() {
        const map = new form.Map(
        'eboylight',
        _('灯控配置'),
        _('设置开关灯、调光阶段.')
        )
        let s = map.section(form.NamedSection, 'pwm','pwm', _('PWM'))
        s.addremove = false
        s.anonymous = true
        let msg = s.option(form.Value, 'value', _('PWM值(%)'))
        msg.datatype = 'range(0,100)'
        msg.default = '50'
        msg.rmempty = false
        msg = s.option(form.Value, 'cycle', _('PWM周期(秒)'))
        msg.datatype = 'range(0,1000)'
        msg.default = '1'
        msg.rmempty = false
        msg = s.option(form.ListValue, 'is_positive', _('PWM极性'))
        msg.value('1', _('正'))
        msg.value('0', _('负'))
        msg.default = '1'
        map.save = function(){
            const options = {
                value: parseInt(uci.get('eboylight', 'pwm', 'value')),
                cycle: parseFloat(uci.get('eboylight', 'pwm', 'cycle')),
                is_positive: parseInt(uci.get('eboylight', 'pwm', 'is_positive'))
            }
            console.log(options)
            callPWMSet(options.value, options.cycle, options.is_positive).then(function (res) {
                if (res.status === 'ok') {
                alert(_('PWM已设置'))
                } else {
                alert(_('Error: %s').format(res.error || 'Unknown'))
                }
            })
            return form.Map.prototype.save.apply(this, arguments)
        }
    }
});
  1. 对应配置文件:/etc/config/eboylight
config pwm 'pwm'
	option is_positive '1'
	option cycle '1'
	option value '60'

第六步:配置权限

创建 /usr/share/rpcd/acl.d/t113_pwm.json

{
    "t113_led": {
        "description": "T113 PWM control",
        "read": {
            "ubus": {
                "t113_pwm": [ "list" ]
            }
        },
        "write": {
            "ubus": {
                "t113_pwm": [ "set" ]
            }
        }
    }
}

重启rpcd服务

/etc/init.d/rpcd restart
#or service rpcd restart
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值