上篇文章,通過狀態(tài)機編程,實現(xiàn)了全自動洗衣機的邏輯控制,并通過串口打印的方式顯示各個狀態(tài)。
本篇,為了更加直觀的感受狀態(tài)機的運行,使用0.96寸OLED來顯示各個狀態(tài),并搭配對應(yīng)的動態(tài)圖標來體現(xiàn)洗衣機工作的各個狀態(tài)。
1 OLED圖片顯示
為了能方便的在OLED上顯示文字和圖片,可以借助一些圖形庫來幫我們顯示,這里使用的是U8g2圖形庫。
1.1 U8g2庫移植
U8g2庫在STM32上的移植,之前的文章已經(jīng)介紹過,具體的移植過程可以參考這篇:
移植成功后,可以使用測試例程驗證U8g2庫的顯示效果。

1.2 圖片顯示
圖片相比較文字,可以展示更加豐富的內(nèi)容,因此本篇通過簡單的單色圖片來展示洗衣機的工作狀態(tài)。
U8g2庫顯示圖片,可以使用u8g2_DrawXBM函數(shù),需要先將圖片轉(zhuǎn)為數(shù)組。
可以使用這個在線網(wǎng)頁來進行圖片數(shù)據(jù)的轉(zhuǎn)換:https://tools.clz.me/image-to-bitmap-array
這里可以使用自己喜歡的圖片,進行展示,比如我選取了不同水量的洗衣機圖標來顯示洗衣機的當前水量,使用多張圖片的交替顯示產(chǎn)生洗衣機在清洗的動畫效果。

2 更多狀態(tài)輸出
OLED屏幕要想顯示洗衣機的工作狀態(tài),就需要獲取狀態(tài)機的具體工作狀態(tài)。這里自定義了一些展示需要用到的數(shù)據(jù),組成一個結(jié)構(gòu)體,狀態(tài)機在運行過程中,對各個成員變量進行修改,然后OLED端獲取這些數(shù)據(jù),再進行展示。
typedef struct
{
WASHER_STATUS washerStatus; /*洗衣機的工作狀態(tài)*/
int targetWaterLevel; /*洗衣機的目標水位*/
int targetWashTimes; /*洗衣機的目標清洗次數(shù)*/
int remainingTime; /*洗衣機的剩余工作時間(暫未使用)*/
int curWaterLevel; /*洗衣機當前的水位*/
bool hasNewData; /*是否有新的數(shù)據(jù)(用于告訴OLED是否刷新顯示)*/
}WASHER_OUTPUT_DATA;
對于OLED的展示邏輯,這里是在狀態(tài)機的每個循環(huán)結(jié)束后,調(diào)用下面的程序邏輯進行展示:
void show_washer_status(WASHER_OUTPUT_DATA washerOutPutData)
{
if (washerOutPutData.hasNewData)
{
WASHER_STATUS s = washerOutPutData.washerStatus;
printf("u8g2 get status:%d(%s)\r\n", s, washer_status_name[s]);
switch(s)
{
case WS_INIT: showWasherInit(&u8g2, washerOutPutData); break;
case WS_IDLE: showWasherIdle(&u8g2, washerOutPutData); break;
case WS_ADD_WATER: showWasherAddWater(&u8g2, washerOutPutData); break;
case WS_WASH: showWasherWash(&u8g2, washerOutPutData); break;
case WS_DRAIN_WATER: showWasherDrainWater(&u8g2, washerOutPutData); break;
case WS_SPIN_DRY: showWasherSpinDry(&u8g2, washerOutPutData); break;
case WS_PAUSE: showWasherPause(&u8g2, washerOutPutData); break;
case WS_DONE: showWasherDone(&u8g2, washerOutPutData); break;
default: break;
}
}
}
當此輪狀態(tài)循環(huán)有新的數(shù)據(jù)產(chǎn)生時,則根據(jù)狀態(tài)機的主狀態(tài),分別顯示對應(yīng)狀態(tài)下的圖片或動畫。
比如加水狀態(tài),會根據(jù)當前加的水位,不斷更新圖片展示的水位:
void drawCurWaterLevel(u8g2_t *u8g2, int level)
{
switch(level)
{
case 0: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_0); break;
case 1: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_1); break;
case 2: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_2); break;
case 3: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_3); break;
case 4: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_4); break;
case 5: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_5); break;
case 6: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_6); break;
case 7: u8g2_DrawXBM(u8g2,64, 16, 48, 48, pic_water_7); break;
default: break;
}
}
void showWasherAddWater(u8g2_t *u8g2, WASHER_OUTPUT_DATA data)
{
char strStatus[14] = "AddWater";
u8g2_ClearBuffer(u8g2);
u8g2_SetFont(u8g2,u8g2_font_ncenB10_tr);
u8g2_DrawStr(u8g2,0,15,strStatus);
drawCurWaterLevel(u8g2, data.curWaterLevel);
u8g2_SendBuffer(u8g2);
}
?對于主程序的結(jié)構(gòu),和上篇一樣,只是增加了OLED的顯示:
int main(void)
{
delay_init(); //延時函數(shù)初始化
LED_Init(); //初始化與LED連接的硬件接口
oled_init();
KEY_Init();
uart_init(115200);
TIM3_Int_Init(500-1,7200-1); //調(diào)用定時器使得50ms產(chǎn)生一個中斷
printf("hello\r\n");
while(1)
{
washer_run_loop();
WASHER_OUTPUT_DATA data = get_washer_output_data();
show_washer_status(data);
delay_ms(100);
}
}
在狀態(tài)機每運行一個循環(huán),獲取一下具體的狀態(tài)數(shù)據(jù),然后使用OLED將具體的狀態(tài)數(shù)據(jù)展示出來。
3 具體演示
再來對比看下這個狀態(tài)圖,實驗測試狀態(tài)機的執(zhí)行。

