import machineimport utime as time# use the on-board LED (GP25 pin)led = machine.Pin( 25, machine.Pin.OUT )try:whileTrue: state =not led.value() led.value( state )print('LED state:', state) time.sleep(0.5)exceptKeyboardInterrupt:passled.value(0)# turn off LED
import utime as timefrom machine import Pin, PWM# use onboard LED and PWM output pin pwm =PWM( Pin(25) )# set PWM freq. to 1kHzpwm.freq(1000)# set counter to 0cnt =0try:whileTrue:if cnt <256: duty = cntelse: duty =511-cnt pwm.duty_u16( duty *256 ) cnt = (cnt+1) %512 time.sleep(0.01)exceptKeyboardInterrupt:pass# set duty cycle to 0 (ns)pwm.duty_ns(0)# deinitialize the GPIO pin used for PWM outputpwm.deinit()
ถ้าทดสอบการทำงานของโค้ดตัวอย่างนี้กับบอร์ด RPi Pico จะเห็น LED บนบอร์ดค่อย ๆ สว่างขึ้นและดับลงซ้ำไปเรื่อย ๆ
ถ้าจะลองใช้โมดูล RGB LED ที่ใช้ขาสัญญาณควบคุมแบบ 3 ขา ก็สามารถทำได้เช่นกัน โค้ดตัวอย่างนี้สาธิตการใช้ขา GPIO-11, 12, 13(GP11,GP12,GP13) เป็นขาสัญญาณเอาต์พุต นำไปต่อกับขาสัญญาณของโมดูล RGB LED (Active-High) เพื่อเปลี่ยนค่า Duty Cycle ของสัญญาณแต่ละช่องไปตามลำดับ
import utime as timefrom machine import Pin, PWMpwm_list = [ PWM( Pin(p) )for p in [11,12,13] ]for pwm in pwm_list: pwm.freq(1000)# set freq. to 1kHz pwm.duty_ns(0)# set duty cycle (high pulse) = 0nstry:whileTrue: time.sleep(0.1)for pwm in pwm_list:for cnt inrange(512):if cnt <256: duty = cntelse: duty = (511-cnt) pwm.duty_u16( duty *256 ) time.sleep(0.005)exceptKeyboardInterrupt:passfor pwm in pwm_list: pwm.duty_ns(0) pwm.deinit()
โค้ดตัวอย่างที่ 5: Timer-based LED Blink
ตัวอย่างนี้สาธิตการใช้งาน Timer (ตอนนี้ใช้ได้เฉพาะ Software Timer และใช้ Timer id เท่ากับ -1) เพื่อทำคำสั่งหรือเรียกใช้ฟังก์ชันตามคาบเวลาหรือความถี่ที่ได้กำหนดไว้ ซึ่งเป็นเหตุการณ์ที่เกิดขึ้นซ้ำ (Periodic) เช่น การสลับสถานะเอาต์พุตของ LED ที่อัตรา 10 Hz
from machine import Pin, Timerled =Pin( 25, Pin.OUT )# use onboard LEDdeftick(timer):global led led.toggle()# create the hardware timer objecttimer =Timer(-1)# configure the timer object, 10Hz tick rate, periodic modetimer.init( freq=10, mode=Timer.PERIODIC, callback=tick )try:whileTrue:passexceptKeyboardInterrupt:passtimer.deinit()
โค้ดตัวอย่างที่ 6: LED Blink Using a Thread
ตัวอย่างนี้สาธิตการใช้คำสั่ง _thread.start_new_thread() เพื่อสร้าง"เธรด" (Thread)ใหม่ให้ทำงานบน CPU Core อีกอันหนึ่ง โดยให้ทำหน้าที่สลับสถานะลอจิกของ LED ตามข่วงเวลาที่กำหนดไว้
from machine import Pinimport utime as timeimport _threadlock =Nonedone =Falsedefled_task(led_pin,n,delay):global done lock.acquire()print( 'LED Task: Thread ID=%d'% _thread.get_ident() ) lock.release() led =Pin( led_pin, Pin.OUT )try:for i inrange(2*n): led.toggle() time.sleep(delay)exceptKeyboardInterrupt:pass done =True lock.acquire()print('Task done') lock.release()# create a lock objectlock = _thread.allocate_lock()# create a new thread and run it on the second CPU core# blink the LED on GPIO-25 pin 10 times with 500ms delay time_thread.start_new_thread( led_task, (25, 10, 0.5) )try: lock.acquire()print( 'Main: Thread ID=%d'%_thread.get_ident() ) lock.release()whilenot done:passexceptKeyboardInterrupt:passfinally: lock.acquire()print('Main thread done') lock.release()
from utime import sleep_msclassBH1750():"""Micropython BH1750 ambient light sensor driver.""" PWR_OFF =0x00 PWR_ON =0x01 RESET =0x07 CONT_LOWRES =0x13 CONT_HIRES_1 =0x10 CONT_HIRES_2 =0x11 ONCE_HIRES_1 =0x20 ONCE_HIRES_2 =0x21 ONCE_LOWRES =0x23def__init__(self,bus,addr=0x23): self.bus = bus self.addr = addr self.reset()defreset(self): # reset sensor self.on() self.set_mode(self.RESET)defoff(self): # turn device off self.set_mode(self.PWR_OFF)defon(self): # turn device on self.set_mode(self.PWR_ON)defset_mode(self,mode): # set sensor mode self.mode = mode self.bus.writeto(self.addr, bytes([self.mode]))defread(self): # read sensor value (luminance in Lux)sleep_ms(24if self.mode in (0x13, 0x23) else180) data = self.bus.readfrom(self.addr, 2) factor =2.0if self.mode in (0x11,0x21) else1.0return (data[0]<<8| data[1])/(1.2* factor)
และโค้ดสาธิตการใช้งานไฟล์ bh1750.py
from machine import Pin, I2Cimport utime as timefrom bh1750 import BH1750 # import from file bh1750.pyBH1750_ADDR =0x23# use I2C1 and GPIO 14,15 for SDA and SCL pinsi2c =I2C( 1, scl=Pin(15), sda=Pin(14), freq=400000 )print( [hex(addr) for addr in i2c.scan()] )try: dev =BH1750(i2c, addr=BH1750_ADDR) dev.on() dev.set_mode( BH1750.CONT_HIRES_1 )whileTrue: value =int(dev.read())# read sensor value (luminance in Lux) text ='BH1750 (0x{:02x}): '.format(BH1750_ADDR) text +='{:5d} Lux'.format(value)print(text) time.sleep_ms(200)exceptKeyboardInterrupt:pass
import utime as timefrom machine import Pin, WDTprint('Press the button on GPIO-16 to enable WDT.')button =Pin( 16, mode=Pin.IN, pull=Pin.PULL_UP )time.sleep_ms(1000)wdt =Noneif button.value()==0:# enable WDT with timeout of 2000 msec wdt =WDT(timeout=2000)# Note that once the WDT is running the timeout cannot be# changed and it cannot be stopped either.if wdt isNone:print('WDT is disabled.')try:while wdt isnotNone:# feed the WDT to prevent it from resetting the system. print('feed WDT @{} ms'.format( time.ticks_ms() ) ) wdt.feed() time.sleep(1.0)exceptKeyboardInterrupt:pass
from machine import ADCimport utime as timesensor_temp =ADC(4)# use on-chip temperature sensorconversion_factor =3.3/65535# 3.3V -> 16-bit valuewhileTrue: reading = sensor_temp.read_u16()* conversion_factor# Typical value: 0.706V at 27 degrees C# with a slope of -1.721mV (0.001721) per degree. temperature =27- (reading -0.706)/0.001721print('On-chip tempreature: {:.2f} deg.C'.format(temperature) ) time.sleep(2.0)
import utime as timefrom machine import Pin,ADCadc_pins = [ 26,27,28,29 ]adc_units = [ ADC(pin)for pin in adc_pins ]vsys_adc = adc_units[-1]try: values = []whileTrue:# read the first 3 ADC inputs for adc in adc_units[:-1]: values.append( (adc.read_u16()/65535)*3.3 )# read the voltage on the VSYS pin values.append( 3*vsys_adc.read_u16()/65535*3.3 )print( ['{:.3f}V'.format(v) for v in values] ) values = [] time.sleep(2.0)exceptKeyboardInterrupt:pass
โค้ดตัวอย่างนี้ สาธิตการใช้งานโมดูล Rotary Encoder Switch ซึ่งจะได้สัญญาณดิจิทัล A, B และมีการเปลี่ยนสถานะลอจิกเมื่อมีการหมุนตามเข็มหรือทวนเข็มนาฬิกา (Clockwise / Anti-Clockwise Rotation) นอกจากนั้นแล้ว ยังมีอีกหนึ่งสัญญาณ SW ให้ผลเหมือนกับวงจรกดปุ่มหรือสวิตช์ปุ่มกด
การตรวจสอบดูว่า มีการหมุนเปลี่ยนตำแหน่งหรือไม่ และเปลี่ยนไปในทิศทางใด เราจะใช้อินเทอร์รัพท์เพื่อดูการเปลี่ยนสถานะที่ขา A ทั้งขอบขาขึ้นและขาลง (Both Rising Edge & Falling Edge) ถ้าไม่มีการเปลี่ยนตำแหน่ง สถานะลอจิกของขา A และ B จะเป็น High
เมื่อเกิดเหตุการณ์ในแต่ละครั้ง ก็ทำให้ฟังก์ชันที่เป็น ISR Handler ที่เกี่ยวข้องทำงาน โดยตรวจสอบดูว่า สถานะของขา A และ B เป็นอย่างไร แล้วใช้ในการเพิ่มหรือลดค่าของตัวนับ (Incremental / Decremental Counter)
from machine import Pin, I2Cimport utime as timefrom sh1106 import*# use I2C0 and GPIO 16,17 for SDA and SCL pinsi2c =I2C(0, scl=Pin(17), sda=Pin(16), freq=400000)print(i2c.scan())I2C_ADDR =0x3C# the I2C address of SH1106 display moduleW, H =128,64# the screen size (128 x 64 pixels)BLACK, WHITE =0,1# scan for I2C devicesif I2C_ADDR notin i2c.scan():raiseRuntimeError('OLED SH1106 not found!!!')# create an SH1106 object disp =SH1106_I2C( W, H, i2c, addr=I2C_ADDR )# rotate the screendisp.rotate( True )# fill the entire displaydisp.fill( BLACK )# draw a white frame disp.rect( 0, 0, W, H, WHITE )# write some text lines (using the default font)xpos,ypos =0,6text_lines = ["Hi!","MicroPython","Raspberry Pi","RP2040"]for line in text_lines: disp.text( '{:^16s}'.format(line), xpos, ypos ) ypos +=12disp.show()# update the display time.sleep_ms(1000)#disp.poweroff()
ฟังก์ชัน send_byte() ใช้สำหรับการส่งข้อมูลขนาดหนึ่งไบต์เท่านั้นไปยัง 74HC595 และเลือกได้ว่าจะเลื่อนข้อมูลออกแบบ MSB First หรือ LSB First
import utime as timefrom machine import Pinload_pin =Pin( 9, Pin.OUT )# load pinsda_pin =Pin(11, Pin.OUT )# serial data sclk_pin =Pin(10, Pin.OUT )# serial clockdefsend_byte( data,msb_first=False ): sda_pin.low() sclk_pin.low() load_pin.low()for i inrange(8):# shift-out data to the SDA pin, LSB firstif msb_first: bit = (data &0x80) ==0x80 data <<=1else: bit = (data &0x01) ==0x01 data >>=1# send data bit if bit: sda_pin.high()else: sda_pin.low()# send a clock pulse sclk_pin.high() sclk_pin.low()# send a pulse to load pin load_pin.high() load_pin.low()for data in [0x00,0x01,0x81,0x42,0x24,0x18,0x55,0xaa,0xff]:send_byte( data ^0xff, True )# MSB first, use inverted bits time.sleep(0.5)