Zephry传感器模型介绍和bme280测试

2024-01-11 14:10

本文主要是介绍Zephry传感器模型介绍和bme280测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、Sensor模型介绍

Zephry针对传感器这一类设备定义了一套统一传感器驱动接口,如果你的传感器想要在Zephry上实现自己的驱动,那么需要遵守这一套接口模型标准。

因为市面上的传感器大多数所反馈的数据基本上都是差不多的,如水平X、Y轴,温度、气压等一些数据,Zephry为了统一管理实现了一套标准API与宏定义,要求开发者们根据去实现这一套标准API,在结合对应的宏定义来反馈传感器对应的值。

Zephry不关心传感器底层是如何实现的,也不关心如何与传感器进行通讯,它要求开发者们实现这套标准统一API,至于底层怎么写随开发者们,无限制,但要求传递参数与反馈值是统一的。

Zephry要求你的传感器设备需要定义在总线上,即定义在dts文件的总线上,让Zephry知道你的设备是通过什么进行通讯的,是I2C、SPI,基于这些Zephry才能解析并调用对应的API,同时这些通讯方式也要求开发者们自己实现,如果你的传感器支持I2C、SPI,那么你就需要写两套代码给Zephry。

二、统一接口

Zephry提供了五个统一开发接口:

传感器接口模型定义在"include/dirvers/sensor.h"文件中

1. sensor_sample_fetch

1.1 函数介绍

函数原型

作用

返回值

int sensor_sample_fetch(struct device *dev);将传感器的所有类型数据放置内存0成功,非0失败

1.2 参数介绍

参数名

类型

作用

devstruct device *指向实例化传感器设备指针

1.3 备注

如果想要从传感器获取数据需要先执行这个函数,目的是将传感器的数据放置到内存里,我们就可以往内存里存取数据了,这里的类型是指气压,温度,湿度或者水平数据

2. sensor_sample_fetch_chan

1.1 函数介绍

函数原型

作用

返回值

int sensor_sample_fetch_chan(struct device *dev, enum sensor_channel type);将传感器指定类型数据放置内存0成功,非0失败

1.2 参数介绍

参数名

类型

作用

devstruct device *指向实例化传感器设备指针

3. sensor_channel_get

1.1 函数介绍

函数原型

作用

返回值

int sensor_channel_get(struct device *dev, enum sensor_channel chan, struct sensor_value *val);从内存获取指定类型的数据0成功,非0失败

1.2 参数介绍

参数名

类型

作用

devstruct device *指向实例化传感器设备指针
chanenum sensor_channel chan,数据类型
valstruct sensor_value *存放数据的结构体指针

4. sensor_attr_set

1.1 函数介绍

函数原型

作用

参数

int sensor_attr_set(struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val);设置传感器参数,如采样频率,触发阈值0成功,非0失败

1.2 参数介绍

参数名

类型

作用

devstruct device *指向实例化传感器设备指针
chanenum sensor_channel数据类型
attrenum sensor_attribute要设定的属性类型
valconst struct sensor_value *要设定的值

5. sensor_trigger_set

1.1 函数介绍

函数原型

作用

参数

static inline int sensor_trigger_set(const struct device *dev, struct sensor_trigger *trig, sensor_trigger_handler_t handler)激活传感器触发器,并设置触发器的处理函数0成功,非0失败

1.2 参数介绍

参数名

类型

作用

devstruct device *指向实例化传感器设备指针
trigstruct sensor_trigger *触发器激活属性
handlersensor_trigger_handler_t触发器的激活函数入口地址

三、数据类型

1.  传感器数据类型

枚举值供sensor_sample_fetch_chan、sensor_channel_get函数使用

以下枚举类型为“enum sensor_channel”

枚举

作用

表示单位

枚举

作用

表示单位

