就在几周前,我们在这个博客中展示了电动扫雪机的制造商版本,类似于许多小商店里的那种。事实上,我们的是一种特殊的履带,是传统扫雪机的缩小版,但可以通过索尼PS2控制器轻松进行无线电控制。在第一篇文章中,我们描述了该项目的硬件,即机械和电子控制器,并解释说它完全基于Arduino Uno。在这篇文章中,我们将描述要加载到Arduino上的固件,以执行所有所需的功能,操作驱动电机,控制刀片,并根据通过无线电接收的命令打开/关闭前投影仪。
本文引用地址:
简要概述
扫雪机的电气和电子部分基于Arduino Uno Rev.3,它拥有三个护罩和与这些卡的接口:
PCBWAY
电机驱动器DRI0018;
继电器电路RELAY1CH;
DC/DC转换器升压STEPUP30VADJ。
安装在Arduino上的防护罩是控制三个线性电机的电机防护罩,用于管理刀片的移动,以及允许您与控制台PlayStation 2(PS2)接口的PS2SHIELD;后一种屏蔽要求通过将其插入连接器来安装RX-PS2,它是一个2.4 GHz的无线电接收器,用于接收来自上述控制台的特定命令。
电路中使用的所有电路板和元件都可以在我们的商店购买。电源由两个7.2 Ah的铅凝胶电池组成:我们在两者的中点取12伏,而在该系列的负极和正极之间取24伏。
使用12伏电压,我们为Arduino供电,Arduino将通过其引脚条为屏蔽的逻辑供电;LED(内部配备限制电阻器)将指示Arduino何时开启。
12伏电压也用于马达护罩的电源部分;事实上,考虑到三个线性执行器的高吸收,直接从Arduino获得12V是不明智的:您必须选择将外部电源连接到适当的端子PWR。
每个线性致动器由一个12 Vdc的齿轮电机组成,该电机使用蜗杆沿其长度来回移动轴(最大偏移5 cm)。致动器的动态负载为50 kg,最大速度为1.3 cm/s。在不移动时,它最多可支撑约250公斤,扭矩螺钉确保即使在没有动力的情况下也能保持轴的位置。
当发动机达到最大伸展和收缩时,两个限位开关会停止发动机,而二极管在达到极限点后允许反向。执行机构由金属制成,并进行密封,以防止灰尘和水进入,这是在雪地中操作的强制性条件。
24V电源线用于为扫雪机的部分供电,即牵引和投影(可选)部分:第一部分基于电源电机驱动器DRI0018,用四根电线连接到相应的Arduino数字线。模块的输出端子连接用于牵引的两个24伏马达。
除了发动机控制器外,24伏还为LED投影仪的部分供电,无论您是否安装,其照明都会根据我们扫雪机电子设备中的光刻胶检测到的环境照明条件进行调整。
投影仪设计为在220 Vac下工作,然而,由于上没有此电压,为了避免使用逆变器,我们对投影仪进行了修改,打开投影仪,移除AC/DC,并将电源LED的两根电线连接到DC/DC转换器(代码:STEPUP30VADJ);后者是一个开关可调输出电压调节器,应该对其进行调谐,以提供合适的电流,使LED在大约10瓦的功率下工作。
从遥控器接收数据是分配给屏蔽PS2SHIELD的任务,为此,制造商提供了我们在Arduino草图中集成的特定库。屏蔽执行命令接收和解码;2.4GHz无线电单独提供(RX_PS2),必须插入屏蔽的连接中。
// Sketch Open Source Snow Plow Robot
// by Vittorio Loschiavo
#include <Shield_PS2.h>
//declare class objects
PS2 ps2=PS2(); //PS2 class object: ps2
int FOTORES = A0;
int RELAY = 13;
int sensorValue = 0;
int ALZAPALA = 12;
int ONALZAPALA = 11;
int RUOTAPALA = 2;
int ONRUOTAPALA = 3;
int E1 = 5; //MOTORE 1 SPEED CONTROL M1_PWM
int E2 = 6; //MOTORE 2 SPEED CONTROL M2_PWM
int M1 = 4; //MOTORE 1 DIRECTION CONTROL M1_EN
int M2 = 7; //MOTORE 2 DIRECTION CONTROL M2_EN
int counter=0;
int stato=0;
int val=0;
int velo=0;
int motori=0;
void setup()
{
Serial.begin(9600);
ps2.init(9600, 8, 9); //initialize the main board to use desired (baudrate, rx, tx)
//for Arduino Mega use RX:10, TX: 11 for software serial
//for Arduino Leonardo use pin 8, 9, 10, 11 as RX and TX for software serial
pinMode (FOTORES, INPUT);
pinMode (RELAY, OUTPUT);
pinMode (RUOTAPALA, OUTPUT);
pinMode (ALZAPALA, OUTPUT);
pinMode (ONRUOTAPALA, OUTPUT);
pinMode (ONALZAPALA, OUTPUT);
pinMode (E1, OUTPUT);
pinMode (M1, OUTPUT);
pinMode (E2, OUTPUT);
pinMode (M2, OUTPUT);
stato=0;
}
void loop(){
motori=0;
if( ps2.getval(p_up)==0 || ps2.getval(p_joy_lu)==100) {
Serial.println("AVANTI"); //
analogWrite (E1,velo); //PWM Speed Control
digitalWrite(M1,HIGH); //
analogWrite (E2,velo); //
digitalWrite(M2,HIGH); ///
motori=1;
}
if (ps2.getval(p_down)==0 || ps2.getval(p_joy_ld)==100) {
Serial.println("INDIETRO");
analogWrite (E1,velo);
digitalWrite(M1,LOW);
analogWrite (E2,velo);
digitalWrite(M2,LOW);
motori=1;
}
if (ps2.getval(p_right)==0 || ps2.getval(p_joy_lr)==100){
Serial.println("DESTRA");
analogWrite (E1,velo);
digitalWrite(M1,HIGH);
analogWrite (E2,velo);
digitalWrite(M2,LOW);
motori=1;
}
if (ps2.getval(p_left)==0 || ps2.getval(p_joy_11)==100) {
Serial.println("SINISTRA"); //
analogWrite (E1,velo); //
digitalWrite(M1,LOW); //
analogWrite (E2,velo); //
digitalWrite(M2,HIGH); //
motori=1; //
}
if (ps2.getval(p_triangle)==0) {
Serial.println("TRIANGOLO"); //
if (velo<250) //
{ //
velo=velo+25; //
} //
else //
{ //
ps2.vibrate(2, 255); //
delay(500); // 500 ms
ps2.vibrate(2,0); //
} //
analogWrite (M1, velo); //
analogWrite (M2, velo); //
Serial.println(velo);
}
if (ps2.getval(p_cross)==0) { //
Serial.println("X"); //
if (velo>0 && velo<=250) //
{ //
velo=velo-25; //
}
else
{
//non fa niente
}
analogWrite (M1, velo);
analogWrite (M2, velo);
Serial.println(velo);
}
if (ps2.getval(p_circle)==0) {
Serial.println("CERCHIO");
if (stato==0)
{ //
stato=stato+1;
delay(100);
Serial.println(stato);
digitalWrite(RELAY, HIGH);
ps2.vibrate(2, 255); //
delay(500); // 500 ms
ps2.vibrate(2,0); //
delay(500);
ps2.vibrate(2,255);
delay(500);
ps2.vibrate(2,0);
}
else
{
stato=0;
delay(100);
Serial.println(stato);
digitalWrite(RELAY, LOW);
ps2.vibrate(2, 255); //
delay(500); // 500 ms
ps2.vibrate(2,0); //
}
}
if (ps2.getval(p_square)==0) { //
Serial.println("QUADRATO");
digitalWrite(E1,0);
digitalWrite(M1,LOW);
digitalWrite(E2,0);
digitalWrite(M2,LOW);
velo=0;
}
if (ps2.getval(p_l1)==0) {
Serial.println("L1");
digitalWrite (ONALZAPALA, HIGH); //
digitalWrite (ALZAPALA, LOW); //
}
if (ps2.getval(p_l1)==1) {
Serial.println("L1");
digitalWrite (ONALZAPALA, LOW); //
digitalWrite (ALZAPALA, LOW); //
}
if (ps2.getval(p_l2)==0) {
Serial.println("L2");
digitalWrite (ONRUOTAPALA, HIGH); //
digitalWrite (RUOTAPALA, LOW); //
}
if (ps2.getval(p_l2)==1) {
Serial.println("L2");
digitalWrite (ONRUOTAPALA, LOW); //
digitalWrite (RUOTAPALA, LOW); //
}
if (ps2.getval(p_r1)==0) {
Serial.println("R1");
digitalWrite (ONALZAPALA, HIGH); //
digitalWrite (ALZAPALA, HIGH); //
}
if (ps2.getval(p_r2)==0) {
Serial.println("R2");
digitalWrite (ONRUOTAPALA, HIGH); //
digitalWrite (RUOTAPALA, HIGH); //
}
if (ps2.getval(p_start)==0) {
Serial.println("START");
}
if (ps2.getval(p_select)==0) {
Serial.println("SELECT");
}
if (motori==0) { //
analogWrite (E1,0);
digitalWrite(M1,LOW);
analogWrite (E2,0);
digitalWrite(M2,LOW);
}
sensorValue = analogRead(FOTORES);
Serial.println(sensorValue);
if (sensorValue<30 || stato==0) {
// {
digitalWrite(RELAY, HIGH);
}
else
{
digitalWrite(RELAY, LOW);
delay(100);
{
//non fa niente
}
}
}
好吧,在总结了扫雪机的制作和特性后,我们可以继续讨论你最感兴趣的东西:固件,也就是要上传到Arduino Uno中的草图,这样它就可以控制扫雪机,并将PlayStation 2控制器发送的命令传给他。
的固件相对简单;为了理解它的结构是合适的,首先,花几个字在受控屏蔽上,特别是在PS2屏蔽上。事实上,关于马达屏蔽,我们在其他文章中已经讲了很多,因为我们在各种项目中都使用过它,所以我们只想说,它的管理涉及我们已经计划在草图中包括的特殊库,需要PWM信号和“启用”逻辑级别。我们介绍了Shield PS2的相关功能以及专用库的主要功能。
该屏蔽允许您使用Playstation 2的无线控制器(或有线控制器),允许远程控制机器人或其他设备;因为它的设计,可以与Arduino Uno Rev 3、Duemilanove、Mega和Leonardo一起使用。它配备了一个重置按钮来镜像Arduino的,带有跳线来设置各种波特率(9600、57600、115200 bps),以及一个状态LED和跳线来选择用于TX和RX数据的引脚,以替代UART默认值。
我们说Arduino Uno引脚D0和D1与硬件串行匹配,它们的含义分别是TX和RX。但是,可以通过软件重新分配TX和RX线路,通过加载适当的库New software Serial将它们分配给其他引脚(TX:引脚1、3、9、11–RX:0、2、8、10),这允许在其他硬件资源(或其他屏蔽)尚未使用的其他数字I/O对上模拟串行端口。
请注意,如果您使用串行硬件(D0,D1)的引脚,请记住在开始对Arduino Uno进行编程之前,将PS2连接器从Shield上拔下。

