In this small guide I will demonstrate how to integrate Riotboard with Ultrasonic sensor HC-SR04 .
Step1:
export ARCH & CROSS_COMPILE to environment path.
in my case its like below, yours might be different.
$ export ARCH=arm
$ export CROSS_COMPILE=<PATH_TO_TOOLCHAIN>/fsl-linaro-toolchain/bin/arm-fsl-linux-gnueabi-
Step2:
create a directory
$ mkdir driver
create a file named "Makefile" and replace with your KDIR value, below is mine.
obj-m := sr04.o
KDIR := /home/tushar/riot_github/kernel_out/lib/modules/3.0.35-02887-g731b440/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
next we will create the driver for sr04 module, create file "sr04.c" with below contents in it.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/interrupt.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("HC-SR04 ultrasonic sensor");
#define HCSR04_ECHO 113
#define HCSR04_TRIGGER 112
static int gpio_irq=-1;
static int valid_value = 0;
static ktime_t echo_start;
static ktime_t echo_end;
// write to "/sys/class/hcsr04/value"
static ssize_t hcsr04_value_write(struct class *class, struct class_attribute *attr, const char *buf, size_t len)
{
printk(KERN_INFO "Buffer len %d bytes\n", len);
return len;
}
// read from "/sys/class/hcsr04/value"
static ssize_t hcsr04_value_read(struct class *class, struct class_attribute *attr, char *buf)
{
int counter;
gpio_set_value(HCSR04_TRIGGER,1);
udelay(10);
gpio_set_value(HCSR04_TRIGGER,0);
valid_value=0;
counter=0;
while (valid_value==0) {
if (++counter>23200) {
return sprintf(buf, "%d\n", -1);;
}
udelay(1);
}
return sprintf(buf, "%lld\n", ktime_to_us(ktime_sub(echo_end,echo_start)));;
}
// Sysfs definitions for hcsr04 class
static struct class_attribute hcsr04_class_attrs[] = {
__ATTR(value, S_IRUGO | S_IWUSR, hcsr04_value_read, hcsr04_value_write),
__ATTR_NULL,
};
// Name of directory created in /sys/class
static struct class hcsr04_class = {
.name = "hcsr04",
.owner = THIS_MODULE,
.class_attrs = hcsr04_class_attrs,
};
// Interrupt handler on ECHO signal
static irqreturn_t gpio_isr(int irq, void *data)
{
ktime_t ktime_dummy;
if (valid_value==0) {
ktime_dummy=ktime_get();
if (gpio_get_value(HCSR04_ECHO)==1) {
echo_start=ktime_dummy;
} else {
echo_end=ktime_dummy;
valid_value=1;
}
}
return IRQ_HANDLED;
}
static int hcsr04_init(void)
{
int rtc;
printk(KERN_INFO "HC-SR04 driver init...\n");
if (class_register(&hcsr04_class)<0) goto fail;
rtc=gpio_request(HCSR04_TRIGGER,"TRIGGER");
if (rtc!=0) {
printk(KERN_INFO "Error %d\n",__LINE__);
goto fail;
}
rtc=gpio_request(HCSR04_ECHO,"ECHO");
if (rtc!=0) {
printk(KERN_INFO "Error %d\n",__LINE__);
goto fail;
}
rtc=gpio_direction_output(HCSR04_TRIGGER,0);
if (rtc!=0) {
printk(KERN_INFO "Error %d\n",__LINE__);
goto fail;
}
rtc=gpio_direction_input(HCSR04_ECHO);
if (rtc!=0) {
printk(KERN_INFO "Error %d\n",__LINE__);
goto fail;
}
rtc=gpio_to_irq(HCSR04_ECHO);
if (rtc<0) {
printk(KERN_INFO "Error %d\n",__LINE__);
goto fail;
} else {
gpio_irq=rtc;
}
rtc = request_irq(gpio_irq, gpio_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_DISABLED , "hc-sr04.trigger", NULL);
if(rtc) {
printk(KERN_ERR "Unable to request IRQ: %d\n", rtc);
goto fail;
}
return 0;
fail:
return -1;
}
static void hcsr04_exit(void)
{
if (gpio_irq!=-1) {
free_irq(gpio_irq, NULL);
}
gpio_free(HCSR04_TRIGGER);
gpio_free(HCSR04_ECHO);
class_unregister(&hcsr04_class);
printk(KERN_INFO "HC-SR04 disabled.\n");
}
module_init(hcsr04_init);
module_exit(hcsr04_exit);
Now hit "make" command to compile the above driver.
Step3:
connect the Vcc pin in hc-sr04 to Pin2 in J13.
connect the Trig pin in hc-sr04 to Pin5 in J13.
connect the Echo pin in hc-sr04 to Pin6 in J13.
connect the Gnd pin in hc-sr04 to Pin4 in J13.
Now copy the compiled sr04.ko to /opt/ in riotboard.
Next insert the compiled module using insmod:
insmod sr04.ko
Now configure the Trigger & Echo for gpio in Riotboard terminal:
devmem 0x20E009C w 0x5
devmem 0x20E00A0 w 0x5
Prepare sr04 for capturing values:
Export the gpio pins
echo 112 > /sys/class/gpio/export
echo 113 > /sys/class/gpio/export
Set the Direction
echo out > /sys/class/gpio/gpio112/direction
echo 1 > /sys/class/gpio/gpio112/value
To view the sonar values , hit below command
cat /sys/class/hcsr04/value
Step4:
To continuously view values & object distance in cm i wrote a small python script.
create a file "sr04_distance.py" in riotboard terminal with below contents:
#!/usr/bin/python
f = open("/sys/class/hcsr04/value",'r')
d=f.read()
f.close()
if (long(d)==-1):
print "N.A."
else:
print "%.1f cm" % (float(d)/58)
With all connections ready, run the sr04_distance.py script:
$ python sr04_distance.py
The sonar will display values as objects encountered in its way .
Note: during module testing if found this hc-sr04 module range is max 3 metres.
That's all.
Thanks
Tushar
