从 Android 读取方向传感器值并将其发送到 Arduino

物联网 蓝牙 安卓 阿杜伊诺
2021-06-18 05:59:09

我正在尝试从 android读取方向传感器值并将它们发送到 Arduino。android 将以字节为单位发送 valueX、valueY 和 valueZ。

每个值将以 x、y 和 z 字符结尾(from.java)。

String valueX = xPosition + "x";
btSocket.getOutputStream().write(valueX.toString().getBytes());

当我旋转手机时,该值将只读取一个值,即 valueZ。

#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 5);
// Pin 13 - LED
int ledG = 13;
int ledR = 12;
int ledW = 11;
int state;
String value,value1,valueZ,valueY,valueX;

void setup() {                
  // initialize the digital pin as an output.
  pinMode(ledG, OUTPUT);  
  pinMode(ledR, OUTPUT);
  pinMode(ledW, OUTPUT);   
  // initialize serial communication at 9600 bits per second:
  mySerial.begin(9600);
}

void loop() {
  if(mySerial.available() > 0){     
     state = ((byte)mySerial.read());}




  if (state == 'z') {
      int state = valueZ.toInt();
      //state = state + valueZ;
      digitalWrite(ledG, HIGH);}   // turn the LED on (HIGH is the voltage level)
  else if (state != 'z' && state!=0) {
      digitalWrite(ledG, LOW);}    // turn the LED off by making the voltage LOW

  else if ( state == 'y') {
    int casted2 = valueY.toInt();
      digitalWrite(ledR, HIGH);}
  else if (state != 'y') {
      digitalWrite(ledR, LOW);}

  else if (state == 'x') {
    int casted = valueX.toInt();
      digitalWrite(ledW, HIGH);}
  else if (state != 'x') {
      digitalWrite(ledW, LOW);}

  delay(1);               // wait for 100ms

  //For debugging purpose
  //Serial.println(state);
}
2个回答

我不确定你为什么要检查z's 等等,但你的第一个else if子句确保块的其余部分中的任何子句都不会被执行。

else if (state != 'z' && state!=0) {
  digitalWrite(ledG, LOW);}    // turn the LED off by making the voltage LOW

state任何值既不z是 0也不是 0(x、y 等)时,则执行此块并跳过其余部分。它似乎state很少为 0,所以你得到的只是一个 LED,它对于任何 x 或 y 值都关闭。你可能应该做的是:

int orientx;
int orienty;
int orientz;

switch (state) {
  case 'z':
    orientz = valueZ.toInt();
    digitalWrite(ledG, HIGH);
    digitalWrite(ledR, LOW);
    digitalWrite(ledW, LOW);
    break;
 case 'y':
    orienty = valueY.toInt();
    digitalWrite(ledG, LOW);
    digitalWrite(ledR, HIGH);
    digitalWrite(ledW, LOW);
    break;
case 'x':
    orientx = valueX.toInt();
    digitalWrite(ledG, LOW);
    digitalWrite(ledR, LOW);
    digitalWrite(ledW, HIGH);
    break;
}
delay(1);

if-else如果您愿意,您也可以使用语句,但如果您只测试 one variable 的值,我发现这更简洁state

一个更优雅的解决方案是:

int orientx;
int orienty;
int orientz;

switch (state) {
  case 'z':
    orientz = valueZ.toInt();
    break;
  case 'y':
    orienty = valueY.toInt();
    break;
  case 'x':
    orientx = valueX.toInt();
    break;
}
digitalWrite(ledG, (state == 'z'));
digitalWrite(ledR, (state == 'y'));
digitalWrite(ledW, (state == 'x'));

为了改进 TisteAndii 的答案,您的程序可能会丢失上下文,这可能是串行线上问题的一部分,因为它没有开始/停止标记。例如,假设一个字节被丢弃,然后下一个字节(一个值字节)是一个“y”,那么下一个状态将被读取为一个值。我建议您对数据包进行帧处理,尤其是使用软件串行。这将有助于防止数据损坏。一个非常简单的版本如下。

 ____________
|Start byte  | Byte 0
|_ _ _ _ _ _ |
|Msg ID      | Byte 1 optional if using only one message type
|_ _ _ _ _ _ |
|Msg Length  | Byte 2 (defined as total length of message including header)
|_ _ _ _ _ _ |
|Data        | Bytes 3-254
|_ _ _ _ _ _ |
|Checksum    | Byte 3 + Len(Data) (Max 255)
|____________|

这种结构将允许您将诸如结构或 protobuf 之类的内容转换为消息,然后无需太多工作即可再次返回。这本质上是 ANT 和 XBee 无线电如何与外部微控制器通信的精简版本。这是一个示例实现