2016-05-31 83 views
1
using UnityEngine; 
using System.Collections; 
using System.IO.Ports; 
using System.Threading; 

public class Sending : MonoBehaviour { 

    //public static SerialPort sp = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One); 
    public static SerialPort sp = new SerialPort("COM3", 9600); 

    void Start() { 
     OpenConnection(); 
    } 



    public void OpenConnection() 
    { 
     if (sp != null) 
     { 
      if (sp.IsOpen) 
      { 
       sp.Close(); 
      } 
      else 
      { 
       sp.Open(); 
      } 
     } 
    } 

    void OnApplicationQuit() 
    {  
     sp.Close(); 
    } 

    public static void Contact(int pos) 
    { 
     string PosStr = pos.ToString(); 
     Debug.Log(PosStr); 
     sp.Write(PosStr); 
    } 
} 

////////////////// ////////////////////Arduino和电机控制统一

using UnityEngine; 
using System.Collections; 

public class GetPosition : MonoBehaviour 
{ 
    Vector3 dragStartPosition; 
    float dragStartDistance; 
    float[] Xfloat; 

    void OnMouseDown() 
    { 
     dragStartPosition = transform.position; 
     dragStartDistance = (Camera.main.transform.position - transform.position).magnitude; 
    } 

    void Update() 
    { 
    } 

    int OnMouseDrag() 
    { 
     Vector3 worldDragTo = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, dragStartDistance)); 
     transform.position = new Vector3 (worldDragTo.x, dragStartPosition.y, dragStartPosition.z); 
     new Vector3 (worldDragTo.x, dragStartPosition.y, dragStartPosition.z); 
     int Newpos = (int)worldDragTo.x; 
     return (Newpos); 
    } 

    void OnMouseUp() 
    { 
     int NewPos = OnMouseDrag(); 
     Sending.Contact (NewPos); 
    } 

} 

/////////////////////// //////////////////////

int motorPin1 = 8; 
int motorPin2 = 9; 
int motorPin3 = 10; 
int motorPin4 = 11; 
int delayTime = 2; 
int i = 0; 
char myCol[5]; 


void setup() { 
    Serial.begin (9600); 
    pinMode(motorPin1, OUTPUT); 
    pinMode(motorPin2, OUTPUT); 
    pinMode(motorPin3, OUTPUT); 
    pinMode(motorPin4, OUTPUT); 
} 


void loop() 
{ 
    int lf = 5; 
    Serial.readBytesUntil(lf, myCol, 5); 
    Serial.setTimeout(0); 


    int Angle = atoi(myCol); 
    int Tick = ((Angle * 51.2)/36.0); 

    Serial.println(Tick); 

    if (i < Tick) 
    { 
    Play(); 
    i++; 
    } 
    if (i > Tick) 
    { 
    Reverse(); 
    i--; 
    } 
} 



void Play() 
{ 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
} 

void Reverse() 
{ 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
} 

嗨! ,我的统一控制电机有问题,我有一个Unity场景,其中包含一个立方体,我可以在x轴上滑动这个立方体,我通过COM3发送x值,在Arduino中获得Value并将其转换为角为我的电机。

我的问题是: 当我在Unity中移动立方体时,我的电机旋转,但是当我将立方体滑动几次后,整体冻结为15/20秒,然后我的电机移动,但没有以正确的角度移动。

谁能告诉我我的问题在哪里?

+0

昨天我看到了同样的问题。我只是觉得你是以错误的方式做整件事情,但是当我明白你到底在做什么时,我会提供答案。在Arduino方面,有什么期待?你说了一些关于电机旋转的东西它何时开始旋转,旋转多久?它什么时候停止旋转?你有一个真实世界的例子,你在做什么?在Unity方面,你什么时候发送给Arduino?它看起来像你正在发送x值。你为什么要发送x值,它用于什么?你什么时候停止发送给Arduino? – Programmer

+0

这是一大堆问题,但它会让你的问题得到解答。你可以在这个评论部分分开Arduino和Unity的回应。 – Programmer

+0

我有我的立方体充当滑块,我将它滑动到x轴上,他的x位置用作角度值,我在arduino中发送此值。 当我拖动立方体没有发生(这是正常的),当我释放它的值发送和我的电机在arduino旋转(例如:我移动我的立方体位置x 450和我的电机旋转450°)大约需要4秒完整旋转(360°) 该值仅在鼠标释放时发送一次。 如果我还没有回答你所有的问题请告诉我! – Sholyu

