05 micropython

(2022/07/25)

利用暑假利用NodeMCU-32S+EZ Start Kit+ 再來玩玩MicroPython!開發板使用Web:Bit或PocketCard也都可以用!


一、安裝Thonny

、下載ESP32的韌體

、開啟Thonny及安裝ESP32的韌體

  • 將電腦與ESP32連接,以下幾塊開發版均可使用,本文以NodeMCU-32S(+EZ Start Kit+擴展板)為主,其他兩板再另文介紹!

    • NodeMCU-32S

    • Web:Bit

    • PocketCard

  • 開啟Thonny

    • 點擊 工具/選項

    • 點擊【直譯器】

    • 選擇【MicroPython(ESP32)】

    • 選擇正確的【連接埠】

    • 點擊【安裝或更新韌體】

、EZ Start Kit+ESP32的腳位說明韌體

  • 腳位圖如下:

測試一:按鍵點燈

  • 按A鍵(或B鍵),點亮NodeMCU-32S內建的LED燈

    • 腳位說明:

      1. A鍵:GPIO5

      2. B鍵:GPIO36

      3. 內建的LED燈:GPIO2

      4. 擴展板上的紅燈:GPIO16

      5. 擴展板上的燈:GPIO12

      6. 擴展板上的燈:GPIO13

    • MicroPython程式:

      1. from machine import Pin #使用外部模組功能的動作叫做匯入 (import),匯入的有類別或函式,這邊是匯入Pin類別

      2. led = Pin(2, Pin.OUT) #建立Pin物件,名稱叫led內建LED燈

      3. button = Pin(5, Pin.IN) #A鍵

      4. led.on() #led.value(1) 也可以

      5. while True:

      6. if button.value() == 0:

      7. led.on()

      8. else:

      9. led.off()

  • 按A鍵點燈、按B鍵關燈

    • MicroPython程式:

      1. from machine import Pin

      2. led = Pin(2, Pin.OUT) #內建LED燈

      3. buttonA = Pin(5, Pin.IN) #A鍵

      4. buttonB = Pin(36, Pin.IN) #B鍵

      5. led.on()

      6. while True:

      7. if buttonA.value() == 0:

      8. led.on()

      9. elif buttonB.value() == 0:

      10. led.off()

  • LED燈一閃一滅 (1秒)

    • MicroPython程式:

      1. from machine import Pin

      2. import time #from time import sleep ,後面sleep(1)

      3. led = Pin(2 , Pin.OUT)

      4. while True:

      5. led.value(1)

      6. time.sleep(1) #等待1秒,也可用 time.sleep_ms(1000)

      7. led.value(0)

      8. time.sleep(1)

    • 如果按鍵不是採用【模組】,而是只有2支腳(一支接GND)時,設定【上拉電阻】如下:button = Pin(5, Pin.IN, Pin.PULL_UP)

    • 將檔案儲存在【MicroPython設備】(ESP32上),並將檔名存成main.py,就可離線執行

測試:繼電器控制

  • 按A鍵啟動繼電器、按B鍵關繼電器

    • 腳位說明:

      1. A鍵:GPIO5

      2. B鍵:GPIO36

      3. 繼電器:GPIO25

    • MicroPython程式:

      1. from machine import Pin

      2. relay = Pin(25, Pin.OUT) #繼電器

      3. buttonA = Pin(5, Pin.IN) #A鍵

      4. buttonB = Pin(36, Pin.IN) #B鍵

      5. while True:

      6. if buttonA.value() == 0:

      7. relay.value(1)

      8. elif buttonB.value() == 0:

      9. relay.value(0)

    • 程式跟開關LED燈一樣,並且要用擴展板供電才能啟動及關閉繼電器

測試三:OLED顯示

  • 在LED上顯示Hello World

    • 簡單程式如下:

      • from machine import Pin, SoftI2C #匯入Pin及I2C模組

      • import ssd1306 #匯入ssd1306模組

      • i2c = SoftI2C( scl=Pin(22), sda=Pin(21), freq=400000) #建立SoftI2C類別物件

      • width = 128

      • height = 64

      • display = ssd1306.SSD1306_I2C(width, height,i2c) #建OLED物件

      • display.text('Hello World',0 ,0) #ssd1306函式

      • display.show() #顯示螢幕

    • 要利用EZ Start kit+擴展板供電,這邊害我浪費好多時間

