2015-05-08 14 views
7

Próbuję odczytać odległość od czujnika ultradźwiękowego (HC-SR04), ale jedyne wartości, które otrzymuję to 0 i 265.xx.czujnik ultradźwiękowy raspberry pi 2 C# .net

Używam Raspberry Pi 2 z zainstalowanym Core 10 IoT Core.

Napisałem kod w języku C#.

Jest to czujnik ultradźwiękowy klasa:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Diagnostics; 
using Windows.Devices.Gpio; 

namespace RaspberryPi 
{ 
    class UcSensor 
    { 
     GpioController gpio = GpioController.GetDefault(); 

     GpioPin TriggerPin; 
     GpioPin EchoPin; 

     //Contructor 
     public UcSensor(int TriggerPin, int EchoPin) 
     { 
      //Setting up gpio pin's 
      this.TriggerPin = gpio.OpenPin(TriggerPin); 
      this.EchoPin = gpio.OpenPin(EchoPin); 

      this.TriggerPin.SetDriveMode(GpioPinDriveMode.Output); 
      this.EchoPin.SetDriveMode(GpioPinDriveMode.Input); 

      this.TriggerPin.Write(GpioPinValue.Low); 
     } 

     public double GetDistance() 
     { 
      ManualResetEvent mre = new ManualResetEvent(false); 
      mre.WaitOne(500); 

      //Send pulse 
      this.TriggerPin.Write(GpioPinValue.High); 
      mre.WaitOne(TimeSpan.FromMilliseconds(0.01)); 
      this.TriggerPin.Write(GpioPinValue.Low); 

      //Recieve pusle 
      while (this.EchoPin.Read() == GpioPinValue.Low) 
      { 
      } 
      DateTime start = DateTime.Now; 

      while (this.EchoPin.Read() == GpioPinValue.High) 
      { 
      } 
      DateTime stop = DateTime.Now; 

      //Calculating distance 
      double timeBetween = (stop - start).TotalSeconds; 
      double distance = timeBetween * 17000; 

      return distance; 
     } 

    } 
} 

Ja również napisałem skrypt w Pythonie do odczytu wartości z czujnika ultradźwiękowego i to działa, ale w C# nie mogę dostać pracy.

Na dole znajdziesz dziennik debugowania:

'BACKGROUNDTASKHOST.EXE' (CoreCLR: defaultdomain): Loaded „C: \ Program Files \ WindowsApps \ Microsoft.NET.CoreRuntime.1.0_1. 0.22816.1_arm__8wekyb3d8bbwe \ mscorlib.ni.dll ". Pominięto symbole ładowania. Moduł jest zoptymalizowany, a opcja debuggera "Just My Code" jest włączona. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowany "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ RaspiCar.winmd". Wczytywane symbole. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowano "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.dll". Pominięto symbole ładowania. Moduł jest zoptymalizowany, a opcja debuggera "Just My Code" jest włączona. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowano "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ WinMetadata \ Windows.winmd". Moduł został zbudowany bez symboli. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowano "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.InteropServices.WindowsRuntime.dll". Moduł został zbudowany bez symboli. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowano "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Threading.dll". Moduł został zbudowany bez symboli. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowano "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Diagnostics.Debug.dll". Pominięto symbole ładowania. Moduł jest zoptymalizowany, a opcja debuggera "Just My Code" jest włączona. "BACKGROUNDTASKHOST.EXE" (CoreCLR: CoreCLR_UAP_Domain): Załadowano "C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.WindowsRuntime.dll". Pominięto symbole ładowania. Moduł jest zoptymalizowany, a opcja debuggera "Just My Code" jest włączona. Odległość: 265.7457 Odległość: 0 Odległość: 0 Odległość: 0 Program "[2508] BACKGROUNDTASKHOST.EXE" zakończył się kodem 0 (0x0).

+0

Czas może nie mieć wymaganej rozdzielczości, nie grałem z IOT W10, więc nie wiem, co jest dostępne (np. Stoper). Czy masz o-zakres, możesz zobaczyć, co czujnik faktycznie robi? –

+0

'DateTime' zwykle nie jest dobrym sposobem na pomiar czasu - może to być rozwiązanie tego problemu, który powoduje problemy. Rozważ użycie klasy 'StopWatch'. –

Odpowiedz

6

Dzięki za reakcje. DateTime było problemem, z którego korzystałem teraz z klasy stopera, a teraz działa. Wielkie dzięki!

Klasa robotnicza:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Diagnostics; 
using Windows.Devices.Gpio; 

namespace RaspberryPi 
{ 
    class UcSensor 
    { 
     GpioController gpio = GpioController.GetDefault(); 

     GpioPin TriggerPin; 
     GpioPin EchoPin; 

