英创公司基于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