SENSOR_CHAN_ACCEL_XX轴加速度m/s^2(每秒变化多少米)
SENSOR_CHAN_ACCEL_Yy轴加速度m/s^2(每秒变化多少米)
SENSOR_CHAN_ACCEL_Zz轴加速度m/s^2(每秒变化多少米)
SENSOR_CHAN_ACCEL_XYZ任意加速度NULL
SENSOR_CHAN_GYRO_X绕X轴角速度radians/s(每秒变化多少角度)
SENSOR_CHAN_GYRO_Y绕y轴角速度radians/s(每秒变化多少角度)
SENSOR_CHAN_GYRO_Z绕z轴角速度radians/s(每秒变化多少角度)
SENSOR_CHAN_GYRO_XYZ任意角速度NULL
SENSOR_CHAN_MAGN_XX轴地磁Gauss(高斯)
SENSOR_CHAN_MAGN_Yy轴地磁Gauss(高斯)
SENSOR_CHAN_MAGN_Zz轴地磁Gauss(高斯)
SENSOR_CHAN_MAGN_XYZ任意轴地磁NULL
SENSOR_CHAN_TEMP温度℃(摄氏度)
SENSOR_CHAN_DIE_TEMP器件温度℃(摄氏度)
SENSOR_CHAN_AMBIENT_TEMP环境温度℃(摄氏度)
SENSOR_CHAN_PRESS大气压1000Pa(千帕)
SENSOR_CHAN_PROX距离(靠近)传感器1表示接近
SENSOR_CHAN_HUMIDITY湿度%(百分比)
SENSOR_CHAN_LIGHT可见光强lux(勒克斯)
SENSOR_CHAN_IR红外光强lux(勒克斯)
SENSOR_CHAN_RED红色光强lux(勒克斯)
SENSOR_CHAN_GREEN绿色光强lux(勒克斯)
SENSOR_CHAN_BLUE蓝色光强lux(勒克斯)
SENSOR_CHAN_ALTITUDE高度传感器m(米)
SENSOR_CHAN_PM_1_0PM1.0传感器ug/m^3(当前天气中细颗粒物在空气中是多少微克每立方米)
SENSOR_CHAN_PM_2_5PM2.5传感器ug/m^3(当前天气中细颗粒物在空气中是多少微克每立方米)
SENSOR_CHAN_PM_10PM2.5传感器ug/m^3(当前天气中细颗粒物在空气中是多少微克每立方米)
SENSOR_CHAN_DISTANCE距离传感器m(米)
SENSOR_CHAN_CO2CO2传感器,ppm(浓度)
SENSOR_CHAN_VOCVOC传感器,ppm(浓度)
SENSOR_CHAN_VOLTAGE电压,V(电压)
SENSOR_CHAN_CURRENT电流,A(电流)
SENSOR_CHAN_ALL所有类型数据NULL

1.1 备注

以上的表示单位是要求获取时的返回单位,传感器不一定要返回对应的单位,但是在调用此API时在返回时需要进行一次转换,转换为对应的单位并返回,这是Zephry定义的一个规范,你可以不遵守,没有强制条件,但如果不遵守的话会不符合规范,你的驱动无法提供给别人,只能自己用。

你的驱动要根据以上数据类型去实现对应的数据获取功能,如果里面没有你的数据类型,可以自己定义。

四、数据格式

1. sensor_value

1.1 结构体原型

struct sensor_value {s32_t val1;s32_t val2;
};

1.2 成员介绍

成员名

类型

作用

val1s32_t整数
val2s32_t小数

2. 备注

Zephry为了防止部分机器可能没有FPU或传感器与当前开发板的内存大小不一致,产生浮点数溢出或值不匹配使用一个结构体来表示整数部分与小数部分,这样有效解决了在传递浮点数时出现的精度问题,以及不支持浮点数运算的硬件条件。

现在GLIB C有一套自己的浮点数运算库,不依赖FPU,但是效率较慢,GLIB C是C语言的运行库。

五、工作参数

1. 传感器参数类型

此类型供sensor_attr_set设置时使用

以下枚举类型为“enum sensor_attribute”

一般情况下这些工作参数都是编译期间已经在DTS文件中定义好了,Zephry在编译期间就已经确定它的工作参数,在运行期间也是可以修改的

枚举

作用