正常的洗衣流程
不考慮暫停這個狀態(tài),洗衣機上點開始后,依次經(jīng)歷空閑、加水、清洗、排水、甩干這幾個流程即結(jié)束,若清洗計數(shù)設(shè)置了不知1次,則加水、清洗、排水這3個動作會循環(huán)執(zhí)行對應(yīng)的次數(shù)。
洗衣流程中暫停再繼續(xù)
在洗衣機的運行狀態(tài):加水、清洗、排水、甩干,通過暫停按鈕,可以暫停這些狀態(tài)的執(zhí)行,此時狀態(tài)機會運行于暫停模式,再按繼續(xù)(暫停/繼續(xù)的一個按鈕),則會繼續(xù)執(zhí)行洗衣工作。
暫停后修改水量或次數(shù)后再繼續(xù)
在洗衣過程中,如果想要修改洗衣的水量或次數(shù),可以先通過暫停鍵來暫停洗衣機的運行,然后通過水位或次數(shù)按鈕,使狀態(tài)機從暫停狀態(tài)先切換到空閑狀態(tài),進行水位或次數(shù)的調(diào)整后,再繼續(xù),即會按照新的設(shè)置參數(shù)繼續(xù)運行洗衣程序。
比如本來的清洗水位是3,清洗次數(shù)是1,在第一次清洗的加水時按下暫停,再將清洗參數(shù)進行修改,比如水位設(shè)為5,次數(shù)設(shè)為2,再繼續(xù)后,會再次進入加水狀態(tài),并將水位補到5后,繼續(xù)清洗,并清洗2遍結(jié)束。
注:本狀態(tài)機還有繼續(xù)優(yōu)化的空間,比如:
水量只會補加,多了此輪清洗不會排出。比如先設(shè)置的水位是5,在加到3個時候,暫停并修改為2,再繼續(xù)后,判斷大于目標水位則會直接開始清洗,不會先由水位3再排水到水位2再清洗
任何清洗狀態(tài)(加水、清洗、排水)按下暫停調(diào)整水位后,再繼續(xù),都會默認跳到加水重新新的清洗循環(huán),如果是在排水狀態(tài),調(diào)整了水位后,此次的水還沒有排位,就又重新加水開始洗,不太合理
以上3種測試方式的演示效果,可以再對比看下演示視頻:
https://www.bilibili.com/video/BV1xT411E7pY

4 總結(jié)
本篇在上篇全自動洗衣機的狀態(tài)機編程實例的基礎(chǔ)上,增加了OLED來更新直觀的展示洗衣機的工作狀態(tài),并通過3種測試場景來展示洗衣機工作狀態(tài)機的執(zhí)行。
-
STM32
+關(guān)注
關(guān)注
2301文章
11069瀏覽量
369330 -
洗衣機
+關(guān)注
關(guān)注
13文章
689瀏覽量
44638 -
狀態(tài)機
+關(guān)注
關(guān)注
2文章
495瀏覽量
28652
發(fā)布評論請先 登錄
FPGA設(shè)計洗衣機
跪求 全自動洗衣機系統(tǒng) proteus仿真!?。?/a>
洗衣機為什么能自動運行呢
如何去實現(xiàn)一種基于單片機的全自動洗衣機模擬系統(tǒng)設(shè)計
基于單片機SPMC75的模擬全自動洗衣機的設(shè)計
基于STM32單片機的全自動洗衣機
STM32狀態(tài)機編程實例——全自動洗衣機(上)

評論