BH60绝对位置编码器测试

■ 简介



BH60 是一款多圈绝对值旋转编码器。本文通过实验验证它的开发使用方式。根据 BH60绝对位置旋转编码器编程资料 中的选型指南,可以知道实验的旋转编码器的性能为:

  • BH60:外径:60mm
  • Z1:0:10mm输出轴
  • M1212:多圈,12-4096圈;12:单圈的分辨率为4096
  • MB1:MODBUS RTU, 引线长1米。

BH60绝对位置编码器测试_第1张图片

▲ BH60的名牌和内部结构示意图

 

01实验电路


1.制作传感器的实验接口

根据编码器铭牌信息,可以知道它使用MODBUS RTU协议。传感器的引线定义由 BH60 给出。

按照上述顺序完成实验接口的焊接和制作。如下:

BH60绝对位置编码器测试_第2张图片

▲ 传感器的功能线定义

2.静态加电测试

  • 工作电压:5V,工作电流约30mA。
  • 各管脚电压: 见下表格:
PIN 电源+ 电源- A+ B- 置零 编程
1 5.056200 0.019221 3.177800 0.065227 0.024253 0.024475

 

02控制板STM8H电路


使用STC8H1K28作为实验控制MCU。设计相应基于面包板连接的实验电路。

1.实验电路板1

BH60绝对位置编码器测试_第3张图片

▲ 实验电路原理图

▲ 实验电路板

2.单片机软件2

□ 工作参数 : 工作时钟:35MHz,调试串口460800bps。

□ 测试UART2波特率

在35MHz时钟频率下, UART2输出19200的波特率设置。 T 2 = 0 x F E 38 T_2 = 0xFE38 T2=0xFE38

BH60绝对位置编码器测试_第4张图片

▲ 输出0x55波形

BH60绝对位置编码器测试_第5张图片

▲ 发送波形以及MAX487的DIR控制波形

□ 将MAX487模块连入

MAX487制作RS485总线接口模块 接入STC8H1K28外部端口。

BH60绝对位置编码器测试_第6张图片

▲ MAX487模块连入单片机接口引线

使用另外一块MAX487对输出总线进行接收。验证前面发送数据的完整性。

▲ 总线波形以及487接收波形|上:总线A线信号;下:487接收信号

□ 将BH60 接入总线

根据前面传感器接口定义,将传感器接入MAX487模块的总线电路。

 

03软件协议


根据传感器型号,BH60使用 MODBUS 协议来传递信息。相关的通信协议可以在 BH60的MODBUS 协议中给出。

在MODBUS的ADU中,最后两个字节为 MODBUS CRC ,它的实现方式见下面的C语言代码。

// Compute the MODBUS RTU CRC
UInt16 ModRTU_CRC(byte[] buf, int len)
{
  UInt16 crc = 0xFFFF;
  
  for (int pos = 0; pos < len; pos++) {
    crc ^= (UInt16)buf[pos];          // XOR byte into least sig. byte of crc
  
    for (int i = 8; i != 0; i--) {    // Loop over each bit
      if ((crc & 0x0001) != 0) {      // If the LSB is set
        crc >>= 1;                    // Shift right and XOR 0xA001
        crc ^= 0xA001;
      }
      else                            // Else LSB is not set
        crc >>= 1;                    // Just shift right
    }
  }
  // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
  return crc;  
}

★ 注意:CRC传输的时候是 低字节在前,高字节在后

BH60绝对位置编码器测试_第7张图片

▲ BH60读出数据波形

//------------------------------------------------------------------------------
unsigned int ModbusCRC(unsigned char * pByte, int nLength) {
    unsigned int nCRC;
    unsigned int i;
    unsigned char ucByte, j;
    
    nCRC = 0xffff;
    
    for(i = 0; i < nLength; i ++) {
        ucByte = *(pByte + i);
        nCRC ^= (unsigned int)ucByte;
        
        for(j = 0; j < 8; j ++) {
            if((nCRC & 0x1) != 0) {
                nCRC >>= 1;
                nCRC ^= 0xA001;
            } else nCRC >>= 1;
        }        
    }
            
    return nCRC;
}