SENSOR_ATTR_SAMPLING_FREQUENCY传感器采样频率(具体含义由实际驱动实现决定,例如:一秒测量多少次)
SENSOR_ATTR_LOWER_THRESH最低触发阈值
SENSOR_ATTR_UPPER_THRESH最高触发阈值
SENSOR_ATTR_SLOPE_TH斜率(任意运动)触发
SENSOR_ATTR_SLOPE_DUR斜率维持超过一定时间触发
SENSOR_ATTR_OVERSAMPLING过采样参数
SENSOR_ATTR_FULL_SCALE传感器量程
SENSOR_ATTR_OFFSET传感器值校正,sensor_channel_get返回的传感器值将被改值偏置final_value = sensor_value + offset
SENSOR_ATTR_CALIB_TARGET传感器自身校正,用芯片内部的算法校正传感器的某个或者所有轴(传感器内部校正功能)

六、触发模式

1. 触发类型

对于一些传感器支持中断,根据传感器应用场景通常有不同的触发模式,Zephry提供了一套标准触发类型

这些类型供sensor_trigger_set函数使用

枚举类型:“enum sensor_trigger_type”

枚举

作用

SENSOR_TRIG_TIMER定时触发
SENSOR_TRIG_DATA_READY传感器数据准备好触发
SENSOR_TRIG_DELTA通道量有连续变化时触发(需设置SENSOR_ATTR_SLOPE_TH和SENSOR_ATTR_SLOPE_DUR)
SENSOR_TRIG_NEAR_FAR接近或者远离触发
SENSOR_TRIG_THRESHOLD超过配置阈值触发(需设置SENSOR_ATTR_LOWER_THRESH和SENSOR_ATTR_UPPER_THRESH)
SENSOR_TRIG_TAP单击触发
SENSOR_TRIG_DOUBLE_TAP双击触发

注意sensor_attr_set仅仅是设置了工作参数,它并不会开启触发中断,开启触发中断需要sensor_trigger_set,它会根据sensor_attr_set设置的工作参数来触发对应的中断类型

七、驱动实现

开发者们需要根据sensor_driver_api成员接口进行实现,这个结构体就是最开始说的统一API的定义,开发者们的传感器驱动代码需要放到“drivers/sensor/”目录下,这是Zephry下的一个编写规范

开发者们根据传感器实现如下五个API,这些API在最开始就已经介绍过了,这里简单列出来:

  • sensor_sample_fetch
  • sensor_sample_fetch_chan
  • sensor_channel_get
  • sensor_attr_set
  • sensor_trigger_set

如我要实现sensor_channel_get

只需要将原型声明一致,名称倒无所谓,最后的时候我们会通过sensor_driver_api这个结构体里的函数指针去指向我们的函数就可以了,最后在调用DT_INST_FOREACH_STATUS_OKAY驱动注册宏将我们的驱动注册到Zephry内核中

static int mysensor_channel_get(struct device *dev,enum sensor_channel chan,struct sensor_value *val)
{//这里写你的实现
}

针对SPI和I2C通讯的传感器,也要有一套注册流程,一般情况下我们会先写好传感器数据处理的API,至于通讯的在另外实现,因为I2C和SPI就是数据交互不涉及到业务代码,所以单独实现一个I2C与SPI通讯的模块并通过特定宏注册到Sensor模型,Zephry会根据dts文件里的定义来调用对应的接口去获取数据,然后将获取到的数据在传递给业务API

1. BME280注册分析

1.1 什么是BME280

BME280是一个温度,气压、湿度三合一的传感器,可以通过它获取当前温度与气压还有湿度,支持I2C与SPI通讯接口

 1.2 注册流程分析

BME280的驱动代码在“drivers/sensor/bem280”目录下

BME280的示例代码在“samples/sensor/bme280”目录下

这里为了让大家更了解Zephry如何注册我们设备,以及如何知道我们传感器使用的是什么通讯协议,从BME280驱动实现给大家分析一下

BME280实现了业务层的API与SPI、I2C通讯的三个模块。

在注册时会将I2C与SPI也注册到Zephry里

SPI的注册

