RK3568 android11 调试光感模块

2023-10-16 21:12

本文主要是介绍RK3568 android11 调试光感模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一,简介

光感模块是一种用于检测光照强度的传感器。它可以感知周围环境的光照水平,并将其转换为电信号输出。光感模块的工作原理基于光电效应,主要有以下几种类型:

  1. 光敏电阻(LDR):光敏电阻是一种基于光电效应的传感器,其电阻值会根据光照强度的变化而变化。当光照强度增加时,光敏电阻的电阻值会减小,反之亦然。通过测量光敏电阻的电阻值,可以得到光照强度的信息。

  2. 光电二极管(Photodiode):光电二极管是一种能够将光能转化为电能的二极管。当光照射到光电二极管上时,光子会激发电子,使其在PN结中产生电流。通过测量光电二极管上的电流,可以得到光照强度的信息。

  3. 光电三极管(Phototransistor):光电三极管是一种具有放大功能的光电二极管。它可以将光能转化为电能,并放大输出的电流。光电三极管通常具有更高的灵敏度和响应速度,适用于需要较高灵敏度的应用。

  4. 光电容传感器(Photocapacitor):光电容传感器是一种基于光电效应的电容传感器。当光照射到光电容传感器上时,光子会激发电子,使其在电容器中产生电荷积累。通过测量电容器上的电荷积累水平,可以得到光照强度的信息。

这些光感模块可以通过模拟电压输出或数字接口输出(例如I2C或SPI)来提供光照强度的信息。它们广泛应用于自动照明系统、环境监测、光线调节和光敏控制等领域。


二,驱动部分

调试光感模块(三个角分别接供电VCC、地GND、ADC),光线越亮, 屏越亮;光线越暗, 屏越暗(亮度不低于50%)

1.添加ADC驱动

源码路径:kernel/drivers/input/keyboard/adc0_driver.c

/*
* Input driver for resistor ladder connected on ADC
*
* Copyright (c) 2016 Alexandre Belloni
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/#include <linux/err.h>
#include <linux/iio/consumer.h>
#include <linux/iio/types.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>/*----<fy:add  api for app read adc value>---------------*/
struct iio_channel *adc_channel;static ssize_t adc_value_read(struct device *dev, struct device_attribute *attr,char *buf)
{//return sprintf(buf, "%d\n",sunxi_keyboard_read_data());int read_value = 0;if(adc_channel !=NULL)iio_read_channel_processed(adc_channel, &read_value);return sprintf(buf, "%d\n",read_value);
}static DEVICE_ATTR(adc_value, S_IRUGO|S_IWUSR|S_IWGRP,adc_value_read, NULL);static struct attribute *adc_value_attributes[] = {&dev_attr_adc_value.attr,NULL
};static struct attribute_group adc_value_attribute_group = {.attrs = adc_value_attributes
};
/*----<fy:end>---------------------------------------*/static int adc0_driver_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;struct kobject *dev_kobj;int err =-1;printk("adc_value:adc_keys_probe 1\n");adc_channel = devm_iio_channel_get(dev, "adc0_chan");if (IS_ERR(adc_channel))return PTR_ERR(adc_channel);printk("adc_value:adc_keys_probe 2\n");/*fy add kobj  to create    sysfs of adc_value>*/dev_kobj = kobject_create_and_add("adc_value",NULL);if(dev_kobj != NULL)err = sysfs_create_group(dev_kobj,&adc_value_attribute_group);if (err < 0){printk("adc_value: sysfs_create_group err\n");}/*fy: end >*/return 0;
}#ifdef CONFIG_OF
static const struct of_device_id adc0_driver_of_match[] = {{ .compatible = "adc0_driver", },{ }
};
MODULE_DEVICE_TABLE(of, adc0_driver_of_match);
#endifstatic struct platform_driver __refdata adc0_driver = {.driver = {.name = "adc0_driver",.of_match_table = of_match_ptr(adc0_driver_of_match),},.probe = adc0_driver_probe,
};
module_platform_driver(adc0_driver);MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
MODULE_DESCRIPTION("Input driver for resistor ladder connected on ADC");
MODULE_LICENSE("GPL v2");
1.1,关于iio_read_channel_processed函数

