SAMD21 Code Examples

ตัวอย่างโค้ด CircuitPython สำหรับบอร์ด SAMD21 เช่น Seeeduino XIAO หรือ SAMD21 M0-Mini

เริ่มต้นด้วยการทำให้ LED บนบอร์ดกระพริบ (ขา D13) โดยใช้คำสั่งจาก digitalio เพื่อใช้งานขา GPIO แบบดิจิทัล (Digital I/O)

import digitalio
from board import *
import time

# use Onboard LED on the XIAO board
led = digitalio.DigitalInOut(D13) 
led.direction = digitalio.Direction.OUTPUT

try:
    while True: # press Ctrl+C to stop
        led.value = True
        time.sleep(0.1)
        led.value = False
        time.sleep(0.1)
except KeyboardInterrupt:
    pass
led.value = 0 # LED output level LOW
led.deinit()  # release the LED pin (D13)
print('Done')

ในการหน่วงเวลา ก็ใช้คำสั่ง time.sleep() โดยระบุค่าเป็นตัวเลขที่มีหน่วยเป็นวินาที

หรือจะเขียนโค้ดในรูปแบบอื่นที่ทำงานได้เหมือนกัน ดังนี้

import digitalio
from board import *
import time

led = digitalio.DigitalInOut(D13)
led.direction = digitalio.Direction.OUTPUT

try:
    t = int(1000*time.monotonic()) # in msec
    while True: # press Ctrl+C to stop
        now = int(1000*time.monotonic()) # in msec
        # toggle LED every 100 msec
        if now - t >= 100:
            t = now
            led.value = not led.value
except KeyboardInterrupt:
    pass
led.value = 0
led.deinit()
print('Done')

ในตัวอย่างนี้ ได้ใช้คำสั่ง time.monotonic() ซึ่งจะได้ค่าเป็นเลขทศนิยมแบบ float นำมาคูณด้วย 1000 แล้วแปลงให้เป็นข้อมูลแบบ int ดังนั้นจึงได้ค่าตัวเลขในหน่วยเป็น msec และค่าที่อ่านได้นี้ จะใช้ในการเปรียบเทียบกับค่าเวลาที่ได้บันทึกไว้ แล้วตรวจสอบดูว่า เวลาผ่านไป 100 msec หรือไม่ ถ้าใช่ ให้สลับสถานะของขาเอาต์พุตหนึ่งครั้ง และอัปเดทค่าเวลาที่บันทึกไว้

หรือจะเขียนโค้ดโดยใช้คำสั่งของ pwmio เพื่อสร้างสัญญาณ PWM ให้มีความถี่ต่ำ เช่น 10Hz และมีค่า Duty Cycle เท่ากับ 50% เพื่อใช้เป็นสัญญาณสำหรับ LED (ขา D13) ก็ได้เช่นกัน

import pwmio
from board import *
import time

pwm = pwmio.PWMOut(pin=D13,duty_cycle=0,frequency=10)
pwm.duty_cycle = (2**15 - 1) # (16-bit value) -> 50%
try:
    while True:
        time.sleep(1.0)
except KeyboardInterrupt:
    pass
pwm.duty_cycle = 0 # set duty cycle to 0
pwm.deinit() # relase the PWM output pin
print('Done')

ข้อสังเกต: ถ้าใช้บอร์ด SAMD21 M0-Mini แทน Seeeduino XIAO ขา D13 (Arduino Pin) ตรงกับขา PA17 (SAMD21 Pin) ซึ่งไม่มีวงจร LED Onboard ดังนั้นจะต้องต่อวงจร LED ภายนอกเพิ่ม

โค้ดตัวอย่างที่ 2: NeoPixel RGB LEDs

ตัวอย่างถัดไปสาธิตการใช้คำสั่งของไลบรารี neopixel_write เพื่อกำหนดสีให้โมดูล NeoPixel (WS2812B) RGB LEDs