#define BME280_CONFIG_SPI(inst)                     \{                               \.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),        \.bus_io = &bme280_bus_io_spi,               \.bus_config.spi_cfg =                   \SPI_CONFIG_DT_INST(inst,            \BME280_SPI_OPERATION,    \0),              \}

在编译期间Zephry会解析DTS里的描述,并将实例化的结构体传递进来,这里可以看到将bus总线的指向,这里可以关注bus_io与bus_config这两个成员

它俩的作用就是告诉Zephry SPI的模块在哪,其中SPI总线是哪根线,驱动名是什么也是在DTS文件中写好的,到时候都会传递进来。

其中bme280_bus_io_spi这个结构体就是bme280下spi模块的实现

原型如下:

const struct bme280_bus_io bme280_bus_io_spi = {.check = bme280_bus_check_spi,.read = bme280_reg_read_spi,.write = bme280_reg_write_spi,
};

然后注册到Zephry里就可以了

I2C的注册

#define BME280_CONFIG_I2C(inst)                     \{                               \.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),        \.bus_io = &bme280_bus_io_i2c,               \.bus_config.i2c_addr = DT_INST_REG_ADDR(inst),      \}

与SPI注册大同小异

然后在声明一个宏注册所有的模块

#define BME280_DEFINE(inst)                     \static struct bme280_data bme280_data_##inst;           \static const struct bme280_config bme280_config_##inst =    \COND_CODE_1(DT_INST_ON_BUS(inst, spi),          \(BME280_CONFIG_SPI(inst)),          \(BME280_CONFIG_I2C(inst)));         \DEVICE_DT_INST_DEFINE(inst,                 \bme280_chip_init,              \bme280_pm_ctrl,                \&bme280_data_##inst,               \&bme280_config_##inst,             \POST_KERNEL,                   \CONFIG_SENSOR_INIT_PRIORITY,           \&bme280_api_funcs);

这个宏会将bme280的data以及config、api、io通讯模块全部注册进来了,最后一步会调用DT_INST_FOREACH_STATUS_OKAY这个宏去注册,这个宏会将DTS里状态为OK的节点创建一个结构体,并传递进来

DT_INST_FOREACH_STATUS_OKAY(BME280_DEFINE)

这样BME280_DEFINE宏里的inst就变成dts文件里定义的设备详细描述结构体了,然后去注册就可以了。

这里讲一下Zephry是如何知道我们获取的是BME280这个结构体的,我们拆开DT_INST_FOREACH_STATUS_OKAY宏函数看一下

#define DT_INST_FOREACH_STATUS_OKAY(fn) \COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT),   \(UTIL_CAT(DT_FOREACH_OKAY_INST_,        \DT_DRV_COMPAT)(fn)),      \())

可以看到里面用DT_HAS_COMPAT_STATUS_OKAY这个宏去取的,其中DT_DRV_COMPAT这个宏就是要序列化DTS节点的名字

这个宏在bme280.h中有定义

#define DT_DRV_COMPAT bosch_bme280

这个名字是COMPAT的,这里可以看下bme280 dts文件里的compat的定义

 bme280@76 {compatible = "bosch,bme280";status = "okay";label = "BME280";reg = <0x76>;};

 compatible表示的是厂商与设备名,用“,”分割开,但是Zephry编译器在实例化的时会将","替换为“_”,这是因为C语言里面不允许使用特殊符号,所以这也是为什么dts里是"bosch,bme280",而在引用时却是"bosch_bme280"的原因

至于Zephry是如何知道你的传感器是怎么通讯的,然后调用对应接口的,这里给大家参考一下我之前移植stm32f746g_disco的一个写法

&i2c1 {pinctrl-0 = <&i2c1_scl_pb8 &i2c1_sda_pb9>;status = "okay";clock-frequency = <I2C_BITRATE_FAST>;bme280@76 {compatible = "bosch,bme280";status = "okay";label = "BME280";reg = <0x76>;};
};

可以看到我bme280是写在i2c1下的,到时候实例化的时候这些硬件信息都会传递给我们的驱动注册宏函数里,刚刚分析的注册函数里有一条代码:

.bus = DEVICE_DT_GET(DT_INST_BUS(inst)),

