2015-05-08 9 views
7

Я пытаюсь прочитать расстояние от ультразвукового датчика (HC-SR04), но единственными значениями, которые я получаю, является 0 и 265.xx.Ультразвуковой датчик малины pi 2 C# .net

Я использую малиновый Pi 2 с установленным IoT Core Windows 10.

Я написал код на C#.

Это ультразвуковой датчик класс:

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; 
     } 

    } 
} 

Я также написал сценарий в питоне, чтобы прочитать значения из ультразвукового датчика, а затем он работает, но в C# я не могу заставить его работать.

В нижней части можно найти в журнале отладки:

'BACKGROUNDTASKHOST.EXE' (CoreCLR: DefaultDomain): Loaded «C: \ Program Files \ WindowsApps \ Microsoft.NET.CoreRuntime.1.0_1. 0.22816.1_arm__8wekyb3d8bbwe \ mscorlib.ni.dll. Пропущенные символы загрузки. Модуль оптимизирован и включен параметр отладчика «Только мой код». 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ RaspiCar.winmd'. Загружены символы. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.dll'. Пропущенные символы загрузки. Модуль оптимизирован и включен параметр отладчика «Только мой код». 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ WinMetadata \ Windows.winmd'. Модуль был построен без символов. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.InteropServices.WindowsRuntime.dll'. Модуль был построен без символов. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Threading.dll'. Модуль был построен без символов. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Diagnostics.Debug.dll'. Пропущенные символы загрузки. Модуль оптимизирован и включен параметр отладчика «Только мой код». 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): загружен 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.WindowsRuntime.dll'. Пропущенные символы загрузки. Модуль оптимизирован и включен параметр отладчика «Только мой код». Расстояние: 265.7457 Расстояние: 0 Расстояние: 0 Расстояние: 0 Программа '[2508] BACKGROUNDTASKHOST.EXE' вышла с кодом 0 (0x0).

+0

У DateTime может не быть необходимого разрешения, я не играл с W10 IOT, поэтому я не знаю, что доступно (например, секундомер). У вас есть o-scope, вы можете видеть, что на самом деле делает датчик? –

+0

'DateTime' обычно не является хорошим способом измерения времени - это может быть разрешение этого, что вызывает у вас проблемы. Вместо этого рассмотрите использование класса «StopWatch». –

ответ

6

Спасибо за реакцию. Проблема DateTime заключалась в том, что теперь я использовал класс секундомера, и теперь он работает. Большое спасибо!

Рабочий класс:

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

Это работает для вас? Не работает для меня и TimeSpan.FromMilliseconds (0.01) возвращает 0 MS. Если вы делаете TimeSpan.FromTicks (10000/NanosecondsPerTick), он в настоящее время дает мне 19.2microseconds – Brent

+0

TimeSpan.FromTicks не зависит от скорости процессора, поэтому 1 Tick = 100 наносекунд. Поэтому 10 микросекунд: TimeSpan.FromTicks (100); https://msdn.microsoft.com/en-us/library/system.timespan.fromticks(v=vs.110).aspx Тем не менее все-таки получить полуслучайные числа от датчика расстояния. – Brent

+0

Я получил это немного по-другому, я также могу написать код здесь, дайте мне знать, если вы заинтересованы. – Brent

1

Существует лучшее решение, как предлагаемый в настоящее время ответ будет время от времени блокировки при получении расстояния. Улучшенная версия кода, которая истекает через 100 миллисекунд (жестко закодированная). Вы можете вернуть null или 0.0. Использовать двойной? если вы хотите вернуть 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

Выглядит неплохо, я получил свою версию до 30 мс и таймаута после 50 мс. – Brent

+0

Я использовал тот же код, он работает нормально, но когда я постоянно держу объект рядом с этим датчиком, не двигаясь, он не возвращает такое же значение в следующий раз, он всегда будет давать значение 0.0. – pradeep