双MIPI摄像头图像系统设计

FPGA技术江湖 2022-11-22 17:18

双MIPI摄像头图像系统设计

介绍

FPGA 的一大优势是我们可以实现并行图像处理数据流。虽然任务比较重,但是我们不需要昂贵的 FPGA,我们可以使用成本低廉范围中的一个,例如 Spartan 7 或 Artix 7。对于这个项目,将展示如何设计一个简单的图像处理应用程序,该应用程序平行处理两个摄像头。

本项目主要使用 Digilent PCAM 扩展板。PCAM 扩展板为最多四个 PCAMS 提供接口。所以只需要有FMC接口的开发板都可以完成本项目移植。

Vivado

为了让系统快速启动和运行,我们将从赛灵思的一个示例项目开始设计。要打开参考项目,我们需要首先创建一个针对自己开发板上 FPGA 的项目。

打开项目后,创建一个新的BD。

打开BD后,在BD中添加一个 MIPI CSI2 IP。

要打开参考设计,右键单击 CSI2 IP并选择打开 IP 示例设计。

我们将使用这个参考项目。首先要做的是移除 DSI 输出路径。这将为我们的图像处理平台释放 FPGA 中的逻辑资源。

下一步是添加以下元素以创建第二条图像处理通道。

  • CSI2 IP Block
  • Register Slices & concatenation
  • Sensor Demosaic
  • VDMA
  • AXI Switch

完成的设计应如下所示:

除了 CSI2 IP 中的设置外,第二个图像处理通道与第一个相同。

原始 CSI2 IP 设置

添加的 CSI2 IP 中的设置

VDMA 内存设置

Sensor Demosaic设置

AXI4 Stream Switch

时钟有不同的上行和下行时钟

完成BD设计接下来就是针对硬件进行管脚约束。

一旦完成,我们就可以生成和构建项目并导出 XSA 用于软件开发。

该设备的利用率如下:

软件开发

导出 XSA 后,我们可以创建一个新的 Vitis 项目,其中包含 hello world 应用程序。

从 hello world 应用程序 BSP 设置中,我们可以导入 MIPI CSI2 示例项目。

我们需要对这个项目进行一些更改。

首先是通过 IIC 与传感器通信并设置传感器。板上的 CSI2 Sensor与FPGA 的 I2C 并没有直接连接。通过一个I2C BUFFER,与四个sensor连接,因为sensor的地址是一样的。

这可以在 fucntion_prototpye.c 中提供的传感器配置函数中进行更改。

所以我们在配置运行之前需要选择多路复用器。


extern int SensorPreConfig(int pcam5c_mode) {


  u32 Index, MaxIndex, MaxIndex1, MaxIndex2;
  int Status;
  SensorIicAddr = SENSOR_ADDRESS;

  u8 SP701mux_addr = 0x75;
    u8 SP701mux_ch = 0x40;

    u8 PCAM_FMC_addr = 0x70;
    u8 PCAM_FMC_ch = 0x01;


    Status = XIic_SetAddress(&IicAdapter, XII_ADDR_TO_SEND_TYPE, SP701mux_addr);
    if (Status != XST_SUCCESS) {
   return XST_FAILURE;
    }

    WriteBuffer[0] = SP701mux_ch;
    Status = AdapterWriteData(1);
   if (Status != XST_SUCCESS) {
     printf("sp701 mux failed\n\r");
     return XST_FAILURE;
   }

    Status = XIic_SetAddress(&IicAdapter, XII_ADDR_TO_SEND_TYPE, PCAM_FMC_addr);
    if (Status != XST_SUCCESS) {
   return XST_FAILURE;
    }

    WriteBuffer[0] = PCAM_FMC_ch;
    Status = AdapterWriteData(1);
   if (Status != XST_SUCCESS) {
     printf("pcam mux failed\n\r");
     return XST_FAILURE;
   }



  Status = XIic_SetAddress(&IicAdapter, XII_ADDR_TO_SEND_TYPE, SensorIicAddr);
  if (Status != XST_SUCCESS) {
 return XST_FAILURE;
  }


  WritetoReg(0x31, 0x03, 0x11);
  WritetoReg(0x30, 0x08, 0x82);

  Sensor_Delay();


  MaxIndex = length_sensor_pre;
  for(Index = 0; Index < (MaxIndex - 0); Index++)
  {
    WriteBuffer[0] = sensor_pre[Index].Address >> 8;
 WriteBuffer[1] = sensor_pre[Index].Address;
 WriteBuffer[2] = sensor_pre[Index].Data;

    Sensor_Delay();

 Status = AdapterWriteData(3);
 if (Status != XST_SUCCESS) {
   return XST_FAILURE;
 }
  }


  WritetoReg(0x30, 0x08, 0x42);


  MaxIndex1 = length_pcam5c_mode1;

  for(Index = 0; Index < (MaxIndex1 - 0); Index++)
  {
    WriteBuffer[0] = pcam5c_mode1[Index].Address >> 8;
 WriteBuffer[1] = pcam5c_mode1[Index].Address;
 WriteBuffer[2] = pcam5c_mode1[Index].Data;

    Sensor_Delay();

 Status = AdapterWriteData(3);
 if (Status != XST_SUCCESS) {
   return XST_FAILURE;
 }
  }


  WritetoReg(0x30, 0x08, 0x02);
  Sensor_Delay();
  WritetoReg(0x30, 0x08, 0x42);


  MaxIndex2 = length_sensor_list;

  for(Index = 0; Index < (MaxIndex2 - 0); Index++)
  {
    WriteBuffer[0] = sensor_list[Index].Address >> 8;
 WriteBuffer[1] = sensor_list[Index].Address;
 WriteBuffer[2] = sensor_list[Index].Data;

    Sensor_Delay();

 Status = AdapterWriteData(3);
   if (Status != XST_SUCCESS) {
  return XST_FAILURE;
   }
  }


  if(Status != XST_SUCCESS) {
    xil_printf("Error: in Writing entry status = %x \r\n", Status);
    return XST_FAILURE;
  }

  return XST_SUCCESS;

}

