我們使用Pico、WIZnet W5100S 和 PicoBricks 開發板開發了MQTT RGB燈,通過ChatGPT 4.0生成和優化代碼。
項目所需組件
硬件組件
PicoBricks 擴展板 x 1
WIZnet W5100S-EVB-Pico x 1
WIZnet W5500-EVB-Pico
WIZnet以太網HAT x 1
樹莓派Pico x 1
軟件應用和在線服務
MicroPython
項目背景
有很多關于如何用ChatGPT編碼的介紹,我還嘗試過用它來創建簡單的例子或生成一些邏輯代碼。但是有沒有可能只用ChatGPT就可以開發一個項目呢?
ChatGPT4最近開放了代碼解釋器功能,讓我們嘗試使用這個新功能。我進行了即時書寫,沒有使用任何命令或擴展應用程序。結果如何?獲得了巨大成功。
除了對一些非常簡單的代碼進行修改之外,大部分代碼都是借助 ChatGPT 完成的。
Pico 遙控燈
這是一份總結。請牢記這一點,并查看以下文本,看看它是如何被運用的。
這項工作是通過編寫并驗證基礎庫和示例代碼,然后將必要的部分進行整合來完成的。
1.如果你正在使用特定的模塊/庫,請明確指出。
2.執行代碼后,如果出現錯誤,請將錯誤信息以及疑似出錯的代碼部分告知GPT,并請求其進行修正。即使你應用了修改后的代碼后錯誤仍然存在,也要堅持不懈地尋求解答。之后,會為你提出一個新的方向。
3.你必須清晰明確地寫出你期望實現的功能、觸發操作的條件、執行時機等信息,這樣才能更接近你想要的執行效果。
4.在創建新類時,如果你能提供一個功能與結構相似的類作為示例,那么將會為你創建一個類似的類。
5.當組合使用各種類時,分別請求每個單獨功能的示例并將它們組合起來,往往比直接輸入類信息并要求得到一個完整功能的效果更好。
6.如果你想為達到同一結果而采用不同的邏輯,請提供一個邏輯示例,并請求將其應用。
與其絞盡腦汁地過度思考,不如就把它讀作:“啊,他們這樣用提示來解決這樣的問題?”
如果你覺得:“這部分不錯!”那就把它記下來,并試著在自己的項目中運用。
設置代碼解釋器
功能定義
為了創建一個恰當的提示,需清晰勾勒出功能特性。
這部分對于開發以及編寫提示都至關重要。當你對功能特性有清晰的理解時,提出的問題就會更加精確,也就能明確劃分并著手處理哪些部分。
由于很多時候需要分部分開展工作然后再進行整合,因此理解整體結構就顯得更為關鍵。
- 控制設備
1.控制設備將使用MQTT協議向RGB燈傳輸JSON格式的數據。這些數據將包含調整燈具RGB顏色和亮度的信息。
2.控制設備將配備一個按鈕,用于控制RGB燈的顏色。
當按鈕按下時間少于0.5秒時,將選擇RGB顏色。
3.控制設備將使用可變電阻來調節燈具的亮度。
電阻值將被映射到1~100的亮度級別。
4.在OLED顯示屏上顯示RGB燈的顏色和亮度信息。
- RGB燈設備
1.RGB燈設備將通過MQTT協議從控制設備接收JSON格式的數據。
這些數據將包含調整燈具RGB顏色和亮度的信息。
2.RGB燈設備將根據接收到的JSON數據調整其RGB值和亮度。
3.在OLED顯示屏上顯示RGB燈的顏色和亮度信息。
- 網絡:MQTT
1.初始化
如果你正在使用特定的模塊/庫,請明確指出。
請求網絡和MQTT的基礎示例。網絡和MQTT的相關信息通過define進行聲明。
MQTT默認設置
提示1:當然,這里有一個使用MicroPython和WIZNET5K驅動器進行MQTT通信的基礎函數示例。在這個函數中,設備被設置為靜態IP地址192.168.11.101,網關為192.168.11.1,子網掩碼為255.255.255.0,DNS服務器為8.8.8.8。MQTT代理位于IP地址192.168.11.100,主題為ctrl_state。未使用用戶名和密碼。保持連接時間為60秒。SPI配置:波特率:2,000,000,MOSI:19,MISO:16,SCK:18,CS:17,RESET:20。添加默認訂閱和發布功能。
提示2:請在你編寫的代碼中定義與用戶名、IP、網關、子網掩碼、DNS和主題相關的內容。
ChatGPT一次性完成了這個任務。我使用Mosquitto測試了訂閱和發布功能。
由于MQTT經常在其他項目中使用,我們將其創建為一個庫。
提示1:我打算將下面的代碼封裝成一個庫,命名為WIZnetMQTT.py。請將其修改為類格式,以便于作為API使用。
提示2:在你編寫的類中,我們打算將初始化函數中的網絡初始化部分放到另一個函數中使用。請將其拆分,不包括網絡初始化部分,僅保留MQTT初始化部分。
在收到庫的更新代碼以及主程序的測試示例后,我再次檢查了其運行情況,它工作得很好。
2.訂閱回調
為了更靈活地使用MQTT庫,我們允許注冊回調函數來處理訂閱的消息。
如果沒有提供回調函數,則設計為直接返回主題和消息。
提示1:請修改def sub_cb(self, topic, msg)函數,使其更具通用性。如果提供了回調函數,則使用該回調函數;如果沒有提供,則返回主題和消息。
classWIZnetMQTT: def__init__(self, username, broker_ip, topic, keep_alive, callback=None):…self.callback = callback…defsub_cb(self, topic, msg): ifself.callback: returnself.callback(topic, msg) else: returntopic, msg
出于測試目的,我將創建一個訂閱回調函數。
由于我們計劃接收JSON格式的數據,我將添加一個解析函數。
提示2:另外,你能提供一個使用回調函數的示例嗎?接收到的消息是JSON格式的,比如{"color":"R", "brightness": 0}。顏色值可以是'R'、'G'或'B',亮度值的范圍是從0.01到1。在WIZnetMQTT類中,請包含一個能夠解析這種JSON消息的回調函數。
defexample_callback(topic, msg): try: data = json.loads(msg) color = data.get("color",None) brightness = data.get("brightness",None) … print(f"Received color:{color}, brightness:{brightness}") exceptjson.JSONDecodeError: print("Error decoding JSON!")
如果直接這樣運行,將會出現錯誤。
執行后,如果發生錯誤,請將錯誤信息以及疑似存在錯誤的代碼告知GPT,并請求修正。
即使你應用了修改后的代碼但錯誤仍然存在,也要堅持不懈地尋求答案。隨后,會提出一個新的解決方向。
提示:我在下面的example_callback函數中遇到了“AttributeError: 'module' object has no attribute 'JSONDecodeError'”錯誤??赡苁悄睦锍隽藛栴}?
…To handlethis, you cancatcha more general exception, like Exception, to capture any kind of error that arises during the JSON decoding process:…except Exception: # Catch any exception,notjust JSONDecodeError…
你需要檢查其是否正常運行。
模塊
對于模塊而言,我擁有一個之前已經創建好的庫。
對于現有的類,我直接使用它們或者在其基礎上進行擴展;對于不存在的類,我會創建它們以匹配相似的格式。
(這個庫的大部分內容也是使用ChatGPT創建的)
1.電位器
電位器的邏輯相對簡單。我將把Pico bricks提供的電位器示例,以及從picobricks_utils.py的類(picobricks_hum_temp)中引用的結構添加到提示中。
你必須清楚地寫出你想要實現的功能、觸發操作的條件、時間安排等,以便更接近期望的動作。
在創建一個新類時,如果你能提供一個功能與結構相似的類作為示例,那么將為你創建一個類似的類。
提示:這是電位器的基本功能代碼?!皃ot=ADC(Pin(26)) pot_val=((pot.read_u16()/65535.0)*20) +1”。請按照下面類的格式來編寫。class picobricks_hum_temp: ...
importmachinefrom machineimportADC, PinclassPotentiometer:...
修改雖然成功了,但輸出值是一個介于1到21之間的小數
請將其更改為一個函數,使其能夠將該值映射到0到100之間的整數(默認范圍是0~100)。
如果你想修改輸出的某一部分,無需創建新的提示,只需從已寫好的輸出中請求修正你希望更改的部分即可。
提示:這個函數的結果是最小值和最大值分別為1.0和21.0之間的小數。請添加一個函數,根據輸入的最小值和最大值進行映射。默認值應設為1和100,并且應能夠通過init方法中的參數進行配置。
def__init__(self, pot_pin=26, read_timer=2, min_val=0, max_val=100): self.min_val = min_val self.max_val = max_val def_map_value(self, value): # Map the value from [1, 21] range to [self.min_val, self.max_val] range return((value -1) / (21-1)) * (self.max_val -self.min_val) +self.min_val
2.按鈕
已經為按鈕創建了一個類。
然而,由于目前只有一個切換按鈕模式,我將添加一個按壓按鈕模式以及一個按壓回調函數。
此外,我還將添加模式選擇功能,以便根據所選模式進行操作。
(由于默認模式是“開/關”,因此與之前編寫的示例不會產生沖突)。
提示1:以下是與按鈕相關的類。請在此處添加一個新函數,用于識別和控制按壓按鈕。同時,確保將按壓按鈕作為回調函數參數接收,并相應地調用它。class picobricks_button:~Omitted~
提示2:請將set_toggle_button_state函數拆分為兩種模式:“開/關”(on/off)和“按壓”(push)。當處于“按壓”模式時,執行按壓回調函數。
classpicobricks_button: def__init__(self, btn_pin=10, detect_time_ms=500, mode="on/off"): self.push_callback =None self.mode = mode
它工作得很好。讓我們為這個功能創建一個回調函數。
基于按壓動作,讓我們將狀態從紅色(R)變為綠色(G),再變為藍色(B)...并創建一個函數來讀取已設置的RGB值。
提示1:創建一個函數以注冊到按壓回調中。實現一個邏輯,即當按下按壓按鈕時,RGB狀態按照“紅(R)”、“綠(G)”、“藍(B)”的順序循環變化。
提示2:使用這個函數時,初始值被設置為“藍(B)”,請修改為從“紅(R)”開始。此外,添加一個“獲?。╣et)”函數,以便能夠讀取當前設置的RGB值。
classRGBController: def__init__(self): defcycle_rgb_state(self):defmain(): btn =picobricks_button(mode="push") btn.set_button_callback(push_callback=rgb_controller.cycle_rgb_state) whileTrue: btn.set_toggle_button_state() time.sleep_ms(50)
我原本請求的是一個函數,但收到的是一個類。不過,由于RGB循環似乎會以多種形式被使用,因此我會將其以類的格式直接添加到picobricks_utils.py文件中。
3.斜坡控制
在組合使用各種類時,相較于直接輸入類信息并要求一個完整的功能,為每個單獨的功能請求示例并將它們組合起來,往往能獲得更好的效果。
基于上述內容,我們將兩個功能(按鈕控制和斜坡控制)組合起來。
同時,我會在過程中修改錯誤信息。
提示1:我需要按鈕按壓和電位器的示例。我需要在主程序中使用的函數。創建一個函數,每當按鈕被按下或電位器值發生變化時,就打印當前的RGB值和電位器值/100的結果。~示例按鈕/電位器~
提示2:當我進行這些修改時,變化并沒有實時更新??赡苁鞘裁磫栴}?
提示3:每1秒讀取一次值,并在按鈕和電位器值與前一次不同時打印變化的值。
提示4:存在一個漏洞,即在沒有任何按鈕操作的情況下,當電位器值變化時,RGB值會自動改變。請修復這個問題。
并且使用[time.sleep(1)]來實現時間延遲。但這并不是最好的方法。
如果你想為相同的結果應用不同的邏輯,請提供一個邏輯示例并請求其應用。
提示5:設置定時器,每1秒讀取一次值。使用'get_time'格式而不是'sleep'。current_pot_value = pot_value_scaled() 如果 current_pot_value != prev_pot_value:打印 f"亮度值已更改為: {current_pot_value:.2f}" prev_pot_value = current_pot_value
提示6:將定時器減少到500毫秒。
4. OLED
我已經為OLED創建了一個類,現在我將添加一個新函數,該函數可以在每一行上顯示不同的內容。
由于有多個打印函數,函數名變得不太易讀。我請求進行修改。
提示1:請在下面的類中添加一個名為'oled'的函數,該函數允許在5行的每一行中輸入不同的內容。
提示2:如果某一行沒有輸入內容,請確保不調用self.oled.text(line5, 5, 48)(或類似針對該行的文本顯示調用)。
提示3:請重命名該函數
使用在按鈕和電位器中創建的變量,在OLED上顯示當前的顏色和亮度值。
由于之前有提示編寫歷史,因此無需輸入額外的變量信息。
提示1:參考下面的函數,請創建一個函數,該函數在OLED的第一行上打印'Color: {rgb}',在第二行上打印'Brightness: {current_pot_value}%',使用提供的cur_rgb和current_pot_value值。
提示2:當值發生變化時,我希望在更改“亮度”時同時更新“顏色”顯示,在更改“顏色”時也同時更新“亮度”顯示。我希望兩者能同時顯示,并且只更新發生變化的值。
我們還將使用生成的值創建一個JSON編碼函數。
5.燈具控制
創建一個燈具控制設備
首先,我們將使用虛擬數據來生成JSON消息。
利用之前創建的類和函數,根據JSON消息在OLED上顯示數據,并控制RGB LED燈。
提示1:這是一個用于解析JSON消息的函數。當“顏色(color)”和“亮度(brightness)”與它們之前的值不同時,創建一個函數來控制Neopixel燈帶。請參考Neopixel類。
我已經進行了測試,效果良好。
現在,各個設備的單獨功能已經完成,讓我們來完善MQTT控制部分。
我將輸入兩個已完成的代碼,并請求將它們合并。
如前所述,與其一開始就要求完整的代碼,不如為每個功能編寫代碼,然后再請求合并,這樣更有效率。這種方法可以確保詳細功能得到良好實現,并減少嘗試次數。
我們還將更改函數名以匹配其功能。
運行代碼后,如果出現錯誤,只需請求修改即可。
提示1:將兩個代碼合并。
提示2:在調用'update_oled_display'函數時,也使用與'update_oled_display'相同的參數調用'generate_json_message'函數。此外,使用'generate_json_message'返回的消息來執行'publish()'函數。
提示3:修改'update_oled_display'的函數名,以反映其更新后的功能。
提示4:NameError: name 'mqtt' isn't defined(名稱錯誤:未定義名稱'mqtt')
對于控制設備,我們將功能分類為MQTT發布、按鈕、電位器和OLED。對于燈具設備,我們將功能分類為MQTT訂閱、OLED和受控的RGB LED。
由于這是一個簡單的任務,我直接編寫了代碼。
我將與你分享我在項目開發過程中使用的編寫提示的過程。
我所有工作的歷史記錄,請參考這里的chatgpt日志。其中記錄了許多嘗試和失敗。
項目現已完成。這是一個簡單的項目,不是嗎?
盡管這是一個小項目,但我們完全使用chatGPT進行了開發。
就像編碼一樣,練習得越多,水平就越高,使用提示似乎也是如此。
雖然體驗大型項目的部分開發過程至關重要,但完成小型項目的從始至終也同樣重要。
我經常使用chatGPT,但這是我第一次完全使用提示從開始到結束進行開發,我感覺自己比以前更得心應手了。
雖然這是我第一次嘗試,還有些生疏,但我會繼續更多地使用它。如果將來有更好的項目,我會帶著另一個項目回來。
代碼
https://github.com/wiznetmaker/RP2040-PicoBricks-HAT-Micropython/tree/main/example/AI_Lamp
原文地址:
https://www.hackster.io/wizscarlet5986/mqtt-project-with-pico-and-ethernethat-using-chatgpt-prompts-0c44eb
-
智能家居
+關注
關注
1933文章
9749瀏覽量
189613 -
樹莓派
+關注
關注
121文章
1942瀏覽量
106982 -
MQTT
+關注
關注
5文章
669瀏覽量
23469 -
ChatGPT
+關注
關注
29文章
1587瀏覽量
8797
發布評論請先 登錄
樹莓派與Z-wave模塊制作一個智能家居的網關
【NanoPi2申請】智能家居主控中心
【NanoPi2申請】智能家居控制系統
【NanoPi2申請】智能家居項目
【品勝云路由申請】智能家居
【orangepi zero申請】智能家居中繼器
【下載】《Linux+樹莓派玩轉智能家居》——親手進行樹莓派應用制作
從智能家居到智慧建筑:NAYOTA LBMS 如何賦能 樹莓派5 實現設備互聯?

評論