2015-05-08 13 views
7

Sto provando a leggere la distanza da un sensore a ultrasuoni (HC-SR04) ma gli unici valori che ottengo sono 0 e 265.xx.sensore ultrasonico raspberry pi 2 C# .net

Sto utilizzando un Raspberry Pi 2 con Windows 10 IoT Core installato.

Ho scritto il codice in C#.

Questa è la classe sensore a ultrasuoni:

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

    } 
} 

Ho anche scritto uno script in python per leggere i valori del sensore ad ultrasuoni e quindi funziona, ma in C# non riesco a farlo funzionare.

In fondo si può trovare il registro di debug:

'BACKGROUNDTASKHOST.EXE' (CoreCLR: DefaultDomain): Loaded 'C: \ Program Files \ WindowsApps \ Microsoft.NET.CoreRuntime.1.0_1. 0.22816.1_arm__8wekyb3d8bbwe \ mscorlib.ni.dll'. Simboli di caricamento saltati Il modulo è ottimizzato e l'opzione debugger 'Just My Code' è abilitata. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Utenti \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ RaspiCar.winmd'. Simboli caricati. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.dll'. Simboli di caricamento saltati Il modulo è ottimizzato e l'opzione debugger 'Just My Code' è abilitata. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Utenti \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ WinMetadata \ Windows.winmd'. Il modulo è stato costruito senza simboli. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.InteropServices.WindowsRuntime.dll'. Il modulo è stato costruito senza simboli. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Threading.dll'. Il modulo è stato costruito senza simboli. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Diagnostics.Debug.dll'. Simboli di caricamento saltati Il modulo è ottimizzato e l'opzione debugger 'Just My Code' è abilitata. 'BACKGROUNDTASKHOST.EXE' (CoreCLR: CoreCLR_UAP_Domain): caricato 'C: \ Users \ DefaultAccount \ AppData \ Local \ DevelopmentFiles \ RaspiCarVS.Debug_ARM.chris \ System.Runtime.WindowsRuntime.dll'. Simboli di caricamento saltati Il modulo è ottimizzato e l'opzione debugger 'Just My Code' è abilitata. Distanza: 265.7457 Distanza: 0 Distanza: 0 Distanza: 0 Il programma '[2508] BACKGROUNDTASKHOST.EXE' è terminato con il codice 0 (0x0).

+0

Il DateTime potrebbe non avere la risoluzione necessaria, non ho giocato con il W10 IOT, quindi non so quali sono disponibili (come il cronometro). Hai un o-scope puoi vedere cosa sta effettivamente facendo il sensore? –

+0

'DateTime' di solito non è un buon modo per misurare il tempo: potrebbe essere la risoluzione di questo a causare problemi. Prendi in considerazione l'uso della classe 'StopWatch'. –

risposta

6

Grazie per le reazioni. DateTime era il problema che ora ho usato la classe cronometro e ora funziona. Molte grazie!

La classe operaia:

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

Funziona per te? Non funziona per me e TimeSpan.FromMilliseconds (0,01) restituisce 0 MS. Se esegui TimeSpan.FromTicks (10000/NanosecondsPerTick) attualmente mi dà 19,2 microsecondi – Brent

+0

TimeSpan.FromTicks è indipendente dalla velocità del processore, quindi 1 Tick = 100 nanosecondi. Quindi 10 microsecondi sono: TimeSpan.FromTicks (100); https://msdn.microsoft.com/en-us/library/system.timespan.fromticks(v=vs.110).aspx Tuttavia recupera comunque numeri semi-casuali dal sensore di distanza. – Brent

+0

Ho funzionato un po 'diversamente, potrei postare il codice anche qui, fammi sapere se interessato. – Brent

1

c'è una soluzione migliore in quanto la risposta attualmente proposto a volte blocca durante il recupero della distanza. La versione migliorata del codice, che scade dopo 100 millisecondi (hardcoded). È possibile restituire un valore null o 0.0. Usa il doppio? se vuoi restituire 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

Sembra buono, ho ottenuto la mia versione fino a eseguire ogni 30 ms e timeout dopo 50 ms. – Brent

+0

Ho usato lo stesso codice, sta funzionando bene ma quando ho tenuto l'oggetto vicino a questo sensore costantemente senza lo spostamento non restituisce lo stesso valore per la prossima volta fornirà sempre valore 0.0. – pradeep