PS2屏蔽能够通过适当的库识别和管理PS2控制器的所有按钮和模拟棒。每个模拟操纵杆(左和右)有两个轴(X和Y)和两种输出格式:模拟1和2。在“模拟输出1”格式中,每个操纵杆有两个变量:X轴和Y轴。根据操纵杆的移动方式,您可以得到一个从0到255的输出值,对应于操纵杆的位置。
Y轴:
•中心位置(中性),值为128。
•向上推,数值从128变为0
•按下,数值从128变为255。
X轴:
•中心位置(中性),值为128。
•向左推,数值从128变为0。
•向右推,数值从128变为255。

在“输出模拟2”中,每个操纵手柄有四个变量(上、下、左和右)。当用户在一个方向上移动操纵杆时,4个变量的值从0变为100。左右操纵手柄各有四个独立变量。
对于PS2控制器按钮管理,只需检查我们感兴趣的按钮的状态并读取返回值,即可:
•如果按下按钮,则为0;
•如果未按下按钮,则为1。
例如,如果我们想知道您是否按下了“UP”按钮,我们必须编写以下声明:
ps2.getval(p_up)==0
也可以将“p_up”替换为相应的十进制值,在本例中为“4”。
屏蔽PS2还能够处理PS2控制器中的两个小型发动机,这两个发动机决定振动(左和右):相关命令需要两个字节的数据,第一个字节指示哪个电机必须振动,而下一个字节(第二个字节)指示发动机状态或速度。
为了使用处理来自PS2控制器的命令的屏蔽,我们使用了shield_PS2.h库。在草图的开头,我们包含了语句“#include<shield_PDS2.h>”,该库需要正确控制屏蔽。
让我们继续看LED投影仪的控制,它通过Arduino Uno Rev3模拟引脚A0进行操作,该引脚连接到检测环境光的光刻胶;当照明低于阈值时,草图激活投影仪,或者更确切地说,它向卡RELAY1CH提供高逻辑状态,该卡包含由逻辑电平激活的继电器。在我们的项目中,我们使用闭合和常开之间的交换,并通过它触发为投影仪供电的DC/DC转换器的电源,因此当Arduino Uno(通过其数字引脚13)进入逻辑状态1时,继电器发出咔哒声并闭合上述触点,打开LED投影仪。