Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[driver] Add driver for Ultrasonic ranging module #47

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ include ':tm1637'
include ':ssd1306'
include ':rainbowhat'
include ':sensehat'
include ':ultrasonic-sensor'

include ':testingutils'
1 change: 1 addition & 0 deletions ultrasonic-sensor/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
57 changes: 57 additions & 0 deletions ultrasonic-sensor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Ultrasonic Ranging Module driver for Android Things
===================================================

This driver is to get proximity of the object using HC-SR04.

How to use the driver
---------------------

### Gradle dependency

To use the `ultrasonic-sensor` driver, simply add the line below to your project's `build.gradle`,
where `<version>` matches the last version of the driver available on [jcenter][jcenter].

```
dependencies {
compile 'com.google.android.things.contrib:ultrasonic-sensor:<version>'
}
```
### Sample usage

Use the `UltrasonicSensorDriver` class to easily get the distance using HC-SR04.
```java
import com.google.android.things.contrib.driver.ultrasonicsensor.DistanceListener;
import com.google.android.things.contrib.driver.ultrasonicsensor.UltrasonicSensorDriver;

//Initialize the driver and start ranging
private UltrasonicSensorDriver mUltrasonicSensorDriver;

//Set trigger and echo pin and also distance listner
mUltrasonicSensorDriver = new UltrasonicSensorDriver(BoardDefaults.getGPIOForTrig(),
BoardDefaults.getGPIOForEcho(),
new DistanceListener() {
@Override
public void onDistanceChange(double distanceInCm) {
Log.d("Distance", distanceInCm + " cm");
}
});

// Close the sensor when finish:
try {
mUltrasonicSensorDriver.close();
} catch (Exception e) {
e.printStackTrace();
}
```



License
-------
Copyright 2016 Google Inc.

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
20 changes: 20 additions & 0 deletions ultrasonic-sensor/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apply plugin: 'com.android.library'

android {
android {
compileSdkVersion 24
buildToolsVersion '24.0.3'

defaultConfig {
minSdkVersion 24
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
}
}

dependencies {
provided 'com.google.android.things:androidthings:0.3-devpreview'
compile 'com.android.support:support-annotations:24.2.0'
}
25 changes: 25 additions & 0 deletions ultrasonic-sensor/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\Keval\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
1 change: 1 addition & 0 deletions ultrasonic-sensor/publish-settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.buildFileName = '../publish.gradle'
21 changes: 21 additions & 0 deletions ultrasonic-sensor/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.things.contrib.driver.ultrasonicsensor">

<application>
<uses-library android:name="com.google.android.things"/>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.things.contrib.driver.ultrasonicsensor;

/**
* Callback listener to get notified when distance changes.
*/

public interface DistanceListener {

/**
* @param distanceInCm Distance of the object from ranging module in centimeter.
*/
void onDistanceChange(double distanceInCm);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*
* Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.android.things.contrib.driver.ultrasonicsensor;

import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;

import com.google.android.things.pio.Gpio;
import com.google.android.things.pio.GpioCallback;
import com.google.android.things.pio.PeripheralManagerService;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
* This is the driver class for Ultrasonic distance measurement sensor - HC-SR04.
* This class uses different threads to send pulses to trigger pin and get the echo pulses. This threads
* are other than main thread. This is to increase the time accuracy for echo pulses by doing
* simultaneous tasks.
*
* @author Keval {https://github.com/kevalpatel2106}
*/

public final class UltrasonicSensorDriver implements AutoCloseable {
private static final int INTERVAL_BETWEEN_TRIGGERS = 500; //Interval between two subsequent pulses

private final DistanceListener mListener; //Listener to get call back when distance changes

private Gpio mEchoPin; //GPIO for echo
private Gpio mTrigger; //GPIO for trigger
private Handler mTriggerHandler; //Handler for trigger.

/**
* Runnable to send trigger pulses.
*/
private Runnable mTriggerRunnable = new Runnable() {
@Override
public void run() {
try {
sendTriggerPulse();
mTriggerHandler.postDelayed(mTriggerRunnable, INTERVAL_BETWEEN_TRIGGERS);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
};

/**
* Callback for {@link #mEchoPin}. This callback will be called on both edges.
*/
private GpioCallback mEchoCallback = new GpioCallback() {
private long mPulseStartTime;

@Override
public boolean onGpioEdge(Gpio gpio) {
try {
if (gpio.getValue()) {
mPulseStartTime = System.nanoTime();
} else {
//Calculate distance.
//From data-sheet (https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf)
double distance = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - mPulseStartTime) / 58.23; //cm

//Notify callback
if (mListener != null) mListener.onDistanceChange(distance);
}
} catch (IOException e) {
e.printStackTrace();
}
return true;
}

@Override
public void onGpioError(Gpio gpio, int error) {
super.onGpioError(gpio, error);
}
};

/**
* Public constructor.
*
* @param triggerPin Name of the trigger pin
* @param echoPin Name of the echo pin
* @param listener {@link DistanceListener} to get callbacks when distance changes.
*/
public UltrasonicSensorDriver(@NonNull String triggerPin, @NonNull String echoPin, DistanceListener listener) {
PeripheralManagerService service = new PeripheralManagerService();

try {
setTriggerPin(service, triggerPin);
setEchoPin(service, echoPin);
} catch (IOException e) {
e.printStackTrace();
throw new IllegalArgumentException("Invalid pin name.");
}

//Set callback listener.
mListener = listener;
if (mListener == null)
throw new IllegalArgumentException("DistanceListener cannot be null.");

//Start sending pulses
//We are using different thread for sending pulses to increase time accuracy.
HandlerThread triggerHandlerThread = new HandlerThread("TriggerHandlerThread");
triggerHandlerThread.start();
mTriggerHandler = new Handler(triggerHandlerThread.getLooper());
mTriggerHandler.post(mTriggerRunnable);
}

/**
* Set the trigger pin
*
* @param service {@link PeripheralManagerService}.
* @param triggerPin Name of the trigger pin.
* @throws IOException If pin initialization fails.
*/
private void setTriggerPin(PeripheralManagerService service, String triggerPin) throws IOException {
mTrigger = service.openGpio(triggerPin);
mTrigger.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
}

/**
* Set the echo pin
*
* @param service {@link PeripheralManagerService}.
* @param echoPin Name of the echo pin.
* @throws IOException If pin initialization fails.
*/
private void setEchoPin(PeripheralManagerService service, String echoPin) throws IOException {
mEchoPin = service.openGpio(echoPin);
mEchoPin.setDirection(Gpio.DIRECTION_IN);
mEchoPin.setEdgeTriggerType(Gpio.EDGE_BOTH);
mEchoPin.setActiveType(Gpio.ACTIVE_HIGH);

// Prepare handler for GPIO callback
HandlerThread handlerThread = new HandlerThread("EchoCallbackHandlerThread");
handlerThread.start();
mEchoPin.registerGpioCallback(mEchoCallback, new Handler(handlerThread.getLooper()));
}

/**
* Fire trigger pulse for 10 micro seconds.
*/
private void sendTriggerPulse() throws IOException, InterruptedException {
//Resetting trigger
mTrigger.setValue(false);
Thread.sleep(0, 2000);

//Set trigger pin for 10 micro seconds.
mTrigger.setValue(true);
Thread.sleep(0, 10000);

// Reset the trigger after 10 micro seconds.
mTrigger.setValue(false);
}

@Override
public void close() throws Exception {
try {
mEchoPin.unregisterGpioCallback(mEchoCallback);
mEchoPin.close();
mTrigger.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}