现在电用电器是必不可少的,因此,电就变成了必需品,但是在用电的过程中带来方便的同时也隐藏着巨大的危险。现在在网上看到很多排插都具备了保护功能,比如,漏电保护,定时开关等。所以打算用dragonboard 410c也做一个智能开关,首先要做的是硬件选择。
主控制器就是dragonboard 410c,这里就不过多的介绍了。接下来就是如何安全的控制排差供电的通断了,最简单的就是继电器了,它的好处就是可以用很小的电压、电流通路来控制很高的电压、电流通路。继电器有很多种,最常见的是电磁继电器和固态继电器。
电磁继电器是利用电磁铁来控制电路通断的开关,不同型号的电磁继电器功能也不同,可以是直流控直流,直流空交流,交流控直流,交流控交流。但是因为有机械触点,所以易损坏,但是价格便宜。
图1 继电器 图2 继电器工作原理图
固态继电器是由微电子电路,分立电子器件,电力电子功率器件组成的无触电开关。微小控制信号就可以直接驱动大电流负载。价格比较贵,一般用在工业,医疗,消防等。
图3 固态继电器 图4 固态继电器工作原理图
因为固态继电器价格稍高一些,固态继电器的价格相对来说比较低,并且固态继电器已经可以满足对220v的控制了,所以选用的固态继电器。
最后就是一个排插了,用的普通排插。
图5 排插
其主要工作原理和功能:
将dragonboard 410c连接网络,手机端也连接到网络。当我们不在家时可以查看排查的工作状态,如果家里没人也在工作,并且没有像冰箱这种不可以断电的电器连接在上面,我们就可以通过手机端将其断电,以确保用电安全和节约。
软件上主要实现有两部分,一部分是底层的继电器驱动,另一部分是上层的apk。底层驱动比较简单,如下:
struct relay_data{
int pin;
int d;
struct mutex data_lock;
};
static int parse_dt(struct platform_device* pdev,struct relay_data* data){
int rc;
struct device_node* node = pdev->dev.of_node;
data->pin = of_get_named_gpio(node,"thunder,gpio",0);
if(gpio_is_valid(data->pin)){
rc = gpio_request(data->pin,"relay_pin");
if(rc < 0){
pr_err("Unable to request pin gpio\n");
}
gpio_direction_output(data->pin, 1);
data->d = '1';
}
return 0;
}
static ssize_t relay_store_value(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size){
struct relay_data* data = dev_get_drvdata(dev);
if(buf[0] == '1'){
gpio_set_value(data->pin, 1);
}else{
gpio_set_value(data->pin, 0);
}
data->d = buf[0];
dump_stack();
return size;
}
static ssize_t relay_show_value(struct device *dev,
struct device_attribute* attr,char* buf){
struct relay_data* data = dev_get_drvdata(dev);
ssize_t da;
mutex_lock(&data->data_lock);
da = sprintf(buf, "%c", data->d);
mutex_unlock(&data->data_lock);
printk("show buf=%c\n", *buf);
dump_stack();
return da;
}
static DEVICE_ATTR(value,0666,relay_show_value,relay_store_value);
static int relay_probe(struct platform_device *pdev){
struct relay_data* data;
int result;
data = kmalloc(sizeof(struct relay_data),GFP_KERNEL);
if(!data){
pr_err("%s kmalloc error\n",__FUNCTION__);
return -ENOMEM;
}
dev_set_drvdata(&pdev->dev,data);
result = parse_dt(pdev,data);
if(result<0){
pr_err("%s error when parse dt\n",__FUNCTION__);
result = -EINVAL;
goto err_parse_dt;
}
mutex_init(&data->data_lock);
result=sysfs_create_file(&pdev->dev.kobj,&dev_attr_value.attr);
printk("relay probe success\n");
return 0;
err_parse_dt:
kfree(data);
printk("relay probe failed\n");
return result;
}
static int relay_remove(struct platform_device *pdev){
return 0;
}
static struct of_device_id relay_match_table[] = {
{ .compatible = "thunder,relay",},
{ },
};
static struct platform_driver relay_driver = {
.probe = relay_probe,
.remove = relay_remove,
.driver = {
.owner = THIS_MODULE,
.name = "relay",
.of_match_table = relay_match_table,
},
};
module_platform_driver(relay_driver);
MODULE_AUTHOR("RELAY");
MODULE_LICENSE("GPL v2");
到这里底层驱动就完成了,接下来就是上层apk的实现了,也比较简单,这里就不介绍了。