今天,无论是电表还是出租车计费表,数字仪表都在取代各个领域的interwetten与威廉的赔率体系 仪表。主要原因是模拟仪表的机械部件在长时间使用时容易磨损,并且不如数字仪表准确。
一个很好的例子是模拟车速表和里程表,用于旧摩托车测量速度和行驶距离。它们具有称为小齿轮和齿条装置的特殊部件,其中当车轮旋转时,电缆用于旋转速度计的销钉。长时间使用会磨损,也需要更换和维护。
在数字仪表中,不是使用机械部件,而是使用一些传感器,如光断续器或霍尔传感器来计算速度和距离。这比模拟仪表更准确,并且不需要长时间维护。
今天,在本教程中,我们将使用 Arduino 制作数字出租车计费器的原型。该项目计算出租车车轮行驶的速度和距离,并在16x2 LCD 显示屏上连续显示。当我们按下按钮时,它会根据行驶的距离生成票价金额。
下图显示了数字出租车计程表项目的完整设置
这个原型有一个 RC 汽车底盘,带有一个速度传感器模块和一个连接到电机的编码器轮。一旦测量了速度,我们可以通过按下按钮测量行驶的距离并找到票价金额。我们可以使用电位器设置车轮的速度。要了解有关在 Arduino 中使用 LM-393 速度传感器模块的更多信息,请点击链接。让我们看一下速度传感器模块的简短介绍。
这是一种槽型模块,可用于测量编码器轮的旋转速度。该速度传感器模块基于插槽式光断续器工作,也称为光源传感器。该模块需要 3.3V 至 5V 的电压并产生数字输出。因此它可以与任何微控制器接口。
红外光 传感器 由光源(IR-LED)和光电晶体管传感器组成。两者之间都有一个小间隙。当物体放置在 IR LED 和光电晶体管的间隙之间时,它将中断光束,导致光电晶体管停止通过电流。
因此,对于这个传感器,使用可以连接到电机的开槽盘(编码器轮),当轮随电机旋转时,它会中断 IR LED 和光电晶体管之间的光束,从而使输出打开和关闭(产生脉冲)。
因此,当源和传感器之间存在中断时(当任何物体放置在两者之间时)它会产生高电平输出,而当没有放置物体时会产生低电平输出。在模块中,我们有一个 LED 来指示引起的光中断。
该模块带有LM393 比较器 IC,用于在输出端产生准确的 HIGH 和 LOW 信号。因此这个模块有时被称为LM393 速度传感器。
测量行驶速度和距离以计算票价
要测量旋转速度,我们需要知道编码器轮中存在的槽数。我有一个编码轮,里面有 20 个插槽。当它们旋转一整圈时,我们在输出端有 20 个脉冲。因此,要计算速度,我们需要每秒产生的脉冲数。
例如
如果一秒内有 40 个脉冲,那么
速度 = Noo。脉冲数/槽数 = 40/20 = 2RPS(每秒转数)
为了以 RPM(每分钟转数)计算速度,请乘以 60。
以 RPM 为单位的速度 = 2 X 60 = 120 RPM(每分钟转数)
测量距离
测量车轮行驶的距离非常简单。在计算距离之前,应该知道车轮的周长。
车轮周长 = π* d
其中 d 是车轮的直径。
π 的值为 3.14。
我有一个直径为 6.60 厘米的轮子(RC 车轮),所以周长是(20.7 厘米)。
因此,要计算行进的距离,只需将检测到的脉冲数乘以周长即可。
行驶距离 = 车轮周长 x(脉冲数 / 槽数)
因此,当一个周长为 20.7 厘米的轮子需要 20 个脉冲,即编码器轮转一圈时,轮子行进的距离由下式计算
行驶距离 = 20.7 x (20/20) = 20.7cm
为了计算以米为单位的距离,将以厘米为单位的距离除以 100。
注意:这是一个小型 RC 汽车车轮,实时汽车的车轮比这个大。所以我假设本教程中车轮的周长为 230 厘米。
根据行驶距离计算票价
要获得总票价金额,请将行驶距离乘以票价(金额/米)。
注意:在本教程中,我假设每米收费 5 卢比。
因此,如果车轮行驶 20m,则票价将为 20*5=100 卢比。
所以现在让我们获取组件并构建电路。
所需组件
Arduino UNO
液晶显示器 (16x2)
按钮
电位器 -10k
ULN2003电机驱动IC
LM393 速度传感器模块 (FC-03)
带速度编码器的 RC 智能汽车底盘
电池 9V
面包板
连接电线
电路原理图
使用 Arduino 的数字出租车计费器项目的电路图 如下所示:
用遥控车底盘安装速度传感器
速度传感器安装在传感器间隙之间的编码器轮。在我的机箱中,我有一个用于放置传感器的特殊孔。见下图
速度传感器模块和 Arduino 之间的连接
Arduino 和 16x2 LCD 之间的连接
Arduino 与 ULN2003 之间的连接
ULN2003、直流电机和9v电池之间的连接
我使用了 9V 电池和 ULN2003 IC 为电机外部供电。
按钮和电位器连接
带有下拉电阻的按钮连接到 Arduino 的引脚 3,用于在按下时生成票价金额。
电位器用于向 Arduino 的引脚 A0 提供模拟输入电压,以改变电机轮的速度。
为数字出租车计价器编程 Arduino
本教程末尾提供了带有演示视频的完整代码。在这里,我们了解了代码的几个重要部分。
在进入代码之前,我们需要了解代码中使用的中断和定时器 One 库。
此处使用中断是因为我们需要不断检查在速度传感器模块处检测到的输出作为高优先级。所以代码中使用了ISR。ISR 是中断服务程序,当中断引脚 2 和 3 发生中断时调用。
Arduino UNO 有两个中断引脚 2 和 3。
在引脚 2 处,连接速度传感器 D0 的输出。
在引脚 3 处,连接了一个带有下拉电阻的按钮。
此代码中使用TimerOne 库来检查一秒钟内检测到多少次旋转(多少个脉冲),据此我们可以计算每秒的速度并将其显示在输出中。此 ISR 函数每秒执行一次
那么让我们详细看看我们的代码:
1. 首先,包含程序中要使用的函数的库。
#include "TimerOne.h" #include
2. 接下来声明全局变量,因为它们将在整个程序中使用。
挥发性无符号整数计数器=0; 挥发性无符号整数旋转=0; 浮动旋转inm = 0; 无符号整数速度=0;
3. 接下来定义并初始化连接到 Arduino 的 LCD 引脚。
const int rs = 12, en = 13, d4 = 8, d5 = 9, d6 = 10, d7 = 11; LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
4. 接下来在void setup()
定义引脚模式,此处引脚 A0 用于从电位器获取模拟输入,引脚 5 用于写入连接到 ULN2003 IC 的 IN1 引脚的模拟输出。
pinMode(A0,输入); pinMode(5,输出);
接下来显示一些欢迎信息并清除它们。
lcd.开始(16,2);//设置 LCD 为 16x2 类型 lcd.setCursor(0,0); lcd.print("电路文摘"); lcd.setCursor(0,1); lcd.print("欢迎来到出租车"); 延迟(3000); lcd.clear(); lcd.print("开始吧:)"); 延迟(1000); lcd.clear();
下一个重要部分是设置中断引脚和中断发生时要调用的 ISR
首先,我们需要将 timer1 设置为 1 秒,然后为 timer1 附加一个 ISR,以便每秒调用一次此 ISR。ISR 名称是timerIsr
Timer1.initialize(1000000); Timer1.attachInterrupt(timerIsr);
接下来附加两个外部中断。第一个中断使 Arduino 引脚 2 作为中断引脚,并在引脚 2 检测到 RISING(LOW TO HIGH)时调用 ISR(计数)。此引脚 2 连接到速度传感器模块的 D0 输出。
第二个使 Arduino 引脚 3 作为中断引脚,并在引脚 3 检测到高电平时调用 ISR(generatefare)。该引脚通过下拉电阻连接到按钮。
attachInterrupt(digitalPinToInterrupt(2),计数,上升); attachInterrupt(digitalPinToInterrupt(3), generatefare , HIGH);
5.接下来看看我们这里使用的ISR:
ISR1-count()当引脚 2(连接到速度传感器)发生上升(从低到高)时调用 ISR。
void count() // 速度传感器计数的 ISR { counter++; // 将计数器值增加 一圈++;//将旋转值增加一个 delay(10); }
ISR2- timerIsr()每隔一秒调用一次 ISR 并执行 ISR 中存在的那些行。
无效 timerIsr() { detachInterrupt(digitalPinToInterrupt(2)); Timer1.detachInterrupt(); lcd.clear(); 浮动速度=(计数器/20.0)* 60.0; 浮动旋转= 230 *(旋转/ 20); rotationinm = 转数/100; lcd.setCursor(0,0); lcd.print("距离(m):"); lcd.print(旋转); lcd.setCursor(0,1); lcd.print("速度(RPM):"); lcd.print(速度); 计数器=0; int 类比 = 类比读取(A0); int motorspeed = map(analogip,0,1023,0,255); 模拟写入(5,电机速度); Timer1.attachInterrupt(timerIsr); attachInterrupt(digitalPinToInterrupt(2),计数,上升); }
这个函数包含实际上首先分离 Timer1 和 Interrupt pin2 的行,因为我们在 ISR 中有 LCD 打印语句。
为了以 RPM 计算SPEED,我们使用以下代码,其中 20.0 是编码器轮中预设的插槽数。
浮动速度=(计数器/20.0)* 60.0;
并使用以下代码计算距离:
浮动旋转= 230 *(旋转/ 20);
这里假设车轮周长为 230 厘米(因为这对于实时汽车来说是正常的)
接下来通过将距离除以 100 来转换以 m 为单位的距离
rotationinm = 转数/100;
之后我们在液晶显示屏上显示速度和距离
lcd.setCursor(0,0); lcd.print("距离(m):"); lcd.print(旋转); lcd.setCursor(0,1); lcd.print("速度(RPM):"); lcd.print(速度);
重要提示:我们必须将计数器重置为 0,因为我们需要获取每秒检测到的加号数,因此我们使用此行
计数器=0;
接下来读取模拟引脚 A0 并将其转换为数字值(0 到 1023)并进一步将这些值映射到 0-255 用于 PWM 输出(电机的设置速度),最后使用连接到 ULN2003 的模拟写入函数写入这些 PWM 值电机集成电路。
int 类比 = 类比读取(A0); int motorspeed = map(analogip,0,1023,0,255); 模拟写入(5,电机速度);
ISR3:generatefare()ISR 用于根据行驶距离生成票价金额。当检测到中断引脚 3 为高电平(按下按钮时)时调用此 ISR。该函数分离引脚 2 的中断和定时器中断,然后清除 LCD。
无效generatefare () { detachInterrupt(digitalPinToInterrupt(2)); 引脚 2 Timer1.detachInterrupt(); lcd.clear(); lcd.setCursor(0,0); lcd.print("票价卢比:"); 浮动卢比=rotationinm * 5; lcd.print(卢比); lcd.setCursor(0,1); lcd.print("每米 5 卢比"); }
之后,行驶距离乘以 5(我使用 5 表示 5 卢比/米的费率)。您可以根据自己的意愿进行更改。
浮动卢比=rotationinm * 5;
计算金额值后,将其显示在连接到 Arduino 的 LCD 显示器上。
lcd.setCursor(0,0); lcd.print("票价卢比:"); lcd.print(卢比); lcd.setCursor(0,1); lcd.print("每米 5 卢比");
完整代码
#include "TimerOne.h" //包含使用Timer1函数的Timer1库
#include
const int rs = 12, en = 13, d4 = 8, d5 = 9, d6 = 10, d7 = 11; //定义 LCD 引脚
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
挥发性无符号整数计数器=0;
挥发性无符号整数旋转=0;
浮动旋转inm = 0;
无符号整数速度=0;
void count() // 速度传感器计数的 ISR
{
counter++; //将计数器值增加
一圈++;//将旋转值增加一个
delay(10);
}
无效 timerIsr()
{
detachInterrupt(digitalPinToInterrupt(2)); //停止中断引脚2
Timer1.detachInterrupt(); //停止timer1中断
lcd.clear();
浮动速度=(计数器/20.0)* 60.0;//以分钟为单位计算速度(20-编码器轮中的槽数)
浮点旋转 = 230*(旋转 / 20);//以厘米为单位计算距离(230-车轮周长假设为 20-槽数)
rotationinm = rotations/100;
lcd.setCursor(0,0);
lcd.print("距离(m):");
lcd.print(旋转);//在LCD显示rotationinm
lcd.setCursor(0,1);
lcd.print("速度(RPM):");
lcd.print(速度);//在 RPM
计数器中显示速度=0;//重置计数器为0
int 类比 = 类比读取(A0);// 从引脚 A0 读取模拟
量 int motorspeed = map(analogip,0,1023,0,255); //将数字值 0-1023 转换为 0-255 模拟写入
(5,电机速度);//设置引脚 5 的 PWM 值
Timer1.attachInterrupt( timerIsr ); //再次启动timer1
attachInterrupt(digitalPinToInterrupt(2), count, RISING); //再次在pin2处附加中断
}
void generatefare() //ISR 生成票价
{
detachInterrupt(digitalPinToInterrupt(2)); //在 2 处禁用中断引脚
Timer1.detachInterrupt(); //禁用Timer1中断
float rupees = rotationinm*5; //行驶距离乘以 5(每米 5 卢比)
lcd.clear(); //清除 LCD
lcd.setCursor(0,0);
lcd.print("票价卢比:");
lcd.print(卢比);//显示票价金额
lcd.setCursor(0,1);
lcd.print("每米 5 卢比");
}
无效设置()
{
pinMode(A0,INPUT);//将引脚A0设置为INPUT
pinMode(5,OUTPUT); //将引脚 5 设置为 OUTPUT
lcd.begin(16,2); //设置 LCD 为 16x2 类型
lcd.setCursor(0,0); //以下代码显示欢迎信息
lcd.print("CIRCUIT DIGEST");
lcd.setCursor(0,1);
lcd.print("欢迎来到出租车");
延迟(3000);
lcd.clear();
lcd.print("开始吧:)");
延迟(1000);
lcd.clear();
Timer1.initialize(1000000); //初始化 timer1 1 秒
Timer1.attachInterrupt( timerIsr ); //每隔一秒调用一次 ISR 例程
attachInterrupt(digitalPinToInterrupt(2), count, RISING); // 引脚 2 作为中断引脚,计数 ISR 在发生从低到右时被调用。
attachInterrupt(digitalPinToInterrupt(3), generatefare, HIGH); //当检测到高电平时,引脚 3 作为带有 generatefare ISR 的中断引脚被调用。
}
无效循环()
{
}
-
显示屏
+关注
关注
28文章
4484浏览量
74264 -
计费器
+关注
关注
0文章
7浏览量
7328 -
Arduino
+关注
关注
188文章
6469浏览量
186994
发布评论请先 登录
相关推荐
评论