由于我们添加了第二个 Demosaic,我们还需要更新其配置。

int demosaic()
{
  demosaic_Config = XV_demosaic_LookupConfig(DEMOSAIC_DEVICE_ID);
  XV_demosaic_CfgInitialize(&InstancePtr, demosaic_Config,
                             demosaic_Config->BaseAddress);
  XV_demosaic_Set_HwReg_width(&InstancePtr, 1920);
  XV_demosaic_Set_HwReg_height(&InstancePtr, 1080);
  XV_demosaic_Set_HwReg_bayer_phase(&InstancePtr, 0x3);
  XV_demosaic_EnableAutoRestart(&InstancePtr);
  XV_demosaic_Start(&InstancePtr);

  demosaic_Config1 = XV_demosaic_LookupConfig(DEMOSAIC_DEVICE1_ID);
  XV_demosaic_CfgInitialize(&InstancePtr1, demosaic_Config1,
                             demosaic_Config1->BaseAddress);
  XV_demosaic_Set_HwReg_width(&InstancePtr1, 1920);
  XV_demosaic_Set_HwReg_height(&InstancePtr1, 1080);
  XV_demosaic_Set_HwReg_bayer_phase(&InstancePtr1, 0x3);
  XV_demosaic_EnableAutoRestart(&InstancePtr1);
  XV_demosaic_Start(&InstancePtr1);
  return XST_SUCCESS;

}

最后阶段是设置第二个 DMA,这里必须注意 DDR3地址管理以确保帧不会相互重叠。

int vdma_hdmi() {

  InitVprocSs_CSC(1);

  ResetVDMA();

  RunVDMA(&AxiVdma, XPAR_AXI_VDMA_0_DEVICE_ID, HORIZONTAL_RESOLUTION, \
    VERTICAL_RESOLUTION, srcBuffer, FRAME_COUNTER, 0);

  RunVDMA(&AxiVdma1, XPAR_AXI_VDMA_1_DEVICE_ID, HORIZONTAL_RESOLUTION, \
    VERTICAL_RESOLUTION, srcBuffer1, FRAME_COUNTER, 0);

  return XST_SUCCESS;

}

我们还需要注释掉 DSI 和TPG等函数使用的任何代码。

主代码也需要更新,以便在串口命令下控制 AXI Switch。

/******************************************************************************
* Copyright (C) 2018 - 2022 Xilinx, Inc.  All rights reserved.
* SPDX-License-Identifier: MIT
*******************************************************************************/

/*****************************************************************************/
/**
*
* @file xmipi_sp701_example.c
*

* MODIFICATION HISTORY:
*
* Ver   Who    Date     Changes
* ----- ------ -------- --------------------------------------------------
* X.XX  XX     YY/MM/DD
* 1.00  RHe    19/09/20 Initial release.

*
******************************************************************************/
/***************************** Include Files *********************************/

