英创公司基于SBC870和SBC880工控应用底板设计了专用于扩展驱动电路模块的DM5028规范,并基于该规范推出了多种扩展模块,用来满足工业现场的应用需求。具体可以参考网站上的资料:SBC880工控底板与整机,SBC870工控底板与整机。
ETA104扩展模块是一款可用于扩展AD输入的模块,它使用了ADS7871模拟信号转换芯片进行扩展,这款芯片的采样精度为14bit,最高采样速率为48KSPS,使用SPI总线来通讯,可以和ESMARC系列的任意核心板搭配使用。英创公司在此基础上做了进一步升级,使其支持采集四路4-20mA电流(精度为14bit),并增加了两路RS232,两路RS485,一路CAN总线,四路带隔离IO输入以及一路继电器输出,详细资料可以参考ETA104的手册。
连接示意图
同时为了进一步降低成本,当ETA104配合英创公司的低成本核心板ESM6800使用时,可以利用ESM6800核心板CPU上自带的ADC功能来采集电流值,这样可以省去ETA104模块上扩展AD部分的器件。ESM6800核心板自带的ADC采样精度为12bit,最高采样速率为1KSPS,通过这种方式能够较多的降低成本,ESM6800核心板对应的功能管脚配置如下:
AD通道 | 对应管脚 | 对应设备节点 |
AD输入通道1 | GPIO0 | /sys/bus/iio/devices/iio:device0/ in_voltage9_raw |
AD输入通道2 | GPIO1 | /sys/bus/iio/devices/iio:device0/ in_voltage8_raw |
AD输入通道3 | GPIO27 | /sys/bus/iio/devices/iio:device0/ in_voltage0_raw |
AD输入通道4 | UART2_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.015 | 4.019 |
10.022 | 10.025 |
19.988 | 19.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.014 | 4.018 |
10.021 | 10.027 |
19.992 | 19.996 |
根据上面的表格可以看出,使用ESM6800核心板自带的ADC读取的数据精度同样可以达到1%以内。
如有感兴趣的客户,欢迎和英创工程师联系,索取相关测试代码和资料。
成都英创信息技术有限公司 028-8618 0660