Mar 12, 2016
Technology背景
淘宝上买的5050RGB模块, 外观如下图:

连线:
这个RGB模块比较奇怪,直接使用Arduino的5v输出一直有问题,我是用的外接5V电源供电,
动用了面包板模块.(之后发现不是供电的问题, 是因为淘宝上卖的模块提供示例代码的问
题)
更具体的连线如下:
// V-VCC 5V R-9 B-10 G-11
#define LEDR 9
#define LEDB 10
#define LEDG 11
测试
按照厂方提供的程序,未能成功运行.
厂方提供的电路图如下:

Debug
百思不得其解后,用万用表测试, 电阻发声的那档, 发现加电后,某两个LED可以亮, 另外
一个不能亮.
发现奇怪的一点是, VCC接高电压, RGB接低电压时, 无法点亮LED. RGB接高电压, VCC接
低电压时, LED可以被点亮两个.
猜测: 厂方给的参考资料有误, 接线错误. 而且LED坏了一个.
验证, 正确.
连线更改为:
// V-VCC 5V R-9 B-10 G-11
#define LEDR 9
#define LEDG 10
蓝色的LED已坏, 所以示例代码中,不许配置LEDB.
// V-VCC GND R-9 G-10
#define LEDR 9
#define LEDG 10
int i = 0;
void setup()
{
pinMode(LEDG,OUTPUT);
pinMode(LEDR,OUTPUT);
}
void loop()
{
analogWrite(LEDR,0);
analogWrite(LEDG,0); //off
delay(1000);
analogWrite(LEDR,255);
delay(1000);
analogWrite(LEDR,0);
analogWrite(LEDG,0);
delay(1000);
analogWrite(LEDR,30);
analogWrite(LEDG,200);
delay(1000);
analogWrite(LEDR,0);
analogWrite(LEDG,0);
delay(1000);
analogWrite(LEDG,30);
analogWrite(LEDR,200);
delay(1000);
}
正确的电路连线应该是:

Mar 11, 2016
Technology参考
参考如下:
http://www.bigiot.net/help/6.html
问题
上报的数据不准确.
原因是因为W5100抄版的淘宝版本有短路, 换成别的模拟口:
const int LM35 = 3;//LM35 pin
byte mac[] = {0x00, 0x1D, 0x72, 0x82, 0x35, 0x9D};
EthernetClient client ;
IPAddress ip(192, 168, 17, 177);//local IP
//IPAddress server(121,42,180,30);
char server[] = "www.bigiot.net";
连线改为了3, 即A3口以后,上报数据成功.
Mar 10, 2016
Technology为了快速验证镜像,配置出一个在本机上的tap0端口,虚拟机则通过VDE虚拟交换机连接到此端口后
,DHCP获得IP地址,从而得到网络连接, 以下是步骤。
安装VDE
ArchLinux下安装命令为sudo pacman -S vde2.
配置
贴出配置文件如下, 摘录自ArchLinux的Wiki. 值得注意的是,在Systemd的配置文件中,需要先把
tun驱动装载上,才能使得VDE启动成功。
配置qemu网络环境配置脚本:
$ vim /etc/systemd/scripts/qemu-network-env
#!/bin/sh
# QEMU/VDE network environment preparation script
# The IP configuration for the tap device that will be used for
# the virtual machine network:
TAP_DEV=tap0
TAP_IP=10.33.34.254
TAP_MASK=24
TAP_NETWORK=10.33.34.0
# Host interface
NIC=enp2s0
case "$1" in
start)
echo -n "Starting VDE network for QEMU: "
# If you want tun kernel module to be loaded by script uncomment here
modprobe tun 2>/dev/null
# Wait for the module to be loaded
while ! lsmod | grep -q "^tun"; do echo "Waiting for tun device"; sleep 1; done
# Start tap switch
vde_switch -tap "$TAP_DEV" -daemon -mod 660 -group users
# Bring tap interface up
ip address add "$TAP_IP"/"$TAP_MASK" dev "$TAP_DEV"
ip link set "$TAP_DEV" up
# Start IP Forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE
;;
stop)
echo -n "Stopping VDE network for QEMU: "
# Delete the NAT rules
iptables -t nat -D POSTROUTING "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE
# Bring tap interface down
ip link set "$TAP_DEV" down
# Kill VDE switch
pgrep -f vde_switch | xargs kill -TERM
;;
restart|reload)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac
exit 0
配置symtemd服务:
$ vim /etc/systemd/system/qemu-network-env.service
[Unit]
Description=Manage VDE Switch
[Service]
Type=oneshot
ExecStart=/etc/systemd/scripts/qemu-network-env start
ExecStop=/etc/systemd/scripts/qemu-network-env stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
使能服务,并重新启动机器:
$ sudo systemctl enable qemu-network-env.service
配置DHCPD
需要配置dhcpd以使得在10.33.34.0/24网段提供DHCP服务:
$ sudo vim /etc/dhcpd.conf
subnet
10.33.34.0 netmask 255.255.255.0 {
# --- default gateway
option routers
10.33.34.254;
# --- Netmask
option subnet-mask
255.255.255.0;
# --- Broadcast Address
option broadcast-address
10.33.34.255;
# --- Domain name servers, tells the clients which DNS servers to use.
option domain-name-servers
223.5.5.5,180.76.76.76;
option time-offset 0;
range 10.33.34.2 10.33.34.253;
default-lease-time 1209600;
max-lease-time 1814400;
}
修改完dhcpd的配置后, 重新启动dhcpd服务:
$ sudo systemctl restart dhcpd4
启动虚拟机
启动虚拟机,并使其使用我们刚才添加的vde网络:
$ sudo qemu-system-x86_64 -net nic -net vde -hda ./test1.qcow2 -m 2048 --enable-kvm
启动的虚拟机将获得10.33.34.2~10.33.33.253之间的地址。
如果使用普通用户,会出错, To be solved.
Mar 7, 2016
Technology这一节将添加一个LED到已有的方案中. 这个LED将使用11口, 通过./set-led new来设
置状态.
连线
新加一个LED如图:

