본문 바로가기
제품소개

라즈베리파이 피코 베이직 트레이닝보드 구성

by 땜블리 2023. 2. 22.
728x90
반응형
SMALL

라즈베리파이 피코 보드의 펌웨어실습을 위한 베이직 트레이닝보드를 소개 합니다.

현재 네이버 스마트스토어에서 판매가 진행되고 있습니다.

라즈베리파이 피코 베이직 트레이닝 보드

 

라즈베리 파이 피코 실습보드 / 베이직 트레이닝 보드 / 마이크로 파이썬 라즈베리 파이 피코 실

[포레스텍] IoT에 관한 모든것 아두이노 라즈베리파이 시제품 제작 부품 및 센서 등등

smartstore.naver.com

라즈베리파이 피코보드를 DIP 타입으로 사용성을 높인 도킹보드는 아래에서 판매 중입니다.

라즈베리파이 피코 도킹보드

 

라즈베리 파이 피코 도킹 보드 / 마이크로 파이썬 라즈베리 파이 피코 도킹 보드 : 포레스텍

[포레스텍] IoT에 관한 모든것 아두이노 라즈베리파이 시제품 제작 부품 및 센서 등등

smartstore.naver.com

 

피코 베이직 트레이닝보드의 기능은 아래와 같습니다.

 

라즈베리파이 피코 베이직 트레이닝 보드

 

DC 파워 홀더 : 5V 파워 잭을 결합하여 전원을 공급합니다.

보드 결합 핀 : 보드와 연결 할 수 있는 핀 헤더

OLED : 텍스트나 정보를 디스플레이 할 수 있는 OLED 

부저 : 주파수 신호로 소리를 나타낼 수 있습니다.

DHT11 센서 : 온도 습도를 측정하는 센서입니다.

LED : GPIO 신호 출력으로 ON OFF가 가능합니다.

SD CARD : SD CARD에 파일을 저장 할 수 있습니다.

BLE 모듈 : UART 통신으로 스마트폰과 무선 통신을 할 수 있습니다.

슬라이드 스위치를 이용하여 UART외부 컨넥터 및 블루투스를 이용한 제어가 가능합니다.

외부 전원 인가 단자 : PWM을 외부 전원으로 사용하여 12V 모터와 12V LED를 컨트롤 할 수 있습니다.

점퍼소켓을 이용하여 외부전원 및 내부 5V전원을 사용 할 수 있습니다.

PWM 출력단자 : PWM 신호를 출력하는 단자입니다.

DC모터 속도제어 및 LED 밝제어를 할 수 있습니다.

CDS : 빛을 감지하는 센서 입니다.

외부 모듈 연결핀: 외부 모듈을 사용하거나 I2C 확장 핀입니다.

버튼 : 버튼 스위치이며 디지털 신호를 입력 할 수 있습니다 .

WS2812 : 풀컬러 LED 이며 통신으로 컨트롤 가능합니다.

서보모터핀 : 서보모터를 사용할 수 있는 핀입니다.

가변저항 : 가변되는 저항체로 분배법칙을 이용하여 전압을 조절합니다.(ADC 제어 실습 가능)

릴레이 : 스위치와 같은 계념으로 5V신호를 이용하여 250V 10A까지 사용가능 합니다.

SMALL

피코 베이직 트레이닝 보드는 피코 도킹보드를 이용하여 사용이 가능합니다.

- 피코보드의 핀맵 입니다.

  *  헤더소켓이 앵글 커넥터 내장으로 실크와 실제 연결하는 부분이 반대로 되어있습니다.

     이점을 유의하여 연결하여야 합니다.

피코 핀 맵 베이지트레이닝 보드 핀 맵 베이지트레이닝 보드 핀 맵 피고 핀 맵
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GP0 / PWM1   
GP1 / PWM2   
GND   
GP2 / LED0   
GP3 / LED1   
GP4   
GP5   
GND   
GP6 / BUZZER   
GP7 / DHT11   
GP8 / SDMISO   
GP9 / SDCS   
GND   
GP10 / SDCLK   
GP11 / SDMOSI   
GP12 / RELAY   
GP13 / WS2812   
GND   
GP14 / SDA0   
GP15 / SDL0   
   VBUS
   VSYS
   GND
   3.3V_EN
   3.3V_OUT
   ADC_REF
   GP28
   GND
   GP27 / CdS
   GP26 / VR
   RUN / RESET
   GP22 / SW
   GND
   GP21
   GP20
   GP19 / SERVO1
   GP18 / SERVO2
   GND
   GP17 / RXD0
   GP16 / TXD0
