【CS创世 SD NAND】SD NAND芯片的测评与使用(基于卷积神经网络的数字识别)

目录

前言:

简介:

对照:

测试:

使用:

照片存储:

基于卷积神经网络的数字识别:


前言:

感谢深圳雷龙公司寄送的样品,其中包括两张2代的4gbit和32gbit的SD NAND FLASH芯片以及一份测试板卡。

简介:

根据官方文档的描述,这款芯片采用LGA-8封装,具有标准SDIO接口,并同时兼容SPI和SD接口。因此,可以直接移植标准驱动代码,支持使用SD NAND FLASH的SOC也可以用于TF卡启动。

以下是该芯片的主要参数(以CSNP32GCR01-BOW手册为准):

  • 接口:符合标准SD Specification Version 2.0规范,包括1-I/O和4-I/O两种模式。

  • 默认模式:在默认模式下,时钟频率可变范围为0-25 MHz,接口速度高达12.5 MB/sec(使用4条并行数据线路)。

  • 高速模式:在高速模式下,时钟频率可变范围为0-50 MHz,接口速度高达25 MB/sec(使用4条并行数据线路)。

对照:

下面是SD NAND芯片和传统TF卡的一些对比:

特点SD NAND FlashTF卡(MicroSD卡)
类型存储芯片类型存储卡格式
物理尺寸通常较大,适用于嵌入式系统通常是小型尺寸(15mm x 11mm x 1mm)
用途主要用于嵌入式设备和SSD主要用于移动设备(例如,相机、手机、平板电脑)和嵌入式系统
读写速度通常更高,适用于快速数据访问通常较低,适用于存储和应用程序加载
数据容量可以存储大容量数据(GB到TB级别)通常容量较小(GB级别),但有高容量版本
插拔耐用性不适合频繁插拔,适合稳定嵌入式环境设计用于频繁插拔,例如用于相机和手机
主要接口NAND Flash接口(例如NAND、NOR)SPI、SD、UHS-I、UHS-II等
擦写寿命通常较高(数百万次到数千万次擦写)较低(数千次到数十万次擦写)
容量选项大量容量选项可供选择通常有限的容量选项
数据可移植性不适合移动,用于固定设备适用于移动设备,易于数据传输和共享
安全性可以通过加密和安全擦除增强数据安全性通常具有数据加密和写保护特性
成本成本较低成本因容量和速度而异
高温和低温性能在极端温度条件下性能稳定部分型号适用于极端温度条件

目前,一些树莓派和一些国产的微处理器经常通过SD卡进行系统的移植,但一些设计不合理的卡槽经常不能保护SD卡,反而会损坏折断。相比之下,SD NAND可以通过贴片直接嵌入嵌入式设备中,更适合嵌入式环境的开发。同时,裸露的SD卡槽和松动的SD卡时常会影响系统的稳定性,因此一个可以反复擦拭的稳定存储芯片显得十分重要。

通过将测试板和芯片进行简单的焊接,我们可以像使用SD卡一样对SD NAND FLASH进行测试。

测试:

首先,我们使用CrystalDiskMark 8.0.4c对这款储存器进行了测试:

本次测试的是512MB的容量的产品,容量是真实的。我们可以看出,在包括顺序读取、顺序写入、随机读取和随机写入的四个测试方式下,SD NAND取得了不错的测试结果,接近官方数据,可以成功进行高速存储。

照片失真了

使用:

此外,我们还利用k210与SD NAND进行了照片的存储和基于卷积神经网络的数字识别。

1.照片存储

通过向SD NAND内烧录micropython代码,实现了k210对照片的拍摄和存储。存储速度非常快。


import sensor, lcd
from Maix import GPIO
from fpioa_manager import fm
from board import board_info
import os, sys
import time
import image

#### image size ####
set_windowing = (224, 224)       

#### sensor config ####

sensor.reset(freq=22000000, dual_buff=False)
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA) # 320x240
try:
    sensor.set_jb_quality(95)         # for IDE display quality
