AS5600为绝对编码器,即根据安装的磁铁角度不同,初始位置的读数不同,读出来的数是当前初始位置在0~360°的一个值。(复现记录自用)
流程图:
初始化:
校准标定磁块【checkMagnetPresence()函数,通过返回值确定磁块位置是否准确距离】→读取初始角度值【ReadRawAngle()读取当前的绝对位置角度值信息】→
进入循环(每次循环都是有耗时,故转速不能超过某特定的值):
读取更新当前的角度值【ReadRawAngle()函数】→计算转过的角度数值【correctAngle()函数,可以计算角度值】→计算、累计转过的圈数【checkQuadrant()函数,通每次读取的象限,来确定是否转过一周】→更新显示屏的数值信息【refreshDisplay()函数】
1、该工程使用的是IIC总线通信,显示屏和编码器连接同一接口。
2、代码一

// 编码器测量出旋转角度值,并在显示屏中显示出来
// AS5600编码器
#include <Wire.h> //This is for i2C
#include <SSD1306Ascii.h> //i2C OLED库
#include <SSD1306AsciiWire.h> //i2C OLED库,GitHub开源可下载// i2C OLED
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
float OLEDTimer = 0; //屏幕刷新时间
//I2C pins:
//STM32: SDA: PB7 SCL: PB6
//Arduino: SDA: A4 SCL: A5//---------------------------------------------------------------------------
//Magnetic sensor things
int magnetStatus = 0; //磁块3种状态 (MD, ML, MH)int lowbyte; //raw angle 7:0
word highbyte; //raw angle 7:0 and 11:8
int rawAngle; //final raw angle
float degAngle; //raw angle in degrees (360/4096 * [value between 0-4095])int quadrantNumber, previousquadrantNumber; //quadrant IDs
float numberofTurns = 0; //number of turns
float correctedAngle = 0; //tared angle - based on the startup value
float startAngle = 0; //starting angle
float totalAngle = 0; //total absolute angular displacement
float previoustotalAngle = 0; //for the display printingvoid setup()
{Serial.begin(115200); //start serial - tip: don't use serial if you don't need it (speed considerations)Wire.begin(); //start i2C  Wire.setClock(800000L); //fast clockcheckMagnetPresence(); //check the magnet (blocks until magnet is found)校准磁极ReadRawAngle(); //make a reading so the degAngle gets updatedstartAngle = degAngle; //update startAngle with degAngle - for taring//------------------------------------------------------------------------------//OLED 部分#if RST_PIN >= 0oled.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);#else // RST_PIN >= 0oled.begin(&Adafruit128x32, I2C_ADDRESS);#endif // RST_PIN >= 0oled.setFont(Adafruit5x7);oled.clear(); //clear displayoled.set2X(); //double-line font size - better to read itoled.println("Welcome!"); //print a welcome message  oled.println("AS5600"); //print a welcome messagedelay(3000);OLEDTimer = millis(); //start the timer}void loop()
{    ReadRawAngle(); //ask the value from the sensorcorrectAngle(); //tare the valuecheckQuadrant(); //check quadrant, check rotations, check absolute angular positionrefreshDisplay();//delay(100); //wait a little - adjust it for "better resolution"}// 读取编码器的绝对位置的数值
void ReadRawAngle()
{ //7:0 - bitsWire.beginTransmission(0x36); //connect to the sensorWire.write(0x0D); //figure 21 - register map: Raw angle (7:0)Wire.endTransmission(); //end transmissionWire.requestFrom(0x36, 1); //request from the sensorwhile(Wire.available() == 0); //wait until it becomes available lowbyte = Wire.read(); //Reading the data after the request//11:8 - 4 bitsWire.beginTransmission(0x36);Wire.write(0x0C); //figure 21 - register map: Raw angle (11:8)Wire.endTransmission();Wire.requestFrom(0x36, 1);while(Wire.available() == 0);  highbyte = Wire.read();//4 bits have to be shifted to its proper place as we want to build a 12-bit numberhighbyte = highbyte << 8; //shifting to left//What is happening here is the following: The variable is being shifted by 8 bits to the left://Initial value: 00000000|00001111 (word = 16 bits or 2 bytes)//Left shifting by eight bits: 00001111|00000000 so, the high byte is filled in//Finally, we combine (bitwise OR) the two numbers://High: 00001111|00000000//Low:  00000000|00001111//      -----------------//H|L:  00001111|00001111rawAngle = highbyte | lowbyte; //int is 16 bits (as well as the word)//We need to calculate the angle://12 bit -> 4096 different levels: 360° is divided into 4096 equal parts://360/4096 = 0.087890625//Multiply the output of the encoder with 0.087890625degAngle = rawAngle * 0.087890625; Serial.println(degAngle);//Serial.print("Deg angle: ");//Serial.println(degAngle, 2); //absolute position of the encoder within the 0-360 circle}// 校对编码器的数值,因为编码器是0~360°的位置绝对值,需要计算其的圈数进行累加
void correctAngle()
{//recalculate anglecorrectedAngle = degAngle - startAngle; //this tares the position 没变动则为0;变动的数值if(correctedAngle < 0) //if the calculated angle is negative, we need to "normalize" it{correctedAngle = correctedAngle + 360; //correction for negative numbers (i.e. -15 becomes +345)}else{//do nothing}//Serial.print("Corrected angle: ");//Serial.println(correctedAngle, 2); //print the corrected/tared angle
}// 用相数的变化来计算旋转的圈数,用于校对
void checkQuadrant()
{/*//Quadrants:4  |  1---|---3  |  2*///Quadrant 1if(correctedAngle >= 0 && correctedAngle <=90){quadrantNumber = 1;}//Quadrant 2if(correctedAngle > 90 && correctedAngle <=180){quadrantNumber = 2;}//Quadrant 3if(correctedAngle > 180 && correctedAngle <=270){quadrantNumber = 3;}//Quadrant 4if(correctedAngle > 270 && correctedAngle <360){quadrantNumber = 4;}//Serial.print("Quadrant: ");//Serial.println(quadrantNumber); //print our position "quadrant-wise"if(quadrantNumber != previousquadrantNumber) //if we changed quadrant{if(quadrantNumber == 1 && previousquadrantNumber == 4){numberofTurns++; // 4 --> 1 transition: CW rotation}if(quadrantNumber == 4 && previousquadrantNumber == 1){numberofTurns--; // 1 --> 4 transition: CCW rotation}//this could be done between every quadrants so one can count every 1/4th of transitionpreviousquadrantNumber = quadrantNumber;  //update to the current quadrant}  //Serial.print("Turns: ");//Serial.println(numberofTurns,0); //number of turns in absolute terms (can be negative which indicates CCW turns)  //after we have the corrected angle and the turns, we can calculate the total absolute positiontotalAngle = (numberofTurns*360) + correctedAngle; //number of turns (+/-) plus the actual angle within the 0-360 range//Serial.print("Total angle: ");//Serial.println(totalAngle, 2); //absolute position of the motor expressed in degree angles, 2 digits
}// 初始时对MCU进行锁定,确定其位置进行标定
void checkMagnetPresence()
{  //This function runs in the setup() and it locks the MCU until the magnet is not positioned properly// 他的函数在setup()中运行,它锁定MCU,直到磁铁没有正确定位  while((magnetStatus & 32) != 32) //while the magnet is not adjusted to the proper distance - 32: MD = 1// 磁铁位置是否调整到合适的位置。{  magnetStatus = 0; //reset readingWire.beginTransmission(0x36); //connect to the sensorWire.write(0x0B); //figure 21 - register map: Status: MD ML MHWire.endTransmission(); //end transmissionWire.requestFrom(0x36, 1); //request from the sensorwhile(Wire.available() == 0); //wait until it becomes available magnetStatus = Wire.read(); //Reading the data after the request//Serial.print("Magnet status: ");//Serial.println(magnetStatus, BIN); //print it in binary so you can compare it to the table (fig 21)      }      //Status register output: 0 0 MD ML MH 0 0 0  //MH: Too strong magnet - 100111 - DEC: 39 //ML: Too weak magnet - 10111 - DEC: 23     //MD: OK magnet - 110111 - DEC: 55//Serial.println("Magnet found!");//delay(1000);
}void refreshDisplay()
{if (millis() - OLEDTimer > 100) //chech if we will update at every 100 ms{ if(totalAngle != previoustotalAngle) //if there's a change in the position*{oled.clear(); //delete the content of the displayoled.println(totalAngle); //print the new absolute positionOLEDTimer = millis(); //reset timer   previoustotalAngle = totalAngle; //update the previous value}}else{//skip}//*idea: you can define a certain tolerance for the angle so the screen will not flicker//when there is a 0.08 change in the angle (sometimes the sensor reads uncertain values)
}

二、AS5600利用数码轮同步转动

1、解释
旋转脉冲编码器,步进电机同步旋转到对应的位置,而编码器起到测量反馈的作用。

2、代码二

#include <Wire.h> //This is for i2C
#include <SSD1306Ascii.h> //i2C OLED
#include <SSD1306AsciiWire.h> //i2C OLED// i2C OLED
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
float OLEDTimer = 0; //Timer for the screen refresh
//I2C pins:
//STM32: SDA: PB7 SCL: PB6
//Arduino: SDA: A4 SCL: A5//---------------------------------------------------------------------------
//Magnetic sensor things
int magnetStatus = 0; //value of the status register (MD, ML, MH)int lowbyte; //raw angle 7:0
word highbyte; //raw angle 7:0 and 11:8
int rawAngle; //final raw angle
float degAngle; //raw angle in degrees (360/4096 * [value between 0-4095])int quadrantNumber, previousquadrantNumber; //quadrant IDs
float numberofTurns = 0; //number of turns
float correctedAngle = 0; //tared angle - based on the startup value
float startAngle = 0; //starting angle
float totalAngle = 0; //total absolute angular displacement
float previoustotalAngle = 0; //for the display printing
float encoderTimer = 0;
//---------------------------------------------------------------------------
int pinA = PB10; // Pin A of the encoder
int pinB = PB11; // Pin B of the encoder//CNC Decoder behavior
// CNC编译器特性
//CW rotation: output of B is half square wave delayed from output of A
// CW旋转模式下:B输出比A的输出延迟半个方波
//CCW rotation: output of A is half square wave delayed from output of B
// CCW旋转模式下:A输出比B的输出延迟半个方波//The pulse generator's output can be DIRECTLY wired to the step and dir pins.
//脉冲发生器的输出可以直接连接到step和dir引脚。
//This means that the microcontroller can be omitted!!! - of course there won't be any feedback then
//这意味着可以省略微控制器!! 当然那时不会有任何反馈  volatile int numberofclicks = 0; //Stores the number of click done by the encoder. 1 turn = 100 clicks// 存储编码器完成的点击次数。 1回合= 100次点击
int previous_numberofclicks = 0; //Stores the "previous" number of clicks. Helps us to see if the encoder was moved// 存储“以前”的点击次数。 帮助我们确定编码器是否被移动过  //--Stepper motor related 步进电机相关----------------------------------------------------------
#include <AccelStepper.h>
AccelStepper stepper(1, PA9, PA8);// pulses/steps 9; Direction 8
const int stepperEnablePin = PB12;  //enable/disable pin for the stepper motor driver
//remember that for Arduino, you don't need the "PA" and "PB" prefixes. Just use 1,2,3...etc.void setup()
{pinMode(pinA, INPUT_PULLUP); //A terminal of the CNC wheelpinMode(pinB, INPUT_PULLUP); //B terminal of the CNC wheelattachInterrupt(digitalPinToInterrupt(pinA), pinAInterrupt, RISING); //pin A is an interrupt 低电平变高电平触发,中断函数被触发pinAInterrupt()。Serial.begin(115200); //start serial - tip: don't use serial if you don't need it (speed considerations)Wire.begin(); //start i2C  Wire.setClock(800000L); //fast clock//General remark on i2C: it seems that the i2C interferes with the attachInterrupt() in some way causing//strange readings if the i2C-related hardware is read too often (in every loop iteration). // 注意的bug: 似乎i2C以某种方式干扰了attachInterrupt()导致;// 如果i2c相关的硬件被读得太频繁(在每个循环迭代中),则会出现奇怪的读数。checkMagnetPresence(); //check the magnet (blocks until magnet is found)ReadRawAngle(); //make a reading so the degAngle gets updatedstartAngle = degAngle; //update startAngle with degAngle - for taring//------------------------------------------------------------------------------//OLED part#if RST_PIN >= 0oled.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);#else // RST_PIN >= 0oled.begin(&Adafruit128x32, I2C_ADDRESS);#endif // RST_PIN >= 0oled.setFont(Adafruit5x7);oled.clear(); //clear displayoled.set2X(); //double-line font size - better to read it 建立两行oled.println("Welcome!"); //print a welcome message  oled.println("AS5600"); //print a welcome message//Stepper setup---------------------------------------------------------stepper.setSpeed(1000); //SPEED = Steps / secondstepper.setMaxSpeed(1000); //SPEED = Steps / secondstepper.setAcceleration(5000); //ACCELERATION = Steps /(second)^2  pinMode(stepperEnablePin, OUTPUT); //enable/disable pin is defined as an outputdigitalWrite(stepperEnablePin, LOW); //enable motor current//disabling the current can prevent the driver and the motor running hot//on the other hand, it can lead to inaccuracies because the motor is not held at place when it is not under power  delay(2000);OLEDTimer = millis(); //start the timerencoderTimer = millis(); //start encoder timer} void loop()
{    if(millis()- encoderTimer > 125) //125 ms will be able to make 8 readings in a sec which is enough for 60 RPM//60转每分钟{    ReadRawAngle(); //ask the value from the sensorcorrectAngle(); //tare the valuecheckQuadrant(); //check quadrant, check rotations, check absolute angular position        encoderTimer = millis();  /*A little brainstorm on determining the required delay* The above 3 functions require about 300-310 us to finish* They mess up the interrupt of the CNC encoder due to the i2C communication* Therefore it is not good if they are called very often* We want to detect at least every rotations of the shaft* I say (arbitrarily), that we need to detect at least 2 angles in each quadrants, so in 1 turn of the shaft, there are 8 readings* 我说(随意地),我们需要在每个象限中检测至少两个角度,所以在轴的一圈中,有8个读数  * 8 readings per turn can be converted into readings per second based on the expected highest speed* 每轮8个读数可转换为基于预期的最高速度的每秒读数  * Example:* 60 RPM = 60/60 RPS (rounds per seconds) = 1 RPS* 1 round per second -> 8 reading per second -> 1 second/8 readings = 0.125 s = 125 ms is the frequency of readings* * Example 2:* * 100 RPM = 100/60 = 1.667 RPS* 1 round = 0.599 s -> 0.599 s/ 8 readings = 74.98 ~ 75 ms. * Check: 60/100 = 0.6 -> 75/125 = 0.6.    */}refreshDisplay(); //refresh the display - won't refresh until certain conditions are not fulfilled  // 刷新显示-在某些条件未满足之前不会刷新  while (stepper.distanceToGo() != 0) //This blocks the rest of the code!{stepper.runSpeedToPosition(); //Runs to the target position defined by the moveTo() function   //does not use accelerations    //运行到moveTo()函数定义的目标位置 ,不使用加速  }}void ReadRawAngle()
{ //7:0 - bitsWire.beginTransmission(0x36); //connect to the sensorWire.write(0x0D); //figure 21 - register map: Raw angle (7:0)Wire.endTransmission(); //end transmissionWire.requestFrom(0x36, 1); //request from the sensorwhile(Wire.available() == 0); //wait until it becomes available lowbyte = Wire.read(); //Reading the data after the request//11:8 - 4 bitsWire.beginTransmission(0x36);Wire.write(0x0C); //figure 21 - register map: Raw angle (11:8)Wire.endTransmission();Wire.requestFrom(0x36, 1);while(Wire.available() == 0);  highbyte = Wire.read();//4 bits have to be shifted to its proper place as we want to build a 12-bit numberhighbyte = highbyte << 8; //shifting to left//What is happening here is the following: The variable is being shifted by 8 bits to the left://Initial value: 00000000|00001111 (word = 16 bits or 2 bytes)//Left shifting by eight bits: 00001111|00000000 so, the high byte is filled in//Finally, we combine (bitwise OR) the two numbers://High: 00001111|00000000//Low:  00000000|00001111//      -----------------//H|L:  00001111|00001111rawAngle = highbyte | lowbyte; //int is 16 bits (as well as the word)//We need to calculate the angle://12 bit -> 4096 different levels: 360° is divided into 4096 equal parts://360/4096 = 0.087890625//Multiply the output of the encoder with 0.087890625degAngle = rawAngle * 0.087890625; //Serial.print("Deg angle: ");//Serial.println(degAngle, 2); //absolute position of the encoder within the 0-360 circle}void correctAngle()
{//recalculate anglecorrectedAngle = degAngle - startAngle; //this tares the positionif(correctedAngle < 0) //if the calculated angle is negative, we need to "normalize" it{correctedAngle = correctedAngle + 360; //correction for negative numbers (i.e. -15 becomes +345)}else{//do nothing}//Serial.print("Corrected angle: ");//Serial.println(correctedAngle, 2); //print the corrected/tared angle
}void checkQuadrant()
{/*//Quadrants:4  |  1---|---3  |  2*///Quadrant 1if(correctedAngle >= 0 && correctedAngle <=90){quadrantNumber = 1;}//Quadrant 2if(correctedAngle > 90 && correctedAngle <=180){quadrantNumber = 2;}//Quadrant 3if(correctedAngle > 180 && correctedAngle <=270){quadrantNumber = 3;}//Quadrant 4if(correctedAngle > 270 && correctedAngle <360){quadrantNumber = 4;}//Serial.print("Quadrant: ");//Serial.println(quadrantNumber); //print our position "quadrant-wise"if(quadrantNumber != previousquadrantNumber) //if we changed quadrant{if(quadrantNumber == 1 && previousquadrantNumber == 4){numberofTurns++; // 4 --> 1 transition: CW rotation}if(quadrantNumber == 4 && previousquadrantNumber == 1){numberofTurns--; // 1 --> 4 transition: CCW rotation}//this could be done between every quadrants so one can count every 1/4th of transitionpreviousquadrantNumber = quadrantNumber;  //update to the current quadrant}  //Serial.print("Turns: ");//Serial.println(numberofTurns,0); //number of turns in absolute terms (can be negative which indicates CCW turns)  //after we have the corrected angle and the turns, we can calculate the total absolute positiontotalAngle = (numberofTurns*360) + correctedAngle; //number of turns (+/-) plus the actual angle within the 0-360 range//Serial.print("Total angle: ");//Serial.println(totalAngle, 2); //absolute position of the motor expressed in degree angles, 2 digits
}void checkMagnetPresence()
{  //This function runs in the setup() and it locks the MCU until the magnet is not positioned properlywhile((magnetStatus & 32) != 32) //while the magnet is not adjusted to the proper distance - 32: MD = 1{magnetStatus = 0; //reset readingWire.beginTransmission(0x36); //connect to the sensorWire.write(0x0B); //figure 21 - register map: Status: MD ML MHWire.endTransmission(); //end transmissionWire.requestFrom(0x36, 1); //request from the sensor while(Wire.available() == 0); //wait until it becomes available magnetStatus = Wire.read(); //Reading the data after the request//Serial.print("Magnet status: ");//Serial.println(magnetStatus, BIN); //print it in binary so you can compare it to the table (fig 21)      }      //Status register output: 0 0 MD ML MH 0 0 0  //MH: Too strong magnet - 100111 - DEC: 39 //ML: Too weak magnet - 10111 - DEC: 23     //MD: OK magnet - 110111 - DEC: 55//Serial.println("Magnet found!");delay(1000);
}void refreshDisplay()
{if (millis() - OLEDTimer > 250) //chech if we will update at every 100 ms 检查我们是否每100毫秒更新一次{ if(totalAngle != previoustotalAngle || previous_numberofclicks != numberofclicks) //if there's a change in the position*//if(previous_numberofclicks != numberofclicks) //if there's a change in the position*{oled.clear(); //delete the content of the displayoled.print("M: "); //M: Magnet signal (Degrees)电磁信号(度)oled.println(totalAngle); //print the new absolute positionoled.print("W: "); //W: Wheel signal (Clicks) (轮的信号:点击数oled.println(numberofclicks);OLEDTimer = millis(); //reset timer 重置时钟  previoustotalAngle = totalAngle; //update the previous valueprevious_numberofclicks = numberofclicks; //update current position}}else{//skip}//*idea: you can define a certain tolerance for the angle so the screen will not flicker//when there is a 0.08 change in the angle (sometimes the sensor reads uncertain values)// //*想法:你可以定义一定的角度公差,这样屏幕就不会闪烁  //当角度有0.08的变化时(有时传感器读取不确定值)
}void pinAInterrupt()
{//When pin A's wave is detected...//当检测到引脚A的波时…if (digitalRead(pinB) == 0) //if B is LOW, it means that pin A's wave occured first -> CW rotation occured (I had to change it because of the stepper motor)//如果B是低的,这意味着引脚A的波先发生-> CW旋转发生(我不得不改变它,因为步进电机)  {numberofclicks++; //increase value //Serial.println(numberofclicks); //do not use delays or prints in the final code, use it only for debugging/developing}else //if B is HIGH, it means that pin B's wave occured first. So, when pin A has a rising edge, pin B is alreadi high -> CCW rotation//如果B为高,则表示B引脚的波先出现。 因此,当引脚A有上升边时,引脚B已经是高的-> CCW旋转  {numberofclicks--; //decrease value//Serial.println(numberofclicks);}//Serial.println(numberofclicks);stepper.moveTo(-1*numberofclicks); //Updates the "go to" position of the stepper motor - absolute value//The above moveTo() function means that if the numberofclick variable = 936, then the stepper motor will be//936 steps away from the origin. //更新步进电机的“go to”位置-绝对值  //上面的moveTo()函数的意思是,如果numberofclick变量= 936,则步进电机将  //距离原点936步。

AS5600编码器的使用相关推荐

  1. AS5600编码器使用讲解

    AS5600编码器使用讲解 //³õʼ»¯IIC void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphCl ...

  2. 步进电机正反转驱动、AS5600编码器信息读取及速度检测

    步进电机基本运动 1.思路: 用定时器替代mstimer2库,mstimer2底层实现是延时函数控制,delay函数占用CPU资源,使得CPU在delay函数工作时无法处理其他任务,二是delay函数 ...

  3. INA240三相无刷电机电流采样实例(arduino)

    目录 前言&&准备材料 arduino程序 参考链接: 前言&&准备材料 我这里用的控制器是esp32,它的adc采集器分辨率是12位,工作电压是3.3V.因此我们读取 ...

  4. 从零开始做手机云台/稳定器

    最近完成手机云台/稳定器的产品化,特意记录整个手机云台的开发过程 (内容持续细化中...) 一. 电机驱动篇 硬件描述: 直流无刷电机,7对极,控制板mcu为stm32f0. 驱动方式: FOC 控制 ...

  5. Makerbase SimpleFOC ESP32 例程1 双电机开环速度测试

    Makerbase SimpleFOC ESP32 例程1 双电机开环速度测试 第一部分 硬件介绍 1.1 硬件清单 序号 品名 数量 1 ESP32 FOC V1.0 主板 1 2 YT2804电机 ...

  6. SimpleFOC之ESP32(三)—— 闭环控制

    目录 一.硬件介绍 1.1.原理图 1.2.ESP32drive方案 1.2.1.准备清单 1.2.2.硬件连接 1.3.SimpleFOCShield方案 1.3.1.准备清单 1.3.2.硬件连接 ...

  7. SimpleFOC移植STM32(五)—— 电流采样及其变换

    目录 一.原理说明 1.1.电流采样 1.1.1.为什么要采样电流 1.1.2.电流采样方式 1.1.2.1.低侧电流采样 1.1.2.2.高侧电流采样 1.1.2.3.内置电流采样 1.2.电流变换 ...

  8. SimpleFOC之ESP32(六)—— 双电机控制

    目录 说明 一.硬件介绍 1.1.原理图 1.2.ESP32drive-D方案 1.2.1.准备清单 1.2.2.硬件连接 1.3.SimpleFOCShield方案 1.3.1.SimpleFOCS ...

  9. TLE5012B磁编码器原理及优点,径向充磁磁铁的安装。AS5047、AS5048、AS5600、TLE5012、MA730

      磁编码器以其独特的优点,在近两年的产品应用上十分流行.它体积小巧.安装方便.分辨率高.较光电编码器成本更低.不受灰尘油渍影响.可非接触安装.便于与电机集成一体实现伺服控制.相较于光电编码器,磁编码 ...

最新文章

  1. Winform中实现文件批量更名器(附代码下载)
  2. ios 图片 相册 存储方式
  3. android异步线程未执行,关于多线程:当服务在后台运行时,Android异步任务无法正常运行(doInBackground未执行)...
  4. js input 自动换行_深入Slate.js - 拯救 ContentEditble
  5. 小程序 pagescrollto_微信小程序学习笔记(三)-- 首页及详情页开发
  6. 刘慈欣推荐!这本“疯狂的书”预言9年后人类将永生?
  7. python多继承_Python多继承,__init__
  8. 2022 电工杯 B 物资配送 全部图解
  9. Java 一个简单的接口使用案例
  10. c语言标准库详解(九):实用函数stdlib.h
  11. 学习了pr后的收获_Pr实训报告心得体会
  12. 王宇阳:六个案例里的SEO启发
  13. 挖掘人工智能心理学新方向
  14. Android 中网络连接检测和使用ping检测网络是否可访问
  15. Word下划线怎么打?速速get这5个实用方法!
  16. 用python将多张图片拼接成一张
  17. 6年全栈工程师回答:web前端的主要学习什么,现在还有前途吗?一般工资是多少?
  18. Elixir服务器接收客户端消息01
  19. 湖北大学计算机考入清华,高考上湖北大学保送清华大学直博生,失聪左耳给了他一个安静世界...
  20. Yahoo 前端雅虎军规

热门文章

  1. Netty框架架构解析+API+运行流程+网络编程文章集锦
  2. 制作Linux嵌入式系统开机LOGO(图片)
  3. 【解决】装有Windows 10的笔记本电脑空闲时风扇突然转得很快,CPU与磁盘等占用率飙升的解决方法
  4. 为什么需要智能化,他和自动化相比有什么有利方面?
  5. SAP770系统FI模块配置(向一个会计年度变式分配公司代码)
  6. 【selenium】对浏览器的操作 浏览器的最大化,设置浏览器的宽和高,浏览器的前进和后退,浏览器滚动条的控制
  7. 斐波那契数列的迭代算法和递归算法
  8. 解决预览pdf不能下载的问题
  9. vr全景看房是怎么做的?vr全景看房平台有哪些?
  10. 解开IPA文件的灰沙-通过静态分析工具了解IPA实现