//------------------------------------------------------------------------------
void BH60AppendCRC(unsigned char ucLength) {
    unsigned int nCRC;
    nCRC = ModbusCRC(g_ucBH60Buffer, ucLength);
    g_ucBH60Buffer[ucLength + 1] = (unsigned char)(nCRC >> 8);
    g_ucBH60Buffer[ucLength] = (unsigned char)nCRC;
}
long BH60Buffer2Number(void) {
    unsigned long lnNumber;
    
    if(g_ucBH60Buffer[6] & 0x80)
        lnNumber = 0xff;
    else lnNumber = 0;
        
    lnNumber = (lnNumber << 8) + g_ucBH60Buffer[6];
    lnNumber = (lnNumber << 8) + g_ucBH60Buffer[3];
    lnNumber = (lnNumber << 8) + g_ucBH60Buffer[4];
    return (long)lnNumber;
}
else IFARG0("readbh60") {
    sscanf(SDA(1), "%d", &nNumber);
    for(i = 0; i < nNumber; i ++) {
        printf("%ld ", BH60ReadNumber());
        WaitTime(50);
    }
    
    printf("\r\n");
} else IFARG0("readbh60b") {
    lnNumber = BH60ReadNumber();
    SendChar((unsigned char)(lnNumber));
    lnNumber >>= 8;
    SendChar((unsigned char)(lnNumber));
    lnNumber >>= 8;
    SendChar((unsigned char)(lnNumber));
}

 

04测试传感器分辨率


手动旋转传感器10圈,然后读取输出的角度,大约41074。平均下来每圈为4107.4。这个参数对应每圈4096数据。

▲ 手动旋转传感器

BH60绝对位置编码器测试_第8张图片

▲ 旋转10圈读取的数据

 

※ 结论


通过STC8H1K28通过485总线的MODBUS读取传感器的数据,测试了旋转传感器的基本参数以及通信协议。

/*
**==============================================================================
** BH60.C:             -- by Dr. ZhuoQing, 2020-07-13
**
**==============================================================================
*/
#include 
//------------------------------------------------------------------------------
#define BH60_GLOBALS        1              // Define the global variables
#include "BH60.H"
#include "MAIN.H"
#include "STC8H.H"
#include "C51BASIC.H"

//------------------------------------------------------------------------------
void BH60Init(unsigned char ucAddress) {
    g_ucBH60Address = ucAddress;
}

//------------------------------------------------------------------------------
unsigned int ModbusCRC(unsigned char * pByte, int nLength) {
    unsigned int nCRC;
    unsigned int i;
    unsigned char ucByte, j;
    
    nCRC = 0xffff;
    
    for(i = 0; i < nLength; i ++) {
        ucByte = *(pByte + i);
        nCRC ^= (unsigned int)ucByte;
        
        for(j = 0; j < 8; j ++) {
            if((nCRC & 0x1) != 0) {
                nCRC >>= 1;
                nCRC ^= 0xA001;
            } else nCRC >>= 1;
        }        
    }
            
    return nCRC;
}

//------------------------------------------------------------------------------
void BH60AppendCRC(unsigned char ucLength) {
    unsigned int nCRC;
    nCRC = ModbusCRC(g_ucBH60Buffer, ucLength);
    g_ucBH60Buffer[ucLength + 1] = (unsigned char)(nCRC >> 8);
    g_ucBH60Buffer[ucLength] = (unsigned char)nCRC;
}

//------------------------------------------------------------------------------
void BH60SendBuffer(unsigned char ucLength) {
    unsigned char i;

    BH60AppendCRC(ucLength);
    
    ON(DIR_PIN);
    
    for(i = 0; i < ucLength + 2; i ++) {
        UART2SendChar(g_ucBH60Buffer[i]);
    }
     
    OFF(DIR_PIN);
    
    UART2_CLEAR;

}