#include "xparameters.h"
#include "xiic.h"
#include "xil_exception.h"
#include "function_prototype.h"
#include "pcam_5C_cfgs.h"
#include "xstatus.h"
#include "sleep.h"
#include "xiic_l.h"
#include "xil_io.h"
#include "xil_types.h"
//#include "xv_tpg.h"
#include "xil_cache.h"
#include "stdio.h"
#include "xaxis_switch.h"



/************************** Constant Definitions *****************************/


#define PAGE_SIZE   16
#define XAXIS_SWITCH_DEVICE_ID  XPAR_AXIS_SWITCH_0_DEVICE_ID

#define IIC_BASE_ADDRESS XPAR_IIC_2_BASEADDR

#define EEPROM_TEST_START_ADDRESS 0x80

#define IIC_SWITCH_ADDRESS 0x74
#define IIC_ADV7511_ADDRESS 0x39
//XV_tpg_Config  *tpg1_Config;XV_tpg_Config  *tpg1_Config;
//XV_tpg    tpg1;
//XV_tpg    tpg1;
typedef u8 AddressType;

typedef struct {
 u8 addr;
 u8 data;
 u8 init;
} HDMI_REG;

#define NUMBER_OF_HDMI_REGS  16
HDMI_REG hdmi_iic[NUMBER_OF_HDMI_REGS] = {
 {0x41, 0x00, 0x10},
 {0x98, 0x00, 0x03},
 {0x9A, 0x00, 0xE0},
 {0x9C, 0x00, 0x30},
 {0x9D, 0x00, 0x61},
 {0xA2, 0x00, 0xA4},
 {0xA3, 0x00, 0xA4},
 {0xE0, 0x00, 0xD0},
 {0xF9, 0x00, 0x00},
 {0x18, 0x00, 0xE7},
    {0x55, 0x00, 0x00},
    {0x56, 0x00, 0x28},
    {0xD6, 0x00, 0xC0},
    {0xAF, 0x00, 0x4},
 {0xF9, 0x00, 0x00}
};

u8 EepromIicAddr;  /* Variable for storing Eeprom IIC address */

int IicLowLevelDynEeprom();

u8 EepromReadByte(AddressType Address, u8 *BufferPtr, u8 ByteCount);
u8 EepromWriteByte(AddressType Address, u8 *BufferPtr, u8 ByteCount);



/****************i************ Type Definitions *******************************/

typedef u8 AddressType;

/************************** Variable Definitions *****************************/

extern XIic IicFmc, IicAdapter ; /*  IIC device. */

//HDMI IIC
int IicLowLevelDynEeprom()
{
  u8 BytesRead;
  u32 StatusReg;
  u8 Index;
  int Status;
  u32 i;
  EepromIicAddr = IIC_SWITCH_ADDRESS;
  Status = XIic_DynInit(IIC_BASE_ADDRESS);
  if (Status != XST_SUCCESS) {
 return XST_FAILURE;
  }
  xil_printf("\r\nAfter XIic_DynInit\r\n");
  while (((StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS,
    XIIC_SR_REG_OFFSET)) &
    (XIIC_SR_RX_FIFO_EMPTY_MASK |
    XIIC_SR_TX_FIFO_EMPTY_MASK |
    XIIC_SR_BUS_BUSY_MASK)) !=
    (XIIC_SR_RX_FIFO_EMPTY_MASK |
    XIIC_SR_TX_FIFO_EMPTY_MASK)) {

  }


  EepromIicAddr = IIC_ADV7511_ADDRESS;
  for ( Index = 0; Index < NUMBER_OF_HDMI_REGS; Index++)
  {
    EepromWriteByte(hdmi_iic[Index].addr, &hdmi_iic[Index].init, 1);
  }

  for ( Index = 0; Index < NUMBER_OF_HDMI_REGS; Index++)
  {
    BytesRead = EepromReadByte(hdmi_iic[Index].addr, &hdmi_iic[Index].data, 1);
    for(i=0;i<1000;i++) {}; // IIC delay
 if (BytesRead != 1) {
      return XST_FAILURE;
 }
  }


  return XST_SUCCESS;

}


