英创公司Linux主板低成本AD方案介绍

 2020-1-23 10:28:07     作者:黄志超    

  英创公司基于SBC870和SBC880工控应用底板设计了专用于扩展驱动电路模块的DM5028规范,并基于该规范推出了多种扩展模块,用来满足工业现场的应用需求。具体可以参考网站上的资料:SBC880工控底板与整机SBC870工控底板与整机


  ETA104扩展模块是一款可用于扩展AD输入的模块,它使用了ADS7871模拟信号转换芯片进行扩展,这款芯片的采样精度为14bit,最高采样速率为48KSPS,使用SPI总线来通讯,可以和ESMARC系列的任意核心板搭配使用。英创公司在此基础上做了进一步升级,使其支持采集四路4-20mA电流(精度为14bit),并增加了两路RS232,两路RS485,一路CAN总线,四路带隔离IO输入以及一路继电器输出,详细资料可以参考ETA104的手册。


DSC_0588.png

连接示意图


  同时为了进一步降低成本,当ETA104配合英创公司的低成本核心板ESM6800使用时,可以利用ESM6800核心板CPU上自带的ADC功能来采集电流值,这样可以省去ETA104模块上扩展AD部分的器件。ESM6800核心板自带的ADC采样精度为12bit,最高采样速率为1KSPS,通过这种方式能够较多的降低成本,ESM6800核心板对应的功能管脚配置如下:


AD通道对应管脚对应设备节点
AD输入通道1GPIO0/sys/bus/iio/devices/iio:device0/  in_voltage9_raw
AD输入通道2GPIO1/sys/bus/iio/devices/iio:device0/  in_voltage8_raw
AD输入通道3GPIO27/sys/bus/iio/devices/iio:device0/  in_voltage0_raw
AD输入通道4UART2_RXD/sys/bus/iio/devices/iio:device0/  in_voltage5_raw


  串口,GPIO和CAN总线均使用系统的标准接口就可以正常工作,可以参考英创公司提供的相关例程,本文主要介绍关于AD部分的使用方法。下面首先来看利用扩展芯片ADS7871是如何读取数据的,因为ADS7871模拟信号转换芯片是通过SPI总线进行的通讯,所以利用核心板上的SPI总线就可以设置和读取数据,读取数据的部分代码如下:


txbuf[0] = 0x40;
txbuf[1] = 0x00;
memset(tr, 0 , sizeof(tr));
tr[0].tx_buf = (unsigned long)txbuf;
tr[0].rx_buf = (unsigned long)rx;
tr[0].len = 2;
tr[0].delay_usecs = 0;
tr[0].speed_hz = 2500000;
tr[0].bits_per_word = 8;
/* 进行SPI数据传输 */
ret = ioctl(m_fd, SPI_IOC_MESSAGE(1), tr );
if (ret < 1 )
       pabort("can't send spi message");
buffer = rx[1];
 
txbuf[0] = 0x41;
txbuf[1] = 0x00;
memset(tr, 0 , sizeof(tr));
tr[0].tx_buf = (unsigned long)txbuf;
tr[0].rx_buf = (unsigned long)rx;
tr[0].len = 2;
tr[0].delay_usecs = 0;
tr[0].speed_hz = 2500000;
tr[0].bits_per_word = 8;
/* 进行SPI数据传输 */
ret = ioctl(m_fd, SPI_IOC_MESSAGE(1), tr );
if (ret < 1 )
       pabort("can't send spi message");
 
/* 将数据拼接起来 */
buffer |= rx[1] << 8;
buffer = buffer>>2;


  因为信号源可能存在抖动,所以在读取数据后增加了中值滤波算法,代码如下:



#define N 9
int filter(int ch)
{
       uint16_t value_buf[N];
       int   temp, count;
       int i, j;
       for ( count=0;count<N;count++)
       {
              value_buf[count] = ETA104_ReadAD(ch, 1);
              usleep(5000);
       }
       /* 采用冒泡法排序 */
       for (j=0;j<N-1;j++)
       {
               for (i=0;i<N-j;i++)
               {
                      if ( value_buf[i] > value_buf[i+1] )
                      {
                              temp = value_buf[i];
                              value_buf[i] = value_buf[i+1];
                              value_buf[i+1] = temp;
                      }
              }
       }
       /* 取排序中间值返回 */
       return value_buf[(N-1)/2];
}


  可以根据实际的情况选择取使用多少个值来进行中值滤波,实际的测试结果如下:


电流表读取值(单位:毫安)实际读取值(单位:毫安)
4.0154.019
10.02210.025
19.98819.992


  通过上面的表格可以看出,使用ETA104模块扩展芯片ADS7871读取的数据精度为完全能够达到1%以内。


  下面来看看如何使用ESM6800核心板自带的ADC功能。在Linux内核中,CPU自带的ADC功能是通过IIO的驱动来实现的,英创公司已经将所需要的驱动集成在了系统中,并且ESM6800核心板的ADC会自动采样32个点做平均,客户可以直接读取,操作十分简单,具体代码如下:


char iiotype[4][100] = {
                                          "in_voltage9_raw",
                                          "in_voltage8_raw",
                                          "in_voltage0_raw",
                                          "in_voltage5_raw"
                                          };
int get_ad(int i)
{
        int ret = 0, ch;
        char filename[80];
        FILE *fp;
        char buf[20];
 
        sprintf( filename, "/sys/bus/iio/devices/iio:device0/%s", iiotype[i]);
        fp = fopen(filename, "rt");
        if( fp==NULL )
        {
               printf("open %s fail!\n", filename);
               ret = -1;
               return ret;
        }
        /* 读取对应的ADC通道值 */
        fread( buf, 1, sizeof(buf), fp );
        fclose(fp);
 
        sscanf( buf, "%d", &ch );
 
        return ch;
}


  同样在读取数据后可以增加中值滤波算法,实际测试结果如下::


电流表读取值(单位:毫安)实际读取值(单位:毫安)
4.0144.018
10.02110.027
19.99219.996


  根据上面的表格可以看出,使用ESM6800核心板自带的ADC读取的数据精度同样可以达到1%以内。


  如有感兴趣的客户,欢迎和英创工程师联系,索取相关测试代码和资料。