Fork me on GitHub

Raspberry Pi GPIO的编号规范 2013-03-22

树莓派和普通电脑不一样的地方在于它还带了17个可编程的GPIO(General Purpose Input/Output),可以用来驱动各种外设(如传感器,步进电机等)。但GPIO的编号方法有些混乱,不同的API(如wiringPi,RPi.GPIO等)对GPIO的端口号编号并不一样,下面则用图表标明了对应的叫法,这样在看程序例子的时候可以确定物理是哪个接口。

GPIO库

  1. wiringPi C,有Perl, PHP, Ruby, Node.JS和Golang的扩展,支持wiringPi Pin和BCM GPIO两种编号
  2. RPi.GPIO Python,支持Board Pin和BCM GPIO两种编号
  3. Webiopi,Python, 使用BCM GPIO编号
  4. WiringPi-Go, Go语言,支持以上三种编号

编号规范

  1. 第一列是wiringPi API中的缺省编号,wiringPiSetup()采用这列编号
  2. 第二列(Name)往往是转接板的编号
  3. 第三列是树莓派板子上的自然编号(左边引脚为1-15,右边引脚为2-26),RPi.GPIO.setmode(GPIO.BOARD)采用这列编号
  4. 树莓派主芯片提供商Broadcom的编号方法,相当于调用了WiringPiSetupGpio()RPi.GPIO.setmode(GPIO.BCM)采用这列编号
wiringPi Pin Name Board Pin BCM GPIO
0 GPIO 0 11 17
1 GPIO 1 12 18
2 GPIO 2 13 21
3 GPIO 3 15 22
4 GPIO 4 16 23
5 GPIO 5 18 24
6 GPIO 6 22 25
7 GPIO 7 7 4
8 SDA 3 0
9 SCL 5 1
10 CE0 24 8
11 CE1 26 7
12 MOSI 19 10
13 MISO 21 9
14 SCLK 23 11
15 TXD 8 14
16 RXD 10 15

如何使用Raspberry Pi测量室内温度和湿度并绘制曲线 2013-03-17

硬件准备

需要以下硬件:

  1. 可以工作的树莓派一个
  2. 面包板公对母杜邦线
  3. 10K 电位器一个
  4. DHT11温度和湿度传感器一个或DHT22

传感器电路及原理

DHT11传感器外观

参数

如何使用Raspberry Pi控制步进电机旋转高清摄像头并拍照 2013-03-16

硬件准备

需要以下硬件:

  1. 可以工作的树莓派一个
  2. 母对母1P杜邦线6根
  3. DC 5V4相28YBJ-48步进电机一个
  4. UL2003芯片步进电机驱动板一块

安装

按下图将步进电机接到驱动板上,也就是白色的接口

如何在Raspberry Pi上用LED闪烁提示网站首页新访客 2013-03-13

本方法只适合小网站,主要是好玩。Raspberry Pi不是很合适需要实时控制的系统(比如,飞行器,遥控小车),因为Linux内核要多任务,应用程序的优先级不能保持最高,会带来延时,但做些实时性要求不高的系统还是可以的。

硬件安装

需要以下硬件:

  1. 可以工作的树莓派一个
  2. 1P杜邦线2条
  3. 面包板一个
  4. 面包板跳线单排针 两根
  5. 发光二极管一个
  6. 300欧姆的电阻一个

GPIO接口

用杜邦线将上图的3.3V输出和GPIO 23引出(板子正面朝上,GPIO引脚在左上角),将电阻和LED串联起来(电阻防止LED电流过大烧掉),注意二极管的两根脚不一样长,长脚的接正级,这样GPIO 23如果输出高电平,二极管就不发光了,输出低电平就亮啦!

在Raspberry Pi上安装ArchLinux 2013-03-09

介绍