40
39
38
37
36
35
34
33
32
31
30
29
28
27
26
25
24
23
22
21

 

반응형

 

- 라즈베리파이 피코 베이지 트레이닝보드 전체 기능제어 맛보기

  아래의 코드를 이용하여 동영상의 구동 제어 실습을 할 수 있습니다.

main.py

from machine import UART, Pin, I2C, ADC, PWM,SPI
from time import sleep
import neopixel
import ssd1306
import dht
import sdcard
import uos
import random
led1 = Pin(2,Pin.OUT)
led2 = Pin(3,Pin.OUT)
relay = Pin(12,Pin.OUT)#릴레이 설정
CdS_adc = ADC(Pin(27))
vr_adc = ADC(Pin(26)) 
buzzer = PWM(Pin(6))
i2c = I2C(1,scl=Pin(15), sda=Pin(14))#I2C설정
oled = ssd1306.SSD1306_I2C(128,64,i2c,0x3c)#OLED설정
dhtIn = Pin(7,Pin.IN) # 온/습도 센서 설정
dhtOut = dht.DHT11(dhtIn)# 온/습도 센서 설정
uart0 = UART(0, baudrate=115200, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17))# UART 설정
uart0.write("pico sensorBoard Test\n")
swCount=0
def handle_interrupt(sw):
    global swCount
    swCount = swCount+1
    if swCount==8:
        swCount=0    
sw = Pin(22,Pin.IN,Pin.PULL_UP)    
sw.irq(trigger=Pin.IRQ_FALLING, handler=handle_interrupt)
CS = Pin(9, Pin.OUT)
spi = machine.SPI(1,baudrate=1000000,polarity=0,phase=0,bits=8,firstbit=SPI.MSB,sck=Pin(10),mosi=Pin(11),miso=Pin(8))
sd = sdcard.SDCard(spi,CS)
vfs = uos.VfsFat(sd)
uos.mount(vfs, '/sd')
print(uos.listdir('/sd'))
servo1_pwm = Pin(19, Pin.OUT)
servo2_pwm = Pin(18, Pin.OUT)
servo1 = PWM(servo1_pwm)
servo2 = PWM(servo2_pwm)
servo1.freq(50)
servo2.freq(50)
servo1.duty_u16(0)
servo2.duty_u16(0)
in_min =0
in_max =65535
out_min =1000
out_max =9000
out1 = Pin(20,Pin.OUT)
pwm_out1 = PWM(out1)
pwm_out1.freq(500)
pwm_out1.duty_u16(0)
out2 = Pin(21,Pin.OUT)
pwm_out2 = PWM(out2)
pwm_out2.freq(500)
pwm_out2.duty_u16(0)
oled.fill(1)
oled.show()
led1.value(0)
led2.value(0)
sleep(1)
oled.fill(0)
oled.show()
led1.value(1)
led2.value(1)
sleep(1)
##########################################################################################
#NEOPIXEL FUN
n =4# 네오픽셀 개체 수
p =13# 핀 번호
np = neopixel.NeoPixel(Pin(p),n)# 네오픽셀 설정
def set_color(r,g,b):
    for i in range(n):
        np[i] = (r,g,b)
    np.write()