     public UcSensor(int TriggerPin, int EchoPin) 
     { 
      this.TriggerPin = gpio.OpenPin(TriggerPin); 
      this.EchoPin = gpio.OpenPin(EchoPin); 

      this.TriggerPin.SetDriveMode(GpioPinDriveMode.Output); 
      this.EchoPin.SetDriveMode(GpioPinDriveMode.Input); 

      this.TriggerPin.Write(GpioPinValue.Low); 
     } 

     public double GetDistance() 
     { 
      ManualResetEvent mre = new ManualResetEvent(false); 
      mre.WaitOne(500); 
      Stopwatch pulseLength = new Stopwatch(); 

      //Send pulse 
      this.TriggerPin.Write(GpioPinValue.High); 
      mre.WaitOne(TimeSpan.FromMilliseconds(0.01)); 
      this.TriggerPin.Write(GpioPinValue.Low); 

      //Recieve pusle 
      while (this.EchoPin.Read() == GpioPinValue.Low) 
      { 
      } 
      pulseLength.Start(); 


      while (this.EchoPin.Read() == GpioPinValue.High) 
      { 
      } 
      pulseLength.Stop(); 

      //Calculating distance 
      TimeSpan timeBetween = pulseLength.Elapsed; 
      Debug.WriteLine(timeBetween.ToString()); 
      double distance = timeBetween.TotalSeconds * 17000; 

      return distance; 
     } 

    } 
} 
+0

Czy to działa dla Ciebie? Nie działa dla mnie i TimeSpan.FromMilliseconds (0.01) zwraca 0 MS. Jeśli wykonujesz TimeSpan.FromTicks (10000/NanosecondsPerTick), to obecnie daje mi 19,2 milisekundy. – Brent

+0

TimeSpan.FromTicks jest niezależny od prędkości procesora, więc 1 Tick = 100 Nanosekund. Dlatego 10 mikrosekund to: TimeSpan.FromTicks (100); https://msdn.microsoft.com/en-us/library/system.timespan.fromticks(v=vs.110).aspx Nadal wracają pół-losowe liczby z czujnika odległości. – Brent

+0

Rozumiem, że działa to trochę inaczej, mogę też zamieścić tutaj kod, daj mi znać, jeśli jesteś zainteresowany. – Brent

1

Jest lepsze rozwiązanie, ponieważ obecnie proponowanym odpowiedź będzie od czasu do czasu zablokowania podczas uzyskiwania odległość. Ulepszona wersja kodu, która kończy się po 100 milisekundach (na stałe). Możesz zwrócić wartość zerową lub 0.0. Użyj podwójnie? jeśli chcesz zwrócić wartość null.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using Windows.Devices.Gpio; 

namespace MTP.IoT.Devices.Sensors 
{ 
public class HCSR04 
{ 
    private GpioPin triggerPin { get; set; } 
    private GpioPin echoPin { get; set; } 
    private Stopwatch timeWatcher; 

    public HCSR04(int triggerPin, int echoPin) 
    { 
     GpioController controller = GpioController.GetDefault(); 
     timeWatcher = new Stopwatch(); 
     //initialize trigger pin. 
     this.triggerPin = controller.OpenPin(triggerPin); 
     this.triggerPin.SetDriveMode(GpioPinDriveMode.Output); 
     this.triggerPin.Write(GpioPinValue.Low); 
     //initialize echo pin. 
     this.echoPin = controller.OpenPin(echoPin); 
     this.echoPin.SetDriveMode(GpioPinDriveMode.Input); 
    } 

    public double GetDistance() 
    { 
     ManualResetEvent mre = new ManualResetEvent(false); 
     mre.WaitOne(500); 
     timeWatcher.Reset(); 
     //Send pulse 
     this.triggerPin.Write(GpioPinValue.High); 
     mre.WaitOne(TimeSpan.FromMilliseconds(0.01)); 
     this.triggerPin.Write(GpioPinValue.Low); 
     return this.PulseIn(echoPin, GpioPinValue.High);   
    } 

    private double PulseIn(GpioPin echoPin, GpioPinValue value) 
    { 
     var t = Task.Run(() => 
     { 
      //Recieve pusle 
      while (this.echoPin.Read() != value) 
      { 
      } 
      timeWatcher.Start(); 

      while (this.echoPin.Read() == value) 
      { 
      } 
      timeWatcher.Stop(); 
      //Calculating distance 
      double distance = timeWatcher.Elapsed.TotalSeconds * 17000; 
      return distance; 
     }); 
     bool didComplete = t.Wait(TimeSpan.FromMilliseconds(100)); 
     if(didComplete) 
     { 
      return t.Result; 
     } 
     else 
     { 
      return 0.0;     
     } 
    } 

} 
} 
+0

Wygląda dobrze, moja wersja została uruchomiona co 30ms i timeout po 50 ms. – Brent

+0

Użyłem tego samego kodu, działa dobrze, ale kiedy trzymałem obiekt blisko tego czujnika bez przerwy, nie zwraca tej samej wartości dla następnego razu, zawsze da wartość 0.0. – pradeep

Powiązane problemy