Fork me on GitHub

mongoose——mongodb的ORM

Publish: July 5, 2016 Category: node.js

mongoose的使用实例,太爽了啊,更多看这里:http://mongoosejs.com/docs/schematypes.html

var schema = new Schema({
  name:    String,
  binary:  Buffer,
  living:  Boolean,
  updated: { type: Date, default: Date.now },
  age:     { type: Number, min: 18, max: 65 },
  mixed:   Schema.Types.Mixed,
  _someId: Schema.Types.ObjectId,
  array:      [],
  ofString:   [String],
  ofNumber:   [Number],
  ofDates:    [Date],
  ofBuffer:   [Buffer],
  ofBoolean:  [Boolean],
  ofMixed:    [Schema.Types.Mixed],
  ofObjectId: [Schema.Types.ObjectId],
  nested: {
    stuff: { type: String, lowercase: true, trim: true }
  }
})

// example use

var Thing = mongoose.model('Thing', schema);

var m = new Thing;
m.name = 'Statue of Liberty';
m.age = 125;
m.updated = new Date;
m.binary = new Buffer(0);
m.living = false;
m.mixed = { any: { thing: 'i want' } };
m.markModified('mixed');
m._someId = new mongoose.Types.ObjectId;
m.array.push(1);
m.ofString.push("strings!");
m.ofNumber.unshift(1,2,3,4);
m.ofDates.addToSet(new Date);
m.ofBuffer.pop();
m.ofMixed = [1, [], 'three', { four: 5 }];
m.nested.stuff = 'good';
m.save(callback);

DA14580的外部中断

Publish: June 2, 2016 Category: 蓝牙/WIFI/单片机

函数申明: 
GPIO_EnableIRQ( GPIO_PORT port, GPIO_PIN pin, IRQn_Type irq, bool low_input,
                 bool release_wait, uint8_t debounce_ms )
参数说明:
port 不解释
pin 不解释
IRQn_Type 中断类型
low_input 触发类型:true,下降沿触发;false,上升沿触发
release_wait 是否锁住中断,直到按键放开。如果输入true,即使按键一直保持,也只会触发一次中断;如果输入false,则按键保持期间会不断触发中断,直到松开按键。
debounce_ms 设定按键防抖控制的时间,单位毫秒

da14580和大多数单片机一样,某个端口的所有引脚都可以配置成中断输入,但是同一个端口只能有一个中断回调函数,所以在中断回调函数那里最好判断一下指定的引脚状态是不是处于需要的中断状态。

#define CLICK_IRQ_PORT         GPIO_PORT_0
#define CLICK_IRQ_PIN          GPIO_PIN_0
#define CLICK_IRQ_TYPE        GPIO0_IRQn

int press_count=0;
void button_press_callback(void) {

    //这里要判断中断是不是来自于我们指定的引脚
    if(GPIO_GetPinStatus(CLICK_IRQ_PORT, CLICK_IRQ_PIN)) {
        
        printf_string("*********CLICKED:");
        printf_byte_dec(press_count++);
        printf_string("**********\n\r");
    }

    GPIO_ResetIRQ(CLICK_IRQ_TYPE);

}

void button_press_enable(void) {
    //配置成下拉输入
    GPIO_ConfigurePin(CLICK_IRQ_PORT, CLICK_IRQ_PIN, INPUT_PULLDOWN, PID_GPIO, false ); 
    
    //开启中断
    GPIO_EnableIRQ( CLICK_IRQ_PORT, CLICK_IRQ_PIN, CLICK_IRQ_TYPE, false, true, 120 );
    
    //注册中断回调函数
    GPIO_RegisterCallback(CLICK_IRQ_TYPE, button_press_callback);
}

int main (void)
{
        system_init();
        periph_init();
    
    button_press_enable();
    
        while(1);
}
...

da14580驱动全彩RGB LED(内嵌芯片ws2813/ws2812)

Publish: March 1, 2016 Category: 蓝牙/WIFI/单片机

类似单总线,但是对时钟要求比较高,需要能精细到0.5微秒的延时,记得传输数据前需要拉低至少50微秒.

#include <stdio.h>
#include <stdbool.h>
#include "datasheet.h"
#include "gpio.h"

#define RGB_PORT         GPIO_PORT_0
#define RGB_PIN          GPIO_PIN_3

void set_colori(uint32_t color) {
    //author:yoyo(http://yoyo.play175.com/p/da14580-ws2813.html)
    int i;
    for(i = 0; i < 24; ++i) {
        if(color & 1) {
            SetWord16(GPIO_BASE + (RGB_PORT << 5) + 2, 1 << RGB_PIN);
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            SetWord16(GPIO_BASE + (RGB_PORT << 5) + 4, 1 << RGB_PIN);
            __nop();
            __nop();
        } else {
            SetWord16(GPIO_BASE + (RGB_PORT << 5) + 2, 1 << RGB_PIN);
            __nop();
            __nop();
            SetWord16(GPIO_BASE + (RGB_PORT << 5) + 4, 1 << RGB_PIN);
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
            __nop();
        }
        color >>= 1;
    }
}