/*****************************************************************************/
/**
* This function writes a buffer of bytes to the IIC serial EEPROM.
*
* @param BufferPtr contains the address of the data to write.
* @param ByteCount contains the number of bytes in the buffer to be
*  written. Note that this should not exceed the page size of the
*  EEPROM as noted by the constant PAGE_SIZE.
*
* @return The number of bytes written, a value less than that which was
*  specified as an input indicates an error.
*
* @note  one.
*
******************************************************************************/
u8 EepromWriteByte(AddressType Address, u8 *BufferPtr, u8 ByteCount)
{
  u8 SentByteCount;
  u8 WriteBuffer[sizeof(Address) + PAGE_SIZE];
  u8 Index;

  /*
   * A temporary write buffer must be used which contains both the address
   * and the data to be written, put the address in first based upon the
   * size of the address for the EEPROM
   */
  if (sizeof(AddressType) == 2) {
 WriteBuffer[0] = (u8) (Address >> 8);
 WriteBuffer[1] = (u8) (Address);
  } else if (sizeof(AddressType) == 1) {
 WriteBuffer[0] = (u8) (Address);
 EepromIicAddr |= (EEPROM_TEST_START_ADDRESS >> 8) & 0x7;
  }

  /*
   * Put the data in the write buffer following the address.
   */
  for (Index = 0; Index < ByteCount; Index++) {
 WriteBuffer[sizeof(Address) + Index] = BufferPtr[Index];
  }

  /*
   * Write a page of data at the specified address to the EEPROM.
   */
  SentByteCount = XIic_DynSend(IIC_BASE_ADDRESS, EepromIicAddr,
    WriteBuffer, sizeof(Address) + ByteCount,
    XIIC_STOP);

  /*
   * Return the number of bytes written to the EEPROM.
   */
  return SentByteCount - sizeof(Address);

}


/******************************************************************************
*
* This function reads a number of bytes from the IIC serial EEPROM into a
* specified buffer.
*
* @param BufferPtr contains the address of the data buffer to be filled.
* @param ByteCount contains the number of bytes in the buffer to be read.
*  This value is constrained by the page size of the device such
*  that up to 64K may be read in one call.
*
* @return The number of bytes read. A value less than the specified input
*  value indicates an error.
*
* @note  None.
*
******************************************************************************/
u8 EepromReadByte(AddressType Address, u8 *BufferPtr, u8 ByteCount)
{
  u8 ReceivedByteCount;
  u8 SentByteCount;
  u16 StatusReg;

  /*
   * Position the Read pointer to specific location in the EEPROM.
   */
  do {
 StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
    if (!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
   SentByteCount = XIic_DynSend(IIC_BASE_ADDRESS, EepromIicAddr,
       (u8 *) &Address, sizeof(Address), XIIC_REPEATED_START);
    }

  } while (SentByteCount != sizeof(Address));
  /*
   * Receive the data.
   */
  ReceivedByteCount = XIic_DynRecv(IIC_BASE_ADDRESS, EepromIicAddr,
                                            BufferPtr, ByteCount);

  /*
   * Return the number of bytes received from the EEPROM.
   */

  return ReceivedByteCount;

}


/*****************************************************************************/
/**
 *
 * Main function to initialize interop system and read data from AR0330 sensor

 * @param  None.
 *
 * @return
 *   - XST_SUCCESS if MIPI Interop was successful.
 *   - XST_FAILURE if MIPI Interop failed.
 *
 * @note   None.
 *
 ******************************************************************************/