เลือกใช้ขา D10 เป็นขาเอาต์พุต เพื่อนำไปต่อกับขา DIN ของโมดูล NeoPixel ซึ่งมีทั้งหมด 8 พิกเซล และกำหนดให้ทุกพิกเซลเป็นสีแดง เริ่มต้นด้วยความสว่างระดับ 255 แล้วค่อย ๆ ลดลงจนเป็น 0

import board
import neopixel_write
import digitalio
import time

np_pin = digitalio.DigitalInOut(board.D10)
np_pin.direction = digitalio.Direction.OUTPUT
NUM_PIXELS = 8
for i in range(256):
    colors = bytearray(NUM_PIXELS*[0,255-i,0])  # GRB
    neopixel_write.neopixel_write(np_pin, colors)
    time.sleep(0.01)
np_pin.deinit() # release the output pin

หรือจะใช้คำสั่งของไลบรารี neopixel (API) ก็ได้เช่นกัน ตามตัวอย่างโค้ดต่อไปนี้ และจะต้องใช้ไฟล์ neopixel.mpy และ adafruit_pypixelbuf.mpy ซึ่งมีอยู่ใน CircuiPython Library Bundle และให้นำไฟล์ทั้งสองไปใส่ลงใน Flash File Storage ของ CircuitPython ภายใต้ /lib

import board
import time
import neopixel

NUM_PIXELS = 8
# bpp=3 (3 bytes per pixel), pixel order GRB 
pixels = neopixel.NeoPixel(board.D10, NUM_PIXELS,
    bpp=3, pixel_order=neopixel.GRB, auto_write=False)

color = (255, 0, 0) # red, green, blue
pixels[0] = color
for i in range(NUM_PIXELS): # turn on (use red color)
    pixels[i] = color if i==0 else pixels[i-1]
    pixels.show()
    time.sleep(0.1)
    
pixels.fill( (0,255,0) ) # change all pixels to green
for i in range(101): # fade the RGB LEDS off
    pixels.brightness = (100-i)/100.0
    pixels.show()
    time.sleep(0.02)

time.sleep(2.0)
# turn off the Neopixel strip and release pin
pixels.deinit() 
del pixels

โค้ดตัวอย่างที่ 3: DHT22 Sensor Reading

ตัวอย่างถัดไปสาธิตการใช้ไลบรารี adafruit_dht (API) สำหรับอ่านค่าอุณหภูมิและความชื้นสัมพัทธ์ของโมดูล DHT11 / DHT22 ถ้าจะใช้งานไลบรารีดังกล่าว จะต้องใช้ไฟล์ adafruit_dht.mpy ร่วมด้วย ซึ่งมีอยู่ใน CircuiPython Library Bundle

import time
import board
from adafruit_dht import DHT22

dht = DHT22(pin=board.D9,use_pulseio=True)
try:
    text = '{:.1f} deg.C, {:.1f} %RH'
    while True: # press Ctrl+C to stop
        dht.measure() # perform measurement
        values = (dht.temperature, dht.humidity)
        print( text.format(*values) )
        time.sleep(2.0)
except KeyboardInterrupt:
    pass
dht.exit()
del dht

ในการต่อวงจรทดลอง ได้เลือกใช้ขา D9 สำหรับต่อกับขา DATA ของโมดูล DHT22 (ใช้แรงดันไฟเลี้ยง +3.3V)

โค้ดตัวอย่างที่ 4: SI7021 Sensor Reading

ตัวอย่างถัดไปสาธิตการใช้ไลบรารี adafruit_si7021 (API) เพื่ออ่านค่าอุณหภูมิและความชื้นสัมพัทธ์จากโมดูล SI7021 (Address=0x40) โดยใช้วิธีบัส I2C (ขาสัญญาณ SDL/D5 และ SDA/D4 สำหรับบอร์ด Seeeduino XIAO)

ไลบรารีต้องใช้ร่วมกับไลบรารี Adafruit Bus Device ซึ่งมีอยู่ใน CircuiPython Library Bundle และเราต้องใช้สองไฟล์นี้ร่วมด้วย

  • adafruit_bus_device/i2c_device

  • adafruit_bus_device/spi_device

