技术标签: # Arduino & Ros 嵌入式学习笔记 编码器 Arduino
原理参考:https://www.arduino.cn/thread-42559-1-1.html
https://blog.csdn.net/qq_42795251/article/details/90057308
利用Arduino、增量式光电编码器测量速度、方向、位移。
材料:
编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换成电信号,前者称为码盘,后者称为码尺。(对于电机测速来说应该需要将角位移转变为电信号,所以应该是码盘。)按照工作原理编码器可分为增量式和绝对式两类。增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。(淘宝上搜“带编码器的电机”大多是这种类型的编码器)绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。(From 百度百科)
旋转编码器是一种光电式旋转测量装置,它将被测的角位移直接转换成数字信号(高速脉冲信号)。编码器如以信号原理来分,有增量型编码器,绝对型编码器。我们通常用的是增量型编码器,不同型号的旋转编码器,其输出脉冲的相数也不同,有的旋转编码器输出A、B、Z三相脉冲,有的只有A、B相两相,最简单的只有A相。
脉冲数/(编码器分辨率*时间)
A脉冲为下降沿,B脉冲为高电平,方向为正;
A脉冲为下降沿,B脉冲为低电平,方向为负。
————————————————
/*
* 测速原理
脉冲数/(编码器分辨率*时间)
A脉冲为下降沿,B脉冲为高电平,方向为正;
A脉冲为下降沿,B脉冲为低电平,方向为负。
*/
#include <FlexiTimer2.h> //定时器库头文件
#define PinA 2 //外部中断0
#define PinZ 3 //外部中断1
#define PinB 8 //编码器的OUT_B信号连接到数字端口8
//变量初始化
const double sampTime = 100; // 定时器周期100ms,采样频率10Hz
volatile long time1;
volatile int num = 0;//采样周期内圈数,由Z相中断计数
volatile double count = 0; // 脉冲数计数器,由A相计数
int tmp = 0; //暂存编码器计数脉冲数值
volatile float spdVal = 0; //采样周期内,返回的速度计算结果
volatile double distance = 0;
const float D = 0.30; //轮子的直径,单位m
const float pi = 3.141592654;//圆周率
Z相零位中断子程序
//void Set_state(){
// tmp = count; //暂存当前A相计数
// count = 0; //脉冲计数归零
// num +=1;
//}
// 编码器B相脉冲计数中断子程序
void Encode()
{
//为了不计入噪音干扰脉冲,
//当2次中断之间的时间大于0.1ms时,计一次有效计数
if ((millis() - time1) > 0.1)
{
//当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
if ((digitalRead(PinA) == LOW) && (digitalRead(PinB) == HIGH))
{
count++;
}
else
{
count--;
}
}
time1 == millis();
}
// 编码器转速计算中断子程序
void Speed(){
spdVal = 60 * (count/256)/(sampTime/1000);
distance += (count/256) * pi * D;
count = 0;
Serial.print("The wheel has run : ");Serial.print(distance); Serial.println("m.");
Serial.print("The w_speed is: ");Serial.print(spdVal); Serial.println("r/min.");
}
void setup()
{
pinMode(PinA, INPUT_PULLUP);//因为编码器信号为欧姆龙E6B2-CWZ6C,为开漏输出,因此需要上拉电阻,此处采用arduino的内部上拉输入模式,置高
pinMode(PinB, INPUT_PULLUP);//同上
pinMode(PinZ, INPUT_PULLUP);//同上
attachInterrupt(0, Encode, FALLING);//触发脉冲中断函数:执行Encode函数,捕捉A相信号,并判断A、B相先后顺序
// attachInterrupt(1, Set_state , FALLING);//用于在捕捉到Z的零信号时,进行状态置零
FlexiTimer2::set(sampTime,Speed); //设置计时器参数以及终端子程序
FlexiTimer2::start();
Serial.begin (9600);
}
void loop()
{
}
用手转动编码器码盘,转速测量结果如下,但可信度和准确度有待考量,请按需改进优化。
arduino-mega2560上要用FlexiTimer2.h,否则编译能通过,但不会产生定时中断,中断库函数在附件中查看。
#include <FlexiTimer2.h > void flash() { static boolean output = HIGH; digitalWrite(13, output); output = !output; } void setup() { pinMode(13, OUTPUT); FlexiTimer2::set(1000, flash); FlexiTimer2::start(); } void loop() { } |
volatile关键字
volatile这个关键字是变量修饰符,常用在变量类型的前面,以告诉编译器和接下来的程序怎么对待这个变量。
声明一个volatile变量是编译器的一个指令。编译器是一个将你的C/C++代码转换成机器码的软件,机器码是arduino上的Atmega芯片能识别的真正指令。
具体来说,它指示编译器编译器从RAM而非存储寄存器中读取变量,存储寄存器是程序存储和操作变量的一个临时地方。在某些情况下,存储在寄存器中的变量值可能是不准确的。
如果一个变量所在的代码段可能会意外地导致变量值改变那此变量应声明为volatile,比如并行多线程等。在arduino中,唯一可能发生这种现象的地方就是和中断有关的代码段,成为中断服务程序。
例子
//当中断引脚改变状态时,开闭LED
int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state;
}
java.io.IOException: java.lang.reflect.InvocationTargetException at org.apache.hadoop.hbase.client.HConnectionManager.createConnection(HConnectionManager.java:389) at org.apache.hadoop.hbase
Loadrunner参数化如何在记事本中将参数值显示超过100个用户参数值 1.loadrunner的参数值没有最大的限度,可以修改C:\Program Files\HP\L...
目录一、安装二、sonarqube生成令牌三、Jenkins配置四、代码扫描五、查看sonarqube扫描报告一、安装Jenkins安装不再赘述,自行搜索网上教程。Sonarqube安装不再赘述,自行搜索网上教程。二、sonarqube生成令牌登录sonarqube,找到我的账号—>安全—>生成令牌,然后填写一个令牌名称,生成密钥并复制。三、Jenkins配置1、sonarqube scanner插件安装2、系统管理—>系统配置---->sonarqube srv
一、需求定义Goals(目标)-->Problem(问题)-->Option(可选方案)-->Answer(建议方案)重点:明确项目的目标和范围二、需求捕获问问你从事哪些工作,这些工作是如何进行的?然后再逐步过度到存在什么样的障碍,有什么困难需要解决三、软件需求与需求工程 业务需求:通常是企业/组织的高层管理人员提出,它是彻底从业务角度描述,是需求定义的产物用户需求:描
首次写博客中国裁判文书网 从2018年8月7日网站更新后,网上代码全军覆没不可用,着手研究了下。分析 思路主要通过python去破解网站js的加密数据。该网站请求数据都是通过post请求的,分析一下header,会发现,它是一个post请求,请求的表单数据包括param、index、page、order、direction、vl5x、number、guid这几个参数。很显...
原 实际项目中如何使用Git做分支管理 2018年06月24日 18:08:24 ShuSheng007 阅读数:2304 &lt;span class="tags-box artic-tag-box"&gt; &lt;span clas...
JDK1.5新特性:1.自动装箱与拆箱:2.枚举3.静态导入,如:import staticjava.lang.System.out4.可变参数(Varargs)5.内省(Introspector),主要用于操作JavaBean中的属性,通过getXxx/setXxx。一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取...
主题的分区数设置在server.properties配置文件中可以指定一个全局的分区数设置,这是对每个主题下的分区数的默认设置,默认是1。当然每个主题也可以自己设置分区数量,如果创建主题的时候没有指定分区数量,则会使用server.properties中的设置。bin/kafka-topics.sh--zookeeperlocalhost:2181--create--topicmy-topic--partitions2--replication-factor1...
韩联社 29 日报导,IHS 报告称,预估今年全球 4K 电视面板市场将增至 4,000 万片,和去年相比,等于大增 108%。估计 4K 面板在整体电视市场的比重将提高到 15%。IHS 表示,4K 电视面板的龙头业者是韩国的 Samsung Display 和 LG Display,今年合并市占率将达 57%。台湾厂商市占居次,估计为 27%。中国厂商在当局的大力金援下,预料也可拿
Xilinx Kintex-7 XC7K325T-2FFG676I嵌入式核心板简介图 1Xilinx Kintex-7核心板简介创龙科技SOM-TLK7是一款基于Xilinx Kintex-7系列FPGA设计的高端工业级核心板。FPGA引脚资源通过工业级高速B2B连接器引出。核心板经过专业的PCB Layout和高低温测试验证,稳定可靠,可满足各种工业应用环境。用户使用核心板进行二次开发时,仅需专注上层运用,降低了开发难度和时间成本,可快速进行产品方案评估与技术预研。..
主要逻辑流程存在问题:一:用户多次下单解决方案:1.1前端控制,1.2分布式锁实现redis(key:商品id+用户id)不存在则设置代表获取锁成功,否则失败。二:库存超卖解决方案:思路 :(redis redission zookpeer等)分布式锁实现,在原子操作中,获取key的锁,来一套扣减库存,生成订单的操作。同时可以用sql where stock > 0 或者加版本号来实现。理解分布式锁:(附带了优化思路)参考:https://blog.csdn.net/u.
当QList容器中的数据用qDebug() 有这样一个 LogLat 类定义如下class LogLat{ //需要将 friend QDebug& operatorQDebug &debug, const LogLat &obj); public: LogLat(double log=0.0, double lat=0.0)