Tips On 5050RGB

背景

淘宝上买的5050RGB模块, 外观如下图:

/images/2016_03_12_19_36_05_351x233.jpg

连线:

这个RGB模块比较奇怪,直接使用Arduino的5v输出一直有问题,我是用的外接5V电源供电, 动用了面包板模块.(之后发现不是供电的问题, 是因为淘宝上卖的模块提供示例代码的问 题)

更具体的连线如下:

// V-VCC 5V   R-9   B-10  G-11
#define LEDR 9
#define LEDB 10
#define LEDG 11

测试

按照厂方提供的程序,未能成功运行.

厂方提供的电路图如下:

/images/2016_03_12_20_31_25_373x471.jpg

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); 
}

正确的电路连线应该是:

/images/2016_03_12_20_54_55_707x379.jpg

Tips on w5100

参考

参考如下:

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口以后,上报数据成功.

配置Qemu的VDE网络

为了快速验证镜像,配置出一个在本机上的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.

Tips on V-USB and Arduino(5)

这一节将添加一个LED到已有的方案中. 这个LED将使用11口, 通过./set-led new来设 置状态.

连线

新加一个LED如图:

/images/2016_03_07_21_52_18_683x513.jpg

仅仅添加了一个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被点亮/熄灭.

效果如图:

/images/70584386.jpg

延伸

既然点亮了LED, 其他各种设备就不在话下了. 引入一个舵机,或者步进电机, 就可以实现 e-buddy人偶的提醒功能.

当然我们可以想得更妙, 例如,用蓝牙或者WIFI来替代USB传输. 这样可以做到更远距离.

Tips on V-USB and Arduino(4)

前面把玩了一下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的头灯.