import time
from busio import I2C
from board import SCL, SDA
import adafruit_si7021 as si7021

SI7021_ADDR = 0x40
i2c = I2C(SCL, SDA,frequency=100000) # 100kHz speed

addr_found = []
if i2c.try_lock():
    addr_found = i2c.scan()
    print("I2C found:", [hex(addr) for addr in addr_found])
    i2c.unlock()
if SI7021_ADDR not in addr_found:
    print('SI7021 not found')

dev = si7021.SI7021(i2c,address=SI7021_ADDR)
text = '{:.1f} deg.C, {:.1f} %RH'
try:
    while True: # press Ctrl+C to stop
        values = (dev.temperature,dev.relative_humidity)
        print( text.format(*values) )
        time.sleep(1.0)
except OSError:
    print('Sensor reading error!')
except KeyboardInterrupt:
    pass
finally:
    i2c.deinit()
print('Done')

โค้ดตัวอย่างที่ 5: BME680 Sensor Reading

ตัวอย่างนี้สาธิตการใช้ไลบรารี adafruit_bme680 (API) เพื่ออ่านค่าจากเซ็นเซอร์ BME680 (address=0x77) ผ่านทางบัส I2C แล้วนำค่าของอุณหภูมิ ความชื้นสัมพัทธ์ และความดันบรรยากาศ มาแสดงผลเป็นข้อความเอาต์พุต

import time
from busio import I2C
from board import SCL, SDA
import adafruit_bme680 as bme680

BME680_ADDR = 0x77
i2c = I2C(SCL, SDA,frequency=100000) # 100kHz speed

addr_found = []
if i2c.try_lock():
    addr_found = i2c.scan()
    print("I2C found:", [hex(addr) for addr in addr_found])
    i2c.unlock()
if BME680_ADDR not in addr_found:
    print('BME680 not found')

dev = bme680.Adafruit_BME680_I2C(i2c,address=BME680_ADDR)
text = '{:.1f} deg.C, {:.1f} %RH, {:.2f} hPa'
try:
    while True: # press Ctrl+C to stop
        t = dev.temperature       # deg.C
        h = dev.relative_humidity # %RH
        p = dev.pressure          # hPa
        print( text.format(t,h,p) )
        time.sleep(1.0)
except OSError:
    print('Sensor reading error!')
except KeyboardInterrupt:
    pass
finally:
    i2c.deinit()
print('Done')

โค้ดตัวอย่างที่ 6: DHT22 + SI7021 + BME680

ตัวอย่างนี้สาธิตการอ่านค่าจากเซ็นเซอร์จำนวน 3 ชนิดที่แตกต่างกันซึ่งได้มีการสาธิตการใช้งานแต่ละโมดูลในตัวอย่างก่อนหน้านี้ไปแล้ว

ในการรันโค้ด CircuitPython แนะนำให้ใช้ Mu Editor แทนการใช้งาน Thonny IDE เนื่องจากใช้หน่วยความจำน้อยกว่า และจะไม่เกิด Runtime Memory Error (SAMD21 มีหน่วยความจำ SRAM ค่อนข้างน้อย)

import time
import gc
from busio import I2C
from board import SCL, SDA, D9

SI7021_ADDR = 0x40
BME680_ADDR = 0x77
i2c = I2C(SCL, SDA)

addr_found = []
if i2c.try_lock():
    addr_found = i2c.scan()
    print("I2C found:", [hex(addr) for addr in addr_found])
    i2c.unlock()
if BME680_ADDR not in addr_found:
    print('BME680 not found')
if SI7021_ADDR not in addr_found:
    print('SI7021 not found')

def read_si7021(dev):
    text = 'SI7021: {:.1f} deg.C, {:.1f} %RH'
    t = dev.temperature
    h = dev.relative_humidity
    print( text.format(t,h) )

def read_bme680(dev):
    text = 'BME680: {:.1f} deg.C, {:.1f} %RH, {:.2f} hPa'
    t = dev.temperature # deg.C
    h = dev.relative_humidity # %RH
    p = dev.pressure          # hPa
    print( text.format(t,h,p) )