void set_color3(uint8_t r, uint8_t g, uint8_t b) {
    set_colori((b << 16) | (r << 8) | g);
}

void delay(int ms) {
    unsigned int i = 2400 * ms;
    while(i--) {}
}

void system_init(void) {
    SetWord16(CLK_AMBA_REG, 0x00);                 // set clocks (hclk and pclk ) 16MHz
    SetWord16(SET_FREEZE_REG, FRZ_WDOG);           // stop watch dog
    SetBits16(SYS_CTRL_REG, PAD_LATCH_EN, 1);      // open pads
    SetBits16(SYS_CTRL_REG, DEBUGGER_ENABLE, 1);   // open debugger
    SetBits16(PMU_CTRL_REG, PERIPH_SLEEP, 0);      // exit peripheral power down
}

int main (void) {
    system_init();

    GPIO_ConfigurePin(RGB_PORT, RGB_PIN, OUTPUT, PID_GPIO, false);
    SetWord16(GPIO_BASE + (RGB_PORT << 5) + 4, 1 << RGB_PIN);
    delay(1);

    set_color3(0xff,0,0);

    while(1);
}

nrf51822的程序烧录

Publish: January 22, 2016 Category: 蓝牙/WIFI/单片机

nrf51822的蓝牙协议栈称之为softdevice,是一段80k的二进制,需要使用nrfgo studio来烧录到地址为0x00的区段,而程序是烧录到0x14000的地址。如果你不需要使用蓝牙协议栈,只是普通的单片机程序的话,程序烧录到地址为0x00即可(需要先使用nrfgo studio把把整个flash擦除掉,即Erase All)

»» 点击浏览全文 »»»»»»

简易串口调试工具——uart.exe

Publish: January 15, 2016 Category: project,蓝牙/WIFI/单片机

花了点时间写了个Windows系统下的简易串口调试工具,虽然简易,但是使用起来和Tera Term差不多。接收后显示到控制台,同时可以直接输入要发送的字符,还支持串口断开后重连功能。截图如下:

uart-snap

可以使用参数快速开启串口功能,最佳方式是,你可以把启动参数加到快捷方式里面。

参数说明:uart.exe [-p 串口名] [-b 波特率]
例如:uart.exe -p COM3 -b 9600

下载地址:uart.zip (26KB)

2016-2-20 更新:增加utf8编码支持

STM8 UART的使用,以及串口调试环境的建立(超精简代码)

Publish: January 11, 2016 Category: 蓝牙/WIFI/单片机

学习arduino的时候只能使用串口来调试程序,STM8就有强大的ST-Link来调试,但是有时候还是需要串口来输出一些调试信息,我提取了stm8的官方uart1库函数,然后结合了我以前c语言调试函数宏的应用,写出一份代码,可以最快的速度建立起串口调试环境,支持printf、debug、error三种函数,炒鸡清爽,炒鸡好用有木有?

»» 点击浏览全文 »»»»»»

android开发tips

Publish: August 28, 2015 Category: android

最近又折腾上安卓了,开发了两个APP,相比于iOS,android的开发还是感觉更容易一点。界面layout xml非常强大。
我整理一些网上比较难找到,或者自己琢磨出来的一些经验在这个文章里列出来,不定期更新(可能就不更新了。。。)

列出系统内所有歌曲

//返回歌曲id列表
public List<Integer> querySongs(Context context) {
    ArrayList<Integer> list = null;
    String[] columns = { MediaStore.Audio.AudioColumns._ID
            ,MediaStore.Audio.AudioColumns.IS_MUSIC};  
    
    Cursor c = context.getContentResolver().query(  
            MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns, null,  
            null, null);  
  
    list = new ArrayList<Integer>();
    while (c.moveToNext())  
    {  
        if(c.getInt(1) != 0) {
            list.add(c.getInt(0));  
        }
    }
    return list;
}

»» 点击浏览全文 »»»»»»

Unity在非PC平台提示找不到某些IO函数的解决

Publish: June 12, 2015 Category: unity3d

unity5在为ios打包资源的时候,提示:

 error CS0117: `System.IO.File' does not contain a definition for `WriteAllBytes'

