資料介紹
描述
#25projectsofchristmas
數字物聯網作弊骰子
M5STickC-plus 具有內置加速度計。和一個顯示器。有了這個,您可以輕松地對數字骰子進行編程,當您搖動設備時會產生新的值。此外,M5STickC-plus 還擁有一個 WiFi 芯片,可以讓它連接到互聯網。這就是物聯網進入游戲的地方:想象一下和你的朋友玩骰子,看看誰在酒吧買單。估計最遠的人必須支付。您搖動 M5Stick 并將其正面朝下放在桌子上。每個人都必須猜測一個值,但您首先檢查您的智能手機以查看滾動的值,因為您的錢包中沒有足夠的錢來支付賬單。
骰子展示
兩個骰子的值應該顯示在顯示器上,骰子應該看起來像骰子:
為此,首先將沒有點的骰子圖像加載為背景圖像。
現在,根據隨機生成的 1 到 6 之間的值,必須在骰子的區域上繪制點。為此,6 個可能值的點坐標存儲在一個 3 維數組中:
// Array to define the position of the dots on the dice
int dot_positions[7][6][2] {
{}, // 0
{{55,55}}, // 1
{{25,25},{85,85}}, // 2
{{25,25},{55,55},{85,85}}, // 3
{{25,25},{85,25},{25,85},{85,85}}, // 4
{{25,25},{85,25},{55,55},{25,85},{85,85}},// 5
{{25,25},{25,55},{25,85},{85,25},{85,55},{85,85}}, // 6
};
我認為這些值需要解釋得更詳細一點:M5StickC-plus 的顯示器分辨率為135*240 像素。空間足以容納兩個大小為 110x110 像素的芯片圖像。原點在左上角,模具上每個可能的點位置的坐標可以這樣定義:
如果現在擲出 2,則必須在顯示屏上的相應位置繪制兩個圓圈。為了讓骰子的點位于正確的位置,坐標必須在顯示器上移動骰子的目標位置:
dot_positions []數組包含骰子可以取的所有 6 個值對應的圓的位置。然后可以使用它來編寫一個簡單的函數,為 1 到 6 之間的每個數值繪制相應的點排列:
// function to draw the dice
void draw_dice(int16_t x, int16_t y, int dice_value) {
// M5StickC-plus Display size is 135x240
// Dice size is 110x110
M5.Lcd.pushImage(x, y, 110, 110, (uint16_t *)Dice_background);
if(dice_value > 0 && dice_value < 7){
for(int dot_index = 0; dot_index < dice_value; dot_index++) {
M5.Lcd.fillCircle(x+dot_positions[dice_value][dot_index][0],
y+dot_positions[dice_value][dot_index][1],
DOT_SIZE, TFT_BLACK);
}
}
}
如上所述,對值為 2 的骰子的函數調用將如下所示:
draw_dice(12,9, 2);
現在我們可以畫骰子了,但是應用程序仍然需要在一個好的過程中運行。所以我們需要一個“過程序列控制東西功能的東西” ,或者換句話說:我們需要一個狀態機!
有限狀態機
所謂的“狀態機”是過程序列的行為模型。它由有限數量的狀態組成,因此通常稱為有限狀態機 (FSM)。簡單地說:基于當前狀態和給定輸入,狀態機執行狀態轉換并產生輸出。這聽起來比實際更復雜。對于骰子軟件,我們可以定義三個簡單的狀態:
軟件應保持在啟動狀態,直到檢測到設備晃動。然后結果應該只在搖動停止時顯示。因此,軟件應保持在搖動狀態,直到檢測到搖動結束。最后,軟件應保持顯示狀態,直到按下 M5Stick 上的按鈕。這是狀態機的基本原理。
為了表示骰子程序的流程控制,代碼中定義了以下狀態:
// 0 = start with printing text
#define START_STATE 0
// 10 = waiting for start shaking
#define WAIT_STATE 10
// 20 = generate random numbers and wait for stop shaking
#define SHAKE_STATE 20
// 30 = display dice #1 value
#define DISPLAY1_STATE 30
// 40 = display dice #2 value
#define DISPLAY2_STATE 40
// 50 = wait for button press to start new game
#define BUTTON_STATE 50
操作順序的詳細圖形表示如下所示:
狀態機實現
有幾種方法可以實現狀態機。由于該軟件只需要一個簡單的狀態機,因此也可以通過一個簡單的switch()函數來實現:
// state machine cases
switch(process_State) {
// ******** START_STATE = start with printing text
case START_STATE :
...
// next state
process_State = WAIT_STATE;
break;
// ******** WAIT_STATE = waiting for acceleration (start shaking)
case WAIT_STATE :
...
process_State = SHAKE_STATE;
break;
// ******** SHAKE_STATE = generate random numbers and wait for stop shaking
case SHAKE_STATE :
...
process_State = DISPLAY1_STATE;
break;
// ******** DISPLAY1_STATE = display dice #1
case DISPLAY1_STATE :
...
process_State = DISPLAY2_STATE;
break;
// ******** DISPLAY2_STATE = display dice #2
case DISPLAY2_STATE :
...
process_State = BUTTON_STATE;
break;
// ******** BUTTON_STATE = wait for button press to start new roll
case BUTTON_STATE :
...
process_State = START_STATE;
break;
}
在每個“開關狀態”中,都實現了相應的功能。詳情請查看完整的源代碼。基本上這就是全部。不像一開始聽起來那么復雜,對吧?
如果你想學習如何處理背景圖像,請查看我的“M5Stack Screen Capture”項目或我的“M5Stack Christmas Snow Globe”項目。
震動檢測
集成加速度傳感器 (IMU) 測量 3 個軸(X、Y 和 Z)的加速度:
因此,左右晃動可以通過沿 X 軸的加速度來確定。但不應檢測到敲擊、撞擊或敲擊,只有實際的搖晃。一種簡單的方法是在很短的時間間隔內進行兩次測量。然后,這些值的絕對差異可以用作設備加速程度的指標。方向無關緊要(向左或向右),因為計算的是絕對值。但是,該值也會檢測到設備上的敲擊。為了防止這種情況,可以計算 10 次測量的移動平均值,從而過濾掉高頻數據,如敲擊或敲擊。
非阻塞解決方案
如果你編寫一個函數,以 100ms 的間隔測量加速度 10 次來計算平均值,那么整個軟件將被阻塞 10*100ms = 1 秒。情況不妙。人們應該始終避免這種阻塞功能。與其在函數內部循環進行 10 次測量,不如讓函數只進行一次測量,然后將結果存儲在全局變量中。在狀態機內,函數在WAIT_STATE和SHAKE_STATE內被調用,這導致狀態機的非阻塞流。
移動平均過濾功能
通常人們會通過將單個值相加然后將總和除以相加值的數量來計算平均值:
此方法適用于逐塊計算平均值:您只需將多個值相加,然后將最后的總和除以值的數量。對于下一個塊,您再次從總結新值開始。但是,如果要計算每個新值的平均值(移動平均值),則必須刪除列表的第一個值并在末尾添加新值。編寫這樣的方法既麻煩又在數學上是不必要的。
另一種(順便說一下,在數學上相同)方法是將最后計算的平均值乘以減 1 的值的數量,然后將新值添加到其中,并將該總和除以要平均的值的數量:
與存儲 10 個值的列表相比,此方法速度更快,所需內存更少。
從技術上講,這是一種低通濾波器,其背后的理論幾乎可以變得任意復雜,但是對于這個簡單的程序,可以通過反復試驗很好地確定合適的值。要平均的值的數量值越高,過濾掉的高頻信號就越多,但產生的延遲也就越多。檢測抖動的函數的實現如下所示:
int mean_accX_n = 8;
.....
float get_horizontal_shaking(){
// two values of X-acceleration
float accX_1, accX_2;
// Y and Z values are needed for function call
float accY, accZ;
// differential value of X-acceleration
float accX_d = 0;
// get the first and the second sensor data
M5.Imu.getAccelData(&accX_1,&accY,&accZ);
delay(100);
M5.Imu.getAccelData(&accX_2,&accY,&accZ);
// calculate the absolute differential value
accX_d = fabs(accX_2 - accX_1);
// building the mean value (Moving average calculation)
mean_accX_d = ((mean_accX_d * (mean_accX_n-1)) + accX_d)/mean_accX_n;
return mean_accX_d;
}
返回值大于 3 表示設備已搖晃。小于 1 的值表示晃動已停止:
有了這個,骰子軟件就可以運行了,你可以為酒吧賬單滾動了。唯一缺少的是作弊功能。
物聯網作弊
只需幾行簡單的代碼,M5StickC 就變成了一個 WiFi 接入點:
// WiFi network configuration:
char wifi_ssid[] = "M5StickC-plus";
char wifi_key[] = "1234567890";
IPAddress ip(192, 168, 0, 1);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiClient myclient;
WiFiServer server(80);
void web_server_init(){
WiFi.mode(WIFI_AP);
WiFi.softAP(wifi_ssid, wifi_key);
WiFi.softAPConfig(ip, gateway, subnet);
WiFi.begin();
// Start TCP/IP-Server
server.begin();
}
現在您可以將手機連接到 M5Stick 創建的 WiFi 接入點。同時,Web 服務器正在等待您使用瀏覽器連接到 IP 地址。
我已經在我的項目“ M5ATOM ENV 迷你數據監視器”中描述了 Web 服務器的功能。對于骰子網頁,我還使用動態 HTML 代碼通過外部 Java 腳本請求包含立方體的值:
<script>
window.onload = function(){
document.getElementById('dice1').innerHTML = dice1value;
document.getElementById('dice2').innerHTML = dice2value;
};
script>
<script type="text/javascript" src="dicevalue.js">script>
擲出的兩個骰子的值被定義為全局變量。當 Web 瀏覽器請求 Java 腳本文件“ dicevalue.js ”時,Web 服務器會根據當前值生成它:
case GET_dicevalue: {
client.println("HTTP/1.1 200 OK");
client.println("Content-type:application/javascript");
client.println();
client.printf("var dice1value = %c;\n", dice1_html_value);
client.printf("var dice2value = %c;\n", dice2_html_value);
break;
}
其他一切都與我的項目“M5ATOM ENV 迷你數據監視器”中的描述完全相同。但是,在這段代碼中,我將 Web 服務器功能外包給了外部文件。這使骰子軟件的代碼保持簡單和干凈。帶有接入點的 Web 服務器只需要在 setup() 函數中初始化,并在每次運行時在 loop() 函數中調用:
void setup() {
M5.begin();
...
// init and start the web-server for the dice-web-page
web_server_init();
delay(3000);
}
void loop() {
M5.update();
...
// check for web browser requests
web_server_update();
delay(20);
}
現在你可以帶著空錢包去酒吧和朋友喝一杯。但是請確保 M5Stick 的電池始終充滿電,因為如果有人拿出真正的骰子,您必須依靠您的運氣而不是您的智能手機。
反饋
我希望你喜歡這個簡短有趣的項目,并且這段代碼可以證明對你們中的一些人有用。如果您有任何問題或意見,請隨時給我留言。
享受擲骰子的樂趣!
問候,
漢斯-君特
- 物聯網感知技術及系統應用 1次下載
- 基于Arduino的7段顯示數字骰子
- 具有隨機功能的簡單LED骰子
- 什么是智能工廠-物聯網系統 7次下載
- 物聯網工程概要設計課件下載 0次下載
- 物聯網工程PCB詳細設計課件下載 0次下載
- 物聯網工程需求分析課件下載 0次下載
- 物聯網工程概述課件下載 0次下載
- 工業物聯網的詳細解析工業物聯網到底是什么 11次下載
- 物聯網芯片設計應該如何降耗
- 如何使用物聯網操作系統Zephyr實現“連續集成”開源軟件的詳細說明
- 物聯網金融系統方案設計的詳細資料說明 23次下載
- 物聯網無線連接技術是什么?物聯網產品的射頻測試資料概述 26次下載
- 物聯網是什么?現在物聯網通信標準和協議有哪些?物聯網應用的概述
- 物聯網的真正價值是什么?
- 物聯網網關的類型和功能 1804次閱讀
- 分享一個棋盤游戲電子骰子電路 2234次閱讀
- 三個簡單的電子骰子電路分析 5765次閱讀
- 基于AT89C205構建的電子骰子的電路圖 2178次閱讀
- 物聯網是什么和物聯網基本架構 5697次閱讀
- 如何通過藍牙微控制器控制多功能骰子? 2905次閱讀
- 帶反接保護的電子骰子電路 3381次閱讀
- 具有階梯計價功能的物聯網智能水表的原理及設計 1688次閱讀
- LED骰子diy教程 4650次閱讀
- 物聯網典型的四層架構分析 9.3w次閱讀
- 物聯網的專業技能在實際生活中的應用 7361次閱讀
- 農業物聯網的意義_農業物聯網的功能_農業物聯網的應用 9619次閱讀
- 工業物聯網的意義_工業物聯網前景分析 1.2w次閱讀
- 蜂窩物聯網是什么_蜂窩物聯網建設意義 1.3w次閱讀
- 驅動電子骰子至少需要幾個I/O口? 3962次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數據手冊
- 1.06 MB | 532次下載 | 免費
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費
- 5元宇宙深度解析—未來的未來-風口還是泡沫
- 6.40 MB | 227次下載 | 免費
- 6迪文DGUS開發指南
- 31.67 MB | 194次下載 | 免費
- 7元宇宙底層硬件系列報告
- 13.42 MB | 182次下載 | 免費
- 8FP5207XR-G1中文應用手冊
- 1.09 MB | 178次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 2555集成電路應用800例(新編版)
- 0.00 MB | 33566次下載 | 免費
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費
- 4開關電源設計實例指南
- 未知 | 21549次下載 | 免費
- 5電氣工程師手冊免費下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費
- 6數字電路基礎pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅動電路設計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉中文版)
- 78.1 MB | 537798次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191187次下載 | 免費
- 7十天學會AVR單片機與C語言視頻教程 下載
- 158M | 183279次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138040次下載 | 免費
評論
查看更多