測試:溫濕度感測

  • 在OLED上顯示溫濕度的值

    • 腳位說明:

      1. DHT11溫濕度感測器:GPIO15

    • MicroPython程式:

      1. import dht

      2. from machine import Pin, SoftI2C #匯入Pin及I2C模組

      3. import ssd1306 #匯入ssd1306模組

      4. import time

      5. sensor = dht.DHT11(Pin(15))

      6. i2c = SoftI2C( scl=Pin(22), sda=Pin(21), freq=400000) #建立SoftI2C類別物件

      7. width = 128

      8. height = 64

      9. display = ssd1306.SSD1306_I2C(width, height,i2c) #建OLED物件

      10. while True:

      11. display.fill(0) #螢幕全變黑(清除螢幕)

      12. sensor.measure() #溫濕度量測

      13. temp = sensor.temperature() #取得溫度

      14. humi = sensor.humidity() #取得

      15. temp = 'Temp = {0:4.1f} '.format(temp) + ' C' #格式化

      16. humi = 'Humi = {0:4.1f} '.format(humi) + ' %'

      17. display.text(temp,0 ,0)

      18. display.text(humi,0 ,8)

      19. display.show() #顯示螢幕

      20. time.sleep(1) #等待1秒

    • 可以利用哈氣來看量測到的值有沒有變化

測試:光照量測

  • 在OLED上顯示光照亮度的值(或可變電阻值)

    • 腳位說明:

      1. 光感測器:GPIO39

      2. 可變電阻:GPIO34

    • MicroPython程式:

      1. from machine import Pin, ADC, SoftI2C #匯入Pin,ADC及I2C模組

      2. import ssd1306 #匯入ssd1306模組

      3. import time

      4. adc1 = ADC(Pin(39))

      5. adc2 = ADC(Pin(34))

      6. adc1.atten(ADC.ATTN_11DB) #設定最高的量測電壓,此為3.6V

      7. adc2.atten(ADC.ATTN_11DB)

      8. i2c = SoftI2C( scl=Pin(22), sda=Pin(21), freq=400000) #建立SoftI2C類別物件

      9. width = 128

      10. height = 64

      11. display = ssd1306.SSD1306_I2C(width, height,i2c) #建OLED物件

      12. while True:

      13. display.fill(0)

      14. light = 'Light = '+ str(adc1.read())

      15. vr = 'VR = '+str(adc2.read())

      16. display.text(light,0 ,0)

      17. display.text(vr,0 ,8)

      18. display.show()

      19. time.sleep(0.5)

    • 量測出的結果:

      1. 光感測器的值為0~2800,遮光可到0,但加光的值變化不大

      2. 可變電阻器的值為0~4095

測試燈條測試

  • 點亮燈條的燈

    • 腳位說明:

      1. 燈條(WS2812B):GPIO26

      2. 只有3顆燈

    • MicroPython程式:

      1. from machine import Pin

      2. import neopixel

      3. #import machine, neopixel


      4. n = 3 #燈數

      5. p = 26 #腳位

      6. #np = neopixel.NeoPixel(machine.Pin(p), n) #搭配上面紫色的

      7. np = neopixel.NeoPixel(Pin(p, Pin.OUT), n) #建立neopixel物件


      8. np[0] = (255, 0, 0) #設定第一顆燈顏色

      9. np[1] = (0, 255, 0)

      10. np[2] = (0, 0, 255)

      11. np.write() #write()方法


    • 基本使用很簡單,但不知如何設定【亮度】?!

測試蜂鳴器測試

  • 使蜂鳴器發出 1KHz 的 Bee Bee 告警聲

    • 腳位說明:

      1. 蜂鳴器:GPIO14

    • MicroPython程式:

      1. from machine import Pin,PWM

      2. import time

      3. def alarmBeep(pwm):

      4. pwm.init() #初始化PWM ,之前沒設這條出錯誤

      5. pwm.freq(1000) #設定頻率為 1KHz

      6. pwm.duty(512) #設定工作週期為 50%

      7. time.sleep(1) #持續時間 1 秒

      8. pwm.deinit() #停止發聲

      9. time.sleep(2) #持續時間 2 秒


      10. pwm=PWM(Pin(14))


      11. while True:

      12. alarmBeep(pwm)

    • 一開始一直出現"ValueError: failed to bind timer to channel"錯誤,在函式一開始加個pwm.init()就解決了!


  • 按A鍵播放全家歡迎的音樂

    • 全家歡迎音樂簡譜:3 1 5(低音) 1 / 2 5~ 2 / 3 2 5(低音) 1

    • MicroPython程式:

      1. from machine import Pin,PWM

      2. import time

      3. buttonA = Pin(5, Pin.IN) #A鍵

      4. buzzer = 14 #蜂鳴器

      5. pwm=PWM(Pin(buzzer))

      6. pwm.deinit() #去除一開始的雜音


      7. def family(pwm):

      8. pwm.init() #初始化PWM

      9. pwm.duty(512)

      10. pwm.freq(330)

      11. time.sleep(0.5)

      12. pwm.freq(262)

      13. time.sleep(0.5)

      14. pwm.freq(196)

      15. time.sleep(0.5)

      16. pwm.freq(262)

      17. time.sleep(0.5)

      18. pwm.freq(294)

      19. time.sleep(0.5)

      20. pwm.freq(392)

      21. time.sleep(1)

      22. pwm.freq(294)

      23. time.sleep(0.5)

      24. pwm.freq(330)

      25. time.sleep(0.5)

      26. pwm.freq(294)

      27. time.sleep(0.5)

      28. pwm.freq(196)

      29. time.sleep(0.5)

      30. pwm.freq(262)

      31. time.sleep(0.5)

      32. pwm.deinit()

      33. while True:

      34. if buttonA.value() == 0:

      35. family(pwm)