回答

1

在您的代码中发现很多错误,我不知道是哪一个导致了问题。修正了所有这些问题。阅读下面,看看我修好了。

1.Unity冻结是因为您没有使用Thread

2.Arduino冻结很可能是因为您有Serial.println(Tick);。它发送给Unity,但你没有阅读Unity的一面。也许有一个缓冲区溢出。评论它。

3. OnMouseDrag是一个Unity回调函数。从OnMouseUp函数自己调用它并不是一个好主意。

4.单击立方体的一侧会使其跳转到鼠标的位置。通过添加偏移量来修复它。

5.取代OnMouseDown,OnMouseDrag,OnMouseUp带拖动回调函数。

6.改变数据在Arduino端的读取方式。删除Serial.readBytesUntil(lf, myCol, 5);代码。

7.在致电Serial.available()之前添加了delay(1);。不要删除它。某些Arduino板要求或Serial.available()不能按预期运行。

8.删除代码中的所有静态内容。

9.您的字符串未终止。您必须在与myCol[index]= '\0';myCol[index]= 0一起阅读后终止它;

我不明白你的角度转换是如何在Arduino上完成的,所以我保持原样。将每个脚本替换为下面的新脚本,并在出现问题时留下评论。我没有电机,因此无法测试电机部件。

的Arduino

int motorPin1 = 8; 
int motorPin2 = 9; 
int motorPin3 = 10; 
int motorPin4 = 11; 
int delayTime = 2; 
char myCol[10]; 

enum class READSTAT {NONE, READING, DONEREADING}; 

READSTAT readStat = READSTAT::NONE; 

void setup() { 
    Serial.begin (9600); 
    pinMode(motorPin1, OUTPUT); 
    pinMode(motorPin2, OUTPUT); 
    pinMode(motorPin3, OUTPUT); 
    pinMode(motorPin4, OUTPUT); 
} 


void loop() 
{ 
    //Must delay 1 milliseconds to make Serial.available() work properly 
    delay(1); 

    //Serial.setTimeout(0); 
    static int avalData = 0; 
    if (Serial.available() > 0) { 
    readStat = READSTAT::READING; 
    myCol[avalData] = Serial.read(); 
    avalData++; 
    } else { 
    //If we are in READING mode and there are no more available bytes, change mode to DONEREADING 
    if (readStat == READSTAT::READING) { 
     readStat = READSTAT::DONEREADING; 
     myCol[avalData] = '\0'; 
    } 
    } 

    //[CODE INSIDE HERE WILL RUN WHEN EVERY BYTE HAS BEEN RECEIVED FROM UNITY] 
    //If we are in DONEREADING mode, change mode to NONE 
    if (readStat == READSTAT::DONEREADING) { 

    checkMotor(avalData); 

    //SET TO NONE then reset avalData 
    readStat = READSTAT::NONE; 
    avalData = 0; 
    } 

} 

void checkMotor(int avalData) { 
    int Angle = atoi(myCol); 
    int Tick = ((Angle * 51.2)/36.0); 


    if (0 < Tick) { 
    Tick = abs(Tick); 
    for (int i = 0; i < Tick; i++) { 
     Play(); 
    } 
    } else if (0 > Tick) { 
    Tick = abs(Tick); 
    for (int i = 0; i < Tick; i++) { 
     Reverse(); 
    } 
    } 
} 

void Play() 
{ 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
} 

void Reverse() 
{ 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, HIGH); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, LOW); 
    delay(delayTime); 
    digitalWrite(motorPin1, LOW); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, HIGH); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
    digitalWrite(motorPin1, HIGH); 
    digitalWrite(motorPin2, LOW); 
    digitalWrite(motorPin3, LOW); 
    digitalWrite(motorPin4, HIGH); 
    delay(delayTime); 
} 

发送:

using UnityEngine; 
using System.Collections; 
using System.IO.Ports; 
using System.Threading; 

public class Sending : MonoBehaviour 
{ 
    public SerialPort sp; 
    Thread SerialThread; 
    bool stopSerialCom = true; 

    bool sendNow = false; 
    int posTosend = 0; 

    void Start() 
    { 
     startCommuncation(); 
    } 