# bounce
def bounce(r, g, b, wait):
  for i in range(2* n):
    for j in range(n):
      np[j] = (r, g, b)
    if (i // n) % 2==0:
      np[i % n] = (0, 0, 0)
    else:
      np[n -1- (i % n)] = (0, 0, 0)
    np.write()
    sleep(wait)
# cycle
def cycle(r, g, b, wait):
  for i in range(n):
    for j in range(n):
      np[j] = (0, 0, 0)
    np[i % n] = (r, g, b)
    np.write()
    sleep(wait)
def wheel(pos):
  if pos <0or pos >255:
    return (0, 0, 0)
  if pos <85:
    return (255- pos *3, pos *3, 0)
  if pos <170:
    pos -=85
    return (0, 255- pos *3, pos *3)
  pos -=170
  return (pos *3, 0, 255- pos *3)
# rainbow 
def rainbow_cycle(wait):
  for j in range(255):
      if swCount ==2:
        for i in range(n):
            if swCount ==2:
              rc_index = (i *256// n) + j
              np[i] = wheel(rc_index &255)
            else: break
        np.write()
        sleep(wait)
      else: break
# turn off all pixels
def clear():
  for i in range(n):
    np[i] = (0, 0, 0)
    np.write()
    
##########################################################################################
tones = {
"B0": 31,"C1": 33,"CS1": 35,"D1": 37,"DS1": 39,"E1": 41,"F1": 44,"FS1": 46,
"G1": 49,"GS1": 52,"A1": 55,"AS1": 58,"B1": 62,"C2": 65,
"CS2": 69,"D2": 73,"DS2": 78,"E2": 82,"F2": 87,"FS2": 93,"G2": 98,
"GS2": 104,"A2": 110,"AS2": 117,"B2": 123,"C3": 131,"CS3": 139,
"D3": 147,"DS3": 156,"E3": 165,"F3": 175,"FS3": 185,
"G3": 196,"GS3": 208,"A3": 220,"AS3": 233,"B3": 247,"C4": 262,"CS4": 277,"D4": 294,"DS4": 311,
"E4": 330,"F4": 349,"FS4": 370,"G4": 392,"GS4": 415,"A4": 440,"AS4": 466,"B4": 494,"C5": 523,"CS5": 554,"D5": 587,"DS5": 622,"E5": 659,"F5": 698,
"FS5": 740,"G5": 784,"GS5": 831,"A5": 880,"AS5": 932,"B5": 988,"C6": 1047,"CS6": 1109,"D6": 1175,"DS6": 1245,"E6": 1319,"F6": 1397,"FS6": 1480,"G6": 1568,"GS6": 1661,
"A6": 1760,"AS6": 1865,"B6": 1976,"C7": 2093,"CS7": 2217,"D7": 2349,"DS7": 2489,"E7": 2637,"F7": 2794,"FS7": 2960,"G7": 3136,"GS7": 3322,"A7": 3520,
"AS7": 3729,"B7": 3951,"C8": 4186,"CS8": 4435,"D8": 4699,"DS8": 4978
}
song = ["E5","G5","A5","P","E5","G5","B5","A5","P","E5","G5","A5","P","G5","E5"]
mario = ["E7", "E7", 0, "E7", 0, "C7", "E7", 0, "G7", 0, 0, 0, "G6", 0, 0, 0, "C7", 0, 0, "G6",
         0, 0, "E6", 0, 0, "A6", 0, "B6", 0, "AS6", "A6", 0, "G6", "E7", 0, "G7", "A7", 0, "F7", "G7",
         0, "E7", 0,"C7", "D7", "B6", 0, 0, "C7", 0, 0, "G6", 0, 0, "E6", 0, 0, "A6", 0, "B6", 0,
         "AS6", "A6", 0, "G6", "E7", 0, "G7", "A7", 0, "F7", "G7", 0, "E7", 0,"C7", "D7", "B6", 0, 0]
def playtone(frequency):
    buzzer.duty_u16(30000)
    buzzer.freq(frequency)
def bequiet():
    buzzer.duty_u16(0)
def playsong(mysong):
    for i in range(len(mysong)):
        if swCount ==1:
            if (mysong[i] =="P"or mysong[i] ==0 ):
                bequiet()
            else:
                playtone(tones[mysong[i]])
        else: break
        sleep(0.2)
    bequiet()
    
temp=0
humi=0
def tempHumiSensor():
    global temp, humi
    dhtOut.measure()
    temp = dhtOut.temperature()
    humi = dhtOut.humidity()
    sleep(0.5)
    
VRData=0
def adcInput(ch):
    global VRData
    if ch ==0: #VR
        VRData = vr_adc.read_u16()
        VRDataV = (3.3/65535) * VRData
        VRDataV = round(VRDataV,2)
        return VRDataV
    elif ch ==1: #CdS
        CdSData = CdS_adc.read_u16()
        CdSDataV = (3.3/65535) * CdSData
        CdSDataV = round(CdSDataV,2)
        return CdSDataV
   
#file = open("/sd/sample1.txt","w")
#file.write("SDCARD DATA TEST\n")
#file.close()
def sdcardwrite():
    led2.value(0)
    file=open("/sd/sample1.txt","a")
    file.write("{:>5d}  Temperature : {:.0f}C   Humidity : {:.0f}%   VRVolt : {:.2f}V   CdSVolt : {:.2f}V   RELAY : {}\r\n".format(num, temp, humi, adcInput(0),adcInput(1),relayState))
    file.close()
    led2.value(1)
    
##########################################################################################
num=1
relayState=0
whileTrue:         
               
    print(uart0.readline())
        
        
    tempHumiSensor()
    print('Temperature = {:<05.2f}C   Humidity = {:.2f}%'.format(temp,humi))
    print('CdS Volt    = {:<05.2f}V   VR Volt  = {:.2f}V'.format(adcInput(0),adcInput(1)))
    print('SW COUNTER = {0}\n'.format(swCount))
        
        
    vrInput = adcInput(0)
    cdsInput = adcInput(1)       
    if cdsInput <=1:
        relay.off() #relay on
        relayState=1
    else: 
        relay.on() #relay off
        relayState=0
    uart0.write("temp : ")
    uart0.write(str(temp))
    uart0.write('C')
    uart0.write("   Humi : ")
    uart0.write(str(humi))
    uart0.write('%')
    uart0.write("   CdSV : ")
    uart0.write(str(cdsInput))
    uart0.write('V')
    uart0.write("   VR_V : ")
    uart0.write(str(vrInput))
    uart0.write('V')
    uart0.write("   SW COUNTER : ")
    uart0.write(str(swCount))
    uart0.write('\n')
      
      
    oled.fill(0)
    oled.text("Temp(C) : ",0,0)
    oled.text(str(temp),80,0)
    oled.text("Humi(%) : ",0,12)
    oled.text(str(humi),80,12)
    oled.text("CdS(V)  : ",0,24)
    oled.text(str(cdsInput),80,24)
    oled.text("VR(V)   : ",0,36)
    oled.text(str(vrInput),80,36)
    if swCount==1:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(BUZZER)",50,48)                    
    elif swCount==2:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(WS2812)",50,48)                   
    elif swCount==3:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(SERVO1)",50,48)                   
    elif swCount==4:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(SERVO2)",50,48)                    
    elif swCount==5:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(PWM1)",50,48)                            
    elif swCount==6:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(PWM2)",50,48)
    elif swCount==7:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
        oled.text("(SDCARD)",50,48)
    else:
        oled.text("SW : ",0,48)
        oled.text(str(swCount),40,48)
    oled.show()  
    if swCount==1:
        led1.value(0)        
        playsong(mario)
        led1.value(1)
                    
    elif swCount==2:
        led1.value(0)
        rainbow_cycle(0.01)
        clear()
        led1.value(1)
                    
    elif swCount==3:
        servo1Data = (VRData - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
        servo1.duty_u16(int(servo1Data))
                   
    elif swCount==4:
        servo2Data = (VRData - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
        servo2.duty_u16(int(servo2Data))
                    
    elif swCount==5:    
        pwm_out1.duty_u16(VRData)
                            
    elif swCount==6:           
        pwm_out2.duty_u16(VRData)
    
    elif swCount==7:           
        sdcardwrite()
        num = num +1
        if num ==101:
            led2.value(0)
            file=open("/sd/sample1.txt","a")
            file.write("\r\n")
            file.close()
            led2.value(1)
            num=1
       
    else:
        servo1.duty_u16(0)
        servo2.duty_u16(0)
        pwm_out1.duty_u16(0)
        pwm_out2.duty_u16(0)
      
    sleep(0.5)

ssd1306.py

from micropython import const
import framebuf

# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_IREF_SELECT = const(0xAD)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)

class SSD1306(framebuf.FrameBuffer):
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        self.buffer = bytearray(self.pages * self.width)
        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
        self.init_display()

    def init_display(self):
        for cmd in (
            SET_DISP,  # display off
            # address setting
            SET_MEM_ADDR,
            0x00,  # horizontal
            # resolution and layout
            SET_DISP_START_LINE,  # start at line 0
            SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
            SET_MUX_RATIO,
            self.height - 1,
            SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
            SET_DISP_OFFSET,
            0x00,
            SET_COM_PIN_CFG,
            0x02 if self.width > 2 * self.height else 0x12,
            # timing and driving scheme
            SET_DISP_CLK_DIV,
            0x80,
            SET_PRECHARGE,
            0x22 if self.external_vcc else 0xF1,
            SET_VCOM_DESEL,
            0x30,  # 0.83*Vcc
            # display
            SET_CONTRAST,
            0xFF,  # maximum
            SET_ENTIRE_ON,  # output follows RAM contents
            SET_NORM_INV,  # not inverted
            SET_IREF_SELECT,
            0x30,  # enable internal IREF during display on
            # charge pump
            SET_CHARGE_PUMP,
            0x10 if self.external_vcc else 0x14,
            SET_DISP | 0x01,  # display on
        ):  # on
            self.write_cmd(cmd)
        self.fill(0)
        self.show()

    def poweroff(self):
        self.write_cmd(SET_DISP)

    def poweron(self):
        self.write_cmd(SET_DISP | 0x01)

    def contrast(self, contrast):
        self.write_cmd(SET_CONTRAST)
        self.write_cmd(contrast)

    def invert(self, invert):
        self.write_cmd(SET_NORM_INV | (invert & 1))

    def rotate(self, rotate):
        self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3))
        self.write_cmd(SET_SEG_REMAP | (rotate & 1))

    def show(self):
        x0 = 0
        x1 = self.width - 1
        if self.width != 128:
            # narrow displays use centred columns
            col_offset = (128 - self.width) // 2
            x0 += col_offset
            x1 += col_offset
        self.write_cmd(SET_COL_ADDR)
        self.write_cmd(x0)
        self.write_cmd(x1)
        self.write_cmd(SET_PAGE_ADDR)
        self.write_cmd(0)
        self.write_cmd(self.pages - 1)
        self.write_data(self.buffer)


class SSD1306_I2C(SSD1306):
    def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.temp = bytearray(2)
        self.write_list = [b"\x40", None]  # Co=0, D/C#=1
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.temp[0] = 0x80  # Co=1, D/C#=0
        self.temp[1] = cmd
        self.i2c.writeto(self.addr, self.temp)

    def write_data(self, buf):
        self.write_list[1] = buf
        self.i2c.writevto(self.addr, self.write_list)


class SSD1306_SPI(SSD1306):
    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
        self.rate = 10 * 1024 * 1024
        dc.init(dc.OUT, value=0)
        res.init(res.OUT, value=0)
        cs.init(cs.OUT, value=1)
        self.spi = spi
        self.dc = dc
        self.res = res
        self.cs = cs
        import time

        self.res(1)
        time.sleep_ms(1)
        self.res(0)
        time.sleep_ms(10)
        self.res(1)
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        self.cs(1)
        self.dc(0)
        self.cs(0)
        self.spi.write(bytearray([cmd]))
        self.cs(1)

    def write_data(self, buf):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(buf)
        self.cs(1)

dht.py

import sys

if sys.platform.startswith("esp"):
    from esp import dht_readinto
elif sys.platform == "mimxrt":
    from mimxrt import dht_readinto
elif sys.platform == "rp2":
    from rp2 import dht_readinto
elif sys.platform == "pyboard":
    from pyb import dht_readinto
else:
    from machine import dht_readinto


class DHTBase:
    def __init__(self, pin):
        self.pin = pin
        self.buf = bytearray(5)

    def measure(self):
        buf = self.buf
        dht_readinto(self.pin, buf)
        if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]:
            raise Exception("checksum error")


class DHT11(DHTBase):
    def humidity(self):
        return self.buf[0]

    def temperature(self):
        return self.buf[2]


class DHT22(DHTBase):
    def humidity(self):
        return (self.buf[0] << 8 | self.buf[1]) * 0.1

    def temperature(self):
        t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1
        if self.buf[2] & 0x80:
            t = -t
        return t

sdcard.py

from micropython import const
import time

_CMD_TIMEOUT = const(100)

_R1_IDLE_STATE = const(1 << 0)
# R1_ERASE_RESET = const(1 << 1)
_R1_ILLEGAL_COMMAND = const(1 << 2)
# R1_COM_CRC_ERROR = const(1 << 3)
# R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
# R1_ADDRESS_ERROR = const(1 << 5)
# R1_PARAMETER_ERROR = const(1 << 6)
_TOKEN_CMD25 = const(0xFC)
_TOKEN_STOP_TRAN = const(0xFD)
_TOKEN_DATA = const(0xFE)


class SDCard:
    def __init__(self, spi, cs, baudrate=1320000):
        self.spi = spi
        self.cs = cs

        self.cmdbuf = bytearray(6)
        self.dummybuf = bytearray(512)
        self.tokenbuf = bytearray(1)
        for i in range(512):
            self.dummybuf[i] = 0xFF
        self.dummybuf_memoryview = memoryview(self.dummybuf)

        # initialise the card
        self.init_card(baudrate)

    def init_spi(self, baudrate):
        try:
            master = self.spi.MASTER
        except AttributeError:
            # on ESP8266
            self.spi.init(baudrate=baudrate, phase=0, polarity=0)
        else:
            # on pyboard
            self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)

    def init_card(self, baudrate):

        # init CS pin
        self.cs.init(self.cs.OUT, value=1)

        # init SPI bus; use low data rate for initialisation
        self.init_spi(100000)

        # clock card at least 100 cycles with cs high
        for i in range(16):
            self.spi.write(b"\xff")

        # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
        for _ in range(5):
            if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
                break
        else:
            raise OSError("no SD card")

        # CMD8: determine card version
        r = self.cmd(8, 0x01AA, 0x87, 4)
        if r == _R1_IDLE_STATE:
            self.init_card_v2()
        elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
            self.init_card_v1()
        else:
            raise OSError("couldn't determine SD card version")

        # get the number of sectors
        # CMD9: response R2 (R1 byte + 16-byte block read)
        if self.cmd(9, 0, 0, 0, False) != 0:
            raise OSError("no response from SD card")
        csd = bytearray(16)
        self.readinto(csd)
        if csd[0] & 0xC0 == 0x40:  # CSD version 2.0
            self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
        elif csd[0] & 0xC0 == 0x00:  # CSD version 1.0 (old, <=2GB)
            c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4
            c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7
            self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2))
        else:
            raise OSError("SD card CSD format not supported")
        # print('sectors', self.sectors)

        # CMD16: set block length to 512 bytes
        if self.cmd(16, 512, 0) != 0:
            raise OSError("can't set 512 block size")

        # set to high data rate now that it's initialised
        self.init_spi(baudrate)

    def init_card_v1(self):
        for i in range(_CMD_TIMEOUT):
            self.cmd(55, 0, 0)
            if self.cmd(41, 0, 0) == 0:
                self.cdv = 512
                # print("[SDCard] v1 card")
                return
        raise OSError("timeout waiting for v1 card")

    def init_card_v2(self):
        for i in range(_CMD_TIMEOUT):
            time.sleep_ms(50)
            self.cmd(58, 0, 0, 4)
            self.cmd(55, 0, 0)
            if self.cmd(41, 0x40000000, 0) == 0:
                self.cmd(58, 0, 0, 4)
                self.cdv = 1
                # print("[SDCard] v2 card")
                return
        raise OSError("timeout waiting for v2 card")

    def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
        self.cs(0)

        # create and send the command
        buf = self.cmdbuf
        buf[0] = 0x40 | cmd
        buf[1] = arg >> 24
        buf[2] = arg >> 16
        buf[3] = arg >> 8
        buf[4] = arg
        buf[5] = crc
        self.spi.write(buf)

        if skip1:
            self.spi.readinto(self.tokenbuf, 0xFF)

        # wait for the response (response[7] == 0)
        for i in range(_CMD_TIMEOUT):
            self.spi.readinto(self.tokenbuf, 0xFF)
            response = self.tokenbuf[0]
            if not (response & 0x80):
                # this could be a big-endian integer that we are getting here
                for j in range(final):
                    self.spi.write(b"\xff")
                if release:
                    self.cs(1)
                    self.spi.write(b"\xff")
                return response

        # timeout
        self.cs(1)
        self.spi.write(b"\xff")
        return -1

    def readinto(self, buf):
        self.cs(0)

        # read until start byte (0xff)
        for i in range(_CMD_TIMEOUT):
            self.spi.readinto(self.tokenbuf, 0xFF)
            if self.tokenbuf[0] == _TOKEN_DATA:
                break
            time.sleep_ms(1)
        else:
            self.cs(1)
            raise OSError("timeout waiting for response")

        # read data
        mv = self.dummybuf_memoryview
        if len(buf) != len(mv):
            mv = mv[: len(buf)]
        self.spi.write_readinto(mv, buf)

        # read checksum
        self.spi.write(b"\xff")
        self.spi.write(b"\xff")

        self.cs(1)
        self.spi.write(b"\xff")

    def write(self, token, buf):
        self.cs(0)

        # send: start of block, data, checksum
        self.spi.read(1, token)
        self.spi.write(buf)
        self.spi.write(b"\xff")
        self.spi.write(b"\xff")

        # check the response
        if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
            self.cs(1)
            self.spi.write(b"\xff")
            return

        # wait for write to finish
        while self.spi.read(1, 0xFF)[0] == 0:
            pass

        self.cs(1)
        self.spi.write(b"\xff")

    def write_token(self, token):
        self.cs(0)
        self.spi.read(1, token)
        self.spi.write(b"\xff")
        # wait for write to finish
        while self.spi.read(1, 0xFF)[0] == 0x00:
            pass

        self.cs(1)
        self.spi.write(b"\xff")

    def readblocks(self, block_num, buf):
        nblocks = len(buf) // 512
        assert nblocks and not len(buf) % 512, "Buffer length is invalid"
        if nblocks == 1:
            # CMD17: set read address for single block
            if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
                # release the card
                self.cs(1)
                raise OSError(5)  # EIO
            # receive the data and release card
            self.readinto(buf)
        else:
            # CMD18: set read address for multiple blocks
            if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
                # release the card
                self.cs(1)
                raise OSError(5)  # EIO
            offset = 0
            mv = memoryview(buf)
            while nblocks:
                # receive the data and release card
                self.readinto(mv[offset : offset + 512])
                offset += 512
                nblocks -= 1
            if self.cmd(12, 0, 0xFF, skip1=True):
                raise OSError(5)  # EIO

    def writeblocks(self, block_num, buf):
        nblocks, err = divmod(len(buf), 512)
        assert nblocks and not err, "Buffer length is invalid"
        if nblocks == 1:
            # CMD24: set write address for single block
            if self.cmd(24, block_num * self.cdv, 0) != 0:
                raise OSError(5)  # EIO

            # send the data
            self.write(_TOKEN_DATA, buf)
        else:
            # CMD25: set write address for first block
            if self.cmd(25, block_num * self.cdv, 0) != 0:
                raise OSError(5)  # EIO
            # send the data
            offset = 0
            mv = memoryview(buf)
            while nblocks:
                self.write(_TOKEN_CMD25, mv[offset : offset + 512])
                offset += 512
                nblocks -= 1
            self.write_token(_TOKEN_STOP_TRAN)

    def ioctl(self, op, arg):
        if op == 4:  # get number of blocks
            return self.sectors

* main.py, ssd1306.py, dht.py, sdcard.py 모듈을 Pico 보드에 넣으면 됩니다.

* Thonny 프로그램에서의 F5 또는 재생 버튼을 누르면 보드의 각 기능을 체크할 수 있습니다.

라즈베리파이 피코 베이직 트레이닝 보드

 

라즈베리 파이 피코 실습보드 / 베이직 트레이닝 보드 / 마이크로 파이썬 라즈베리 파이 피코 실

[포레스텍] IoT에 관한 모든것 아두이노 라즈베리파이 시제품 제작 부품 및 센서 등등

smartstore.naver.com

라즈베리파이 피코 도킹보드

 

라즈베리 파이 피코 도킹 보드 / 마이크로 파이썬 라즈베리 파이 피코 도킹 보드 : 포레스텍

[포레스텍] IoT에 관한 모든것 아두이노 라즈베리파이 시제품 제작 부품 및 센서 등등

smartstore.naver.com

 

 

 

728x90
반응형
LIST

댓글