測試:超音波測距感測器測試

  • 顯示HC-SR04P所量測到的距離

    • 腳位:

      1. TRIG:GPIO16 (IO4)

      2. ECHO:GPIO12 (IO5)

    • MicroPython程式:

      1. from machine import Pin, I2C

      2. from ssd1306 import SSD1306_I2C

      3. from hcsr04 import HCSR04

      4. import utime


      5. oled = SSD1306_I2C(128, 64, I2C(scl=Pin(22), sda=Pin(21)))

      6. sonar = HCSR04(trigger_pin=16, echo_pin=12)


      7. while True:

      8. distance = sonar.distance_cm()

      9. oled.fill(0)

      10. oled.text("Distance:", 0, 0)

      11. oled.text(str(distance) + " cm", 0, 16)

      12. oled.show()

      13. print("偵測距離: " + str(distance) + " 公分")

      14. utime.sleep_ms(25)

    • hcsr04.py:直接把下面程式內容上傳到ESP32裝置上,此檔取自謝昌勳老師

      1. import machine, time

      2. from machine import Pin


      3. __version__ = '0.2.0'

      4. __author__ = 'Roberto Sánchez'

      5. __license__ = "Apache License 2.0. https://www.apache.org/licenses/LICENSE-2.0"


      6. class HCSR04:

      7. """

      8. Driver to use the untrasonic sensor HC-SR04.

      9. The sensor range is between 2cm and 4m.


      10. The timeouts received listening to echo pin are converted to OSError('Out of range')


      11. """

      12. # echo_timeout_us is based in chip range limit (400cm)

      13. def __init__(self, trigger_pin, echo_pin, echo_timeout_us=500*2*30):

      14. """

      15. trigger_pin: Output pin to send pulses

      16. echo_pin: Readonly pin to measure the distance. The pin should be protected with 1k resistor

      17. echo_timeout_us: Timeout in microseconds to listen to echo pin.

      18. By default is based in sensor limit range (4m)

      19. """

      20. self.echo_timeout_us = echo_timeout_us

      21. # Init trigger pin (out)

      22. self.trigger = Pin(trigger_pin, mode=Pin.OUT, pull=None)

      23. self.trigger.value(0)


      24. # Init echo pin (in)

      25. self.echo = Pin(echo_pin, mode=Pin.IN, pull=None)


      26. def _send_pulse_and_wait(self):

      27. """

      28. Send the pulse to trigger and listen on echo pin.

      29. We use the method `machine.time_pulse_us()` to get the microseconds until the echo is received.

      30. """

      31. self.trigger.value(0) # Stabilize the sensor

      32. time.sleep_us(5)

      33. self.trigger.value(1)

      34. # Send a 10us pulse.

      35. time.sleep_us(10)

      36. self.trigger.value(0)

      37. try:

      38. pulse_time = machine.time_pulse_us(self.echo, 1, self.echo_timeout_us)

      39. return pulse_time

      40. except OSError as ex:

      41. if ex.args[0] == 110: # 110 = ETIMEDOUT

      42. raise OSError('Out of range')

      43. raise ex


      44. def distance_mm(self):

      45. """

      46. Get the distance in milimeters without floating point operations.

      47. """

      48. pulse_time = self._send_pulse_and_wait()


      49. # To calculate the distance we get the pulse_time and divide it by 2

      50. # (the pulse walk the distance twice) and by 29.1 becasue

      51. # the sound speed on air (343.2 m/s), that It's equivalent to

      52. # 0.34320 mm/us that is 1mm each 2.91us

      53. # pulse_time // 2 // 2.91 -> pulse_time // 5.82 -> pulse_time * 100 // 582

      54. mm = pulse_time * 100 // 582

      55. return mm


      56. def distance_cm(self):

      57. """

      58. Get the distance in centimeters with floating point operations.

      59. It returns a float

      60. """

      61. pulse_time = self._send_pulse_and_wait()


      62. # To calculate the distance we get the pulse_time and divide it by 2

      63. # (the pulse walk the distance twice) and by 29.1 becasue

      64. # the sound speed on air (343.2 m/s), that It's equivalent to

      65. # 0.034320 cm/us that is 1cm each 29.1us

      66. cms = (pulse_time / 2) / 29.1

      67. return cms