def read_dht22(dev):
    text = 'DHT22 : {:.1f} deg.C, {:.1f} %RH'
    dev.measure()
    values = (dev.temperature, dev.humidity)
    print( text.format(*values) )

try:
    while True: # press Ctrl+C to stop
        ## read DHT22
        import adafruit_dht as dht
        dev = dht.DHT22(pin=D9,use_pulseio=True)
        read_dht22(dev)
        dev.pulse_in.deinit()
        del dev
        gc.collect() # call garbage collector
        time.sleep(1.0)

        ## read SI7021
        import adafruit_si7021 as si7021
        dev = si7021.SI7021(i2c,address=SI7021_ADDR)
        read_si7021(dev)
        del dev
        gc.collect() # call garbage collector
        time.sleep(1.0)
        
        ## read BME680
        import adafruit_bme680 as bme680
        dev = bme680.Adafruit_BME680_I2C(i2c,address=BME680_ADDR)
        read_bme680(dev)
        del dev
        gc.collect()  # call garbage collector
        time.sleep(1.0)
        print(50*'-')

except OSError:
    print('Sensor reading error!')
except KeyboardInterrupt:
    pass
finally:
    i2c.deinit()
print('Done')

โค้ดตัวอย่างที่ 7: Analog Key Switches

ตัวอย่างนี้สาธิตการอ่านค่าสถานะจากปุ่มกดแบบแอนะล็อก โดยใช้คำสั่งของไลบรารี analogio ของ CircuitPython แล้วนำมาตรวจสอบค่าเพื่อดูว่า ตรงกับการกดปุ่มในกรณีใด ซึ่งมีทั้งหมด 5 ปุ่ม (SW1, ..., SW5) การกดปุ่มใดปุ่มหนึ่งจะทำให้ค่าที่อ่านได้จากขาแอนะล็อกอินพุตไม่เท่ากันในแต่ละกรณี ข้อมูลที่อ่านได้จากการใช้คำสั่งของ CircuitPython จะมีขนาด 16 บิต (0..65535) แต่ในตัวอย่างนี้ ข้อมูลตัวเลขนี้ จะถูกสเกลค่าให้ลดลงเป็น 10 บิต หรือ 0..1023

import time     
import board
from analogio import AnalogIn
from microcontroller import pin

## pin map for Seeeduino-XIAO
## A0=PA02, A1=PA04, A2=PA10, A3=PA11, A4=PA08, A5=PA09,
## A6=PB08, A7=PA09, A8=PA07, A9=PA05, A10=PA06

## For Seeeduino XIAO: A1 and PA04 are the same pin.
ain = AnalogIn(board.A1) # use A1 pin
#ain = AnalogIn(pin.PA04) # use PA04 pin