//------------------------------------------------------------------------------
void BH60ReadData2Buffer(void) {
    unsigned char i, c;
    
    g_ucBH60Buffer[0] = g_ucBH60Address;
    g_ucBH60Buffer[1] = 0x3;
    g_ucBH60Buffer[2] = 0x0;
    g_ucBH60Buffer[3] = 0x3;
    g_ucBH60Buffer[4] = 0x0;
    g_ucBH60Buffer[5] = 0x2;
    BH60SendBuffer(6);
    
    for(i = 0; i < 9; i ++) {
        if(UART2ReceChar(&c)) return;
        g_ucBH60Buffer[i] = c;
    }

}

void BH60ReadConfig2Buffer(void) {
    unsigned char i, c;
    
    g_ucBH60Buffer[0] = g_ucBH60Address;
    g_ucBH60Buffer[1] = 0x3;
    g_ucBH60Buffer[2] = 0x0;
    g_ucBH60Buffer[3] = 0x0;
    g_ucBH60Buffer[4] = 0x0;
    g_ucBH60Buffer[5] = 0x3;
    BH60SendBuffer(6);
    
    for(i = 0; i < 11; i ++) {
        if(UART2ReceChar(&c)) return;
        g_ucBH60Buffer[i] = c;
    }
}

//------------------------------------------------------------------------------
long BH60Buffer2Number(void) {
    unsigned long lnNumber;
    
    if(g_ucBH60Buffer[6] & 0x80)
        lnNumber = 0xff;
    else lnNumber = 0;
        
    lnNumber = (lnNumber << 8) + g_ucBH60Buffer[6];
    lnNumber = (lnNumber << 8) + g_ucBH60Buffer[3];
    lnNumber = (lnNumber << 8) + g_ucBH60Buffer[4];
    return (long)lnNumber;
}

//------------------------------------------------------------------------------
long BH60ReadNumber(void) {
    BH60ReadData2Buffer();
    return BH60Buffer2Number();
}

//==============================================================================
//                END OF THE FILE : BH60.C
//------------------------------------------------------------------------------

/*
**==============================================================================
** BH60.H:            -- by Dr. ZhuoQing, 2020-07-13
**
**  Description:
**
**==============================================================================
*/
#ifndef __BH60__
#define __BH60__
//------------------------------------------------------------------------------
#ifdef BH60_GLOBALS
   #define BH60_EXT
#else
   #define BH60_EXT extern
#endif // BH60_GLOBALS

//------------------------------------------------------------------------------
#define BH60_ADDRESS            1

//==============================================================================
void BH60Init(unsigned char ucAddress);

//------------------------------------------------------------------------------
#define BH60_BUFFER     16

BH60_EXT unsigned char xdata g_ucBH60Buffer[BH60_BUFFER];
BH60_EXT unsigned char xdata g_ucBH60Address;

unsigned int ModbusCRC(unsigned char * pByte, int nLength);
void BH60AppendCRC(unsigned char ucLength);

//------------------------------------------------------------------------------
void BH60SendCharBuffer(unsigned char ucLength);

void BH60ReadData2Buffer(void);
void BH60ReadConfig2Buffer(void);

long BH60Buffer2Number(void);

//------------------------------------------------------------------------------
long BH60ReadNumber(void);

//==============================================================================
//             END OF THE FILE : BH60.H
//------------------------------------------------------------------------------
#endif // __BH60__


  1. 实验电路板硬件AD工程文件:AD\Test\2020\Tools\BUS487STC8H.SchDoc ↩︎

  2. 单片机软件工程文件:C51\STC\Test\2020\Tools\BUS487STC8H1K28\BUS487STC8H1K28.uvproj ↩︎

你可能感兴趣的:(嵌入式系统,基础电子,测量模块)