    public void startCommuncation() 
    { 
     SerialThread = new Thread(onConnected); 
     SerialThread.IsBackground = true; 
     SerialThread.Start(); 
    } 

    private void onConnected() 
    { 
     //Open Connection 
     openCon(); 
     sp.ReadTimeout = 2; 

     //Run forever until stopSerialCom = true 
     while (!stopSerialCom) 
     { 
      //Check if we should send 
      if (sendNow) 
      { 

       Debug.Log("Sent: " + posTosend.ToString()); 
       //Send 
       sendToSerial(posTosend); 
       posTosend = 0; //Reset to 0 
       sendNow = false; 
      } 
      Thread.Sleep(1); 
     } 
    } 

    private void openCon(string comPort = "COM3", int port = 9600) 
    { 
     sp = new SerialPort(comPort, port); 

     if (sp != null) 
     { 
      if (sp.IsOpen) 
      { 
       sp.Close(); 
       sp.Open(); 
       stopSerialCom = false; 
       Debug.Log("Opened!"); 
      } 
      else 
      { 
       sp.Open(); 
       stopSerialCom = false; 
       Debug.Log("Opened!"); 
      } 
     } 
    } 

    public void closeConnection() 
    { 
     stopSerialCom = true; 

     //stop thread 
     if (SerialThread != null && SerialThread.IsAlive) 
     { 
      Debug.Log("Thread Aborted!"); 
      SerialThread.Abort(); 
     } 

     if (sp != null && sp.IsOpen) 
     { 
      sp.Close(); 
      Debug.Log("Closed!"); 
     } 
    } 

    void OnApplicationQuit() 
    { 
     closeConnection(); 
    } 


    public void Send(int pos) 
    { 
     posTosend = pos; 
     sendNow = true; 
    } 

    private void sendToSerial(int pos) 
    { 
     try 
     { 
      string PosStr = pos.ToString(); 
      sp.Write(PosStr); 
     } 
     catch (System.Exception e) 
     { 
      Debug.Log("Error: " + e.Message); 
     } 
    } 
} 

为getPosition:

using UnityEngine; 
using System.Collections; 
using UnityEngine.EventSystems; 

public class GetPosition : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler 
{ 
    Vector3 dragStartPosition; 
    float dragStartDistance; 
    float[] Xfloat; 

    Vector3 clickOffset = Vector3.zero; 
    Sending sending; 

    Camera mainCamera; 
    Transform camTransform; 

    void Start() 
    { 
     mainCamera = Camera.main; 
     camTransform = mainCamera.transform; 
     mainCamera.gameObject.AddComponent<PhysicsRaycaster>(); 

     sending = GetComponent<Sending>(); 
    } 

    public void OnBeginDrag(PointerEventData eventData) 
    { 
     dragStartPosition = transform.position; 
     dragStartDistance = (camTransform.position - transform.position).magnitude; 

     //Get offset 
     clickOffset = transform.position - mainCamera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, dragStartDistance)); 
    } 

    public void OnDrag(PointerEventData eventData) 
    { 
     Vector3 tempPos = mainCamera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, dragStartDistance)); 

     //Apply Offset to prevent the Cube from Jumping when mouse is clicke on the side/edge 
     tempPos = tempPos + clickOffset; 

     tempPos.y = dragStartPosition.y; 
     tempPos.z = dragStartPosition.z; 

     transform.position = tempPos; 

    } 

    public void OnEndDrag(PointerEventData eventData) 
    { 
     sending.Send((int)transform.position.x); 
    } 
} 

确保SendingGetPosition连接到同一的游戏对象/立方。只用一个立方体进行测试。

+0

只是在Arduino代码中修复了一些东西。在发表任何评论前,重新复制新的Arduino代码。 – Programmer

+0

它的工作原理并不完全如预期,当我将立方体移动到90时,它会在我的电机上达到90°,但如果我将它移动到-10之后,它会向后移动10°,但我需要它移动-10°,距离最后位置不是10°。 – Sholyu

+0

@Sholyu **当我将立方体移动到90时,它会在我的电机上达到90°,但如果我将它移动到-10之后,它会向后/向后移动10°**是不是它假设?它应该以负数反向移动,并用正数播放/转发。你有关于你在说什么的视频,因为我现在很困惑。 – Programmer