last_btn = 0
NUM_SAMPLES = 5
last_t = int(1000*time.monotonic())
try:
    while True:
        now = int(1000*time.monotonic())
        if now - last_t >= 50:
            last_t = now
        else:
            continue
        values = []
        for i in range(NUM_SAMPLES):
            # read a 16-bit value from the analog pin 
            value = ain.value >> 6 # reduce to 10 bits
            values.append(value) 
        # apply the median filter
        value = sorted(values)[NUM_SAMPLES//2]
        if value > 600: # no button press
            last_btn = 0
            continue
        btn = 0
        if value < 30:
            btn = 1
        elif value < 60:
            btn = 2
        elif value < 120:
            btn = 3
        elif value < 240:
            btn = 4
        elif value > 320 and value < 450:
            btn = 5
        if last_btn != btn and btn > 0:
            print( 'SW{} ({})'.format(btn, value) )
        last_btn = btn
except KeyboardInterrupt:
    pass
ain.deinit() # release the analog pin
print('Done')

โมดูลนี้มีขา GND, VCC, OUT ตามลำดับ

  • GND ต่อกับ GND ของบอร์ด XIAO

  • VCC ต่อกับ +3.3V ของบอร์ด XIAO

  • OUT ต่อกับขา A1/PA04 ของบอร์ด XIAO

โค้ดตัวอย่างที่ 8: PWM-based LED Fading

โค้ดสาธิตการสร้างสัญญาณ PWM ที่มีความถี่คงที่ เช่น 250Hz แต่ปรับค่า Duty Cycle ได้ เพื่อกำหนดความสว่างของ LED โดยใช้คำสั่งในไลบรารี pwmio

ในตัวอย่างนี้ได้เลือกใช้ขา PA18 และ PA19 สำหรับ LED จำนวน 2 ดวง (ทำงานแบบ Active-Low)

ถ้าใช้บอร์ด XIAO ขา PA18 และ PA19 ต่อกับวงจร LED สีน้ำเงินที่มีอยู่แล้วบนบอร์ด

import time
import pwmio
import board
from microcontroller import pin
import math

led_pins = [pin.PA18, pin.PA19]
pwm_objects = [
    pwmio.PWMOut(pin=pin,duty_cycle=65535,frequency=250)
    for pin in led_pins ]

# create a table of (N+1) sine wave values
N=64
sine_int = lambda i: int(65535*(1-math.sin(math.pi*i/N)))
values = [sine_int(i) for i in range(N+1)]

try:
    while True:
        for pwm in pwm_objects:
            for i in range(N+1):
                pwm.duty_cycle = values[i]
                time.sleep(0.04)
except KeyboardInterrupt:
    pass
for pwm in pwm_objects:
    pwm.deinit()
print('Done')

โค้ดตัวอย่างที่ 9: UART Loopback Test

ตัวอย่างนี้สาธิตการใช้คำสั่งของไลบรารี busio (API) ที่เกี่ยวข้องกับการรับส่งข้อมูลผ่าน UART และทดสอบการส่งข้อมูลซึ่งเป็นข้อความทีละบรรทัด ออกทางขา TX แล้วรับข้อมูลกลับเข้ามาที่ขา RX ในลักษณะ Loopback (ต้องใช้สาย Jumper Wire เขื่อมต่อขา TX ไปยัง RX) และเลือกใช้ค่า Baudrate เท่ากับ 115200

ถ้าทดสอบการทำงานกับบอร์ด XIAO ขา TX และ RX คือ ขา D6/PB08 และ D7/PB09 ตามลำดับ

import board
import busio

# UART loopback test: connect TX pin to RX pin

uart = busio.UART(board.TX, board.RX,
    bits=8, parity=None, stop=1, timeout=0.1,
    baudrate=115200)
    
for i in range(10): # repeat 10 times
    text = 'count: {}\n'.format(i)
    uart.write( bytes(text, 'utf-8') ) # send string
    data = uart.readline()             # receive string
    print( str(data,'utf-8').strip() )
uart.deinit()

โค้ดตัวอย่างที่ 10: Laser Dust Sensor Reading

ตัวอย่างนี้สาธิตการอ่านค่าจากเซ็นเซอร์ประเภท Particulate Matter Concentration Sensor (Laser Dust Sensor) เช่น รุ่น PMS7003 หรือ PMS9003M (Plantower) สำหรับวัดปริมาณฝุ่น PM1.0 / PM2.5 / PM10 หน่วยเป็น µg/m^3 (ไมโครกรัม/ลูกบาศก์เมตร)

โมดูล PMS7003 ใช้แรงดันไฟเลี้ยง +5V (แต่มีระดับ Logic Level +3.3V) และเมื่อเริ่มทำงาน จะส่งข้อมูลจำนวน 32 ไบต์ ต่อการอ่านค่าหนึ่งครั้ง ทุก ๆ 1 วินาที โดยอัตโนมัติ (Default Mode) ออกทาง Serial และใช้ความเร็ว Baudrate 9600 ในการรับส่งข้อมูล

import board
import busio
import time

def pms7003( uart ):
    if uart.in_waiting < 32:
        return None
    try:
        data = uart.read(32) # read the next 32 bytes
        if data[0] != 0x42 and data[1] != 0x4d:
            uart.read(512) # invalid start bytes, flush input data
            return None
    except OSError:
        return None

    data = data[2:] # skip the first two bytes
    # get the data length (in bytes)
    data_len = (data[0] << 8) | data[1]
    # Standard particle concentration (CF-1)
    pm1_0 = (data[2] << 8) | data[3] 
    pm2_5 = (data[4] << 8) | data[5] 
    pm10  = (data[6] << 8) | data[7]
    values = {}        
    values['std'] = (pm10, pm2_5, pm1_0)
    # Atmospheric particulate concentration
    pm1_0 = (data[8]  << 8) | data[9] 
    pm2_5 = (data[10] << 8) | data[11] 
    pm10  = (data[12] << 8) | data[13]
    values['atm'] = (pm10, pm2_5, pm1_0)
    version  = data[26]
    err_code = data[27]
    cksum_calculated = (data[28] << 8) | data[29]
    cksum_expected   = sum(data[:-2]) + sum([0x42,0x4d])
    if cksum_calculated != cksum_expected or err_code !=0:
        return None
    text = '{{"pm10":{}, "pm2.5":{}, "pm1.0":{}, "unit":"ug/m^3"}}'
    return text.format(*values['std'])

uart = busio.UART( board.TX, board.RX,
    bits=8, parity=None, stop=1,
    timeout=0.1, baudrate=9600)

try:
    uart.read(512) # flush input data from serial
except OSError:
    print('Serial error')

try:
    while True:
        result = pms7003(uart)
        if result:
            print(result)
            time.sleep(5.0)
except KeyboardInterrupt:
    pass
uart.deinit()
print('Done')

ตัวอย่างข้อความเอาต์พุตหนึ่งบรรทัด

{"pm10":41, "pm2.5":36, "pm1.0":23, "unit":"ug/m^3"}

การเชื่อมต่อกับโมดูล PSM9003M จะเชื่อมต่อผ่าน PCB Adapter ที่ด้านหนึ่งเชื่อมต่อกับโมดูลดังกล่าวด้วยสายเคเบิล (มาพร้อมกับโมดูล) และอีกด้านหนึ่งจะเป็น Pin Header แบบ 6 ขา (2.54mm spacing) และมีขาตามลำดับดังนี้

  • VCC (+5V)

  • GND

  • SET (N.C.)

  • RXD (เชื่อมต่อกับขา TX ของบอร์ด XIAO)

  • TXD (เชื่อมต่อกับขา RX ของบอร์ด XIAO)

  • RST (ให้เชื่อมต่อแบบ Pull-up ไปยัง 3.3V)

โค้ดตัวอย่างนี้ สามารถใช้ได้กับโมดูล PMS7003 ของ Plantower ได้เช่นกัน

โค้ดตัวอย่างที่ 11: SHT31-D Sensor Reading

ตัวอย่างนี้สาธิตการอ่านค่าจากโมดูล SHT31-D ซึ่งเป็นเซ็นเซอร์วัดอุณหภูมิและความชื้นสัมพัทธ์ และใช้วิธีสื่อสารข้อมูลด้วย I2C อุปกรณีนี้มีหมายเลขแอดเดรสเท่ากับ 0x44

การเขียนโค้ดเพื่ออ่านค่าจาก SHT31-D ก็ทำได้ง่าย เนื่องจากมีไลบรารีให้ใช้งานคือ adafruit_sht31d (API) ดังนั้นถ้าจะรันโค้ดตัวอย่าง จะต้องนำไฟล์ adafruit_sht31d.mpy และไฟล์ของ Adafruit Bus Device ไปใส่ลงในไดเรกทอรี /lib ภายใน Flash File Storage ของ CircuitPython ด้วย

import time
from busio import I2C
import board
from microcontroller import pin
import adafruit_sht31d

SHT31D_ADDR = 0x44
## 1) use board pins or
#scl_pin, sda_pin = board.SCL, board.SDA 
## 2) use microcontroller pins
scl_pin, sda_pin = pin.PA23, pin.PA22

i2c = I2C(scl_pin, sda_pin, frequency=100000)

addr_found = []
if i2c.try_lock():
    addr_found = i2c.scan() # scan I2C devices
    print("I2C found:", [hex(addr) for addr in addr_found])
    i2c.unlock()
if SHT31D_ADDR not in addr_found:
    print('SHT31D not found')
else:
    print('SHT31D found')

dev = adafruit_sht31d.SHT31D(i2c,address=SHT31D_ADDR)
text = '{:.1f} deg.C, {:.1f} %RH'
try:
    while True: # press Ctrl+C to stop
        values = (dev.temperature,dev.relative_humidity)
        print( text.format(*values) )
        time.sleep(2.0)
except OSError:
    print('Sensor reading error!')
except KeyboardInterrupt:
    pass
finally:
    i2c.deinit()
print('Done')

โค้ดตัวอย่างที่ 12: Rotary Encode Input

ตัวอย่างนี้สาธิตการตรวจสอบการเปลี่ยนตำแหน่งของ (Incremental) Rotary Encoder ที่มีอินพุต-ดิจิทัล 2 ขา (Channel A & B) ซึ่งมีลักษณะเป็นสัญญาณแบบพัลส์ เมื่อมีการหมุนเปลี่ยนตำแหน่ง และนำไปต่อเข้าที่ขา board.D0 และ board.D1 ตามลำดับ

ในการตรวจสอบและอ่านค่าตำแหน่ง (Postion) จาก Rotary Encoder เราสามารถใช้คำสั่งของไลบรารี rotaryio (API) และใช้คลาส IncrementalEncoder

การเปลี่ยนตำแหน่งดังกล่าว มีสองทิศทางที่เป็นไปได้คือ การหมุนทวนหรือการหมุนตามเข็มนาฬิกา และเราจะตรวจสอบทิศทางการหมุน เพื่อมาใช้ในการเพิ่มหรือลดระดับความสว่างของ Neopixel (แบบ 12 Pixels) โดยเลือกใช้สีแดง และใช้ขา board.D2 เป็นขาสัญญาณเอาต์พุต

ข้อสังเกต: ในตัวอย่างนี้จะต้องใช้ไฟล์ที่เป็นไลบรารีร่วมด้วยได้แก่ neopixel.mpy and adafruit_pypixelbuf.mpy

import time
from rotaryio import IncrementalEncoder
from board import *
import neopixel

NUM_PIXELS = 12
# bpp=3 (3 bytes per pixel), pixel order GRB 
pixels = neopixel.NeoPixel(D2, NUM_PIXELS,
    bpp=3, pixel_order=neopixel.GRB, auto_write=False)

enc = IncrementalEncoder(D0, D1)
last_position = enc.position
try:
    level = 127 # brightness level
    while True:
        # read current position
        position = enc.position
        if position != last_position:
            delta = position - last_position
            level = (level + 16*delta)
            level = min(255,level)
            level = max(0,level)
            pixels.fill( (level,0,0) )
            pixels.show()
            print('pos={}, level={}'.format(position,level))
        last_position = position
        time.sleep(0.01)
except KeyboardInterrupt:
    pass
enc.deinit()
pixels.deinit()
print('Done')

ข้อสังเกต: ในการต่อวงจรบนเบรดบอร์ดเพื่อใช้งานโมดูล Rotary Encoder และ NeoPixel ได้ใช้แรงดันไฟเลี้ยง +3.3V จากโมดูล Voltage Regulator (LM1117-3.3) ที่แปลง +5V (VUSB) ให้เป็น +3.3V

กล่าวสรุป

เนื้อหาในส่วนนี้ได้นำเสนอตัวอย่างการเขียนโค้ด CircuitPython สำหรับไมโครคอนโทรลเลอร์ SAMD21 เช่น การเชื่อมต่อและอ่านค่าอินพุตจากโมดูลเซ็นเซอร์ประเภทต่าง ๆ

เผยแพร่ภายใต้ลิขสิทธิ์ Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)

Last updated