int main() {
  int Status;
  int pcam5c_mode = 1;
  int usr_entry ,prev_sel;
  int default_input;
  int dsi_hdmi_select = 0;

  Xil_ICacheDisable();
  Xil_DCacheDisable();
  XAxis_Switch AxisSwitch;
  XAxis_Switch_Config *ASWConfig;

  ASWConfig = XAxisScr_LookupConfig(XAXIS_SWITCH_DEVICE_ID);
  XAxisScr_CfgInitialize(&AxisSwitch, ASWConfig,ASWConfig->BaseAddress);
  XAxisScr_RegUpdateDisable(&AxisSwitch);
  XAxisScr_MiPortDisableAll(&AxisSwitch);
  XAxisScr_MiPortEnable(&AxisSwitch, 0, 0);
  XAxisScr_RegUpdateEnable(&AxisSwitch);

  xil_printf("\n\r******************************************************\n\r");
  xil_printf("\n\r**           SP701 Example Design            **");

  Status = IicLowLevelDynEeprom();
  if (Status != XST_SUCCESS) {
    xil_printf("ADV7511 IIC programming FAILED\r\n");
    return XST_FAILURE;
  }
  xil_printf("ADV7511 IIC programming PASSED\r\n");


  //Initialize FMC, Adapter and Sensor IIC
  Status = InitIIC();
  if (Status != XST_SUCCESS) {
 xil_printf("\n\r IIC initialization Failed \n\r");
 return XST_FAILURE;
  }
  xil_printf("IIC Initializtion Done \n\r");

  //Initialize FMC Interrupt System
  Status = SetupFmcInterruptSystem(&IicFmc);
  if (Status != XST_SUCCESS) {
    xil_printf("\n\rInterrupt System Initialization Failed \n\r");
    return XST_FAILURE;
  }
  xil_printf("FMC Interrupt System Initialization Done \n\r");

  //Set up IIC Interrupt Handlers
  SetupIICIntrHandlers();
  xil_printf("IIC Interrupt Handlers Setup Done \n\r");

  Status =  SetFmcIICAddress();
  if (Status != XST_SUCCESS) {
    xil_printf("\n\rFMC IIC Address Setup Failed \n\r");
 return XST_FAILURE;
  }
  xil_printf("Fmc IIC Address Set\n\r");

  //Initialize Adapter Interrupt System
  Status = SetupAdapterInterruptSystem(&IicAdapter);
  if (Status != XST_SUCCESS) {
    xil_printf("\n\rInterrupt System Initialization Failed \n\r");
    return XST_FAILURE;
  }
  xil_printf("Adapter Interrupt System Initialization Done \n\r");

  //Set Address of Adapter IIC
  Status =  SetAdapterIICAddress();
  if (Status != XST_SUCCESS) {
    xil_printf("\n\rAdapter IIC Address Setup Failed \n\r");
 return XST_FAILURE;
  }
  xil_printf("Adapter IIC Address Set\n\r");

  Status = InitializeCsiRxSs();
  if (Status != XST_SUCCESS) {
    xil_printf("CSI Rx Ss Init failed status = %x.\r\n", Status);
 return XST_FAILURE;
  }


  dsi_hdmi_select = 0;
  //using default_input var to compare same option selection
  default_input = 1;
  //SetupDSI();
  resetIp();
  EnableCSI();
  GPIOSelect(dsi_hdmi_select);

  Status = demosaic();
  if (Status != XST_SUCCESS) {
 xil_printf("\n\rDemosaic Failed \n\r");
 return XST_FAILURE;
  }

  CamReset();

  //Preconifgure Sensor
  Status = SensorPreConfig(pcam5c_mode);
  if (Status != XST_SUCCESS) {
 xil_printf("\n\rSensor PreConfiguration Failed \n\r");
 return XST_FAILURE;
  }
  xil_printf("\n\rSensor 1 is PreConfigured\n\r");
  WritetoReg(0x30, 0x08, 0x02);

  //Preconifgure Sensor
  Status = SensorPreConfig1(pcam5c_mode);
  if (Status != XST_SUCCESS) {
 xil_printf("\n\rSensor PreConfiguration Failed \n\r");
 return XST_FAILURE;
  }
  xil_printf("\n\rSensor 2 is PreConfigured\n\r");
  WritetoReg(0x30, 0x08, 0x02);


  Status = vdma_hdmi();
  if (Status != XST_SUCCESS) {
    xil_printf("\n\rVdma_hdmi Failed \n\r");
 return XST_FAILURE;
  }

  Status = vtpg_hdmi();
  if (Status != XST_SUCCESS) {
    xil_printf("\n\rVtpg Failed \n\r");
 return XST_FAILURE;
  }


  Sensor_Delay();
  xil_printf("\n\rPipeline Configuration Completed \n\r");

  while(1) {

    xil_printf("\r\nPlease Select Camera(1 or 2) + ENTER:");


    usr_entry = getchar();

   char b;
   scanf("%c", &b);// This will take ENTER key



 switch(usr_entry) {

   case '1':
    xil_printf("\n\rSwitching to Camera 1\n\r");
    XAxisScr_RegUpdateDisable(&AxisSwitch);
    XAxisScr_MiPortDisableAll(&AxisSwitch);
    XAxisScr_MiPortEnable(&AxisSwitch, 0, 0);
    XAxisScr_RegUpdateEnable(&AxisSwitch);
    break;

   case '2':
    xil_printf("\n\rSwitching to Camera 1\n\r");
    XAxisScr_RegUpdateDisable(&AxisSwitch);
    XAxisScr_MiPortDisableAll(&AxisSwitch);
    XAxisScr_MiPortEnable(&AxisSwitch, 0, 1);
    XAxisScr_RegUpdateEnable(&AxisSwitch);
    break;

   default:
    xil_printf("\n\rSelection is unavailable. Please try again\n\r");
    break;
 }

  }
  return XST_SUCCESS;

}

