目录 前言: 简介: 对照: 测试: 使用: 照片存储: 基于卷积神经网络的数字识别: ———————————————— 前言: 感谢深圳雷龙公司寄送的样品,其中包括两张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卡进行系统的移植,但一些设计不合理的卡槽经常不能保护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卡进行数据存储表现出了极大的优势和稳定性。
|