这段代码就是去取当前总线类型,我们当前是i2c1,就会将这个总线取出来,类型为i2c,编号为1的这条线上,然后就是这条线的一些硬件信息,到时候这些硬件信息都会传递给驱动,让驱动知道该去哪个地址找进行控制

这里需要注意status="okay"代表这是一个驱动节点,会将这个节点传递给驱动,如果没有okay不会视为驱动节点,不会进行驱动注册时的传递

八、测试

1. 基于BME280驱动写一个Test

1.1 开发

如果不清楚如何使用Drive以及如何知道Drive注册时的名称可以参考这篇文章:Zephry I2C和SPI驱动器介绍和操作FM24V10闪存

1.1.1 包含基本头文件

#include <zephyr.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/sensor.h>

注意这里不需要包含我们驱动的头文件,只需要包含sensor的头文件就可以了,因为基于它的模型,我们只需要保证我们的dev是指向我们的驱动就可以了,因为Zephry会根据okay为标志去将Drivers目录下的驱动进行注册实例化,到时候调用的时会读取dev的名称然后去调用对应的实现API,会通过Device Name来找对应的注册好的驱动结构体,然后去调用。

1.1.2 获取我们的设备

const struct device *dev = DEVICE_DT_GET_ANY("BME280");

1.1.3 获取气压,温度,湿度

while (1) {struct sensor_value temp, press, humidity;sensor_sample_fetch(dev);sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);printk("temp: %d.%06d; press: %d.%06d; humidity: %d.%06d\n",temp.val1, temp.val2, press.val1, press.val2,humidity.val1, humidity.val2);k_sleep(K_MSEC(1000));}

1.1.4 完整代码

#include <device.h>
#include <devicetree.h>
#include <drivers/sensor.h>void main(){const struct device *dev = DEVICE_DT_GET_ANY("BME280");if(dev == NULL){printk("get drive error\n");return;}while (1) {//获取设备句柄struct sensor_value temp, press, humidity;//将传感器数据读入到内存sensor_sample_fetch(dev);//读取数据sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);//打印printk("temp: %d.%06d; press: %d.%06d; humidity: %d.%06d\n",temp.val1, temp.val2, press.val1, press.val2,humidity.val1, humidity.val2);//延迟一秒k_sleep(K_MSEC(1000));}}

1.1.5 运行结果

temp: 24.080000; press: 100.887019; humidity: 55.473632
temp: 24.080000; press: 100.886230; humidity: 55.484375
temp: 24.080000; press: 100.886144; humidity: 55.484375
temp: 24.070000; press: 100.886222; humidity: 55.496093

2. 触发方式获取数据

这个需要传感器支持中断方式,触发方式也比较简单,使用的API以及结构体类型都已经介绍过了

#include <zephyr.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/sensor.h>//触发函数
static void trigger_handler(struct device *dev, struct sensor_trigger *trig)
{//通过触发方式获取temp护具struct sensor_value temp;//读入内存sensor_sample_fetch(dev);//读取数据sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);//打印printf("trigger fired, temp %d.%06d\n", temp.val1, temp.val2);
}void main(void)
{//获取传感器struct device *dev = device_get_binding("Trigger_SenSor");if (dev == NULL) {printf("device not found.  aborting test.\n");return;}//触发参数struct sensor_value val;//触发类型struct sensor_trigger trig;//设置最高阈值触发为26.0度val.val1 = 26;val.val2 = 0;//设置26度为高阈值sensor_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP,SENSOR_ATTR_UPPER_THRESH, &val);//设置触发类型trig.type = SENSOR_TRIG_THRESHOLD;          //触发类型为超出这个预设阈值trig.chan = SENSOR_CHAN_AMBIENT_TEMP;       //以温度为阈值来源//设定触发状态,并设置触发处理函数if (sensor_trigger_set(dev, &trig, trigger_handler)) {printf("Could not set trigger.  aborting test.\n");return;}//进入循环等待while (1) {k_sleep(2000);}
}

当温度高出26度时会自动跳转到trigger_handler函数进行处理

这篇关于Zephry传感器模型介绍和bme280测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测