仅仅添加了一个LED + 220欧电阻.
代码修改
requests.h
添加新的request定义:
diff --git a/requests.h b/requests.h
index 90275f5..b354a73 100644
--- a/requests.h
+++ b/requests.h
@@ -32,4 +32,6 @@
#define CUSTOM_RQ_BLINK 3
+#define CUSTOM_RQ_NEWLED 4
+
hid_custom_rq.h
添加新的管脚, 和对CUSTOM_RQ_NEWLED的处理代码:
diff --git a/hid_custom_rq.h b/hid_custom_rq.h
index f5509e4..b5411cf 100644
--- a/hid_custom_rq.h
+++ b/hid_custom_rq.h
@@ -13,6 +13,7 @@ class hid_custom_rqDevice {
hid_custom_rqDevice () {
usbInit();
ledPin = 13; // pin 13 as default ledPin
+ newledPin = 11; // pin 11 as newledPin
}
void poll() {
@@ -20,6 +21,7 @@ class hid_custom_rqDevice {
}
unsigned int ledPin;
+ unsigned int newledPin;
};
hid_custom_rqDevice hid_custom_rq = hid_custom_rqDevice();
@@ -99,6 +101,14 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
usbMsgPtr = dataBuffer; /* tell the driver which data to
return */
return 1; /* tell the driver to send 1 byte
*/
}
+ /* Added for newly added LED */
+ else if(rq->bRequest == CUSTOM_RQ_NEWLED){
+ if(rq->wValue.bytes[0] & 1){ /* set new LED */
+ digitalWrite(hid_custom_rq.newledPin, HIGH);
+ }else{ /* clear new LED */
+ digitalWrite(hid_custom_rq.newledPin, LOW);
+ }
+ }
}
set-led.c
这个文件中,添加了两条新命令,分别为./set-led newledon和./set-led newledoff用于点亮/
熄灭新加的LED.
diff --git a/examples/hid_custom_rq_demo/commandline/set-led.c b/examples/hid_custom_rq_demo/commandline/set-led.c
index 44d39f9..a306eca 100644
--- a/examples/hid_custom_rq_demo/commandline/set-led.c
+++ b/examples/hid_custom_rq_demo/commandline/set-led.c
@@ -91,12 +91,19 @@ buffer[3] = 0;
}else{
printf("LED is %s\n", buffer[0] ? "on" : "off");
}
- }else if((isOn = (strcasecmp(argv[1], "on") == 0)) || strcasecmp(argv[1], "off") == 0){
+ }
+ else if((isOn = (strcasecmp(argv[1], "on") == 0)) || strcasecmp(argv[1], "off") == 0){
cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_STATUS, isOn, 0, buffer, 0, 5000);
if(cnt < 0){
fprintf(stderr, "USB error: %s\n", usb_strerror());
}
}
+ else if((isOn = (strcasecmp(argv[1], "newledon") == 0)) || strcasecmp(argv[1], "newledoff") == 0){
+ cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_NEWLED, isOn, 0, buffer, 0, 5000);
+ if(cnt < 0){
+ fprintf(stderr, "USB error: %s\n", usb_strerror());
+ }
+ }
else if(strcasecmp(argv[1], "onoff") == 0){ /* Test custom on/off */
hid_custom_rq_demo.ped
因为新添加了硬件,ped文件同样需要更新.
diff --git a/examples/hid_custom_rq_demo/hid_custom_rq_demo.pde b/examples/hid_custom_rq_demo/hid_custom_rq_demo.pde
index 77e3912..6d98151 100644
--- a/examples/hid_custom_rq_demo/hid_custom_rq_demo.pde
+++ b/examples/hid_custom_rq_demo/hid_custom_rq_demo.pde
@@ -1,10 +1,13 @@
#include <hid_custom_rq.h>
const int ledPin = 13;
+const int newledPin = 11;
void setup() {
hid_custom_rq.ledPin = ledPin;
pinMode(hid_custom_rq.ledPin, OUTPUT);
+ hid_custom_rq.newledPin = newledPin;
+ pinMode(hid_custom_rq.newledPin, OUTPUT);
}
void loop() {
验证
写入新编译的Arduino固件, 并新编译set-led程序, 即可看到新增的LED被点亮/熄灭.
效果如图:

延伸
既然点亮了LED, 其他各种设备就不在话下了. 引入一个舵机,或者步进电机, 就可以实现
e-buddy人偶的提醒功能.
当然我们可以想得更妙, 例如,用蓝牙或者WIFI来替代USB传输. 这样可以做到更远距离.
Mar 7, 2016
Technology前面把玩了一下ebuddy, 回去想了一下, 觉得基于v-usb和arduino来实现
一个自己的ebuddy也不是特别难的事情.
思路
还是参考:
V-USB examples for Arduino
以hid_custom_rq项目来改. 例子里已经实现了Arduino板载的LED亮/灭. 我们只需要在
原例上修改, 添加自定义命令和硬件即可.
代码
示例代码我做完后放到了github上, 可以通过以下命令获得:
$ git clone git@github.com:purplepalmdash/arduino-usb-led.git
主要修改
request.h
这个头文件被USB固件和主机所共享, 定义了USB的request number数字, request number
被用于主机和设备之间的通信.
添加:
#define CUSTOM_RQ_BLINK 3
hid_custom_rq.h
这个文件是Arduino板上固件程序中对各种来自主机的request信息的响应, 或者说, 消息
处理函数.
针对上面在requst.h文件中添加的消息, 我们需要在usbFunctionSetup()函数中添加
对应的消息处理代码, 为简单起见, 直接添加在函数的入口处就好.
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (usbRequest_t *)((void *)data);
+ if(rq->bRequest == CUSTOM_RQ_BLINK){ /* blink -- used for blink the LED */
+ /* First set the led pin to high */
+ unsigned char i = 6;
+ while(i >= 1)
+ {
+ digitalWrite(hid_custom_rq.ledPin, HIGH);
+ delay(1000);
+ digitalWrite(hid_custom_rq.ledPin, LOW);
+ delay(1000);
+ i--;
+ }
+ }
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR){
if(rq->bRequest == CUSTOM_RQ_SET_STATUS){
上面添加的代码, 在监测到CUSTOM_RQ_BLINK消息后, 会将led闪烁6次.
set-led.c
set-led.c文件用于编译出主机端程序, 编译出来的程序将接受用户输入, 将对应的输
入发送给USB设备.
在set-led.c文件中我们添加一条命令,用于发送CUSTOM_RQ_BLINK消息:
$ vim examples/hid_custom_rq_demo/commandline/set-led.c
int main(int argc, char **argv)
{
//.......
+ else if(strcasecmp(argv[1], "blink") == 0){ /* set blink goes here */
+ cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_BLINK, 0, 0, buffer, 0, 5000);
+ if(cnt < 0){
+ fprintf(stderr, "USB error: %s\n", usb_strerror());
+ }
+ }
//.......
}
验证
将代码拷贝到Arduino IDE的libraries目录下:
$ pwd
/media/y/arduino/1.0.5/libraries/hid_custom_rq
IDE菜单里的File -> Examples -> hid_custom_rq下将出现hid_custom_rq_demo, 点
击, 开始编译. 编译完以后, 上传到Arduino板.
按
http://purplepalmdash.github.io/blog/2016/02/26/tips-on-v-usb-and-arduino-2/
设置并检查Arduino连线.
现在拔掉Arduino串口的USB线, 插上我们新加的USB连线, 而后运行以下验证例程:
➜ hid_custom_rq git:(master) cd examples/hid_custom_rq_demo/commandline
➜ commandline git:(master) ./set-led blink
USB error: Connection timed out
出现USB error是因为在板子上的服务例程中耗费了太多时间. 问题不大. 每次运行
./set-led blink命令将使得板子上13口的led闪烁6次.
做到这里, 我们已经能模拟出ebuddy的心脏灯光效果了. 通过编写不同的request消息,发
送给Arduino板子即可.
下面将研究添加一个新的LED灯, 等同于ebuddy的头灯.