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