我想创建一个项目/安卓应用程序,可以将命令传输到arduino并通过USB-OTG接收响应。规格如下:
用户只需按一下按钮(在应用程序上),就需要自动完成整个过程。
这个项目基本上是一个智能卡读卡器模拟器(它是一个模拟器,因为APDU响应被硬编码到arduino代码中,因此整个系统不需要实际的智能卡和读卡器。)
问题的描述如下,其后是问题。这很长,所以请耐心等待。
我修改的java代码是:
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
@Override
public void onReceivedData(byte[] arg0) {
//the part that I modified :
String balance = "";
try{
if ((arg0[0] == (byte) 0x50) && (arg0[1] == (byte) 0x33)) {
byte[] CMD2 = {0x00,(byte)0xA2,0x00,0x00,0x05,0x41,0x00};
serialPort.write(CMD2);
}
else if ((arg0[0] == (byte) 0x50) && (arg0[1] == (byte) 0x44)) {
byte[] CMD3 = {0x00,(byte)0xA2,0x00,0x00,0x05,0x41,0x11};
serialPort.write(CMD3);
}
else if ((arg0[0] == (byte) 0x50) && (arg0[1] == (byte) 0x1C)) {
byte[] CMD4 = {0x00,(byte)0xD1,0x00,0x00,0x10};
serialPort.write(CMD4);
}
else if (arg0[0] == (byte) 0xC5) {
byte[] bufferData = PickData(arg0, 8);
balanceData = bytesToLong(bufferData);
balance = Long.toString(balanceData);
balanceView.setText(balance);
}
else{
balanceView.setText("Balance Check Failed! Click Refresh");
}
}catch (Exception e) {
e.printStackTrace();}
}
};
/* The part that I added */
//Picks the balance data from the final response.
public static byte[] PickData(byte[] bytes, int lengthb) {
byte[] buffer= new byte [lengthb];
for (int i = 0; i < lengthb; i++) {
if((bytes[i+1]==0xB0)||(bytes[i+1]==0x90))
buffer[i] = 0;
else
buffer[i] = bytes[1+i];
}
return buffer;
}
//converts array of byte into long.
public static long bytesToLong(byte[] Data) {
long value=0;
for (int i = 0; i < Data.length; i++)
{
value = (value << 8) + (Data[i] & 0xff);
}
return value;
}
这是arduino代码:
#include <SoftwareSerial.h>
#define RX 3
#define TX 5
int c;
SoftwareSerial usbdevice=SoftwareSerial(RX,TX);
byte command[11];
//Hard-coded responses
byte response1[] = {0x50,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
byte response2[] = {0x50,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
byte response3[] = {0x50,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//0x2710 is the balance data. It will be translated to long then to string, which is 10000.
byte response4[] = {0xC5,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x10,0x90,0x00};
String str; //only for serial monitor viewing
byte response[11]; // to be printed on Serial Monitor
void setup() {
pinMode(RX,INPUT);
pinMode(TX,OUTPUT);
Serial.begin(115200);
usbdevice.begin(9600);
Serial.println("Arduino Reader Simulation Start: ");
}
void loop()
{
//Reads the command from android
if(usbdevice.available()>0)
{
c=0;
delay(15);
while(1)
{
if(usbdevice.available()>0)
{
command[c] = usbdevice.read();
c++;
}
else
break;
}
//Checks the command byte-per-byte then sends the response
for(c=0;c<11;c++)
{
if((command[0] == 0x00)&&(command[1] == 0xA2)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x05)&&(command[5] == 0x4e)&&(command[6] == 0x00)){
usbdevice.write(response1[c]);
response[c] = response1[c];
}
else if((command[0] == 0x00)&&(command[1] == 0xA2)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x05)&&(command[5] == 0x41)&&(command[6] == 0x00)){
usbdevice.write(response2[c]);
response[c] = response2[c];
}
else if ((command[0] == 0x00)&&(command[1] == 0xA2)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x05)&&(command[5] == 0x41)&&(command[6] == 0x11)){
usbdevice.write(response3[c]);
response[c] = response3[c];
}
else if((command[0] == 0x00)&&(command[1] == 0xD1)&&(command[2] == 0x00)&&(command[3] == 0x00)&&(command[4] == 0x10)){
usbdevice.write(response4[c]);
response[c] = response4[c];
}
}
//Prints each command and it's response.
printAll();
}
}
在测试这些代码时,我遇到了一些问题:
有时,应用程序成功显示了余额,但大部分时间都失败了。成功的过程:
Command:
0 a2 0 0 5 4e 0 0 0 0 0
Response:
50 33 0 0 0 0 0 0 0 0 0
Command:
0 a2 0 0 5 41 0 0 0 0 0
Response:
50 44 0 0 0 0 0 0 0 0 0
Command:
0 a2 0 0 5 41 11 0 0 0 0
Response:
50 1c 0 0 0 0 0 0 0 0 0
Command:
0 d1 0 0 10 41 11 0 0 0 0
Response:
c5 0 0 0 0 0 0 27 10 90 0
失败的过程:
//First attempt
Command:
0 a2 0 0 5 4e 0 0 0 0 0
Response:
50 33 0 0 0 0 0 0 0 0 0
Command:
48 10 50 e0 5 4e 0 0 0 0 0
Response:
50 33 0 0 0 0 0 0 0 0 0
//Second attempt
Command:
0 a2 0 0 5 4e 0 0 0 0 0
Response:
50 33 0 0 0 0 0 0 0 0 0
Command:
0 a2 0 0 5 41 0 0 0 0 0
Response:
50 44 0 0 0 0 0 0 0 0 0
Command:
0 a2 0 0 5 41 11 0 0 0 0
Response:
50 1c 0 0 0 0 0 0 0 0 0
Command:
0 d1 0 20 5 41 11 0 0 0 0
Response:
50 1c 0 0 0 0 0 0 0 0 0
从失败的过程中可以看出,从android发送到arduino的命令字节与java代码中的硬编码字节不同。不知何故,android会随机发送随机字节作为命令,从而停止进程并显示“失败”消息。我不知道为什么会发生这种情况。我的理解是,如果我不使用try-catch,这可能是导致崩溃的原因。
根据上述问题的详细信息,我的问题是:
1。如何解决崩溃问题以及“随机更改命令数据”问题?
2。有没有其他方法像这样顺序传输数据但实际上有效吗?
提前谢谢你。
P.S。 我怀疑其中一个问题是由java代码中的函数PickData引起的,因为当我禁用它时,应用程序几乎从未失败过显示某些东西,尽管它总会显示一些随机数(如果我很幸运,应用程序可能会显示余额数据)。这个随机改变的字节数据是我非常困惑的。
我正在使用本教程作为参考: https://www.allaboutcircuits.com/projects/communicate-with-your-arduino-through-android/
我还使用Github用户felHR85的USB串行库(如上面的教程中所使用的)。链接:https://github.com/felHR85/UsbSerial/