之前买的Raspberry Pi因为要跑这个网站,不能经常拔下来玩别的,所以又买了一个,这次安装的是Arch Linux。这个发行版安装好后非常基础,占用的空间也只有600M不到,比较合适已有Linux基础的同学玩。初学者可以玩官方推荐的Raspbian

Arch Linux特点:

  1. 启动快,上电后只要3s完成启动
  2. 安装完没有图形界面,干净
  3. 面向开发者的系统
  4. 包管理系统pacman很好用,一个命令就可以完成各种操作
  5. ArchLinux缺省账号和密码是root/root,弄好了后要记得修改root密码
  6. 从中国用下载包很快,比Raspbian的源快多了

增加sudo用户

   useradd hugo
   passwd hugo
   mkdir /home/hugo
   chown hugo:hugo /home/hugo   
   pacman -S sudo
   visudo   
   

如何封杀尝试Raspberry Pi SSH密码的来源IP 2013-03-08

Raspberry Pi整天开着,如果用缺省SSH端口对外开放,就会经常遇到扫描SSH密码的肉鸡。虽然密码不是很简单,但还是感觉很不安全的。

系统的ssh登录日志文件在:/var/log/auth.log,登录失败时会记录以下格式的日志:

Mar  7 10:31:51 raspberrypi sshd[24510]: Failed password for root from 221.8.19.129 port 4066 ssh2
Mar  7 10:31:55 raspberrypi sshd[24514]: Failed password for root from 221.8.19.129 port 4079 ssh2
Mar  7 10:31:56 raspberrypi sshd[24518]: Failed password for sshd from 221.8.19.129 port 4080 ssh2
Mar  7 10:32:26 raspberrypi sshd[24522]: Failed password for sshd from 221.8.19.129 port 4149 ssh2

用最简单的Shell脚本来解决这个问题:

guard.sh

#!/bin/bash

last_ip=""
tail -f /var/log/auth | while read LINE; do
{
    if [[ "${LINE}" =~ "Failed" ]]; then            
        ip="$(echo ${LINE} | awk '{print $(NF-3)}')"
        if [[ "$last_ip" == "$ip" ]]; then
             echo "block $ip"
             #curl -s --data-ascii "uuid=<my iphone's uuid>" --data "body=${LINE}" http://raspberrypi/pushme                 
             iptables -A INPUT -s "$ip" -j DROP
        fi
        last_ip=$ip
        echo $LINE
    fi
}
done

Raspberry Pi做BT下载机+高清播放器 2013-03-06

介绍

首先高清播放器功能只是Raspberry Pi的一个小功能,如果你只需要高清播放功能又不想折腾,那还是买个山寨的的更简单。。。

Raspberry Pi的图形处理器规格:Broadcom VideoCore IV, OpenGL ES 2.0, 1080p 30 h.264/MPEG-4 AVC 高清解码器,内存和CPU共享(可设置成256M),性能还是很强劲的。HDMI支持640x350和1920×1200(1080P)的分辨率。安装了XBMC,基本上可以实现包括Airplay在内的Apple TV上的大部分功能,但价格只有其一半不到,可以播放下载的视频或观看在线视频,如一搜,优酷,搜狐视频,奇艺等。

外设

除了Pi单片机外,你还需要以下外设附件:

  1. 5V-1A左右的电源,可以用iPhone或iPad的充电电源,或手机的充电器,电流最少要800毫安
  2. micro USB线一根,和Kindle以及大多数android手机充电USB线一样
  3. HDMI线一根,接电视机
  4. SD卡一张,最少2G

Raspbmc

Raspbmc 是专为在Raspberry Pi上运行XBMC的定制Linux。最小化的安装,减少了不必要的软件和资源占用,简化了安装和配置,没有Linux知识也可以上手。这个版本的维护者是一个19岁的小朋友Sam Nazarko。有时间折腾的同学可以自己编译XMBC安装。