iio_read_channel_processed` 函数的实现是在 IIO 子系统中完成的。它的主要作用是读取指定 IIO 通道的原始值,并将其转换为工程单位后的值。下面是该函数的伪代码:

int iio_read_channel_processed(struct iio_channel *chan, int *val)
{int ret;long long raw_val;double scale, offset;// 读取 IIO 通道的原始值ret = iio_read_channel_raw(chan, &raw_val);if (ret < 0)return ret;// 获取 IIO 设备的比例因子和偏移量scale = iio_channel_get_scale(chan);offset = iio_channel_get_offset(chan);// 将原始值转换为工程单位后的值*val = (int)round((raw_val * scale) + offset);return 0;
}

在这个函数中,首先调用 iio_read_channel_raw函数读取 IIO 通道的原始值,并将其保存在 raw_val变量中。然后,通过调用 iio_channel_get_scale和 iio_channel_get_offset函数获取 IIO 设备的比例因子和偏移量。比例因子和偏移量是用于将原始值转换为工程单位后的值的参数。最后,将原始值乘以比例因子,加上偏移量,并使用 round函数四舍五入为整数,得到处理后的值,并将其保存在 val 变量中。

需要注意的是,iio_read_channel_processed 函数只能读取处理后的值,而无法读取原始值。如果需要读取原始值,可以使用 iio_read_channel_raw 函数。

1.2 iio操作说明

1> 获取AD通道

struct iio_channel *chan; //定义 IIO 通道结构体
chan = iio_channel_get(&pdev->dev,xxx); //获取 IIO 通道结构体

注: iio_channel_get 通过 probe 函数传进来的参数 pdev 获取 IIO通道结构体,probe 函数如下:

2> 读取AD采集到的原始数据

int val,ret;
ret = iio_read_channel_raw(chan, &val);

调用 iio_read_channel_raw 函数读取 AD 采集的原始数据并存入 val 中。
3> 计算采集到的电压
使用标准电压将 AD 转换的值转换为用户所需要的电压值。其计算公式如下:

Vref / (2^n-1) = Vresult / raw
例如,标准电压为 1.8V,AD 采集位数为 10 位,AD 采集到的原始数据为 568,则: Vresult = (1800mv * 568) / 1023

  • Vref 为标准电压
  • n 为 AD 转换的位数
  • Vresult 为用户所需要的采集电压
  • raw 为 AD 采集的原始数据

2.添加Makefile

源码路径:kernel/drivers/input/keyboard/Makefile

diff --git a/kernel/drivers/input/keyboard/Makefile b/kernel/drivers/input/keyboard/Makefile
index 182e929..0ada96c 100644
--- a/kernel/drivers/input/keyboard/Makefile
+++ b/kernel/drivers/input/keyboard/Makefile
@@ -67,3 +67,4 @@ obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY)    += tm2-touchkey.o
obj-$(CONFIG_KEYBOARD_TWL4030)        += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD)        += xtkbd.o
obj-$(CONFIG_KEYBOARD_W90P910)        += w90p910_keypad.o
+obj-y          += adc0_driver.o

3.dts中添加设备节点

源码路径:kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi

diff --git a/kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi
index 0cf8a59..3384fe1 100644
--- a/kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi
+++ b/kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsi
@@ -291,6 +291,13 @@};};+    adc:adc0_driver {
+            compatible = "adc0_driver";
+            io-channels = <&saradc 4>;
+            io-channel-names = "adc0_chan";
+            //keyup-threshold-microvolt = <1800000>;
+    };firmware {firmware_android: android {compatible = "android,firmware";

驱动部分添加完成后编译烧录, 在进入系统后,会出现一个 /sys/adc_value/adc_value节点,表示创建成功。cat /sys/adc_value/adc_value可看到节点状态。


三,frameworks部分

源码路径:frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java

diff --git a/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 1f41038..3298c78 100644
--- a/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -39,13 +39,40 @@ import java.io.PrintWriter;
import javax.inject.Inject;
-public class SystemUIService extends Service {
+import android.app.smdt.SmdtManagerNew;
+import android.app.smdt.SmdtManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import android.content.Context;
+public class SystemUIService extends Service {
+    private static final String TAG="SystemUIService";private final Handler mMainHandler;private final DumpHandler mDumpHandler;private final BroadcastDispatcher mBroadcastDispatcher;private final LogBufferFreezer mLogBufferFreezer;private final BatteryStateNotifier mBatteryStateNotifier;
+    private SmdtManager mSmdt=null;
+    private SmdtManagerNew smdtManagerNew;
+    private Context mContext;@Injectpublic SystemUIService(
@@ -72,6 +99,13 @@ public class SystemUIService extends Service {// Finish initializing dump logicmLogBufferFreezer.attach(mBroadcastDispatcher);
+        mContext=this;
+        if(mSmdt==null){
+             mSmdt = new SmdtManager(mContext);
+              smdtManagerNew = SmdtManagerNew.getInstance(mContext);
+        }
+        mHandler.sendEmptyMessageDelayed(1001,100);
+// If configured, set up a battery notificationif (getResources().getBoolean(R.bool.config_showNotificationForUnknownBatteryState)) {mBatteryStateNotifier.startListening();
@@ -103,6 +137,87 @@ public class SystemUIService extends Service {UserHandle.SYSTEM);}
+private Handler mHandler=new Handler(){
+    @Override
+        public void dispatchMessage(Message msg) {
+            switch (msg.what){
+                case 1001://wifi
+                    Log.d(TAG, "dispatchMessage: fy==========value="+cccccss());//("cat /sys/adc_value/adc_value"));
+                    readLightSenseValue();
+                    mHandler.removeMessages(1001);
+                    mHandler.sendEmptyMessageDelayed(1001,500);
+                    break;
+                case 1002://
+
+                    break;
+                default:
+                    break;
+            }
+        }
+};
+private int cccccss(){//get light sensor value
+    String a="0";
+    try {
+        BufferedReader bufWriter = null;
+        bufWriter = new BufferedReader(new FileReader("/sys/adc_value/adc_value"));
+        a=bufWriter.readLine();
+        bufWriter.close();
+
+    } catch (IOException e) {
+        e.printStackTrace();
+        Log.e("aaa","can't write the point" );
+    }
+    return Integer.parseInt(a);
+}
+
+//光线越亮, 屏越亮;光线越暗, 屏越暗(亮度不低于50%)
+private int oldvalue = 1800;
+private int time = 0;
+private int readLightSenseValue(){
+    int result=0;
+    int value=cccccss();
+    Log.d(TAG, "dispatchMessage: fy==========value="+value);
+    if(Math.abs(value - oldvalue) < 10)
+        return result;
+    time ++;
+    if(time < 2)
+      return result;
+    time = 0;
+
+    Log.d(TAG, "readLightSenseValue: adc value="+value + " oldvalue="+oldvalue);
+    oldvalue = value;
+    float fv = ((float)value - 1646) / 150;
+    Log.d(TAG, "readLightSenseValue: fv="+fv);
+    value=(int)(fv*255);
+    if(value < 10)
+        value = 10;
+    
+    //value = (int)(((255.0 - 125.0) / 10.0 ) * value + 125 );
+    if(value > 255)
+        value = 255;
+    Log.d(TAG, "smdt set lvds Brightness " + value);
+    setLcdBrightness(value);
+    mSmdt.setBrightness(getContentResolver(), value);
+    return result;
+}
+
+/* //光线越暗 屏越亮,光线越亮 屏越暗(亮度不低于50%)
+private int oldvalue = 1800;
+private int time = 0;
+private int readLightSenseValue(){
+    int result=0;
+    int value=cccccss();
+    if(Math.abs(value - oldvalue) < 40)
+        return result;
+    time ++;
+    if(time < 3)
+      return result;
+    time = 0;+    Log.d(TAG, "readLightSenseValue: adc value="+value + " oldvalue="+oldvalue);
+    oldvalue = value;
+    value = (value - 900) / 40;
+    Log.d(TAG, "readLightSenseValue: value="+value);
+    if(value > 10)
+        value = 10;
+    setLcdBrightness(value);
+    value = (int)(((255.0 - 125.0) / 10.0 ) * value + 125 );
+    if(value > 255)
+        value = 255;
+    Log.d(TAG, "smdt set lvds Brightness " + value);
+    mSmdt.setBrightness(getContentResolver(), value);
+    return result;
+}
+*/+private void setLcdBrightness(int bri){
+    smdtManagerNew.disp_setLcdBackLight(0, bri, 0, false);
+@Overridepublic IBinder onBind(Intent intent) {return null;

这篇关于RK3568 android11 调试光感模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/220820

相关文章

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

Nginx添加内置模块过程

《Nginx添加内置模块过程》文章指导如何检查并添加Nginx的with-http_gzip_static模块:确认该模块未默认安装后,需下载同版本源码重新编译,备份替换原有二进制文件,最后重启服务验... 目录1、查看Nginx已编辑的模块2、Nginx官网查看内置模块3、停止Nginx服务4、Nginx

python urllib模块使用操作方法

《pythonurllib模块使用操作方法》Python提供了多个库用于处理URL,常用的有urllib、requests和urlparse(Python3中为urllib.parse),下面是这些... 目录URL 处理库urllib 模块requests 库urlparse 和 urljoin编码和解码

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

创建springBoot模块没有目录结构的解决方案

《创建springBoot模块没有目录结构的解决方案》2023版IntelliJIDEA创建模块时可能出现目录结构识别错误,导致文件显示异常,解决方法为选择模块后点击确认,重新校准项目结构设置,确保源... 目录创建spChina编程ringBoot模块没有目录结构解决方案总结创建springBoot模块没有目录

idea Maven Springboot多模块项目打包时90%的问题及解决方案

《ideaMavenSpringboot多模块项目打包时90%的问题及解决方案》:本文主要介绍ideaMavenSpringboot多模块项目打包时90%的问题及解决方案,具有很好的参考价值,... 目录1. 前言2. 问题3. 解决办法4. jar 包冲突总结1. 前言之所以写这篇文章是因为在使用Mav

Python标准库datetime模块日期和时间数据类型解读

《Python标准库datetime模块日期和时间数据类型解读》文章介绍Python中datetime模块的date、time、datetime类,用于处理日期、时间及日期时间结合体,通过属性获取时间... 目录Datetime常用类日期date类型使用时间 time 类型使用日期和时间的结合体–日期时间(

在IntelliJ IDEA中高效运行与调试Spring Boot项目的实战步骤

《在IntelliJIDEA中高效运行与调试SpringBoot项目的实战步骤》本章详解SpringBoot项目导入IntelliJIDEA的流程,教授运行与调试技巧,包括断点设置与变量查看,奠定... 目录引言:为良驹配上好鞍一、为何选择IntelliJ IDEA?二、实战:导入并运行你的第一个项目步骤1