很奇怪的问题,后来自己写了读写函数,解决!

    /// <summary>
    /// 擦写文件(用于替换系统File的同名静态方法)
    /// </summary>
    /// <param name="file"></param>
    /// <param name="data"></param>
    /// <param name="offset"></param>
    /// <param name="length"></param>
    public static void WriteAllBytes(string file,byte[] data,int offset = 0,int length = -1)
    {
        if (length == -1) length = data.Length - offset;
        FileStream fs = new FileStream(file, FileMode.Create);
        BinaryWriter w = new BinaryWriter(fs);
        w.Write(data,offset,length);
        w.Flush();
        w.Close();
        fs.Close();
    }

    /// <summary>
    /// 读取文件(用于替换系统File的同名静态方法)
    /// </summary>
    /// <param name="file"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public static byte[] ReadAllBytes(string file)
    {
        FileStream fs = new FileStream(file, FileMode.Open);
        BinaryReader r = new BinaryReader(fs);
        byte[] data = r.ReadBytes((int)fs.Length);
        r.Close();
        fs.Close();
        return data;
    }

Hello2D——一个小巧的图形渲染引擎

Publish: April 28, 2015 Category: project,C/C++

项目开源地址:https://github.com/play175/Hello2D

简单的2D图形渲染引擎(目前采用CPU渲染),主要有以下特点

  • gnu99标准纯C,无其他依赖库
  • 从Unity3D受到启发,采用组件装饰板设计,某个节点上,需要实现什么功能就加什么功能组件
  • 采用优化的脏矩形重绘机制
  • 支持跨平台,只需要简单修改外围窗口相关代码
  • 支持lua(开发中)
  • 暂时没想到。。。

感谢以下给我启发的项目:

Unity3D、iOS UIKit、EJoy2D、Flash AS3 Core、nothings/stb、以及互联网极具分享精神的网友

»» 点击浏览全文 »»»»»»

Unity3D截取物体快照

Publish: April 7, 2015 Category: unity3d

静默截取物体快照,物体可以放在任意位置,不影响屏幕显示。和之前那个截屏不同,这次使用了RenderTexture。其中难点在于,要把相机放到合适的位置才能观察到物体的全貌,具体可以看代码注释。
另外有个技巧,如果不想要背景和其他物体,只要该物体的截图,可以在调用前把物体放置到一个非常远的位置(比如世界坐标y=-1000),调用完后再恢复位置。

/// <summary>
/// 保存物体快照到PNG文件
/// </summary>
/// <author>yoyo(http://yoyo.play175.com)</author>
/// <param name="targetObject">需要快照的物体</param>
/// <param name="filePath">文件路径</param>
/// <param name="imageSize">照片像素大小(正方形照片)</param>
public static void SnapshotToFile(GameObject targetObject,string filePath,int imageSize = 256)
{
    Camera cam = Camera.main;

    //记录相机位置
    Vector3 opos = cam.transform.position;
    Vector3 oscale = cam.transform.localScale;
    Quaternion orot = cam.transform.localRotation;

    //计算物体包围盒
    Renderer[] renderers = targetObject.GetComponentsInChildren<Renderer>();
    Vector3 min = targetObject.transform.position, max = targetObject.transform.position;
    for (int i = 0; i < renderers.Length; i++)
    {
        min = Vector3.Min(renderers[i].bounds.min, min);
        max = Vector3.Max(renderers[i].bounds.max, max);
    }

    //把相机放到合适位置
    Vector3 center = new Vector3((max.x + min.x) / 2, (max.y + min.y) / 2, (max.z + min.z) / 2);//中心点
    Vector3 step = (max - center).normalized;//相对于中心点的单位向量

    //先放到中心点的前右上角
    cam.transform.position = center + step;
    //拉到合适距离
    cam.transform.position = cam.transform.position + step * (max - min).magnitude * 50 / cam.fieldOfView;
    //旋转方向以便看到目标
    cam.transform.LookAt(center);

    RenderTexture rt = new RenderTexture(imageSize, imageSize, 24);
    cam.targetTexture = rt;
    cam.Render();

    RenderTexture.active = rt;//关键点,有点类似make current 的意思

    Texture2D t = new Texture2D(imageSize, imageSize, TextureFormat.RGB24, false);//false代表不需要使用mipmaps
    t.ReadPixels(new Rect(0, 0, imageSize, imageSize), 0, 0);

    RenderTexture.active = null;//置空,以免出错
    GameObject.Destroy(rt);

    //恢复相机位置
    cam.targetTexture = null;
    cam.transform.position = opos;
    cam.transform.localScale = oscale;
    cam.transform.localRotation = orot;

    //转为png数据
    byte[] b = t.EncodeToPNG();
    GameObject.Destroy(t);
    
    //保存文件
    System.IO.File.WriteAllBytes(filePath, b); 
}

//调用举例:SnapshotToFile(gameobj, Application.dataPath + "/snap.png");