特点:

  1. 免费,开源
  2. 支持多语言
  3. 支持1080P回放
  4. 支持直接播放NFS,SMB,FTP,HTTP或USB硬盘的有视频文件,支持大多数格式
  5. 支持AirPlay或AirTune功能,可以把iPhone/iPad上的视频或音乐通过Pi投放到电视上,这点和Apple TV功能一样
  6. 支持GPIO
  7. 基于Debian,可以从Debian的软件源安装其它软件
  8. 支持1080P DTS软解,这个不少播放器是不支持的,需要额外License
  9. 内置了以下服务:
    1. Samba
    2. TVHeadend Server
    3. FTP Server
    4. SSH Server

Java并发包中的同步队列SynchronousQueue实现原理 2013-03-05

介绍

Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样。

不像ArrayBlockingQueue或LinkedListBlockingQueue,SynchronousQueue内部并没有数据缓存空间,你不能调用peek()方法来看队列中是否有数据元素,因为数据元素只有当你试着取走的时候才可能存在,不取走而只想偷窥一下是不行的,当然遍历这个队列的操作也是不允许的。队列头元素是第一个排队要插入数据的线程,而不是要交换的数据。数据是在配对的生产者和消费者线程之间直接传递的,并不会将数据缓冲数据到队列中。可以这样来理解:生产者和消费者互相等待对方,握手,然后一起离开。

SynchronousQueue的一个使用场景是在线程池里。Executors.newCachedThreadPool()就使用了SynchronousQueue,这个线程池根据需要(新任务到来时)创建新的线程,如果有空闲线程则会重复使用,线程空闲了60秒后会被回收。

实现原理

同步队列的实现方法有许多:

阻塞算法实现

阻塞算法实现通常在内部采用一个锁来保证多个线程中的put()和take()方法是串行执行的。采用锁的开销是比较大的,还会存在一种情况是线程A持有线程B需要的锁,B必须一直等待A释放锁,即使A可能一段时间内因为B的优先级比较高而得不到时间片运行。所以在高性能的应用中我们常常希望规避锁的使用。

public class NativeSynchronousQueue<E> {
    boolean putting = false;
    E item = null;

    public synchronized E take() throws InterruptedException {
        while (item == null)
            wait();
        E e = item;
        item = null;
        notifyAll();
        return e;
    }

    public synchronized void put(E e) throws InterruptedException {
        if (e==null) return;
        while (putting)
            wait();
        putting = true;
        item = e;
        notifyAll();
        while (item!=null)
            wait();
        putting = false;
        notifyAll();
    }
}

OpenVPN使用多个端口 2013-03-02

Openvpn本身不能设置多个端口,使用iptables可以解决这个问题 (假设openvpn本来56788端口):

for port in {56780..56787}
do 
    iptables -t nat -A PREROUTING -p tcp -d <your_external_ip> --dport $port -j REDIRECT --to-port 56788
done

Java的资源管理 2013-03-01

Overview

Java程序中的常见的资源有:文件,Socket,数据库连接。在使用这些资源时候要分外小心,因为操作系统可同时操作的资源是有限的,比如默认情况下系统允许同时打开的文件数为1024个,Mysql服务器默认允许的最大连接数是100,所以操作这些资源时候要注意即使在遇到错误时也要让系统能正确回收资源。如果发生错误时候,打开的文件描述符没关闭或数据库连接没关闭,积累到一定程度后,应用将会变得不可用,只能重启。

try-catch-finally

Java提供了try-catch-finally来保证程序遇到异常时总是有机会可以处理资源的关闭 – 调用资源对象的close()方法。但经验不足的Java程序员还是会错误的管理资源,而造成资源的泄露,静态代码分析工具,如FindBugs可以帮助发现此类问题。

首先我们来看一段文件操作代码:

private void copy(String from, String to) throws IOException {
    FileInputStream in = null;  
    FileOutputStream out = null;  
    in = new FileInputStream(from);  
    out = new FileOutputStream(to);  
    int c;  
    while ((c = in.read()) != -1)
        out.write(c);  
    in.close();
    out.close();
}