测试

我们可以在连接到 HDMI 输出时运行应用程序并在显示器上看到图像。

使用应用程序选择图像。

参考

https://www.hackster.io/

总结

该项目展示了一个MIPI摄像头接入FPGA的简单、快捷的方式,同时可以学习一下软件的导入工程的方式,简单的基于MicroBlaze系统要学会自己写控制代码,也许这就是新一代“FPGA打工人”需要掌握的一项新技术吧~(doge~不是)

示例工程

https://github.com/ATaylorCEngFIET/Hackster/tree/master

https://github.com/ATaylorCEngFIET/SP701_Imaging_Vivado


- -THE END- -


往期精选 

 
 

【免费】FPGA工程师人才招聘平台

FPGA人才招聘,企业HR,看过来!

系统设计精选 | 基于FPGA的实时图像边缘检测系统设计(附代码)

基于原语的千兆以太网RGMII接口设计

时序分析理论和timequest使用_中文电子版

求职面试 | FPGA或IC面试题最新汇总篇

FPGA图像处理专题课新增Vivado部分内容,线上线下均可报名

FPGA时序分析及约束专题课新增Vivado部分内容,线上线下均可报名

资料汇总|FPGA软件安装包、书籍、源码、技术文档…(2022.09.24更新)

FPGA就业班,11月28日开班,课程内容丰富,系统性学习FPGA,高薪就业,线上线下同步!

FPGA技术江湖广发江湖帖

无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有,QQ微信双选,FPGA技术江湖打造最纯净最专业的技术交流学习平台。


FPGA技术江湖微信交流群

加群主微信,备注姓名+公司/学校+岗位/专业进群


FPGA技术江湖QQ交流群

备注姓名+公司/学校+岗位/专业进群


FPGA技术江湖 任何技术的学习就好比一个江湖,对于每一位侠客都需要不断的历练,从初入江湖的小白到归隐山林的隐世高人,需要不断的自我感悟自己修炼,让我们一起仗剑闯FPGA乃至更大的江湖。
评论
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 44浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 80浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 85浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 68浏览
  • 自动化已成为现代制造业的基石,而驱动隔离器作为关键组件,在提升效率、精度和可靠性方面起到了不可或缺的作用。随着工业技术不断革新,驱动隔离器正助力自动化生产设备适应新兴趋势,并推动行业未来的发展。本文将探讨自动化的核心趋势及驱动隔离器在其中的重要角色。自动化领域的新兴趋势智能工厂的崛起智能工厂已成为自动化生产的新标杆。通过结合物联网(IoT)、人工智能(AI)和机器学习(ML),智能工厂实现了实时监控和动态决策。驱动隔离器在其中至关重要,它确保了传感器、执行器和控制单元之间的信号完整性,同时提供高
    腾恩科技-彭工 2025-01-03 16:28 170浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 141浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 125浏览
  •     为控制片内设备并且查询其工作状态,MCU内部总是有一组特殊功能寄存器(SFR,Special Function Register)。    使用Eclipse环境调试MCU程序时,可以利用 Peripheral Registers Viewer来查看SFR。这个小工具是怎样知道某个型号的MCU有怎样的寄存器定义呢?它使用一种描述性的文本文件——SVD文件。这个文件存储在下面红色字体的路径下。    例:南京沁恒  &n
    电子知识打边炉 2025-01-04 20:04 100浏览
  • 随着市场需求不断的变化,各行各业对CPU的要求越来越高,特别是近几年流行的 AIOT,为了有更好的用户体验,CPU的算力就要求更高了。今天为大家推荐由米尔基于瑞芯微RK3576处理器推出的MYC-LR3576核心板及开发板。关于RK3576处理器国产CPU,是这些年的骄傲,华为手机全国产化,国人一片呼声,再也不用卡脖子了。RK3576处理器,就是一款由国产是厂商瑞芯微,今年第二季推出的全新通用型的高性能SOC芯片,这款CPU到底有多么的高性能,下面看看它的几个特性:8核心6 TOPS超强算力双千
    米尔电子嵌入式 2025-01-03 17:04 55浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 104浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 75浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 116浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 170浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