except Exception:
    pass # no IDE support
if set_windowing:
    sensor.set_windowing(set_windowing)
# sensor.set_auto_gain(False)
# sensor.set_auto_whitebal(False, rgb_gain_db=(0x52,0x40,0x4d))
# sensor.set_saturation(0)
# sensor.set_brightness(4)
# sensor.set_contrast(0)
# sensor.set_hmirror(True)        # image horizonal mirror
# sensor.set_vflip(True)          # image vertical flip
# sensor.set_auto_whitebal(False)

sensor.skip_frames()

#### lcd config ####
lcd.init(type=1, freq=15000000)
lcd.rotation(2)

#### boot key ####
boot_pin = 16 # board_info.BOOT_KEY
fm.register(boot_pin, fm.fpioa.GPIOHS0)
key = GPIO(GPIO.GPIOHS0, GPIO.PULL_UP)

######################################################

#### main ####
def capture_main(key):
    def draw_string(img, x, y, text, color, scale, bg=None , full_w = False):
        if bg:
            if full_w:
                full_w = img.width()
            else:
                full_w = len(text)*8*scale+4
            img.draw_rectangle(x-2,y-2, full_w, 16*scale, fill=True, color=bg)
        img = img.draw_string(x, y, text, color=color,scale=scale)
        return img

    def del_all_images():
        os.chdir("/sd")
        images_dir = "cap_images"
        if images_dir in os.listdir():
            os.chdir(images_dir)
            types = os.listdir()
            for t in types:
                os.chdir(t)
                files = os.listdir()
                for f in files:
                    os.remove(f)
                os.chdir("..")
                os.rmdir(t)
            os.chdir("..")
            os.rmdir(images_dir)

    # del_all_images()
    os.chdir("/sd")
    dirs = os.listdir()
    images_dir = "cap_images"
    last_dir = 0
    for d in dirs:
        if d.startswith(images_dir):
            if len(d) > 11:
                n = int(d[11:])
                if n > last_dir:
                    last_dir = n
    images_dir = "{}_{}".format(images_dir, last_dir+1)
    print("save to ", images_dir)
    if images_dir in os.listdir():
        img = image.Image()
        img = draw_string(img, 2, 200, "please del cap_images dir", color=lcd.WHITE,scale=1, bg=lcd.RED)
        lcd.display(img)
        sys.exit(1)
    os.mkdir(images_dir)
    last_cap_time = 0
    last_btn_status = 1
    save_dir = 0
    save_count = 0
    os.mkdir("{}/{}".format(images_dir, save_dir))
    while(True):
        img0 = sensor.snapshot()
        if set_windowing:
            img = image.Image()
            img = img.draw_image(img0, (img.width() - set_windowing[0])//2, img.height() - set_windowing[1])
        else:
            img = img0.copy()
        # img = img.resize(320, 240)
        if key.value() == 0:
            time.sleep_ms(30)
            if key.value() == 0 and (last_btn_status == 1) and (time.ticks_ms() - last_cap_time > 500):
                last_btn_status = 0
                last_cap_time = time.ticks_ms()
            else:
                if time.ticks_ms() - last_cap_time > 5000:
                    img = draw_string(img, 2, 200, "release to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)
                else:
                    img = draw_string(img, 2, 200, "release to capture", color=lcd.WHITE,scale=1, bg=lcd.RED)
                    if time.ticks_ms() - last_cap_time > 2000:
                        img = draw_string(img, 2, 160, "keep push to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)
        else:
            time.sleep_ms(30)
            if key.value() == 1 and (last_btn_status == 0):
                if time.ticks_ms() - last_cap_time > 5000:
                    img = draw_string(img, 2, 200, "change object type", color=lcd.WHITE,scale=1, bg=lcd.RED)
                    lcd.display(img)
                    time.sleep_ms(1000)
                    save_dir += 1
                    save_count = 0
                    dir_name = "{}/{}".format(images_dir, save_dir)
                    os.mkdir(dir_name)
                else:
                    draw_string(img, 2, 200, "capture image {}".format(save_count), color=lcd.WHITE,scale=1, bg=lcd.RED)
                    lcd.display(img)
                    f_name = "{}/{}/{}.jpg".format(images_dir, save_dir, save_count)
                    img0.save(f_name, quality=95)
                    save_count += 1
                last_btn_status = 1
        img = draw_string(img, 2, 0, "will save to {}/{}/{}.jpg".format(images_dir, save_dir, save_count), color=lcd.WHITE,scale=1, bg=lcd.RED, full_w=True)
        lcd.display(img)
        del img
        del img0


def main():
    try:
        capture_main(key)
    except Exception as e:
        print("error:", e)
        import uio
        s = uio.StringIO()
        sys.print_exception(e, s)
        s = s.getvalue()
        img = image.Image()
        img.draw_string(0, 0, s)
        lcd.display(img)
main()

 

2.基于卷积神经网络的数字识别:

我们向SD NAND内烧录了功能代码、模型参数和模型结构。SD NAND可以很好地存储以上内容,并通过k210正确加载模型。在使用过程中,SD NAND表现出了出色的稳定性,没有出现崩溃或弹出的情况。

# generated by maixhub, tested on maixpy3 v0.4.8
# copy files to TF card and plug into board and power on
import sensor, image, lcd, time
import KPU as kpu
import gc, sys

input_size = (224, 224)
labels = ['1', '2', '3', '4', '5', '6', '7', '8']
anchors = [0.45, 1.55, 1.46, 2.54, 1.22, 1.55, 1.58, 2.59, 1.47, 2.78]

def lcd_show_except(e):
    import uio
    err_str = uio.StringIO()
    sys.print_exception(e, err_str)
    err_str = err_str.getvalue()
    img = image.Image(size=input_size)
    img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
    lcd.display(img)

def main(anchors, labels = None, model_addr="/sd/m.kmodel", sensor_window=input_size, lcd_rotation=0, sensor_hmirror=False, sensor_vflip=False):
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing(sensor_window)
    sensor.set_vflip(1)
    sensor.run(1)

    lcd.init(type=1)
    lcd.rotation(lcd_rotation)
    lcd.clear(lcd.WHITE)

    if not labels:
        with open('labels.txt','r') as f:
            exec(f.read())
    if not labels:
        print("no labels.txt")
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "no labels.txt", color=(255, 0, 0), scale=2)
        lcd.display(img)
        return 1
    try:
        img = image.Image("startup.jpg")
        lcd.display(img)
    except Exception:
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "loading model...", color=(255, 255, 255), scale=2)
        lcd.display(img)

    try:
        task = None
        task = kpu.load(model_addr)
        kpu.init_yolo2(task, 0.5, 0.3, 5, anchors) # threshold:[0,1], nms_value: [0, 1]
        while(True):
            img = sensor.snapshot()
            t = time.ticks_ms()
            objects = kpu.run_yolo2(task, img)
            t = time.ticks_ms() - t
            if objects:
                for obj in objects:
                    pos = obj.rect()
                    img.draw_rectangle(pos)
                    img.draw_string(pos[0], pos[1], "%s : %.2f" %(labels[obj.classid()], obj.value()), scale=2, color=(255, 0, 0))
            img.draw_string(0, 200, "t:%dms" %(t), scale=2, color=(255, 0, 0))
            lcd.display(img)
    except Exception as e:
        raise e
    finally:
        if not task is None:
            kpu.deinit(task)


if __name__ == "__main__":
    try:
        # main(anchors = anchors, labels=labels, model_addr=0x300000, lcd_rotation=0)
        main(anchors = anchors, labels=labels, model_addr="/sd/model-54796.kmodel")
    except Exception as e:
        sys.print_exception(e)
        lcd_show_except(e)
    finally:
        gc.collect()

通过以上两个实验,SD NAND代替传统的SD/TF卡进行数据存储表现出了极大的优势和稳定性。

  • 17
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值